diff --git a/.eslintrc.js b/.eslintrc.js index b3dd9cb5d0..c9f2a8db03 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,7 +3,8 @@ module.exports = { "env": { "es6": true, "node": true, - "browser": true + "browser": true, + "jest": true }, "parser": "babel-eslint", "parserOptions": { diff --git a/.storybook/config.js b/.storybook/config.js index 2a975ad48c..a08a304f8a 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -1,6 +1,7 @@ import { addDecorator, configure } from '@storybook/react'; import { setOptions } from '@storybook/addon-options'; import apolloStorybookDecorator from 'apollo-storybook-react'; +import StoryRouter from 'storybook-react-router'; import typeDefs from 'react/apollo/schema.graphql'; @@ -17,6 +18,8 @@ addDecorator( addDecorator(wrapWithThemeProvider); +addDecorator(StoryRouter()); + setOptions({ name: 'Are.na', url: 'https://www.are.na', diff --git a/apps/authentication/Routes.js b/apps/authentication/Routes.js new file mode 100644 index 0000000000..25733cca12 --- /dev/null +++ b/apps/authentication/Routes.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; + +import parseRoute from 'react/util/parseRoute'; + +import LoginPage from 'react/pages/authentication/LoginPage'; +import RegistrationPage from 'react/pages/authentication/RegistrationPage'; +import ResetPasswordPage from 'react/pages/authentication/ResetPasswordPage'; +import ForgotPasswordPage from 'react/pages/authentication/ForgotPasswordPage'; +import AcceptInvitationPage from 'react/pages/authentication/AcceptInvitationPage'; + +export default () => ( + + } + /> + + } + /> + + } + /> + + ( + + ))} + /> + + ( + + ))} + /> + +); diff --git a/apps/authentication/client/accept_invitation.coffee b/apps/authentication/client/accept_invitation.coffee deleted file mode 100644 index 8fb475c943..0000000000 --- a/apps/authentication/client/accept_invitation.coffee +++ /dev/null @@ -1,57 +0,0 @@ -Promise = require 'bluebird-q' -{ INVITEE } = require('sharify').data -Serializer = require '../../../components/form/serializer.coffee' -Invitee = require '../../../models/invitee.coffee' -LoggedOutUser = require '../../../models/logged_out_user.coffee' -{ track } = require '../../../lib/analytics.coffee' - -module.exports = -> - $el = $('.js-authentication') - - $form = $el.find '.js-form' - $submit = $el.find '.js-submit' - $errors = $el.find '.js-errors' - - invitee = new Invitee INVITEE - - $form.on 'submit', (e) -> - e.preventDefault() - - serializer = new Serializer $form - - label = $submit.text() - - $submit - .prop 'disabled', true - .text 'Registering...' - - Promise invitee.save(serializer.data()) - .then -> - $submit.text 'Logging in...' - - user = new LoggedOutUser invitee.pick 'email', 'password' - - track.submit 'User successfully registered' - track.submit 'User successfully accepted invitation' - - Promise user.login() - - .then -> - location.href = '/welcome' - - .catch -> - $errors.show().text """ - Invalid registration. - Try retyping your password and submitting again. - """ - - $submit - .prop 'disabled', false - .text 'Error' - - setTimeout -> - $submit.text label - $errors.empty() - , 5000 - - track.error 'User invitation acceptance error' diff --git a/apps/authentication/client/forgot.coffee b/apps/authentication/client/forgot.coffee deleted file mode 100644 index 3ff356d6df..0000000000 --- a/apps/authentication/client/forgot.coffee +++ /dev/null @@ -1,49 +0,0 @@ -Serializer = require '../../../components/form/serializer.coffee' -{ track } = require '../../../lib/analytics.coffee' - -module.exports = -> - $el = $('.js-authentication') - - $form = $el.find '.js-form' - $submit = $el.find '.js-submit' - $errors = $el.find '.js-errors' - - label = $submit.text() - - $form.on 'submit', (e) -> - e.preventDefault() - - $errors.empty() - - serializer = new Serializer $form - - $submit - .prop 'disabled', true - .text 'Resetting...' - - $.ajax - url: $form.attr 'action' - method: $form.attr 'method' - data: serializer.data() - success: -> - $errors.replaceWith $ """ -
- Please check your email for a link to reset your password -
- """ - - $submit - .prop 'disabled', true - .text 'Sent' - - track.submit 'User forgot password' - - error: ({ responseJSON: { description }}) -> - $errors.show() - .text description - - $submit - .prop 'disabled', false - .text 'Try again' - - track.error 'User forgot password error' diff --git a/apps/authentication/client/log_in.coffee b/apps/authentication/client/log_in.coffee deleted file mode 100644 index 997a2ddc4a..0000000000 --- a/apps/authentication/client/log_in.coffee +++ /dev/null @@ -1,55 +0,0 @@ -{ API_URL, REDIRECT_TO } = require('sharify').data -Promise = require 'bluebird-q' -Serializer = require '../../../components/form/serializer.coffee' -LoggedOutUser = require '../../../models/logged_out_user.coffee' -{ track } = require '../../../lib/analytics.coffee' - -module.exports = -> - $el = $('.js-authentication') - - $form = $el.find '.js-form' - $submit = $el.find '.js-submit' - $errors = $el.find '.js-errors' - - label = $submit.text() - - $form.on 'submit', (e) -> - e.preventDefault() - - serializer = new Serializer $form - user = new LoggedOutUser serializer.data() - - $submit - .prop 'disabled', true - .text 'Logging in...' - - Promise user.login() - .then -> - $submit.text 'Redirecting...' - - location.href = REDIRECT_TO - - track.submit 'User logged in' - - .catch (err) -> - console.error err - - { responseJSON: { message, description }, status } = err - - $errors.show() - .text description - - $submit - .prop 'disabled', false - .text 'Try again' - - setTimeout -> - $submit.text label - $errors.empty() - , 2500 - - switch status - when 401 - location.href = "/confirm/expired?email=#{user.get('email')}" - - track.error "User logged in error (#{status}: #{description})" diff --git a/apps/authentication/client/reset.coffee b/apps/authentication/client/reset.coffee deleted file mode 100644 index b47aae62f4..0000000000 --- a/apps/authentication/client/reset.coffee +++ /dev/null @@ -1,53 +0,0 @@ -Serializer = require '../../../components/form/serializer.coffee' -{ track } = require '../../../lib/analytics.coffee' - -module.exports = (token) -> - $el = $('.js-authentication') - - $form = $el.find '.js-form' - $submit = $el.find '.js-submit' - $errors = $el.find '.js-errors' - - label = $submit.text() - - $form.on 'submit', (e) -> - e.preventDefault() - - serializer = new Serializer $form - - $submit - .prop 'disabled', true - .text 'Resetting...' - - $.ajax - url: $form.attr 'action' - method: $form.attr 'method' - data: serializer.data() - success: -> - $errors.replaceWith $ """ -
- Password successfully reset. - Click here to login. -
- """ - - $submit - .prop 'disabled', true - .text 'Reset' - - track.submit 'User successfully reset password' - - error: ({ responseJSON: { description }}) -> - $errors.show() - .text description - - $submit - .prop 'disabled', false - .text 'Try again' - - setTimeout -> - $submit.text label - $errors.empty() - , 5000 - - track.error 'User reset password error' diff --git a/apps/authentication/client/router.coffee b/apps/authentication/client/router.coffee deleted file mode 100644 index f32194f2c2..0000000000 --- a/apps/authentication/client/router.coffee +++ /dev/null @@ -1,11 +0,0 @@ -Backbone = require 'backbone' - -module.exports = class AuthenticationRouter extends Backbone.Router - routes: - 'sign_up': require './sign_up.coffee' - 'log_in': require './log_in.coffee' - 'forgot': require './forgot.coffee' - 'reset/:token': require './reset.coffee' - 'confirm/expired': require './expired.coffee' - 'confirm/:token': require './confirm.coffee' - 'register/:token': require './accept_invitation.coffee' diff --git a/apps/authentication/client/sign_up.coffee b/apps/authentication/client/sign_up.coffee deleted file mode 100644 index a875441fda..0000000000 --- a/apps/authentication/client/sign_up.coffee +++ /dev/null @@ -1,60 +0,0 @@ -{ REDIRECT_TO } = require('sharify').data -Promise = require 'bluebird-q' -Serializer = require '../../../components/form/serializer.coffee' -LoggedOutUser = require '../../../models/logged_out_user.coffee' -Registration = require '../../../models/registration.coffee' -{ track } = require '../../../lib/analytics.coffee' - -module.exports = -> - $el = $('.js-authentication') - - $form = $el.find '.js-form' - $comply = $el.find '.js-comply' - $submit = $el.find '.js-submit' - $errors = $el.find '.js-errors' - - registration = new Registration - - label = $submit.text() - - $comply.on 'change', (e) -> - $submit.prop 'disabled', !this.checked - - $form.on 'submit', (e) -> - e.preventDefault() - - serializer = new Serializer $form - - $submit - .prop 'disabled', true - .text 'Registering...' - - Promise registration.save(serializer.data()) - .then -> - $submit.text 'Logging in...' - - user = new LoggedOutUser registration.pick 'email', 'password' - - track.submit 'User successfully registered' - - Promise user.login() - - .then -> - location.href = REDIRECT_TO - - .catch (err) -> - $errors.show().text """ - Invalid registration. - Try retyping your password and submitting again. - """ - - $submit - .prop 'disabled', false - .text 'Error' - - setTimeout -> - $submit.text label - $errors.empty() - , 5000 - - track.error 'User registration error' diff --git a/apps/authentication/components/navigation/index.jade b/apps/authentication/components/navigation/index.jade deleted file mode 100644 index 0a7bd927b5..0000000000 --- a/apps/authentication/components/navigation/index.jade +++ /dev/null @@ -1,18 +0,0 @@ -include ../../../../components/util/activator - -.AuthenticationNavigation__logo - a( href='/' ) - include ../../../../public/images/arena-mark.svg - -.AuthenticationNavigation__links - a.AuthenticationNavigation__link( - href='/sign_up' - data-state= activeState('/sign_up') - ) Join - - span or - - a.AuthenticationNavigation__link( - href='/log_in' - data-state= activeState('/log_in') - ) Log in diff --git a/apps/authentication/components/navigation/index.styl b/apps/authentication/components/navigation/index.styl deleted file mode 100644 index 425864153e..0000000000 --- a/apps/authentication/components/navigation/index.styl +++ /dev/null @@ -1,34 +0,0 @@ -.AuthenticationNavigation - text-align center - - &__logo - > a // ** - display inline-block - position relative - font-size font-size-base - width @font-size * 2 - height @font-size - top 0.125em - - > svg - position absolute - top 0 - left 0 - width 100% - height 100% - fill colors-gray-text - - &__links - margin fieldset-margin 0 - font-size font-size-base - line-height line-height-base - - &__link - display inline-block - margin 1em 0.5em - font-weight bold - text-decoration underline - - &[data-state='active'] - text-decoration none - font-weight normal diff --git a/apps/authentication/index.coffee b/apps/authentication/index.coffee deleted file mode 100644 index b976391694..0000000000 --- a/apps/authentication/index.coffee +++ /dev/null @@ -1,35 +0,0 @@ -express = require 'express' -routes = require './routes' -middleware = require './middleware' -redirectTo = require '../../lib/middleware/redirect_to' - -app = module.exports = express() - -app - .set 'views', "#{__dirname}/templates" - .set 'view engine', 'jade' - -app - # TODO: None of these paths make any kind of sense (snake_case; - # language: "sign up" vs "join"). Generate new routes and redirect to old. - .get '/sign_up', routes.sign_up - .get '/log_in', routes.log_in - - .get '/forgot', routes.forgot - .get '/reset/:token', routes.reset - - .get '/me/sign_out', - middleware.logout, - redirectTo - - .get '/me/refresh', routes.refresh - - .get '/confirm/expired', routes.expired - .get '/confirm/:token', - middleware.confirm, - routes.confirmed, - routes.unconfirmed - - .get '/register/:token', - routes.acceptInvitation, - routes.invalidInvitation diff --git a/apps/authentication/index.js b/apps/authentication/index.js new file mode 100644 index 0000000000..be730e9d8b --- /dev/null +++ b/apps/authentication/index.js @@ -0,0 +1,45 @@ +import express from 'express'; +import apolloMiddleware from 'react/apollo/middleware'; + +import logoutMiddleware from 'apps/authentication/middleware/logout'; +import redirectToMiddleware from 'lib/middleware/redirect_to.coffee'; + +import Routes from 'apps/authentication/Routes'; +import withStaticRouter from 'react/hocs/WithStaticRouter'; + +const app = express(); + +app + .set('views', `${__dirname}/templates`) + .set('view engine', 'jade') + + .get(/^\/(sign_up|log_in|forgot|register\/\w+|reset\/\w+)/, apolloMiddleware, (req, res, next) => { + if (req.user && req.user.id) return res.redirect('/'); + + res.locals.sd.REDIRECT_TO = req.query['redirect-to'] || '/'; + + return req.apollo.render(withStaticRouter(Routes)) + .then(apollo => res.render('index', { apollo })) + .catch(next); + }) + .get('/me/sign_out', logoutMiddleware, redirectToMiddleware) + .get('/me/refresh', (req, res, next) => { + const { user } = req; + + if (!user) return next(); + + return user.fetch() + .then((response) => { + req.login(user, (err) => { + if (err) return next(err); + + // IMPORTANT: return the `response` instead of the `user.toJSON()` + // Why? Because `user.toJSON()` is already parsed. Returning + // an already parsed response will make it unparesable. + return res.json(response); + }); + }) + .catch(next); + }); + +module.exports = app; diff --git a/apps/authentication/middleware/logout.js b/apps/authentication/middleware/logout.js new file mode 100644 index 0000000000..da91468eb5 --- /dev/null +++ b/apps/authentication/middleware/logout.js @@ -0,0 +1,4 @@ +module.exports = (req, _res, next) => { + req.logout(); + return next(); +}; diff --git a/apps/authentication/routes.coffee b/apps/authentication/routes.coffee deleted file mode 100644 index e8a925105c..0000000000 --- a/apps/authentication/routes.coffee +++ /dev/null @@ -1,67 +0,0 @@ -Promise = require 'bluebird-q' -User = require '../../models/user' -Invitee = require '../../models/invitee' -cache = require '../../lib/cache' - -@sign_up = (req, res) -> - return res.redirect '/' if req.user? - - res.locals.sd.REDIRECT_TO = req.query['redirect-to'] or '/welcome' - res.render 'sign_up' - -@log_in = (req, res) -> - return res.redirect '/' if req.user? - - res.locals.sd.REDIRECT_TO = req.query['redirect-to'] or '/' - res.render 'log_in' - -@forgot = (req, res) -> - return res.redirect '/' if req.user? - res.render 'forgot' - -@reset = (req, res) -> - return res.redirect '/' if req.user? - res.render 'reset', - token: req.params.token - -@expired = (req, res) -> - return res.redirect '/' if req.user? - res.render 'expired' - -@confirmed = (req, res, next) -> - res.render 'confirmed' - -@unconfirmed = (_err, _req, res, _next) -> - res.render 'unconfirmed' - -@refresh = (req, res, next) -> - return next() unless (user = req.user)? - - Promise user.fetch() - .then (response) -> - req.login user, (err) -> - return next(err) if err? - - # IMPORTANT: return the `response` instead of the `user.toJSON()` - # Why? Because `user.toJSON()` is already parsed. Returning - # an already parsed response will make it unparesable. - res.json response - - .catch next - -@acceptInvitation = (req, res, next) -> - return res.redirect '/' if req.user? - - invitee = new Invitee invitation_token: req.params.token - Promise invitee.fetch() - .then -> - invitee.set invitation_token: req.query.invite_token - - res.locals.sd.INVITEE = invitee.toJSON() - res.render 'accept_invitation', - invitee: invitee - - .catch next - -@invalidInvitation = (_err, _req, res, _next) -> - res.render 'invalid_invitation' diff --git a/apps/authentication/stylesheets/form.styl b/apps/authentication/stylesheets/form.styl deleted file mode 100644 index 7e9b2b33b8..0000000000 --- a/apps/authentication/stylesheets/form.styl +++ /dev/null @@ -1,13 +0,0 @@ -.AuthenticationForm - width block_width_mar - - &__password - position relative - collapsed-margins(0.5em) - - > a - position absolute - top 50% - right 1em - transform translateY(-50%) - font-size font-size-xs diff --git a/apps/authentication/stylesheets/index.styl b/apps/authentication/stylesheets/index.styl deleted file mode 100644 index 1eb231993a..0000000000 --- a/apps/authentication/stylesheets/index.styl +++ /dev/null @@ -1,10 +0,0 @@ -.Authentication - display flex - flex-direction column - align-items center - justify-content center - width 100% - height 100vh - -@require './form' -@require '../components/navigation' diff --git a/apps/authentication/templates/accept_invitation.jade b/apps/authentication/templates/accept_invitation.jade deleted file mode 100644 index 5d19ab5423..0000000000 --- a/apps/authentication/templates/accept_invitation.jade +++ /dev/null @@ -1,53 +0,0 @@ -extends ./layout - -block title - | / Complete your registration - -block content - form.AuthenticationForm.js-form - .Fieldset - input.Input( - name='email' - type='email' - placeholder='Email' - value= invitee.get('email') - required - readonly - ) - - input.Input( - id='first_name' - name='first_name' - placeholder='First name' - type='text' - required - ) - - input.Input( - id='last_name' - name='last_name' - placeholder='Last name' - type='text' - required - ) - input.Input( - id='password' - name='password' - placeholder='Password (at least 6 characters)' - type='password' - pattern='.{6,}' - required - ) - input.Input( - id='password_confirmation' - name='password_confirmation' - placeholder='Confirm password (at least 6 characters)' - type='password' - pattern='.{6,}' - required - ) - - .Errors.js-errors - //- - button.Button.Button--divider.js-submit - | Register diff --git a/apps/authentication/templates/forgot.jade b/apps/authentication/templates/forgot.jade deleted file mode 100644 index 4d018128fc..0000000000 --- a/apps/authentication/templates/forgot.jade +++ /dev/null @@ -1,21 +0,0 @@ -extends ./layout - -block title - | / Forgot password - -block content - form.AuthenticationForm.js-form( action='#{sd.API_URL}/accounts/passwords/forgot', method='post' ) - .Fieldset - input.Input( - name='email' - type='email' - placeholder='Email' - required - autofocus - ) - - .Errors.js-errors - //- - - button.Button.Button--divider.js-submit - | Reset password diff --git a/apps/authentication/templates/index.jade b/apps/authentication/templates/index.jade new file mode 100644 index 0000000000..dea070dbf6 --- /dev/null +++ b/apps/authentication/templates/index.jade @@ -0,0 +1,13 @@ +extends ../../../components/layout/layouts/blank + +block meta + != apollo.styles + +block container + #apolloMount + != apollo.html + +block scripts + script. + window.__APOLLO_STATE__ = !{JSON.stringify(apollo.state).replace(/help@are.na diff --git a/apps/authentication/templates/layout.jade b/apps/authentication/templates/layout.jade deleted file mode 100644 index 08912859a1..0000000000 --- a/apps/authentication/templates/layout.jade +++ /dev/null @@ -1,11 +0,0 @@ -extends ../../../components/layout/layouts/blank - -block scripts - script( src= asset('/assets/authentication.js') ) - -block container - .Authentication.js-authentication - .AuthenticationNavigation.js-navigation - include ../components/navigation/index - - block content diff --git a/apps/authentication/templates/log_in.jade b/apps/authentication/templates/log_in.jade deleted file mode 100644 index 68ae1c9410..0000000000 --- a/apps/authentication/templates/log_in.jade +++ /dev/null @@ -1,33 +0,0 @@ -extends ./layout - -block title - | / Log in - -block content - form.AuthenticationForm.js-form( action='/me/sign_in', method='post' ) - .Fieldset - input.Input( - name='email' - type='email' - placeholder='Email' - required - autofocus - ) - - .AuthenticationForm__password - input.Input( - id='password' - name='password' - placeholder='Password' - type='password' - pattern='.{6,}' - required - ) - - a( href='/forgot' ) Forgot? - - .Errors.js-errors - //- - - button.Button.Button--divider.js-submit - | Log in diff --git a/apps/authentication/templates/reset.jade b/apps/authentication/templates/reset.jade deleted file mode 100644 index e21f583dd1..0000000000 --- a/apps/authentication/templates/reset.jade +++ /dev/null @@ -1,31 +0,0 @@ -extends ./layout - -block title - | / Reset password - -block content - form.AuthenticationForm.js-form( action='#{sd.API_URL}/accounts/passwords/#{token}', method='put' ) - .Fieldset - input.Input( - id='password' - name='password' - placeholder='New password (at least 6 characters)' - type='password' - - required - ) - - input.Input( - id='password_confirmation' - name='password_confirmation' - placeholder='Confirm new password' - type='password' - - required - ) - - .Errors.js-errors - //- - - button.Button.Button--divider.js-submit - | Reset password diff --git a/apps/authentication/templates/sign_up.jade b/apps/authentication/templates/sign_up.jade deleted file mode 100644 index eddb16d60f..0000000000 --- a/apps/authentication/templates/sign_up.jade +++ /dev/null @@ -1,74 +0,0 @@ -extends ./layout - -block title - | / Join - -block content - form.AuthenticationForm.js-form - .Fieldset - input.Input( - name='email' - type='email' - placeholder='Email' - required - autofocus - ) - - input.Input( - id='first_name' - name='first_name' - placeholder='First name' - type='text' - required - ) - - input.Input( - id='last_name' - name='last_name' - placeholder='Last name' - type='text' - required - ) - - input.Input( - id='password' - name='password' - placeholder='Password (at least 6 characters)' - type='password' - pattern='.{6,}' - required - ) - - input.Input( - id='password_confirmation' - name='password_confirmation' - placeholder='Confirm password' - type='password' - pattern='.{6,}' - required - ) - - .Checkbox - .Checkbox__check - input.js-comply( type='checkbox', id='agree', name='agree' ) - - label.Checkbox__label( for='agree' ) - = 'Accept Are.na ' - a( href='/terms', target='_blank' ) - | Terms - = ' and ' - a( href='/privacy', target='_blank' ) - | Privacy conditions - - .Checkbox - .Checkbox__check - input( type='checkbox', id='receive_newsletter', name='receive_newsletter' ) - - label.Checkbox__label( for='receive_newsletter' ) - | Receive our monthly newsletter - - .Errors.js-errors - //- - - button.Button.Button--divider( disabled ).js-submit - | Join diff --git a/apps/authentication/client/confirm.coffee b/apps/confirmation/client/confirm.coffee similarity index 100% rename from apps/authentication/client/confirm.coffee rename to apps/confirmation/client/confirm.coffee diff --git a/apps/confirmation/client/confirmed.coffee b/apps/confirmation/client/confirmed.coffee new file mode 100644 index 0000000000..2d8fd9ace8 --- /dev/null +++ b/apps/confirmation/client/confirmed.coffee @@ -0,0 +1,4 @@ +module.exports = -> + setTimeout -> + location.href = '/log_in' + , 3000 diff --git a/apps/authentication/client/expired.coffee b/apps/confirmation/client/expired.coffee similarity index 100% rename from apps/authentication/client/expired.coffee rename to apps/confirmation/client/expired.coffee diff --git a/apps/authentication/client/index.coffee b/apps/confirmation/client/index.coffee similarity index 100% rename from apps/authentication/client/index.coffee rename to apps/confirmation/client/index.coffee diff --git a/apps/confirmation/client/router.coffee b/apps/confirmation/client/router.coffee new file mode 100644 index 0000000000..47d0bba8ed --- /dev/null +++ b/apps/confirmation/client/router.coffee @@ -0,0 +1,6 @@ +Backbone = require 'backbone' + +module.exports = class AuthenticationRouter extends Backbone.Router + routes: + 'confirm/expired': require './expired.coffee' + 'confirm/:token': require './confirm.coffee' diff --git a/apps/confirmation/index.coffee b/apps/confirmation/index.coffee new file mode 100644 index 0000000000..f4bb8a7e38 --- /dev/null +++ b/apps/confirmation/index.coffee @@ -0,0 +1,16 @@ +express = require 'express' +routes = require './routes' +middleware = require './middleware' + +app = module.exports = express() + +app + .set 'views', "#{__dirname}/templates" + .set 'view engine', 'jade' + +app + .get '/confirm/expired', routes.expired + .get '/confirm/:token', + middleware.confirm, + routes.confirmed, + routes.unconfirmed diff --git a/apps/authentication/middleware.coffee b/apps/confirmation/middleware.coffee similarity index 79% rename from apps/authentication/middleware.coffee rename to apps/confirmation/middleware.coffee index 124fb5000e..13c36e53ee 100644 --- a/apps/authentication/middleware.coffee +++ b/apps/confirmation/middleware.coffee @@ -1,10 +1,6 @@ request = require 'superagent' { API_URL } = require('sharify').data -@logout = (req, _res, next) -> - req.logout() - next() - @confirm = (req, res, next) -> request .post "#{API_URL}/confirmations/confirm?token=#{req.params.token}" @@ -12,4 +8,4 @@ request = require 'superagent' .end (err) -> return next(err) if err? - next() + next() \ No newline at end of file diff --git a/apps/confirmation/routes.coffee b/apps/confirmation/routes.coffee new file mode 100644 index 0000000000..041f4bcc7a --- /dev/null +++ b/apps/confirmation/routes.coffee @@ -0,0 +1,14 @@ +Promise = require 'bluebird-q' +User = require '../../models/user' +Invitee = require '../../models/invitee' +cache = require '../../lib/cache' + +@expired = (req, res) -> + return res.redirect '/' if req.user? + res.render 'expired' + +@confirmed = (req, res, next) -> + res.render 'confirmed' + +@unconfirmed = (_err, _req, res, _next) -> + res.render 'unconfirmed' \ No newline at end of file diff --git a/apps/authentication/templates/confirmed.jade b/apps/confirmation/templates/confirmed.jade similarity index 89% rename from apps/authentication/templates/confirmed.jade rename to apps/confirmation/templates/confirmed.jade index d28a48ea01..cc9a79424d 100644 --- a/apps/authentication/templates/confirmed.jade +++ b/apps/confirmation/templates/confirmed.jade @@ -11,4 +11,4 @@ block content p.Type.Type--size-xs.Type--lh-tall.Utility--align-center a( href='/log_in' ) - | Or click here to continue + | Or click here to continue \ No newline at end of file diff --git a/apps/authentication/templates/expired.jade b/apps/confirmation/templates/expired.jade similarity index 92% rename from apps/authentication/templates/expired.jade rename to apps/confirmation/templates/expired.jade index 5f0ae8be05..94514c9f3a 100644 --- a/apps/authentication/templates/expired.jade +++ b/apps/confirmation/templates/expired.jade @@ -15,4 +15,4 @@ block content a.js-resend-confirmation Resend my confirmation p.Type.Type--size-xs.Type--lh-tall.Utility--align-center - | Contact help@are.na if you haven’t received this email or you’re still having trouble. + | Contact help@are.na if you haven’t received this email or you’re still having trouble. \ No newline at end of file diff --git a/apps/confirmation/templates/layout.jade b/apps/confirmation/templates/layout.jade new file mode 100644 index 0000000000..98c8d36aaf --- /dev/null +++ b/apps/confirmation/templates/layout.jade @@ -0,0 +1,9 @@ +extends ../../../components/layout/layouts/blank + +block scripts + script( src= asset('/assets/confirmation.js') ) + +block container + .fullscreen + .valign--flex.halign--flex + block content diff --git a/apps/authentication/templates/unconfirmed.jade b/apps/confirmation/templates/unconfirmed.jade similarity index 97% rename from apps/authentication/templates/unconfirmed.jade rename to apps/confirmation/templates/unconfirmed.jade index 702bfab887..192457ffce 100644 --- a/apps/authentication/templates/unconfirmed.jade +++ b/apps/confirmation/templates/unconfirmed.jade @@ -9,4 +9,4 @@ block content | We were unable to confirm your account. p.Type.Type--size-xs.Type--lh-tall.Utility--align-center - | If you believe this is in error please contact help@are.na + | If you believe this is in error please contact help@are.na \ No newline at end of file diff --git a/apps/index.coffee b/apps/index.coffee index a890cef1f3..8d6ba21172 100644 --- a/apps/index.coffee +++ b/apps/index.coffee @@ -10,6 +10,7 @@ app .use require '../apps/home' .use require '../apps/blog' .use require '../apps/authentication' + .use require '../apps/confirmation' .use require '../apps/getting_started' .use require '../apps/tools' .use require '../apps/util' diff --git a/apps/ui/client/index.coffee b/apps/ui/client/index.coffee index 944b3d615e..85a9b9b477 100644 --- a/apps/ui/client/index.coffee +++ b/apps/ui/client/index.coffee @@ -1,6 +1,5 @@ AddBlockView = require '../../../components/add_block/client/view.coffee' Collection = require '../../../collections/base.coffee' -{ default: mountHello } = require '../../../react/components/Example/index.js' module.exports = -> blocks = new Collection @@ -12,5 +11,3 @@ module.exports = -> collection: blocks view.render() - - mountHello() diff --git a/apps/ui/templates/pages/react.jade b/apps/ui/templates/pages/react.jade deleted file mode 100644 index f7b608050b..0000000000 --- a/apps/ui/templates/pages/react.jade +++ /dev/null @@ -1,10 +0,0 @@ -extends ../../../../components/layout/index--bare - -block body - .Page - .UI - #react-mount-hello - | Component loading... - -block scripts - script( src= asset('/assets/ui.js') ) diff --git a/assets/all.styl b/assets/all.styl index 8e2fedfd47..090d3bddfa 100644 --- a/assets/all.styl +++ b/assets/all.styl @@ -39,7 +39,6 @@ @require '../apps/blog/stylesheets/index' @require '../apps/tools/stylesheets/index' @require '../apps/manage/stylesheets/index' -@require '../apps/authentication/stylesheets/index' @require '../apps/channel/stylesheets/index' @require '../apps/getting_started/stylesheets/index' @require '../apps/user/stylesheets/index' diff --git a/assets/auth.js b/assets/auth.js new file mode 100644 index 0000000000..70c06f95a7 --- /dev/null +++ b/assets/auth.js @@ -0,0 +1,8 @@ +import { mountWithApolloProvider } from 'react/apollo'; + +import withBrowserRouter from 'react/hocs/WithBrowserRouter'; + +import Routes from 'apps/authentication/Routes'; + +document.addEventListener('DOMContentLoaded', () => + mountWithApolloProvider(withBrowserRouter(Routes), {}, document.getElementById('apolloMount'))); diff --git a/assets/authentication.coffee b/assets/authentication.coffee deleted file mode 100644 index 250ea550b2..0000000000 --- a/assets/authentication.coffee +++ /dev/null @@ -1 +0,0 @@ -$ require('../apps/authentication/client/index.coffee') diff --git a/assets/confirmation.coffee b/assets/confirmation.coffee new file mode 100644 index 0000000000..054358e1a0 --- /dev/null +++ b/assets/confirmation.coffee @@ -0,0 +1 @@ +$ require('../apps/confirmation/client/index.coffee') \ No newline at end of file diff --git a/components/layout/index.styl b/components/layout/index.styl index a74d5447cf..1a67ea989f 100644 --- a/components/layout/index.styl +++ b/components/layout/index.styl @@ -125,6 +125,10 @@ blockquote .small-text font-size 12px +.fullscreen + width 100vw + height 100vh + .valign-outer, .v-outer display table position absolute diff --git a/lib/analytics.coffee b/lib/analytics.coffee index 1717fea414..52bc94dffb 100644 --- a/lib/analytics.coffee +++ b/lib/analytics.coffee @@ -90,3 +90,9 @@ module.exports.en = PREMIUM_CHARGE_INITIATED: 'User clicked to submit charge for premium' PREMIUM_PAID: 'User paid for pro account' + + LOGIN: 'User logged in' + REGISTER: 'User successfully registered' + ACCEPTED_INVITATION: 'User successfully accepted invitation' + FORGOT_PASSWORD: 'User forgot password' + RESET_PASSWORD: 'User successfully reset password' diff --git a/lib/setup.coffee b/lib/setup.coffee index dcf3038a07..5ca3324b55 100755 --- a/lib/setup.coffee +++ b/lib/setup.coffee @@ -154,11 +154,13 @@ module.exports = (app) -> if NODE_ENV is 'development' app.use (err, req, res, next) => res.status(err.status or 500) - res.json({ - message: err.message, - status: err.status, - stack: err.stack, - }) + res.send(""" +

#{err.status or 500}

+

Message

+
#{err.message}
+

Stacktrace

+
#{err.stack}
+ """) else # TODO: Kill this/replace with something that's not a Node module artsyError.handlers app, diff --git a/package.json b/package.json index 3c8a8dd849..e3613b7d79 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "deploy-storybook": "storybook-to-ghpages", "mocha": "sh scripts/mocha.sh", "test": "sh scripts/test.sh", + "jest": "jest", "start-dev": "foreman start -f Procfile.dev", "lint": "eslint --ext .js .", "storybook": "start-storybook -p 9001 -c .storybook" @@ -148,16 +149,21 @@ "friendly-errors-webpack-plugin": "^1.6.1", "graphql-tools": "^3.0.2", "html5": "*", + "jest": "^23.4.2", "mocha": "*", "progress-bar-webpack-plugin": "^1.10.0", "rewire": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", "should": "*", "sinon": "*", + "storybook-react-router": "^1.0.1", "webpack": "^3.11.0", "webpack-dev-middleware": "^2.0.4", "webpack-notifier": "^1.5.1" }, "optionalDependencies": { "fsevents": "*" + }, + "jest": { + "testURL": "http://localhost" } } diff --git a/react/apollo/fragmentTypes.json b/react/apollo/fragmentTypes.json index b0dd5000a0..267f0480fd 100644 --- a/react/apollo/fragmentTypes.json +++ b/react/apollo/fragmentTypes.json @@ -1 +1 @@ -[{"kind":"INTERFACE","name":"Model","possibleTypes":[{"name":"Attachment"},{"name":"Channel"},{"name":"ChannelMembership"},{"name":"ChannelTransferRequest"},{"name":"Comment"},{"name":"Connectable"},{"name":"Connection"},{"name":"Customer"},{"name":"Deed"},{"name":"Embed"},{"name":"Group"},{"name":"GroupMembership"},{"name":"Image"},{"name":"Link"},{"name":"Me"},{"name":"PendingBlock"},{"name":"Text"},{"name":"User"}]},{"kind":"INTERFACE","name":"Followable","possibleTypes":[{"name":"Channel"},{"name":"User"}]},{"kind":"INTERFACE","name":"Mutable","possibleTypes":[{"name":"Channel"},{"name":"Connectable"}]},{"kind":"INTERFACE","name":"UserInterface","possibleTypes":[{"name":"Me"},{"name":"User"}]},{"kind":"UNION","name":"ConnectableKind","possibleTypes":[{"name":"Text"},{"name":"Image"},{"name":"Link"},{"name":"Embed"},{"name":"Attachment"},{"name":"Channel"},{"name":"PendingBlock"}]},{"kind":"INTERFACE","name":"Block","possibleTypes":[{"name":"Attachment"},{"name":"Embed"},{"name":"Image"},{"name":"Link"},{"name":"PendingBlock"},{"name":"Text"}]},{"kind":"UNION","name":"Commentable","possibleTypes":[{"name":"Text"},{"name":"Image"},{"name":"Link"},{"name":"Embed"},{"name":"Attachment"}]},{"kind":"UNION","name":"Member","possibleTypes":[{"name":"Group"},{"name":"User"}]},{"kind":"UNION","name":"SearchResult","possibleTypes":[{"name":"Connectable"},{"name":"Channel"},{"name":"User"},{"name":"Null"}]},{"kind":"UNION","name":"FollowableType","possibleTypes":[{"name":"Channel"},{"name":"User"}]},{"kind":"UNION","name":"MutableType","possibleTypes":[{"name":"Channel"},{"name":"Connectable"}]},{"kind":"UNION","name":"DeedKind","possibleTypes":[{"name":"Connectable"},{"name":"Channel"},{"name":"User"},{"name":"Comment"},{"name":"Null"}]}] \ No newline at end of file +[{"kind":"INTERFACE","name":"Model","possibleTypes":[{"name":"Attachment"},{"name":"Channel"},{"name":"ChannelMembership"},{"name":"ChannelTransferRequest"},{"name":"Comment"},{"name":"Connectable"},{"name":"Connection"},{"name":"Customer"},{"name":"Deed"},{"name":"Embed"},{"name":"Group"},{"name":"GroupMembership"},{"name":"Image"},{"name":"Link"},{"name":"Me"},{"name":"PendingBlock"},{"name":"Text"},{"name":"User"}]},{"kind":"INTERFACE","name":"Followable","possibleTypes":[{"name":"Channel"},{"name":"User"}]},{"kind":"INTERFACE","name":"Mutable","possibleTypes":[{"name":"Channel"},{"name":"Connectable"}]},{"kind":"INTERFACE","name":"UserInterface","possibleTypes":[{"name":"Me"},{"name":"User"}]},{"kind":"UNION","name":"ConnectableKind","possibleTypes":[{"name":"Text"},{"name":"Image"},{"name":"Link"},{"name":"Embed"},{"name":"Attachment"},{"name":"Channel"},{"name":"PendingBlock"}]},{"kind":"INTERFACE","name":"Block","possibleTypes":[{"name":"Attachment"},{"name":"Embed"},{"name":"Image"},{"name":"Link"},{"name":"PendingBlock"},{"name":"Text"}]},{"kind":"UNION","name":"Commentable","possibleTypes":[{"name":"Text"},{"name":"Image"},{"name":"Link"},{"name":"Embed"},{"name":"Attachment"}]},{"kind":"UNION","name":"Member","possibleTypes":[{"name":"Group"},{"name":"User"}]},{"kind":"UNION","name":"SearchResult","possibleTypes":[{"name":"Connectable"},{"name":"Channel"},{"name":"User"},{"name":"Null"}]},{"kind":"UNION","name":"FollowableType","possibleTypes":[{"name":"Channel"},{"name":"User"},{"name":"Group"}]},{"kind":"UNION","name":"MutableType","possibleTypes":[{"name":"Channel"},{"name":"Connectable"}]},{"kind":"UNION","name":"DeedKind","possibleTypes":[{"name":"Connectable"},{"name":"Channel"},{"name":"User"},{"name":"Comment"},{"name":"Null"}]},{"kind":"UNION","name":"Identifiable","possibleTypes":[{"name":"User"},{"name":"Group"}]}] \ No newline at end of file diff --git a/react/apollo/schema.graphql b/react/apollo/schema.graphql index 25e82f573d..1e402d9967 100644 --- a/react/apollo/schema.graphql +++ b/react/apollo/schema.graphql @@ -575,11 +575,12 @@ interface Followable { } # Followable object -union FollowableType = Channel | User +union FollowableType = Channel | Group | User # Types of followable objects enum FollowableTypeEnum { CHANNEL + GROUP USER } @@ -600,6 +601,7 @@ type Group implements Model { manageable_user_ids: [Int] memberships: [GroupMembership] name: String + slug: String updated_at(format: String, relative: Boolean): String user: User users: [User] @@ -634,6 +636,15 @@ type GroupMembershipCan { manage: Boolean } +union Identifiable = Group | User + +# An object which exposes and names Users and Groups +type Identity { + identifiable: Identifiable! + name: String! + slug: String! +} + # An image block type Image implements Block & Model { counts: BlockCounts @@ -747,13 +758,14 @@ type Me implements Model & UserInterface { bio(format: Format, no_links: Boolean = false): String can: UserCan connection_search(direction: Directions = DESC, per: Int = 5, q: String = null): [Channel] - contents(direction: Directions = DESC, page: Int = 1, per: Int = 1, q: String = null, seed: Int = 173, sort_by: SearchSorts = UPDATED_AT, type: ConnectableTypeEnum = null): [Connectable] + contents(direction: Directions = DESC, page: Int = 1, per: Int = 1, q: String = null, seed: Int = 202, sort_by: SearchSorts = UPDATED_AT, type: ConnectableTypeEnum = null): [Connectable] counts: MeCounts created_at(format: String, relative: Boolean): String customer: Customer email: String feed(end: String = "-inf", limit: Int = 50, offset: Int = 0, start: String = "+inf", type: String = "User"): Feed first_name: String + flags: MeFlags hidden_email: String home_path: String href: String @@ -788,10 +800,15 @@ type MeCounts { private_connections_limit: Int } +type MeFlags { + has_seen_mute_announcement: Boolean +} + type MeSettings { exclude_from_indexes: Boolean receive_email: String receive_newsletter: Boolean + receive_tips_emails: Boolean show_tour: Boolean } @@ -857,6 +874,8 @@ type Mutation { remove_collaborators(input: RemoveCollaboratorInput!): RemoveCollaboratorPayload @deprecated(reason: "Use `remove_channel_member` instead") remove_connection(input: RemoveConnectionInput!): RemoveConnectionPayload remove_group_users(input: RemoveGroupUsersInput!): RemoveGroupUsersPayload + request_password_reset(input: RequestPasswordResetInput!): RequestPasswordResetPayload + reset_password(input: ResetPasswordInput!): ResetPasswordPayload share_channel(input: ShareChannelInput!): ShareChannelPayload unfollow(input: UnfollowInput!): UnfollowPayload unmute(input: UnmuteInput!): UnmutePayload @@ -942,13 +961,15 @@ type Query { # Interface for getting the follow status of users or channels followable(id: ID, type: FollowableTypeEnum): FollowableType group(id: ID!): Group + identity(id: ID!): Identity # The current logged in user me: Me # Interface for getting the mute status of blocks or channels mutable(id: ID!, type: MutableTypeEnum!): MutableType - search(direction: Directions = DESC, object_id: String = null, object_type: ObjectType = null, page: Int = 1, per: Int = 1, q: String! = null, seed: Int = 173, sort_by: SearchSorts = null, type: SearchType = null): [SearchResult] + password_token(token: ID!): User + search(direction: Directions = DESC, object_id: String = null, object_type: ObjectType = null, page: Int = 1, per: Int = 1, q: String! = null, seed: Int = 202, sort_by: SearchSorts = null, type: SearchType = null): [SearchResult] searches: Searches # Is this endpoint operational? @@ -981,6 +1002,8 @@ input RegistrationInput { last_name: String! password: String! password_confirmation: String! + receive_newsletter: Boolean + receive_tips_emails: Boolean } # Autogenerated return type of Registration @@ -1070,6 +1093,36 @@ type RemoveGroupUsersPayload { group: Group } +# Autogenerated input type of RequestPasswordReset +input RequestPasswordResetInput { + # A unique identifier for the client performing the mutation. + clientMutationId: String + email: String! +} + +# Autogenerated return type of RequestPasswordReset +type RequestPasswordResetPayload { + # A unique identifier for the client performing the mutation. + clientMutationId: String + email: String +} + +# Autogenerated input type of ResetPassword +input ResetPasswordInput { + # A unique identifier for the client performing the mutation. + clientMutationId: String + password: String! + password_confirmation: String! + token: String! +} + +# Autogenerated return type of ResetPassword +type ResetPasswordPayload { + # A unique identifier for the client performing the mutation. + clientMutationId: String + me: Me +} + # Possible types for search results union SearchResult = Channel | Connectable | Null | User @@ -1257,7 +1310,7 @@ type User implements Followable & Model & UserInterface { badge: String bio(format: Format, no_links: Boolean = false): String can: UserCan - contents(direction: Directions = DESC, page: Int = 1, per: Int = 1, q: String = null, seed: Int = 173, sort_by: SearchSorts = UPDATED_AT, type: ConnectableTypeEnum = null): [Connectable] + contents(direction: Directions = DESC, page: Int = 1, per: Int = 1, q: String = null, seed: Int = 202, sort_by: SearchSorts = UPDATED_AT, type: ConnectableTypeEnum = null): [Connectable] counts: UserCounts created_at(format: String, relative: Boolean): String first_name: String @@ -1293,7 +1346,7 @@ interface UserInterface { badge: String bio(format: Format, no_links: Boolean = false): String can: UserCan - contents(direction: Directions = DESC, page: Int = 1, per: Int = 1, q: String = null, seed: Int = 173, sort_by: SearchSorts = UPDATED_AT, type: ConnectableTypeEnum = null): [Connectable] + contents(direction: Directions = DESC, page: Int = 1, per: Int = 1, q: String = null, seed: Int = 202, sort_by: SearchSorts = UPDATED_AT, type: ConnectableTypeEnum = null): [Connectable] first_name: String hidden_email: String href: String diff --git a/react/apollo/ssr.js b/react/apollo/ssr.js index 92ff55f6f9..e0f24cf4fb 100644 --- a/react/apollo/ssr.js +++ b/react/apollo/ssr.js @@ -8,16 +8,19 @@ export default client => (Component, props = {}) => { const sheet = new ServerStyleSheet(); const WrappedComponent = wrapWithApolloProvider(client)(Component, props); - return getDataFromTree(WrappedComponent) - .then(() => { - const html = renderToString(sheet.collectStyles(WrappedComponent)); - const styles = sheet.getStyleTags(); - const state = client.extract(); + const resolve = () => { + const html = renderToString(sheet.collectStyles(WrappedComponent)); + const styles = sheet.getStyleTags(); + const state = client.extract(); + + return { + html, + state, + styles, + }; + }; - return { - html, - state, - styles, - }; - }); + return getDataFromTree(WrappedComponent) + .then(resolve) + .catch(resolve); }; diff --git a/react/components/AuthForm/index.js b/react/components/AuthForm/index.js new file mode 100644 index 0000000000..531563f1fd --- /dev/null +++ b/react/components/AuthForm/index.js @@ -0,0 +1,48 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; + +import Text from 'react/components/UI/Text'; +import Icon from 'react/components/UI/Icon'; + +const Form = styled.form` + width: ${x => x.theme.space[12]}; + margin: 0 auto; + text-align: center; +`; + +const Submit = styled.div` + display: flex; + align-items: center; + flex-direction: column; + margin-top: ${x => x.theme.space[7]}; +`; + +const Subtext = styled(Text).attrs({ + mt: 6, + f: 2, + underlineLinks: true, +})` +`; + +export default class AuthForm extends Component { + static propTypes = { + children: PropTypes.node.isRequired, + onSubmit: PropTypes.func.isRequired, + } + + static Submit = Submit + static Subtext = Subtext + + render() { + const { onSubmit } = this.props; + + return ( +
+ + + {this.props.children} + + ); + } +} diff --git a/react/components/ChannelMetadata/components/ChannelMetadataActions/components/MuteChannelButton/index.js b/react/components/ChannelMetadata/components/ChannelMetadataActions/components/MuteChannelButton/index.js index 5754584a4d..6f8cf105af 100644 --- a/react/components/ChannelMetadata/components/ChannelMetadataActions/components/MuteChannelButton/index.js +++ b/react/components/ChannelMetadata/components/ChannelMetadataActions/components/MuteChannelButton/index.js @@ -47,7 +47,7 @@ class MuteChannelButton extends Component { } = this.props; return ( - + {{ true: 'Unmute', false: 'Mute', diff --git a/react/components/ChannelMetadata/components/ChannelMetadataActions/index.js b/react/components/ChannelMetadata/components/ChannelMetadataActions/index.js index 72e7eaf7c5..a2f90de8d6 100644 --- a/react/components/ChannelMetadata/components/ChannelMetadataActions/index.js +++ b/react/components/ChannelMetadata/components/ChannelMetadataActions/index.js @@ -3,38 +3,19 @@ import { propType } from 'graphql-anywhere'; import styled from 'styled-components'; import Modal from 'react/components/UI/Modal'; -import Icon from 'react/components/UI/Icons'; -import Lock from 'react/components/UI/Icons/Lock/index.svg'; +import Icon from 'react/components/UI/Icon'; import ManageChannel from 'react/components/ManageChannel'; -import GenericButton, { mixin as buttonMixin } from 'react/components/UI/GenericButton'; +import Button, { mixin as buttonMixin } from 'react/components/UI/GenericButton'; import ButtonGroup from 'react/components/UI/ButtonGroup'; import FollowButton from 'react/components/FollowButton'; import MuteChannelButton from 'react/components/ChannelMetadata/components/ChannelMetadataActions/components/MuteChannelButton'; import channelMetadataActionsFragment from 'react/components/ChannelMetadata/components/ChannelMetadataActions/fragments/channelMetadataActions'; -const Buttons = styled(ButtonGroup)` - display: flex; -`; - -const Button = styled(GenericButton).attrs({ f: 1 })` -`; - -const ChannelFollowButton = styled(FollowButton).attrs({ f: 1 })` +const ChannelFollowButton = styled(FollowButton)` ${buttonMixin} `; -const LockIcon = props => ( - - - -); - -const PrivateChannelLockIcon = styled(LockIcon).attrs({ - color: ({ theme }) => theme.colors.gray.bold, -})` - margin-right: 0.33em; -`; export default class ChannelMetadataActions extends Component { static propTypes = { @@ -51,7 +32,7 @@ export default class ChannelMetadataActions extends Component { const { channel, channel: { id, can } } = this.props; return ( - + {can.follow && } @@ -63,11 +44,11 @@ export default class ChannelMetadataActions extends Component { {(can.update || can.destroy) && } - + ); } } diff --git a/react/components/ChannelMetadata/components/ChannelMetadataInfo/components/ChannelShareButton/index.js b/react/components/ChannelMetadata/components/ChannelMetadataInfo/components/ChannelShareButton/index.js index 9cdb199731..f4862b72f0 100644 --- a/react/components/ChannelMetadata/components/ChannelMetadataInfo/components/ChannelShareButton/index.js +++ b/react/components/ChannelMetadata/components/ChannelMetadataInfo/components/ChannelShareButton/index.js @@ -5,7 +5,7 @@ import styled from 'styled-components'; import { isNull } from 'underscore'; import { graphql } from 'react-apollo'; -import GenericInput from 'react/components/UI/GenericInput'; +import { Input } from 'react/components/UI/Inputs'; import CopyToClipboard from 'react/components/UI/CopyToClipboard'; import shareChannelMutation from 'react/components/ChannelMetadata/components/ChannelMetadataInfo/components/ChannelShareButton/mutations/shareChannel'; @@ -104,7 +104,7 @@ class ChannelShareButton extends Component { {mode === 'active' && channel.share.url &&
- x.theme.colors.gray.regular}; diff --git a/react/components/Connect/components/ConnectionSelection/components/RecentChannels/components/LoadingIndicator.js b/react/components/Connect/components/ConnectionSelection/components/RecentChannels/components/LoadingIndicator.js index 46e13437ab..318c02e892 100644 --- a/react/components/Connect/components/ConnectionSelection/components/RecentChannels/components/LoadingIndicator.js +++ b/react/components/Connect/components/ConnectionSelection/components/RecentChannels/components/LoadingIndicator.js @@ -1,12 +1,12 @@ import React from 'react'; import styled from 'styled-components'; -import { inputPadding } from 'react/components/UI/GenericInput'; +import { inputPadding } from 'react/components/UI/Inputs'; const Indicator = styled.div` position: relative; margin-top: -1px; - padding: ${inputPadding}; + padding: ${inputPadding}; // TODO line-height: 1; user-select: none; color: ${x => x.theme.colors.gray.semiBold}; diff --git a/react/components/Connect/components/ConnectionSelection/components/SelectableChannel/index.js b/react/components/Connect/components/ConnectionSelection/components/SelectableChannel/index.js index d4c0d13640..833a63fc69 100644 --- a/react/components/Connect/components/ConnectionSelection/components/SelectableChannel/index.js +++ b/react/components/Connect/components/ConnectionSelection/components/SelectableChannel/index.js @@ -8,7 +8,7 @@ import selectableChannelFragment from 'react/components/Connect/components/Conne import ColoredChannelSpan from 'react/components/UI/ColoredChannelSpan'; import TickerTapeHover from 'react/components/UI/TickerTapeHover'; -import { inputPadding } from 'react/components/UI/GenericInput'; +import { inputPadding } from 'react/components/UI/Inputs'; const Container = styled.div.attrs({ role: 'button', @@ -71,7 +71,7 @@ const HoverableInner = styled(TickerTapeHover).attrs({ speed: 1, offsetBuffer: 32, })` - padding: ${inputPadding}; + padding: ${inputPadding}; // TODO `; const Separator = styled.div` diff --git a/react/components/Connect/components/ConnectionSelection/index.js b/react/components/Connect/components/ConnectionSelection/index.js index 284073e065..4a400a7e66 100644 --- a/react/components/Connect/components/ConnectionSelection/index.js +++ b/react/components/Connect/components/ConnectionSelection/index.js @@ -5,7 +5,7 @@ import { debounce, isEmpty } from 'underscore'; import { outlineBorder } from 'react/styles/mixins'; -import GenericInput, { inputPadding } from 'react/components/UI/GenericInput'; +import { Input, inputPadding } from 'react/components/UI/Inputs'; import RecentChannels from 'react/components/Connect/components/ConnectionSelection/components/RecentChannels'; import SearchedChannels from 'react/components/Connect/components/ConnectionSelection/components/SearchedChannels'; import CreatePrivateChannelButton from 'react/components/Connect/components/ConnectionSelection/components/CreatePrivateChannelButton'; @@ -22,10 +22,10 @@ const Container = styled.div` const Bumper = styled.div` text-align: center; - padding: ${inputPadding}; + padding: ${inputPadding}; // TODO `; -const SearchInput = styled(GenericInput).attrs({ +const SearchInput = styled(Input).attrs({ f: 1, placeholder: 'Type channel name', autoFocus: true, diff --git a/react/components/Connect/index.js b/react/components/Connect/index.js index a56bb048de..e7398a4568 100644 --- a/react/components/Connect/index.js +++ b/react/components/Connect/index.js @@ -10,7 +10,7 @@ import createConnectionMutation from 'react/components/Connect/mutations/createC import removeConnectionMutation from 'react/components/Connect/mutations/removeConnection'; import channelMetadataQuery from 'react/components/ChannelMetadata/queries/channelMetadata'; -import { inputPadding } from 'react/components/UI/GenericInput'; +import { inputPadding } from 'react/components/UI/Inputs'; const Container = styled.div` position: relative; @@ -27,7 +27,7 @@ const Close = styled.a.attrs({ position: absolute; top: 0; right: 100%; - padding: ${inputPadding}; + padding: ${inputPadding}; // TODO text-align: center; font-weight: bold; font-size: ${x => x.theme.fontSizesIndexed.xs}; diff --git a/react/components/Example/index.js b/react/components/Example/index.js deleted file mode 100644 index 6dce3a763d..0000000000 --- a/react/components/Example/index.js +++ /dev/null @@ -1,106 +0,0 @@ -import styled from 'styled-components'; -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import gql from 'graphql-tag'; -import { graphql } from 'react-apollo'; - -import { mountWithApolloProvider } from 'react/apollo'; -import formatErrors from 'react/util/formatErrors'; - -const Container = styled.div` - border: 1px solid yellow; -`; - -const Message = styled.div` - color: red; -`; - -const Title = styled.div` - color: green; -`; - -const Description = styled.div` - color: blue; -`; - -const query = gql` - { - channel(id: "arena-influences") { - title - description(format: HTML) - } - } -`; - -export class Hello extends Component { - static defaultProps = { - data: { - loading: true, - channel: {}, - }, - } - - static propTypes = { - data: PropTypes.shape({ - loading: PropTypes.bool.isRequired, - channel: PropTypes.object, - }), - } - - state = { - message: 'Click me.', - } - - hello = () => { - this.setState({ - message: 'Hello.', - }); - } - - render() { - const { data: { loading, error } } = this.props; - - if (loading) { - return ( - - - Loading... - - - ); - } - - if (error) { - return ( - - - {formatErrors(error)} - - - ); - } - - const { message } = this.state; - const { data: { channel: { title, description } } } = this.props; - - return ( - - - {message} - - - - {title} - - - - - ); - } -} - -export const HelloWithData = graphql(query)(Hello); - -export default (selector = '#react-mount-hello') => { - mountWithApolloProvider(HelloWithData, {}, document.querySelector(selector)); -}; diff --git a/react/components/FollowButton/index.js b/react/components/FollowButton/index.js index d31c78ca5e..a418eefece 100644 --- a/react/components/FollowButton/index.js +++ b/react/components/FollowButton/index.js @@ -57,7 +57,11 @@ class FollowButton extends Component { if (loading) return Follow; const { - id, type, follow: _follow, unfollow: _unfollow, + id, + type, + follow: _follow, + unfollow: _unfollow, + isLoggedIn: _isLoggedIn, data: { followable }, ...rest } = this.props; diff --git a/react/components/ForgotPasswordForm/index.js b/react/components/ForgotPasswordForm/index.js new file mode 100644 index 0000000000..1b9246b5ac --- /dev/null +++ b/react/components/ForgotPasswordForm/index.js @@ -0,0 +1,111 @@ +import React, { Component } from 'react'; +import { graphql } from 'react-apollo'; +import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; + +import mapErrors from 'react/util/mapErrors'; + +import { GenericButton as Button } from 'react/components/UI/GenericButton'; +import Text from 'react/components/UI/Text'; +import AuthForm from 'react/components/AuthForm'; +import { Input, ErrorMessage } from 'react/components/UI/Inputs'; + +import requestPasswordResetMutation from 'react/components/ForgotPasswordForm/mutations/requestPasswordReset'; + +import { track, en } from 'lib/analytics.coffee'; + +class ForgotPasswordForm extends Component { + static propTypes = { + requestPasswordReset: PropTypes.func.isRequired, + } + + state = { + mode: 'resting', + email: '', + attributeErrors: {}, + errorMessage: null, + } + + handleInput = ({ target: { value: email } }) => + this.setState({ + mode: 'active', + email, + }); + + handleSubmit = (e) => { + e.preventDefault(); + + const { email } = this.state; + + this.setState({ mode: 'requesting' }); + + return this.props.requestPasswordReset({ + variables: { email }, + }) + .then(() => { + this.setState({ mode: 'success' }); + track.submit(en.FORGOT_PASSWORD); + }) + .catch((err) => { + this.setState({ + mode: 'error', + ...mapErrors(err), + }); + }); + } + + render() { + const { + email, + mode, + attributeErrors, + errorMessage, + } = this.state; + + return ( + + + + {mode === 'error' && + + {errorMessage} + + } + + {mode === 'success' && + + Please check your email for a link to reset your password. + + } + + + + + + Back + + + + ); + } +} + +export default graphql(requestPasswordResetMutation, { + name: 'requestPasswordReset', +})(ForgotPasswordForm); diff --git a/react/components/ForgotPasswordForm/mutations/requestPasswordReset.js b/react/components/ForgotPasswordForm/mutations/requestPasswordReset.js new file mode 100644 index 0000000000..ee3e6d0c71 --- /dev/null +++ b/react/components/ForgotPasswordForm/mutations/requestPasswordReset.js @@ -0,0 +1,9 @@ +import gql from 'graphql-tag'; + +export default gql` + mutation requestPasswordReset($email: String!) { + request_password_reset(input: { email: $email }) { + email + } + } +`; diff --git a/react/components/LoginForm/index.js b/react/components/LoginForm/index.js new file mode 100644 index 0000000000..e6e876215d --- /dev/null +++ b/react/components/LoginForm/index.js @@ -0,0 +1,131 @@ +import React, { Component } from 'react'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import axios from 'axios'; + +import AuthForm from 'react/components/AuthForm'; +import { GenericButton as Button } from 'react/components/UI/GenericButton'; +import { mixin as textMixin } from 'react/components/UI/Text'; +import { Input, ErrorMessage } from 'react/components/UI/Inputs'; + +import { track, en } from 'lib/analytics.coffee'; + +const { REDIRECT_TO } = require('sharify').data; + +const InputWithLink = styled.div.attrs({ + fontSize: 1, +})` + position: relative; + ${textMixin} + + a { + position: absolute; + ${textMixin} + top: 50%; + right: 1em; + transform: translateY(-50%); + } +`; + +export default class LoginForm extends Component { + state = { + mode: 'resting', + email: '', + password: '', + errorMessage: null, + } + + handleInput = name => ({ target: { value } }) => + this.setState({ + mode: 'active', + errorMessage: null, + [name]: value, + }); + + handleEmail = this.handleInput('email') + handlePassword = this.handleInput('password') + + handleSubmit = (e) => { + e.preventDefault(); + + const { email, password } = this.state; + + this.setState({ mode: 'submitting' }); + + return axios + .post('/me/sign_in', { email, password }) + + .then(() => { + this.setState({ mode: 'redirecting' }); + window.location = REDIRECT_TO; + track.submit(en.LOGIN); + }) + + .catch(({ response: { data: { description } } }) => { + this.setState({ + mode: 'error', + errorMessage: description, + }); + }); + } + + render() { + const { + mode, email, password, errorMessage, + } = this.state; + + return ( + + + + + + + Forgot? + + + {mode === 'error' && + + {errorMessage} + + } + + + + + + Not a member? + {' '} + + Join + + + + + ); + } +} diff --git a/react/components/ManageChannel/components/ExportChannel/index.js b/react/components/ManageChannel/components/ExportChannel/index.js index 229cc863b9..08eaeb814b 100644 --- a/react/components/ManageChannel/components/ExportChannel/index.js +++ b/react/components/ManageChannel/components/ExportChannel/index.js @@ -42,16 +42,16 @@ class ExportChannel extends Component { return (
- - + + PDF - + ZIP - + HTML diff --git a/react/components/ManageChannel/index.js b/react/components/ManageChannel/index.js index 67ae0f1c85..f4821f7df5 100644 --- a/react/components/ManageChannel/index.js +++ b/react/components/ManageChannel/index.js @@ -10,7 +10,7 @@ import manageChannelQuery from 'react/components/ManageChannel/queries/manageCha import updateChannelMutation from 'react/components/ManageChannel/mutations/updateChannel'; import TitledDialog from 'react/components/UI/TitledDialog'; -import { Input, Textarea, Select } from 'react/components/UI/GenericInput'; +import { Input, Textarea, Select } from 'react/components/UI/Inputs'; import ExportChannel from 'react/components/ManageChannel/components/ExportChannel'; import DeleteChannel from 'react/components/ManageChannel/components/DeleteChannel'; import TransferChannel from 'react/components/ManageChannel/components/TransferChannel'; diff --git a/react/components/ManagedMembers/components/ManagedMember/index.js b/react/components/ManagedMembers/components/ManagedMember/index.js index 966241e291..a449272e3d 100644 --- a/react/components/ManagedMembers/components/ManagedMember/index.js +++ b/react/components/ManagedMembers/components/ManagedMember/index.js @@ -148,7 +148,7 @@ export default class ManagedMembers extends Component { {!isOwner && isRemovable && + + + Already a member? + {' '} + Log in + + + + ); + } +} + +export default compose( + graphql(registerMutation, { name: 'register' }), + graphql(acceptInvitationMutation, { name: 'acceptInvitation' }), +)(RegistrationForm); diff --git a/react/components/RegistrationForm/mutations/acceptInvitation.js b/react/components/RegistrationForm/mutations/acceptInvitation.js new file mode 100644 index 0000000000..9118940a48 --- /dev/null +++ b/react/components/RegistrationForm/mutations/acceptInvitation.js @@ -0,0 +1,30 @@ +import gql from 'graphql-tag'; + +export default gql` + mutation acceptInvitationMutation( + $invitation_token: String! + $first_name: String!, + $last_name: String!, + $email: String!, + $password: String!, + $password_confirmation: String!, + $receive_newsletter: Boolean + $receive_tips_emails: Boolean + ) { + accept_invitation(input: { + invitation_token: $invitation_token + first_name: $first_name + last_name: $last_name + email: $email + password: $password + password_confirmation: $password_confirmation + receive_newsletter: $receive_newsletter + receive_tips_emails: $receive_tips_emails + }) { + me { + id + email + } + } + } +`; diff --git a/react/components/RegistrationForm/mutations/register.js b/react/components/RegistrationForm/mutations/register.js new file mode 100644 index 0000000000..9b9f9a26ee --- /dev/null +++ b/react/components/RegistrationForm/mutations/register.js @@ -0,0 +1,25 @@ +import gql from 'graphql-tag'; + +export default gql` + mutation registerMutation( + $first_name: String!, + $last_name: String!, + $email: String!, + $password: String!, + $password_confirmation: String!, + $receive_newsletter: Boolean + ) { + registration(input: { + first_name: $first_name, + last_name: $last_name, + email: $email, + password: $password, + password_confirmation: $password_confirmation, + receive_newsletter: $receive_newsletter + }) { + me { + id + } + } + } +`; diff --git a/react/components/ResetPasswordForm/index.js b/react/components/ResetPasswordForm/index.js new file mode 100644 index 0000000000..00e5694383 --- /dev/null +++ b/react/components/ResetPasswordForm/index.js @@ -0,0 +1,131 @@ +import axios from 'axios'; +import React, { Component } from 'react'; +import { graphql } from 'react-apollo'; +import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; + +import mapErrors from 'react/util/mapErrors'; + +import { GenericButton as Button } from 'react/components/UI/GenericButton'; +import AuthForm from 'react/components/AuthForm'; +import { Input, ErrorMessage } from 'react/components/UI/Inputs'; + +import resetPasswordMutation from 'react/components/ResetPasswordForm/mutations/resetPassword'; + +import { track, en } from 'lib/analytics.coffee'; + +const { REDIRECT_TO } = require('sharify').data; + +class ResetPasswordForm extends Component { + static propTypes = { + resetPassword: PropTypes.func.isRequired, + reset_password_token: PropTypes.string.isRequired, + } + + state = { + mode: 'resting', + password: '', + password_confirmation: '', + attributeErrors: {}, + errorMessage: null, + } + + handleInput = attr => ({ target: { value } }) => + this.setState({ + mode: 'active', + [attr]: value, + }); + + handlePassword = this.handleInput('password') + handlePasswordConfirmation = this.handleInput('password_confirmation') + + handleSubmit = (e) => { + e.preventDefault(); + + const { password, password_confirmation } = this.state; + const { resetPassword, reset_password_token } = this.props; + + this.setState({ mode: 'resetting' }); + + return resetPassword({ + variables: { token: reset_password_token, password, password_confirmation }, + }) + .then(({ data: { reset_password: { me: { email } } } }) => { + this.setState({ mode: 'logging_in' }); + return axios.post('/me/sign_in', { email, password }); + }) + .then(() => { + this.setState({ mode: 'redirecting' }); + window.location = REDIRECT_TO; + track.submit(en.RESET_PASSWORD); + }) + .catch((err) => { + this.setState({ + mode: 'error', + ...mapErrors(err), + }); + }); + } + + render() { + const { + password, + password_confirmation, + mode, + attributeErrors, + errorMessage, + } = this.state; + + return ( + + + + + + {mode === 'error' && + + {errorMessage} + + } + + + + + + Back + + + + ); + } +} + +export default graphql(resetPasswordMutation, { + name: 'resetPassword', +})(ResetPasswordForm); diff --git a/react/components/ResetPasswordForm/mutations/resetPassword.js b/react/components/ResetPasswordForm/mutations/resetPassword.js new file mode 100644 index 0000000000..0f9b800c36 --- /dev/null +++ b/react/components/ResetPasswordForm/mutations/resetPassword.js @@ -0,0 +1,11 @@ +import gql from 'graphql-tag'; + +export default gql` + mutation resetPassword($token: String!, $password: String!, $password_confirmation: String!) { + reset_password(input: {token: $token, password: $password, password_confirmation: $password_confirmation}) { + me { + email + } + } + } +`; diff --git a/react/components/UI/ArenaMark/index.svg b/react/components/UI/ArenaMark/index.svg deleted file mode 100644 index 4607584ebf..0000000000 --- a/react/components/UI/ArenaMark/index.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/react/components/UI/Box/index.js b/react/components/UI/Box/index.js new file mode 100644 index 0000000000..276f217926 --- /dev/null +++ b/react/components/UI/Box/index.js @@ -0,0 +1,12 @@ +import styled from 'styled-components'; +import { display, space, width, alignItems, minHeight, justifyContent, flexDirection } from 'styled-system'; + +export default styled.div` + ${display} + ${width} + ${minHeight} + ${space} + ${alignItems} + ${justifyContent} + ${flexDirection} +`; diff --git a/react/components/UI/ButtonGroup/index.js b/react/components/UI/ButtonGroup/index.js index 82315df51a..af20a148f5 100644 --- a/react/components/UI/ButtonGroup/index.js +++ b/react/components/UI/ButtonGroup/index.js @@ -1,9 +1,12 @@ +import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; -import { buttonBorderWidth, buttonBorderRadius } from 'react/components/UI/GenericButton'; +import provideChildrentWithProps from 'react/util/provideChildrenWithProps'; -const ButtonGroup = styled.div` +import { buttonBorderWidth, BUTTON_BORDER_RADIUS } from 'react/components/UI/GenericButton'; + +const ButtonGroupContainer = styled.div` ${x => x.stretch && ` display: flex; @@ -44,12 +47,19 @@ const ButtonGroup = styled.div` } &:first-child:last-child { - border-radius: ${buttonBorderRadius}; + border-radius: ${BUTTON_BORDER_RADIUS}; } } `; +const ButtonGroup = ({ children, stretch, ...rest }) => ( + + {provideChildrentWithProps(children, rest)} + +); + ButtonGroup.propTypes = { + children: PropTypes.node.isRequired, stretch: PropTypes.bool, }; diff --git a/react/components/UI/CenteringBox/index.js b/react/components/UI/CenteringBox/index.js new file mode 100644 index 0000000000..9565526145 --- /dev/null +++ b/react/components/UI/CenteringBox/index.js @@ -0,0 +1,12 @@ +import styled from 'styled-components'; + +import Box from 'react/components/UI/Box'; + +export default styled(Box).attrs({ + display: 'flex', + width: '100%', + minHeight: '100vh', + alignItems: 'center', + justifyContent: 'center', +})` +`; diff --git a/react/components/UI/GenericButton/index.js b/react/components/UI/GenericButton/index.js index 8069c44321..1387e2bf72 100644 --- a/react/components/UI/GenericButton/index.js +++ b/react/components/UI/GenericButton/index.js @@ -1,14 +1,45 @@ import styled, { css } from 'styled-components'; -import { themeGet, fontSize } from 'styled-system'; +import { themeGet, fontSize, space, alignSelf } from 'styled-system'; -import { preset } from 'react/styles/functions'; +import { defaultTo, preset } from 'react/styles/functions'; import { antialiased } from 'react/styles/mixins'; -export const buttonBorderWidth = '1px'; -export const buttonVerticalPadding = '0.75em'; -export const buttonHorizontalPadding = '1.25em'; -export const buttonPadding = `${buttonVerticalPadding} ${buttonHorizontalPadding}`; -export const buttonBorderRadius = '0.25em'; +export const BUTTON_DEFAULT_FONT_SIZE = 3; +export const BUTTON_VARIANTS = { LARGE: 'LARGE', SMALL: 'SMALL' }; +export const BUTTON_LARGE_PADDING = { px: 8, py: 5 }; +export const BUTTON_SMALL_PADDING = { px: 6, py: 5 }; +export const BUTTON_SMALL_BORDER_WIDTH = '1px'; +export const BUTTON_LARGE_BORDER_WIDTH = '2px'; +export const BUTTON_BORDER_RADIUS = '0.25em'; + +export const buttonSize = x => ( + defaultTo(x.f, x.fontSize) < BUTTON_DEFAULT_FONT_SIZE + ? BUTTON_VARIANTS.SMALL + : BUTTON_VARIANTS.LARGE +); + +export const buttonColor = ({ color, theme }) => { + if (color) { + const value = themeGet(`colors.${color}`, 'colors.gray.base')({ theme }); + + return ` + color: ${value}; + border-color: ${value}; + `; + } + + return ''; +}; + +export const buttonPadding = x => preset(space, { + LARGE: BUTTON_LARGE_PADDING, + SMALL: BUTTON_SMALL_PADDING, +}[buttonSize(x)]); + +export const buttonBorderWidth = x => ({ + LARGE: BUTTON_LARGE_BORDER_WIDTH, + SMALL: BUTTON_SMALL_BORDER_WIDTH, +}[buttonSize(x)]); const activeMixin = css` border: ${buttonBorderWidth} solid ${x => x.theme.colors.gray.bold}; @@ -25,32 +56,20 @@ const disabledMixin = css` opacity: 0.5; `; -const buttonColor = ({ color, theme }) => { - if (color) { - const value = themeGet(`colors.${color}`, 'colors.gray.bold')({ theme }); - - return ` - color: ${value}; - border-color: ${value}; - `; - } - - return ''; -}; - export const mixin = css` all: initial; display: inline-block; - padding: ${buttonPadding}; + ${preset(fontSize, { f: BUTTON_DEFAULT_FONT_SIZE })} border: ${buttonBorderWidth} solid ${x => x.theme.colors.gray.regular}; - border-radius: ${buttonBorderRadius}; + border-radius: ${BUTTON_BORDER_RADIUS}; font-family: ${x => x.theme.fonts.sans}; font-weight: bold; line-height: 1; user-select: none; cursor: pointer; text-align: center; - ${preset(fontSize, { f: 5 })} + ${alignSelf} + ${buttonPadding} ${buttonColor} ${antialiased} @@ -69,8 +88,8 @@ export const GenericButtonLink = styled.a` ${mixin} `; -const GenericButton = styled.a` +export const GenericButton = styled.button` ${mixin} `; -export default GenericButton; +export default GenericButtonLink; diff --git a/react/components/UI/GenericInput/index.js b/react/components/UI/GenericInput/index.js deleted file mode 100644 index 096b4869d3..0000000000 --- a/react/components/UI/GenericInput/index.js +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import styled, { css } from 'styled-components'; -import { fontSize } from 'styled-system'; - -import { preset } from 'react/styles/functions'; -import { antialiased } from 'react/styles/mixins'; - -export const inputVerticalPadding = '0.75em'; -export const inputHorizontalPadding = '1em'; -export const inputPadding = `${inputVerticalPadding} ${inputHorizontalPadding}`; -export const inputBorderRadius = '0.125em'; - -const focusMixin = css` - background-color: ${x => x.theme.colors.gray.light}; - color: ${x => x.theme.colors.gray.bold}; -`; - -export const mixin = css` - all: initial; - box-sizing: border-box; - display: block; - width: 100%; - appearance: none; - padding: ${inputPadding}; - border-radius: ${inputBorderRadius}; - color: ${x => x.theme.colors.gray.semiBold}; - background-color: ${x => x.theme.colors.gray.hint}; - font-family: ${x => x.theme.fonts.sans}; - ${preset(fontSize, { f: 5 })} - ${antialiased} - - ${x => x.focus && focusMixin} - &:focus { - ${focusMixin} - } - - ${x => x.disabled && ` - pointer-events: none; - opacity: 0.5; - `} -`; - -export const Input = styled.input` - ${mixin} -`; - -export const Textarea = styled.textarea` - ${mixin} -`; - -const SelectWrapper = styled.div` - position: relative; - - &:after { - display: inline-block; - content ''; - width: 0; - height: 0; - position: absolute; - top: 50%; - right: 1em; - transform: translate(0.25em, -50%); - border-top: 0.5em solid ${x => x.theme.colors.gray.semiBold}; - border-right: 0.25em solid transparent; - border-left: 0.25em solid transparent; - pointer-events: none; - } -`; - -const SelectTag = styled.select` - ${mixin} - padding-right: 1.5em; -`; - -export const Select = ({ children, ...rest }) => ( - - - {children} - - -); - -Select.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default Input; diff --git a/react/components/UI/Icons/Lock/index.svg b/react/components/UI/Icons/Lock/index.svg deleted file mode 100644 index 7d5b9d1062..0000000000 --- a/react/components/UI/Icons/Lock/index.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/react/components/UI/Icons/index.js b/react/components/UI/Icons/index.js deleted file mode 100644 index 9db649c093..0000000000 --- a/react/components/UI/Icons/index.js +++ /dev/null @@ -1,38 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import styled from 'styled-components'; - -const Container = styled.div` - display: inline-block; - position: relative; - width: 1em; - height: 1em; - vertical-align: text-top; - - > svg { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - fill: ${x => x.color || 'inherit'}; - } -`; - -export default class Icon extends Component { - static propTypes = { - children: PropTypes.node.isRequired, - } - - render() { - const { children, ...rest } = this.props; - - return ( - - {children} - - ); - } -} diff --git a/react/components/UI/Inputs/components/Checkbox/index.js b/react/components/UI/Inputs/components/Checkbox/index.js new file mode 100644 index 0000000000..8bd7276463 --- /dev/null +++ b/react/components/UI/Inputs/components/Checkbox/index.js @@ -0,0 +1,15 @@ +import styled from 'styled-components'; + +export default styled.input.attrs({ + type: 'checkbox', +})` + // all: initial; + box-sizing: border-box; + margin-right: 0.5em; // TODO: + appearance: checkbox; + + ${x => x.disabled && ` + pointer-events: none; + opacity: 0.5; + `} +`; diff --git a/react/components/UI/Inputs/components/ErrorMessage/index.js b/react/components/UI/Inputs/components/ErrorMessage/index.js new file mode 100644 index 0000000000..cae80da675 --- /dev/null +++ b/react/components/UI/Inputs/components/ErrorMessage/index.js @@ -0,0 +1,11 @@ +import styled from 'styled-components'; + +import Text from 'react/components/UI/Text'; + +export default styled(Text).attrs({ + color: 'state.alert', + fontSize: 1, + my: 4, +})` + cursor: default; +`; diff --git a/react/components/UI/Inputs/components/Input/index.js b/react/components/UI/Inputs/components/Input/index.js new file mode 100644 index 0000000000..6aca05c97b --- /dev/null +++ b/react/components/UI/Inputs/components/Input/index.js @@ -0,0 +1,71 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { pick, omit } from 'underscore'; + +import { space } from 'styled-system'; + +import compactObject from 'react/util/compactObject'; + +import Box from 'react/components/UI/Box'; +import TextInput from 'react/components/UI/Inputs/components/TextInput'; +import ErrorMessage from 'react/components/UI/Inputs/components/ErrorMessage'; + +const SPACE_MARGIN_PROPS_KEYS = ['m', 'mt', 'mr', 'mb', 'ml', 'mx', 'my']; + +// TODO: Needs to be configured to accept a tag +// so that other input types can have errors +export default class Input extends Component { + static propTypes = { + errorMessage: PropTypes.string, + hasError: PropTypes.bool, + ...space.propTypes, + } + + static defaultProps = { + errorMessage: null, + hasError: false, + } + + constructor(props) { + super(props); + + const { errorMessage, hasError } = props; + + this.state = { + mode: (hasError || errorMessage) ? 'error' : 'resting', + }; + } + + componentWillReceiveProps({ hasError, errorMessage }) { + this.setState({ + mode: (hasError || errorMessage) ? 'error' : 'resting', + }); + } + + render() { + const { mode } = this.state; + const { errorMessage } = this.props; + + // Allow the outerbox to have configurable margins + const boxProps = compactObject(pick(this.props, ...SPACE_MARGIN_PROPS_KEYS)); + + // While the input can still have configurable padding + const inputProps = omit(this.props, ...SPACE_MARGIN_PROPS_KEYS); + + return ( + + + + {mode === 'error' && + + {errorMessage} + + } + + ); + } +} diff --git a/react/components/UI/Inputs/components/Label/index.js b/react/components/UI/Inputs/components/Label/index.js new file mode 100644 index 0000000000..da6a3f971f --- /dev/null +++ b/react/components/UI/Inputs/components/Label/index.js @@ -0,0 +1,17 @@ +import styled from 'styled-components'; + +import { mixin as textMixin } from 'react/components/UI/Text'; + +export default styled.label.attrs({ + fontSize: 2, + my: 2, +})` + all: initial; + ${textMixin} + display: block; + cursor: default; + + a { + text-decoration: underline; + } +`; diff --git a/react/components/UI/Inputs/components/Select/index.js b/react/components/UI/Inputs/components/Select/index.js new file mode 100644 index 0000000000..91ccfd5508 --- /dev/null +++ b/react/components/UI/Inputs/components/Select/index.js @@ -0,0 +1,43 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; + +import mixin from 'react/components/UI/Inputs/mixin'; + +const SelectWrapper = styled.div` + position: relative; + + &:after { + display: inline-block; + content ''; + width: 0; + height: 0; + position: absolute; + top: 50%; + right: 1em; + transform: translate(0.25em, -50%); + border-top: 0.5em solid ${x => x.theme.colors.gray.semiBold}; + border-right: 0.25em solid transparent; + border-left: 0.25em solid transparent; + pointer-events: none; + } +`; + +const SelectTag = styled.select` + ${mixin} + padding-right: 1.5em; +`; + +const Select = ({ children, ...rest }) => ( + + + {children} + + +); + +Select.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default Select; diff --git a/react/components/UI/Inputs/components/TextInput/index.js b/react/components/UI/Inputs/components/TextInput/index.js new file mode 100644 index 0000000000..3313f85db6 --- /dev/null +++ b/react/components/UI/Inputs/components/TextInput/index.js @@ -0,0 +1,7 @@ +import styled from 'styled-components'; + +import mixin from 'react/components/UI/Inputs/mixin'; + +export default styled.input` + ${mixin} +`; diff --git a/react/components/UI/Inputs/components/Textarea/index.js b/react/components/UI/Inputs/components/Textarea/index.js new file mode 100644 index 0000000000..42f1061d51 --- /dev/null +++ b/react/components/UI/Inputs/components/Textarea/index.js @@ -0,0 +1,7 @@ +import styled from 'styled-components'; + +import mixin from 'react/components/UI/Inputs/mixin'; + +export default styled.textarea` + ${mixin} +`; diff --git a/react/components/UI/Inputs/index.js b/react/components/UI/Inputs/index.js new file mode 100644 index 0000000000..ab96808c9f --- /dev/null +++ b/react/components/UI/Inputs/index.js @@ -0,0 +1,18 @@ +import _Input from 'react/components/UI/Inputs/components/Input'; +import _Textarea from 'react/components/UI/Inputs/components/Textarea'; +import _Select from 'react/components/UI/Inputs/components/Select'; +import _Checkbox from 'react/components/UI/Inputs/components/Checkbox'; +import _ErrorMessage from 'react/components/UI/Inputs/components/ErrorMessage'; +import _TextInput from 'react/components/UI/Inputs/components/TextInput'; +import _Label from 'react/components/UI/Inputs/components/Label'; +import _mixin from 'react/components/UI/Inputs/mixin'; + +export const Input = _Input; +export const Textarea = _Textarea; +export const Select = _Select; +export const Checkbox = _Checkbox; +export const ErrorMessage = _ErrorMessage; +export const TextInput = _TextInput; +export const Label = _Label; +export const mixin = _mixin; +export const inputPadding = x => `${x.theme.space[5]} ${x.theme.space[6]}`; diff --git a/react/components/UI/Inputs/mixin.js b/react/components/UI/Inputs/mixin.js new file mode 100644 index 0000000000..364276d8fd --- /dev/null +++ b/react/components/UI/Inputs/mixin.js @@ -0,0 +1,44 @@ +import { css } from 'styled-components'; +import { fontSize, space, borderColor } from 'styled-system'; + +import { preset } from 'react/styles/functions'; +import { antialiased } from 'react/styles/mixins'; + +const focusMixin = css` + border: 1px solid ${x => x.theme.colors.gray.bold}; + background-color: ${x => x.theme.colors.gray.hint}; + color: black; + ${borderColor} +`; + +export default css` + all: initial; + box-sizing: border-box; + display: block; + width: 100%; + appearance: none; + color: black; + background-color: white; + border: 1px solid ${x => x.theme.colors.gray.medium}; + font-family: ${x => x.theme.fonts.sans}; + ${preset(fontSize, { f: 4 })} + ${preset(space, { px: 5, py: 4 })} + ${borderColor} + ${antialiased} + + ${x => x.focus && focusMixin} + &:focus { + ${focusMixin} + } + + ${x => x.disabled && ` + pointer-events: none; + opacity: 0.5; + `} + + ${x => x.hasError && ` + &, &:focus { + border-color: ${x.theme.colors.state.alert}; + } + `} +`; diff --git a/react/components/UI/SearchInput/index.js b/react/components/UI/SearchInput/index.js index f56dd7612a..f9553c7c88 100644 --- a/react/components/UI/SearchInput/index.js +++ b/react/components/UI/SearchInput/index.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import styled from 'styled-components'; import { isEmpty } from 'underscore'; -import GenericInput from 'react/components/UI/GenericInput'; +import { Input } from 'react/components/UI/Inputs'; const Container = styled.div` position: relative; @@ -39,15 +39,6 @@ const Icon = styled.div` } `; -const Input = styled(GenericInput)` - padding-left: 2.5em; - border: 1px solid ${x => x.theme.colors.gray.regular}; - - &:focus { - border: 1px solid ${x => x.theme.colors.gray.regular}; - } -`; - export default class SearchInput extends Component { static propTypes = { query: PropTypes.string, @@ -102,6 +93,8 @@ export default class SearchInput extends Component { { this.input = input; }} onChange={this.handleChange} diff --git a/react/components/UI/Text/index.js b/react/components/UI/Text/index.js index ce0a8e817e..68e7dfd681 100644 --- a/react/components/UI/Text/index.js +++ b/react/components/UI/Text/index.js @@ -8,12 +8,20 @@ export const mixin = css` ${display} ${space} ${preset(fontFamily, { font: 'sans' })} - ${preset(fontSize, { f: 5 })} + ${preset(fontSize, { f: 4 })} ${preset(lineHeight, { lineHeight: 1 })} ${preset(textColor, { color: 'gray.base' })} ${textAlign} ${antialiased} ${neutralMarginsY} + + a { + color: inherit; + + ${x => x.underlineLinks && ` + text-decoration: underline; + `} + } `; export default styled.div` diff --git a/react/hocs/WithBrowserRouter/index.js b/react/hocs/WithBrowserRouter/index.js new file mode 100644 index 0000000000..adfdf4b3ba --- /dev/null +++ b/react/hocs/WithBrowserRouter/index.js @@ -0,0 +1,20 @@ +import React, { Component } from 'react'; +import { BrowserRouter } from 'react-router-dom'; + +const withBrowserRouter = (WrappedComponent) => { + class WithBrowserRouter extends Component { + render() { + const { ...rest } = this.props; + + return ( + + + + ); + } + } + + return WithBrowserRouter; +}; + +export default withBrowserRouter; diff --git a/react/pages/authentication/AcceptInvitationPage/fragments/invitee.js b/react/pages/authentication/AcceptInvitationPage/fragments/invitee.js new file mode 100644 index 0000000000..344f51d0fe --- /dev/null +++ b/react/pages/authentication/AcceptInvitationPage/fragments/invitee.js @@ -0,0 +1,9 @@ +import gql from 'graphql-tag'; + +export default gql` + fragment Invitee on Invitee { + __typename + id + email + } +`; diff --git a/react/pages/authentication/AcceptInvitationPage/index.js b/react/pages/authentication/AcceptInvitationPage/index.js new file mode 100644 index 0000000000..dc6f64dd9a --- /dev/null +++ b/react/pages/authentication/AcceptInvitationPage/index.js @@ -0,0 +1,62 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Query } from 'react-apollo'; + +import inviteeQuery from 'react/pages/authentication/AcceptInvitationPage/queries/invitee'; + +import Icon from 'react/components/UI/Icon'; +import CenteringBox from 'react/components/UI/CenteringBox'; +import Text from 'react/components/UI/Text'; +import RegistrationForm from 'react/components/RegistrationForm'; + +export default class AcceptInvitationPage extends Component { + static propTypes = { + // `invitation_token` is used to locate the invite + // it is a digest of `raw_invitation_token` and exists on the user record. + invitation_token: PropTypes.string.isRequired, + // `raw_invitation_token` is used to accept the invite + // it is not in the database directly. + // At the moment this is passed as `invite_token` in the + // query string of the URL in the invitation email + raw_invitation_token: PropTypes.string.isRequired, + } + + render() { + const { invitation_token, raw_invitation_token } = this.props; + + return ( + + {({ loading, error, data }) => { + if (loading) return
; + + if (error) { + return ( + + + + + We cannot find that invitation code. + + + + If you believe this is in error please contact + {' '} + help@are.na + + + ); + } + + return ( + + + + ); + }} + + ); + } +} diff --git a/react/pages/authentication/AcceptInvitationPage/queries/invitee.js b/react/pages/authentication/AcceptInvitationPage/queries/invitee.js new file mode 100644 index 0000000000..5765dbe244 --- /dev/null +++ b/react/pages/authentication/AcceptInvitationPage/queries/invitee.js @@ -0,0 +1,12 @@ +import gql from 'graphql-tag'; + +import inviteeFragment from 'react/pages/authentication/AcceptInvitationPage/fragments/invitee'; + +export default gql` + query Invitee($invitation_token: String!) { + invitee(invitation_token: $invitation_token) { + ...Invitee + } + } + ${inviteeFragment} +`; diff --git a/react/pages/authentication/ForgotPasswordPage/index.js b/react/pages/authentication/ForgotPasswordPage/index.js new file mode 100644 index 0000000000..e8bd3e86f9 --- /dev/null +++ b/react/pages/authentication/ForgotPasswordPage/index.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; + +import CenteringBox from 'react/components/UI/CenteringBox'; +import ForgotPasswordForm from 'react/components/ForgotPasswordForm'; + +export default class ForgotPasswordPage extends Component { + render() { + return ( + + + + ); + } +} diff --git a/react/pages/authentication/LoginPage/index.js b/react/pages/authentication/LoginPage/index.js new file mode 100644 index 0000000000..898b82e05e --- /dev/null +++ b/react/pages/authentication/LoginPage/index.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; + +import CenteringBox from 'react/components/UI/CenteringBox'; +import LoginForm from 'react/components/LoginForm'; + +export default class LoginPage extends Component { + render() { + return ( + + + + ); + } +} diff --git a/react/pages/authentication/RegistrationPage/index.js b/react/pages/authentication/RegistrationPage/index.js new file mode 100644 index 0000000000..20a7e64cd1 --- /dev/null +++ b/react/pages/authentication/RegistrationPage/index.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; + +import CenteringBox from 'react/components/UI/CenteringBox'; +import RegistrationForm from 'react/components/RegistrationForm'; + +export default class RegistrationPage extends Component { + render() { + return ( + + + + ); + } +} diff --git a/react/pages/authentication/ResetPasswordPage/fragments/passwordResettableUser.js b/react/pages/authentication/ResetPasswordPage/fragments/passwordResettableUser.js new file mode 100644 index 0000000000..75862d61e8 --- /dev/null +++ b/react/pages/authentication/ResetPasswordPage/fragments/passwordResettableUser.js @@ -0,0 +1,8 @@ +import gql from 'graphql-tag'; + +export default gql` + fragment PasswordResettableUser on User { + __typename + id + } +`; diff --git a/react/pages/authentication/ResetPasswordPage/index.js b/react/pages/authentication/ResetPasswordPage/index.js new file mode 100644 index 0000000000..d68d0b2710 --- /dev/null +++ b/react/pages/authentication/ResetPasswordPage/index.js @@ -0,0 +1,54 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Query } from 'react-apollo'; + +import passwordResettableUserQuery from 'react/pages/authentication/ResetPasswordPage/queries/passwordResettableUser'; + +import Text from 'react/components/UI/Text'; +import Icon from 'react/components/UI/Icon'; +import CenteringBox from 'react/components/UI/CenteringBox'; +import ResetPasswordForm from 'react/components/ResetPasswordForm'; + +export default class ResetPasswordPage extends Component { + static propTypes = { + reset_password_token: PropTypes.string.isRequired, + } + + render() { + const { reset_password_token } = this.props; + + return ( + + {({ loading, error }) => { + if (loading) return
; + + if (error) { + return ( + + + + + We’re unable to reset your password. + + + + If you believe this is in error please contact + {' '} + help@are.na + + + ); + } + + return ( + + + + ); + }} + + ); + } +} diff --git a/react/pages/authentication/ResetPasswordPage/queries/passwordResettableUser.js b/react/pages/authentication/ResetPasswordPage/queries/passwordResettableUser.js new file mode 100644 index 0000000000..3bf53357e3 --- /dev/null +++ b/react/pages/authentication/ResetPasswordPage/queries/passwordResettableUser.js @@ -0,0 +1,12 @@ +import gql from 'graphql-tag'; + +import passwordResettableUserFragment from 'react/pages/authentication/ResetPasswordPage/fragments/passwordResettableUser'; + +export default gql` + query PasswordResettableUser($reset_password_token: String!) { + password_resettable_user(reset_password_token: $reset_password_token) { + ...PasswordResettableUser + } + } + ${passwordResettableUserFragment} +`; diff --git a/react/stories/ButtonGroup.stories.js b/react/stories/ButtonGroup.stories.js index cb54d3aa2f..0df82a05b8 100644 --- a/react/stories/ButtonGroup.stories.js +++ b/react/stories/ButtonGroup.stories.js @@ -20,19 +20,19 @@ storiesOf('ButtonGroup', module) )) .add('default - small buttons', () => ( - - Option 1 - Option 2 - Option 3 - Option 4 + + Option 1 + Option 2 + Option 3 + Option 4 )) .add('default - colors', () => ( - - Option 1 - Option 2 - Option 3 - Option 4 + + Option 1 + Option 2 + Option 3 + Option 4 )) .add('stretch', () => ( @@ -44,10 +44,10 @@ storiesOf('ButtonGroup', module) )) .add('stretch - small buttons', () => ( - - Option 1 - Option 2 - Option 3 - Option 4 + + Option 1 + Option 2 + Option 3 + Option 4 )); diff --git a/react/stories/Buttons.stories.js b/react/stories/Buttons.stories.js index c86b88b111..bf62f4a1f7 100644 --- a/react/stories/Buttons.stories.js +++ b/react/stories/Buttons.stories.js @@ -3,7 +3,6 @@ import { storiesOf } from '@storybook/react'; import theme from 'react/styles/theme'; -import Specimen from 'react/stories/__components__/Specimen'; import States from 'react/stories/__components__/States'; import GenericButton from 'react/components/UI/GenericButton'; @@ -11,7 +10,7 @@ import GenericButton from 'react/components/UI/GenericButton'; storiesOf('Button', module) .add('GenericButton', () => ( - Press + Button )) .add('GenericButton - colors', () => ( @@ -27,7 +26,7 @@ storiesOf('Button', module)
{theme.fontSizes.map((size, i) => ( - {`f={${i}}`} + {`f={${i}}`} ))}
diff --git a/react/stories/Forms.stories.js b/react/stories/Forms.stories.js new file mode 100644 index 0000000000..7e1f86ee39 --- /dev/null +++ b/react/stories/Forms.stories.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; + +import LoginForm from 'react/components/LoginForm'; +import RegistrationForm from 'react/components/RegistrationForm'; +import ResetPasswordForm from 'react/components/ResetPasswordForm'; + +storiesOf('Forms', module) + .add('Login form', () => ( + + )) + .add('Signup form', () => ( + + )) + .add('Forgot password form', () => ( + + )); diff --git a/react/stories/Icons.stories.js b/react/stories/Icons.stories.js new file mode 100644 index 0000000000..897b82e4fb --- /dev/null +++ b/react/stories/Icons.stories.js @@ -0,0 +1,37 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; + +import Specimen from 'react/stories/__components__/Specimen'; +import States from 'react/stories/__components__/States'; + +import Button from 'react/components/UI/GenericButton'; +import Icon, { ICON_NAMES } from 'react/components/UI/Icon'; + +storiesOf('Icons', module) + .add('Names', () => ( +
+ {ICON_NAMES.map(name => ( + + {name}: + + ))} +
+ )) + .add('Configuration', () => ( + + + + )) + .add('Button with icon', () => ( + + + + )); diff --git a/react/stories/Inputs.stories.js b/react/stories/Inputs.stories.js index 777e67f9de..54b16e51cf 100644 --- a/react/stories/Inputs.stories.js +++ b/react/stories/Inputs.stories.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Component } from 'react'; import { storiesOf } from '@storybook/react'; import theme from 'react/styles/theme'; @@ -6,20 +6,67 @@ import theme from 'react/styles/theme'; import Specimen from 'react/stories/__components__/Specimen'; import States from 'react/stories/__components__/States'; -import GenericInput from 'react/components/UI/GenericInput'; +import { Input } from 'react/components/UI/Inputs'; + +class FocusableInput extends Component { + handleClick = () => { + this.input.focus(); + } + + render() { + return ( +
+ + Click me to focus input + + + { this.input = input; }} /> +
+ ); + } +} storiesOf('Input', module) - .add('GenericInput', () => ( - - + .add('Input', () => ( + + )) - .add('GenericInput - sizes', () => ( + .add('Input - sizes', () => (
{theme.fontSizes.map((size, i) => ( - - + + ))}
+ )) + .add('Input - with Errors', () => ( +
+ + + +
+ )) + .add('Input - with ref', () => ( + + + )); diff --git a/react/stories/Labels.stories.js b/react/stories/Labels.stories.js new file mode 100644 index 0000000000..ebc3396799 --- /dev/null +++ b/react/stories/Labels.stories.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; + +import theme from 'react/styles/theme'; + +import Specimen from 'react/stories/__components__/Specimen'; + +import { Label } from 'react/components/UI/Inputs'; + +storiesOf('Label', module) + .add('Label - default', () => ( + + + + + )) + .add('Label - colors', () => ( +
+ {theme.meta.colorNames.map(color => ( + + + + ))} +
+ )); diff --git a/react/stories/__components__/States/index.js b/react/stories/__components__/States/index.js index e6b6b8e93a..7027959f31 100644 --- a/react/stories/__components__/States/index.js +++ b/react/stories/__components__/States/index.js @@ -34,10 +34,10 @@ export default class States extends Component { return ( {states.map(stateProps => ( - + {provideChildrentWithProps(children, stateProps)} - + {JSON.stringify(stateProps)} diff --git a/react/styles/constants.js b/react/styles/constants.js index 5ed026ee24..748ae900fb 100644 --- a/react/styles/constants.js +++ b/react/styles/constants.js @@ -30,11 +30,14 @@ export const SPACING_SCALE = [ '0.25em', '0.33em', '0.66em', - '1em', // 5 + '0.75em', + '1em', // 6 '2em', + '3em', '4em', '8em', '16em', + '24em', '32em', ]; diff --git a/react/styles/functions.js b/react/styles/functions.js index 6fe143620d..23949882a6 100644 --- a/react/styles/functions.js +++ b/react/styles/functions.js @@ -19,7 +19,11 @@ export const calculateLineHeight = (fontSizeName, lineHeightName) => { return fontSizeValue * lineHeightValue; }; -export const preset = (fn, presetProps = {}) => props => fn({ ...presetProps, ...props }); +export const preset = (fn, presetProps = {}) => + props => fn({ ...presetProps, ...props }); + +export const defaultTo = (v, dV) => + ((v == null || v !== v) ? dV : v); // eslint-disable-line no-self-compare export default { parse, diff --git a/react/styles/text.js b/react/styles/text.js index 1b0b13159b..a759826443 100644 --- a/react/styles/text.js +++ b/react/styles/text.js @@ -24,13 +24,12 @@ const __FONT_SIZE_SCALE__ = [ 'xs', // 1 'sx', // 2 'sm', // 3 - 'sm', // 4 - 'md', // 5 (base) - 'lg', // 6 - 'h4', // 7 - 'h3', // 8 - 'h2', // 9 - 'h1', // 10 + 'md', // 4 (base) + 'lg', // 5 + 'h4', // 6 + 'h3', // 7 + 'h2', // 8 + 'h1', // 9 ]; export const FONT_SIZE_NAMES = __FONT_SIZE_SCALE__; diff --git a/react/util/__tests__/compactObject.js b/react/util/__tests__/compactObject.js new file mode 100644 index 0000000000..91c43b58a5 --- /dev/null +++ b/react/util/__tests__/compactObject.js @@ -0,0 +1,18 @@ +import compactObject from 'react/util/compactObject'; + +describe('compactObject', () => { + it('removes null values from the object', () => { + expect(compactObject({ + a: 'foo', + b: false, + c: null, + d: 1, + e: 0, + })).toEqual({ + a: 'foo', + b: false, + d: 1, + e: 0, + }); + }); +}); diff --git a/react/util/__tests__/mapErrors.js b/react/util/__tests__/mapErrors.js new file mode 100644 index 0000000000..89310abed6 --- /dev/null +++ b/react/util/__tests__/mapErrors.js @@ -0,0 +1,80 @@ +import mapErrors from 'react/util/mapErrors'; + +describe('mapErrors', () => { + describe('a response with no attribute errors and a single overall error', () => { + const RESPONSE = { + data: { registration: null }, + errors: [{ + message: 'An account with this email already exists. Login to continue.', locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'BAD_REQUEST' }, + }], + }; + + it('pulls out the errorMessage', () => { + expect(mapErrors({ graphQLErrors: RESPONSE.errors })) + .toEqual({ + attributeErrors: {}, + errorMessage: 'An account with this email already exists. Login to continue.', + }); + }); + }); + + describe('a response with multiple attribute errors', () => { + const RESPONSE = { + data: { registration: null }, + errors: [{ + message: "doesn't match Password", locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'UNPROCESSABLE_ENTITY', attribute: 'password_confirmation' }, + }, { + message: 'is too short (minimum is 6 characters)', locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'UNPROCESSABLE_ENTITY', attribute: 'password' }, + }], + }; + + it('maps the error messages into their respective attributes', () => { + expect(mapErrors({ graphQLErrors: RESPONSE.errors })) + .toEqual({ + attributeErrors: { + password: 'is too short (minimum is 6 characters)', + password_confirmation: "doesn't match Password", + }, + errorMessage: null, + }); + }); + }); + + describe('a response with both multiple general messages and attribute errors', () => { + const RESPONSE = { + data: { registration: null }, + errors: [{ + message: 'Some other error.', locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'BAD_REQUEST' }, + }, { + message: 'Lots of errors here.', locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'BAD_REQUEST' }, + }, { + message: 'An account with this email already exists. Login to continue.', locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'BAD_REQUEST' }, + }, { + message: "doesn't match Password", locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'UNPROCESSABLE_ENTITY', attribute: 'password_confirmation' }, + }, { + message: 'is too short (minimum is 6 characters)', locations: [{ line: 2, column: 3 }], path: ['registration'], extensions: { code: 'UNPROCESSABLE_ENTITY', attribute: 'password' }, + }], + }; + + it('maps the error messages into their respective attributes and returns a correctly formatted errorMessage', () => { + expect(mapErrors({ graphQLErrors: RESPONSE.errors })) + .toEqual({ + errorMessage: 'Some other error. Lots of errors here. An account with this email already exists. Login to continue.', + attributeErrors: { + password: 'is too short (minimum is 6 characters)', + password_confirmation: "doesn't match Password", + }, + }); + }); + }); + + describe('a response with no errors (network error)', () => { + it('returns the message', () => { + expect(mapErrors({ graphQLErrors: [], message: 'Network error: Failed to fetch' })) + .toEqual({ + errorMessage: 'Network error: Failed to fetch', + attributeErrors: {}, + }); + }); + }); +}); diff --git a/react/util/compactObject.js b/react/util/compactObject.js new file mode 100644 index 0000000000..c836703069 --- /dev/null +++ b/react/util/compactObject.js @@ -0,0 +1,7 @@ +export default (x = {}) => + Object.keys(x).reduce((memo, key) => { + if (x[key] !== null) { + return { ...memo, [key]: x[key] }; + } + return memo; + }, {}); diff --git a/react/util/formatErrors.js b/react/util/formatErrors.js deleted file mode 100644 index 8738c6c35d..0000000000 --- a/react/util/formatErrors.js +++ /dev/null @@ -1,6 +0,0 @@ -import { flatten } from 'underscore'; - -export default (errs, separator = '; ') => - flatten([errs]).map(err => (err.graphQLErrors && - err.graphQLErrors.map(({ message }) => message).join(separator) - ) || err.message).join(separator); diff --git a/react/util/mapErrors.js b/react/util/mapErrors.js new file mode 100644 index 0000000000..358eb57f00 --- /dev/null +++ b/react/util/mapErrors.js @@ -0,0 +1,34 @@ +import { compact } from 'underscore'; + +const MEMO = { + errorMessage: null, + attributeErrors: {}, +}; + +module.exports = (err = {}) => { + if (err.graphQLErrors.length === 0) { + return { ...MEMO, errorMessage: err.message }; + } + + return err.graphQLErrors.reduce((memo, gqlErr = {}) => { + // If an attribute is present, + // return the message keyed by that attribute + if (gqlErr.extensions && gqlErr.extensions.attribute) { + return { + ...memo, + attributeErrors: { + ...memo.attributeErrors, + [gqlErr.extensions.attribute]: gqlErr.message, + }, + }; + } + + // Otherwise return a general errorMessage, + // while joining up any/all of them into a single message + const errorMessage = compact([memo.errorMessage, gqlErr.message]) + // We probably have periods but we might not; add them and dedup + .join('. ').replace('..', '.'); + + return { ...memo, errorMessage }; + }, MEMO); +}; diff --git a/react/util/parseRoute.js b/react/util/parseRoute.js new file mode 100644 index 0000000000..b3826af59c --- /dev/null +++ b/react/util/parseRoute.js @@ -0,0 +1,7 @@ +import { parse } from 'qs'; + +export default renderFn => props => renderFn({ + params: props.match.params, + query: parse(props.location.search.slice(1)), + originalProps: props, +}); diff --git a/react/util/provideChildrenWithProps.js b/react/util/provideChildrenWithProps.js index 911e2aea21..a4e8ba699f 100644 --- a/react/util/provideChildrenWithProps.js +++ b/react/util/provideChildrenWithProps.js @@ -1,5 +1,9 @@ import React from 'react'; -export default (children, props) => - React.Children.map(children, child => - React.cloneElement(child, props)); +export default (children, props) => { + const xs = React.isValidElement(children) + ? children + : children.filter(Boolean); + + return React.Children.map(xs, child => React.cloneElement(child, props)); +}; diff --git a/yarn.lock b/yarn.lock index 29c4faddfe..25a6cd8641 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,6 +18,12 @@ esutils "^2.0.2" js-tokens "^3.0.0" +"@babel/code-frame@^7.0.0-beta.35": + version "7.0.0-beta.55" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.55.tgz#71f530e7b010af5eb7a7df7752f78921dd57e9ee" + dependencies: + "@babel/highlight" "7.0.0-beta.55" + "@babel/helper-annotate-as-pure@^7.0.0-beta.37": version "7.0.0-beta.39" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0-beta.39.tgz#cf9506c721c838806ca5eabe15783507ba2edce0" @@ -38,6 +44,14 @@ dependencies: "@babel/types" "7.0.0-beta.36" +"@babel/highlight@7.0.0-beta.55": + version "7.0.0-beta.55" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.55.tgz#988653647d629c261dae156e74d5f0252ba520c0" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + "@babel/template@7.0.0-beta.36": version "7.0.0-beta.36" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.36.tgz#02e903de5d68bd7899bce3c5b5447e59529abb00" @@ -403,6 +417,10 @@ abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" +abab@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -471,6 +489,10 @@ acorn@^5.0.0, acorn@^5.3.0, acorn@^5.4.0: version "5.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" +acorn@^5.5.3: + version "5.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + address@1.0.3, address@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -574,7 +596,7 @@ ansi-styles@^3.1.0: dependencies: color-convert "^1.9.0" -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: @@ -587,6 +609,13 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + apollo-cache-inmemory@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.1.7.tgz#15e6200f70431414d29bd5f20e86d81739e26430" @@ -700,6 +729,12 @@ append-field@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/append-field/-/append-field-0.1.0.tgz#6ddc58fa083c7bc545d3c5995b2830cc2366d44a" +append-transform@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" + dependencies: + default-require-extensions "^2.0.0" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -730,10 +765,18 @@ arr-diff@^2.0.0: dependencies: arr-flatten "^1.0.1" -arr-flatten@^1.0.1: +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -783,6 +826,10 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + array.prototype.flat@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4" @@ -807,7 +854,7 @@ array.prototype.flatten@^1.2.1: es-abstract "^1.10.0" function-bind "^1.1.1" -arrify@^1.0.0: +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -857,6 +904,10 @@ assertion-error@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + ast-types-flow@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" @@ -869,6 +920,10 @@ ast-types@0.9.6: version "0.9.6" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -909,6 +964,10 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + autoprefixer@^6.3.1: version "6.7.7" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" @@ -968,6 +1027,30 @@ babel-code-frame@6.26.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" +babel-core@^6.0.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + babel-core@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" @@ -1003,6 +1086,19 @@ babel-eslint@^8.2.1: eslint-scope "~3.7.1" eslint-visitor-keys "^1.0.0" +babel-generator@^6.18.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + babel-generator@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" @@ -1170,6 +1266,13 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" +babel-jest@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.4.2.tgz#f276de67798a5d68f2d6e87ff518c2f6e1609877" + dependencies: + babel-plugin-istanbul "^4.1.6" + babel-preset-jest "^23.2.0" + babel-loader@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.2.tgz#f6cbe122710f1aa2af4d881c6d5b54358ca24126" @@ -1209,6 +1312,19 @@ babel-plugin-inline-react-svg@^0.5.2: resolve-from "^2.0.0" svgo "^0.7.0" +babel-plugin-istanbul@^4.1.6: + version "4.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.13.0" + find-up "^2.1.0" + istanbul-lib-instrument "^1.10.1" + test-exclude "^4.2.1" + +babel-plugin-jest-hoist@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167" + babel-plugin-macros@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.2.2.tgz#049c93f4b934453688a6ec38bba529c55bf0fa1f" @@ -1360,7 +1476,7 @@ babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" -babel-plugin-syntax-object-rest-spread@^6.8.0: +babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" @@ -1758,6 +1874,13 @@ babel-preset-flow@^6.23.0: dependencies: babel-plugin-transform-flow-strip-types "^6.22.0" +babel-preset-jest@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46" + dependencies: + babel-plugin-jest-hoist "^23.2.0" + babel-plugin-syntax-object-rest-spread "^6.13.0" + babel-preset-minify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.3.0.tgz#7db64afa75f16f6e06c0aa5f25195f6f36784d77" @@ -1860,7 +1983,7 @@ babel-runtime@6.x.x, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-template@^6.15.0, babel-template@^6.24.1, babel-template@^6.26.0: +babel-template@^6.15.0, babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" dependencies: @@ -1870,7 +1993,7 @@ babel-template@^6.15.0, babel-template@^6.24.1, babel-template@^6.26.0: babylon "^6.18.0" lodash "^4.17.4" -babel-traverse@^6.15.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: +babel-traverse@^6.0.0, babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" dependencies: @@ -1884,7 +2007,7 @@ babel-traverse@^6.15.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: invariant "^2.2.2" lodash "^4.17.4" -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: +babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" dependencies: @@ -1946,6 +2069,18 @@ base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + basic-auth@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba" @@ -2064,6 +2199,21 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + brcast@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/brcast/-/brcast-3.0.1.tgz#6256a8349b20de9eed44257a9b24d71493cd48dd" @@ -2086,6 +2236,12 @@ browser-process-hrtime@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" +browser-resolve@^1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" + dependencies: + resolve "1.1.7" + browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" @@ -2156,6 +2312,12 @@ browserslist@^2.1.2, browserslist@^2.11.3: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" +bser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" + dependencies: + node-int64 "^0.4.0" + bucket-assets@aredotna/bucket-assets.git#d253febf7c658673c036afc85d034572011135e4: version "1.0.2" resolved "https://codeload.github.com/aredotna/bucket-assets/tar.gz/d253febf7c658673c036afc85d034572011135e4" @@ -2168,6 +2330,10 @@ bucket-assets@aredotna/bucket-assets.git#d253febf7c658673c036afc85d034572011135e superagent "^1.2.0" underscore "^1.8.3" +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -2224,6 +2390,20 @@ cacache@^10.0.4: unique-filename "^1.1.0" y18n "^4.0.0" +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cacheable-request@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" @@ -2256,6 +2436,10 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + camel-case@3.0.x: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" @@ -2296,6 +2480,12 @@ caniuse-lite@^1.0.30000805: version "1.0.30000851" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000851.tgz#3b498aebf9f92cf6cff4ab54d13b557c0b590533" +capture-exit@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" + dependencies: + rsvp "^3.3.3" + case-sensitive-paths-webpack-plugin@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.2.tgz#c899b52175763689224571dad778742e133f0192" @@ -2418,6 +2608,10 @@ chownr@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" +ci-info@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -2435,6 +2629,15 @@ clap@^1.0.9: dependencies: chalk "^1.1.3" +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + classnames@^2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" @@ -2549,6 +2752,13 @@ coffeescript@1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.11.1.tgz#42d6769fdc61c1bf9a132fb1ddba5a43f4f2785c" +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.3.0, color-convert@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" @@ -2641,7 +2851,11 @@ commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" -component-emitter@^1.2.0, component-emitter@~1.2.0: +compare-versions@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.3.0.tgz#af93ea705a96943f622ab309578b9b90586f39c3" + +component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@~1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -2720,7 +2934,7 @@ contextify@~0.1.5: bindings "^1.2.1" nan "^2.1.0" -convert-source-map@^1.5.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -2783,6 +2997,10 @@ copy-concurrently@^1.0.0: rimraf "^2.5.4" run-queue "^1.0.0" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + copy-to-clipboard@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9" @@ -3045,6 +3263,12 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@~0.3.0: dependencies: cssom "0.3.x" +cssstyle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.0.0.tgz#79b16d51ec5591faec60e688891f15d2a5705129" + dependencies: + cssom "0.3.x" + csstype@^2.2.0: version "2.5.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.3.tgz#2504152e6e1cc59b32098b7f5d6a63f16294c1f7" @@ -3079,6 +3303,14 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.0.tgz#24802de4e81c298ea8a9388bb0d8e461c774684f" + dependencies: + abab "^1.0.4" + whatwg-mimetype "^2.0.0" + whatwg-url "^6.4.0" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -3089,7 +3321,7 @@ debug@*, debug@3.1.0, debug@^3.0.1, debug@^3.1.0: dependencies: ms "2.0.0" -debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: +debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -3135,6 +3367,10 @@ deep-equal@~0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.1.2.tgz#b246c2b80a570a47c11be1d9bd1070ec878b87ce" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" @@ -3143,6 +3379,12 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" +default-require-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" + dependencies: + strip-bom "^3.0.0" + define-properties@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" @@ -3150,6 +3392,25 @@ define-properties@^1.1.2: foreach "^2.0.5" object-keys "^1.0.8" +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -3211,6 +3472,10 @@ detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" +detect-newline@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + detect-passive-events@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/detect-passive-events/-/detect-passive-events-1.0.4.tgz#6ed477e6e5bceb79079735dcd357789d37f9a91a" @@ -3245,6 +3510,10 @@ diff@^3.1.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" +diff@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + diffie-hellman@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" @@ -3307,7 +3576,7 @@ domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" -domexception@^1.0.0: +domexception@^1.0.0, domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" dependencies: @@ -3599,6 +3868,17 @@ escodegen@^1.9.0: optionalDependencies: source-map "~0.5.6" +escodegen@^1.9.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" @@ -3817,6 +4097,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +exec-sh@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" + dependencies: + merge "^1.2.0" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -3833,12 +4119,28 @@ exenv@^1.2.0, exenv@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" dependencies: is-posix-bracket "^0.1.0" +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" @@ -3851,6 +4153,17 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +expect@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-23.4.0.tgz#6da4ecc99c1471253e7288338983ad1ebadb60c3" + dependencies: + ansi-styles "^3.2.0" + jest-diff "^23.2.0" + jest-get-type "^22.1.0" + jest-matcher-utils "^23.2.0" + jest-message-util "^23.4.0" + jest-regex-util "^23.3.0" + express-spam-referral-blocker@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/express-spam-referral-blocker/-/express-spam-referral-blocker-1.2.1.tgz#9eea38788340b006beb10593865bf5f006b35930" @@ -3934,6 +4247,19 @@ express@^4.16.3: utils-merge "1.0.1" vary "~1.1.2" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" @@ -3956,6 +4282,19 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -4013,6 +4352,12 @@ faye-websocket@~0.11.0: dependencies: websocket-driver ">=0.5.1" +fb-watchman@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" + dependencies: + bser "^2.0.0" + fbjs@^0.8.12, fbjs@^0.8.16, fbjs@^0.8.5, fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" @@ -4061,6 +4406,13 @@ filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" +fileset@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" + dependencies: + glob "^7.0.3" + minimatch "^3.0.3" + filesize@3.5.11: version "3.5.11" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" @@ -4075,6 +4427,15 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + finalhandler@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" @@ -4162,7 +4523,7 @@ follow-redirects@^1.2.3: dependencies: debug "^3.1.0" -for-in@^1.0.1: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4252,6 +4613,12 @@ forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -4281,6 +4648,12 @@ fs-jetpack@^0.13.3: dependencies: minimatch "^3.0.2" +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -4301,6 +4674,13 @@ fsevents@*, fsevents@^1.0.0: nan "^2.3.0" node-pre-gyp "^0.6.39" +fsevents@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + fstream-ignore@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" @@ -4363,6 +4743,10 @@ get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -4437,7 +4821,7 @@ glob@7.0.x: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: +glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -4582,6 +4966,16 @@ gzip-size@3.0.0: dependencies: duplexer "^0.1.1" +handlebars@^4.0.3: + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" @@ -4640,6 +5034,33 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + has@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" @@ -4892,7 +5313,7 @@ iconv-lite@0.4.19, iconv-lite@^0.4.17: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@~0.4.13: +iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" dependencies: @@ -4916,6 +5337,12 @@ iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + ignore@^3.3.3: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" @@ -4930,6 +5357,13 @@ immutable@^3.8.1: version "3.8.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" +import-local@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" + dependencies: + pkg-dir "^2.0.0" + resolve-cwd "^2.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -5033,6 +5467,18 @@ is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -5057,10 +5503,44 @@ is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" +is-ci@^1.0.10: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" + dependencies: + ci-info "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" @@ -5093,10 +5573,16 @@ is-expression@^3.0.0: acorn "~4.0.2" object-assign "^4.0.1" -is-extendable@^0.1.1: +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" @@ -5125,6 +5611,10 @@ is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" +is-generator-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" + is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -5173,7 +5663,7 @@ is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" -is-plain-object@^2.0.1, is-plain-object@^2.0.4: +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" dependencies: @@ -5237,7 +5727,11 @@ is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" -is-windows@^1.0.1: +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -5263,7 +5757,7 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" -isobject@^3.0.1: +isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" @@ -5278,25 +5772,89 @@ isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" +istanbul-api@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.1.tgz#4c3b05d18c0016d1022e079b98dc82c40f488954" dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" + async "^2.1.4" + compare-versions "^3.1.0" + fileset "^2.0.2" + istanbul-lib-coverage "^1.2.0" + istanbul-lib-hook "^1.2.0" + istanbul-lib-instrument "^1.10.1" + istanbul-lib-report "^1.1.4" + istanbul-lib-source-maps "^1.2.4" + istanbul-reports "^1.3.0" + js-yaml "^3.7.0" + mkdirp "^0.5.1" + once "^1.4.0" -iterall@^1.1.3, iterall@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" +istanbul-lib-coverage@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" -jade@*, jade@1.11.0, jade@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/jade/-/jade-1.11.0.tgz#9c80e538c12d3fb95c8d9bb9559fa0cc040405fd" +istanbul-lib-hook@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz#f614ec45287b2a8fc4f07f5660af787575601805" dependencies: - character-parser "1.2.1" - clean-css "^3.1.9" - commander "~2.6.0" - constantinople "~3.0.1" + append-transform "^1.0.0" + +istanbul-lib-instrument@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.18.0" + istanbul-lib-coverage "^1.2.0" + semver "^5.3.0" + +istanbul-lib-report@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz#e886cdf505c4ebbd8e099e4396a90d0a28e2acb5" + dependencies: + istanbul-lib-coverage "^1.2.0" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1" + dependencies: + debug "^3.1.0" + istanbul-lib-coverage "^1.2.0" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + +istanbul-reports@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.3.0.tgz#2f322e81e1d9520767597dca3c20a0cce89a3554" + dependencies: + handlebars "^4.0.3" + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +iterall@^1.1.3, iterall@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" + +jade@*, jade@1.11.0, jade@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/jade/-/jade-1.11.0.tgz#9c80e538c12d3fb95c8d9bb9559fa0cc040405fd" + dependencies: + character-parser "1.2.1" + clean-css "^3.1.9" + commander "~2.6.0" + constantinople "~3.0.1" jstransformer "0.0.2" mkdirp "~0.5.0" transformers "2.1.0" @@ -5315,6 +5873,294 @@ jeet@*: version "7.2.0" resolved "https://registry.yarnpkg.com/jeet/-/jeet-7.2.0.tgz#2aa562a2dc1d74cc99527113f16a821e974e30ee" +jest-changed-files@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83" + dependencies: + throat "^4.0.0" + +jest-cli@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.4.2.tgz#49d56bcfe6cf01871bfcc4a0494e08edaf2b61d0" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.1" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.1.11" + import-local "^1.0.0" + is-ci "^1.0.10" + istanbul-api "^1.3.1" + istanbul-lib-coverage "^1.2.0" + istanbul-lib-instrument "^1.10.1" + istanbul-lib-source-maps "^1.2.4" + jest-changed-files "^23.4.2" + jest-config "^23.4.2" + jest-environment-jsdom "^23.4.0" + jest-get-type "^22.1.0" + jest-haste-map "^23.4.1" + jest-message-util "^23.4.0" + jest-regex-util "^23.3.0" + jest-resolve-dependencies "^23.4.2" + jest-runner "^23.4.2" + jest-runtime "^23.4.2" + jest-snapshot "^23.4.2" + jest-util "^23.4.0" + jest-validate "^23.4.0" + jest-watcher "^23.4.0" + jest-worker "^23.2.0" + micromatch "^2.3.11" + node-notifier "^5.2.1" + prompts "^0.1.9" + realpath-native "^1.0.0" + rimraf "^2.5.4" + slash "^1.0.0" + string-length "^2.0.0" + strip-ansi "^4.0.0" + which "^1.2.12" + yargs "^11.0.0" + +jest-config@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.4.2.tgz#62a105e14b8266458f2bf4d32403b2c44418fa77" + dependencies: + babel-core "^6.0.0" + babel-jest "^23.4.2" + chalk "^2.0.1" + glob "^7.1.1" + jest-environment-jsdom "^23.4.0" + jest-environment-node "^23.4.0" + jest-get-type "^22.1.0" + jest-jasmine2 "^23.4.2" + jest-regex-util "^23.3.0" + jest-resolve "^23.4.1" + jest-util "^23.4.0" + jest-validate "^23.4.0" + pretty-format "^23.2.0" + +jest-diff@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.2.0.tgz#9f2cf4b51e12c791550200abc16b47130af1062a" + dependencies: + chalk "^2.0.1" + diff "^3.2.0" + jest-get-type "^22.1.0" + pretty-format "^23.2.0" + +jest-docblock@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7" + dependencies: + detect-newline "^2.1.0" + +jest-each@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.4.0.tgz#2fa9edd89daa1a4edc9ff9bf6062a36b71345143" + dependencies: + chalk "^2.0.1" + pretty-format "^23.2.0" + +jest-environment-jsdom@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023" + dependencies: + jest-mock "^23.2.0" + jest-util "^23.4.0" + jsdom "^11.5.1" + +jest-environment-node@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10" + dependencies: + jest-mock "^23.2.0" + jest-util "^23.4.0" + +jest-get-type@^22.1.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" + +jest-haste-map@^23.4.1: + version "23.4.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.4.1.tgz#43a174ba7ac079ae1dd74eaf5a5fe78989474dd2" + dependencies: + fb-watchman "^2.0.0" + graceful-fs "^4.1.11" + jest-docblock "^23.2.0" + jest-serializer "^23.0.1" + jest-worker "^23.2.0" + micromatch "^2.3.11" + sane "^2.0.0" + +jest-jasmine2@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.4.2.tgz#2fbf52f93e43ed4c5e7326a90bb1d785be4321ac" + dependencies: + babel-traverse "^6.0.0" + chalk "^2.0.1" + co "^4.6.0" + expect "^23.4.0" + is-generator-fn "^1.0.0" + jest-diff "^23.2.0" + jest-each "^23.4.0" + jest-matcher-utils "^23.2.0" + jest-message-util "^23.4.0" + jest-snapshot "^23.4.2" + jest-util "^23.4.0" + pretty-format "^23.2.0" + +jest-leak-detector@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.2.0.tgz#c289d961dc638f14357d4ef96e0431ecc1aa377d" + dependencies: + pretty-format "^23.2.0" + +jest-matcher-utils@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.2.0.tgz#4d4981f23213e939e3cedf23dc34c747b5ae1913" + dependencies: + chalk "^2.0.1" + jest-get-type "^22.1.0" + pretty-format "^23.2.0" + +jest-message-util@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f" + dependencies: + "@babel/code-frame" "^7.0.0-beta.35" + chalk "^2.0.1" + micromatch "^2.3.11" + slash "^1.0.0" + stack-utils "^1.0.1" + +jest-mock@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134" + +jest-regex-util@^23.3.0: + version "23.3.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5" + +jest-resolve-dependencies@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.4.2.tgz#0675ba876a5b819deffc449ad72e9985c2592048" + dependencies: + jest-regex-util "^23.3.0" + jest-snapshot "^23.4.2" + +jest-resolve@^23.4.1: + version "23.4.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.4.1.tgz#7f3c17104732a2c0c940a01256025ed745814982" + dependencies: + browser-resolve "^1.11.3" + chalk "^2.0.1" + realpath-native "^1.0.0" + +jest-runner@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.4.2.tgz#579a88524ac52c846075b0129a21c7b483e75a7e" + dependencies: + exit "^0.1.2" + graceful-fs "^4.1.11" + jest-config "^23.4.2" + jest-docblock "^23.2.0" + jest-haste-map "^23.4.1" + jest-jasmine2 "^23.4.2" + jest-leak-detector "^23.2.0" + jest-message-util "^23.4.0" + jest-runtime "^23.4.2" + jest-util "^23.4.0" + jest-worker "^23.2.0" + source-map-support "^0.5.6" + throat "^4.0.0" + +jest-runtime@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.4.2.tgz#00c3bb8385253d401a394a27d1112d3615e5a65c" + dependencies: + babel-core "^6.0.0" + babel-plugin-istanbul "^4.1.6" + chalk "^2.0.1" + convert-source-map "^1.4.0" + exit "^0.1.2" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.1.11" + jest-config "^23.4.2" + jest-haste-map "^23.4.1" + jest-message-util "^23.4.0" + jest-regex-util "^23.3.0" + jest-resolve "^23.4.1" + jest-snapshot "^23.4.2" + jest-util "^23.4.0" + jest-validate "^23.4.0" + micromatch "^2.3.11" + realpath-native "^1.0.0" + slash "^1.0.0" + strip-bom "3.0.0" + write-file-atomic "^2.1.0" + yargs "^11.0.0" + +jest-serializer@^23.0.1: + version "23.0.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165" + +jest-snapshot@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.4.2.tgz#8fa6130feb5a527dac73e5fa80d86f29f7c42ab6" + dependencies: + babel-types "^6.0.0" + chalk "^2.0.1" + jest-diff "^23.2.0" + jest-matcher-utils "^23.2.0" + jest-message-util "^23.4.0" + jest-resolve "^23.4.1" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + pretty-format "^23.2.0" + semver "^5.5.0" + +jest-util@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561" + dependencies: + callsites "^2.0.0" + chalk "^2.0.1" + graceful-fs "^4.1.11" + is-ci "^1.0.10" + jest-message-util "^23.4.0" + mkdirp "^0.5.1" + slash "^1.0.0" + source-map "^0.6.0" + +jest-validate@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.4.0.tgz#d96eede01ef03ac909c009e9c8e455197d48c201" + dependencies: + chalk "^2.0.1" + jest-get-type "^22.1.0" + leven "^2.1.0" + pretty-format "^23.2.0" + +jest-watcher@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.1" + string-length "^2.0.0" + +jest-worker@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9" + dependencies: + merge-stream "^1.0.1" + +jest@^23.4.2: + version "23.4.2" + resolved "https://registry.yarnpkg.com/jest/-/jest-23.4.2.tgz#1fae3ed832192143070ae85156b25cea891a1260" + dependencies: + import-local "^1.0.0" + jest-cli "^23.4.2" + jquery.finger@*: version "0.1.6" resolved "https://registry.yarnpkg.com/jquery.finger/-/jquery.finger-0.1.6.tgz#24a481103c28ff73eebef3e39328403770eed0fa" @@ -5343,7 +6189,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.4.3, js-yaml@^3.9.0: +js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: @@ -5411,6 +6257,37 @@ jsdom@^0.11.0: request "2.x" xmlhttprequest ">=1.5.0" +jsdom@^11.5.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" + dependencies: + abab "^2.0.0" + acorn "^5.5.3" + acorn-globals "^4.1.0" + array-equal "^1.0.0" + cssom ">= 0.3.2 < 0.4.0" + cssstyle "^1.0.0" + data-urls "^1.0.0" + domexception "^1.0.1" + escodegen "^1.9.1" + html-encoding-sniffer "^1.0.2" + left-pad "^1.3.0" + nwsapi "^2.0.7" + parse5 "4.0.0" + pn "^1.1.0" + request "^2.87.0" + request-promise-native "^1.0.5" + sax "^1.2.4" + symbol-tree "^3.2.2" + tough-cookie "^2.3.4" + w3c-hr-time "^1.0.1" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.3" + whatwg-mimetype "^2.1.0" + whatwg-url "^6.4.1" + ws "^5.2.0" + xml-name-validator "^3.0.0" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -5518,7 +6395,7 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" -kind-of@^3.0.2: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -5530,6 +6407,18 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +kleur@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.1.tgz#7cc64b0d188d0dcbc98bdcdfdda2cc10619ddce8" + knox@caremerge/knox.git#b1e031c209b3c17cab622a458e87728c1ee88cbd: version "0.9.2" resolved "https://codeload.github.com/caremerge/knox/tar.gz/b1e031c209b3c17cab622a458e87728c1ee88cbd" @@ -5558,6 +6447,14 @@ left-pad@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee" +left-pad@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" + +leven@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -5565,6 +6462,16 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -5801,6 +6708,22 @@ make-error@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + dependencies: + tmpl "1.0.x" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + markdown-loader@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-2.0.2.tgz#1cdcf11307658cd611046d7db34c2fe80542af7c" @@ -5856,6 +6779,16 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + dependencies: + readable-stream "^2.0.1" + +merge@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" + methods@^1.1.1, methods@~1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -5878,6 +6811,24 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" +micromatch@^3.1.4, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -5970,7 +6921,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.2.0: +minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -5978,6 +6929,19 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + mississippi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" @@ -5993,11 +6957,18 @@ mississippi@^2.0.0: stream-each "^1.1.0" through2 "^2.0.0" +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -6116,6 +7087,26 @@ nan@^2.1.0, nan@^2.3.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -6132,6 +7123,14 @@ ncp@0.4.x: version "0.4.2" resolved "https://registry.yarnpkg.com/ncp/-/ncp-0.4.2.tgz#abcc6cbd3ec2ed2a729ff6e7c1fa8f01784a8574" +needle@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -6171,6 +7170,10 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + node-libs-browser@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" @@ -6199,7 +7202,7 @@ node-libs-browser@^2.0.0: util "^0.10.3" vm-browserify "0.0.4" -node-notifier@^5.1.2: +node-notifier@^5.1.2, node-notifier@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" dependencies: @@ -6208,6 +7211,21 @@ node-notifier@^5.1.2: shellwords "^0.1.1" which "^1.3.0" +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-pre-gyp@^0.6.39: version "0.6.39" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" @@ -6240,7 +7258,7 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.0, normalize-path@^2.0.1: +normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: @@ -6267,6 +7285,17 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.11" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6315,6 +7344,10 @@ nwmatcher@~1.3.2: version "1.3.9" resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a" +nwsapi@^2.0.7: + version "2.0.8" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.8.tgz#e3603579b7e162b3dbedae4fb24e46f771d8fa24" + oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -6327,10 +7360,24 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-keys@^1.0.11, object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + object.assign@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" @@ -6363,6 +7410,12 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + object.values@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" @@ -6413,19 +7466,19 @@ optimist@0.6.0: minimist "~0.0.1" wordwrap "~0.0.2" -optimist@~0.3.5: - version "0.3.7" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" - dependencies: - wordwrap "~0.0.2" - -optimist@~0.6.0: +optimist@^0.6.1, optimist@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: minimist "~0.0.1" wordwrap "~0.0.2" +optimist@~0.3.5: + version "0.3.7" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" + dependencies: + wordwrap "~0.0.2" + optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -6595,6 +7648,10 @@ parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + passport-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" @@ -6652,6 +7709,14 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" @@ -6740,6 +7805,10 @@ pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + postcss-calc@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" @@ -7046,6 +8115,13 @@ pretty-error@^2.0.2: renderkid "^2.0.1" utila "~0.4" +pretty-format@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.2.0.tgz#3b0aaa63c018a53583373c1cb3a5d96cc5e83017" + dependencies: + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" + prettyjson@^1.1.2: version "1.2.1" resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" @@ -7053,7 +8129,7 @@ prettyjson@^1.1.2: colors "^1.1.2" minimist "^1.2.0" -private@^0.1.6, private@^0.1.7, private@~0.1.5: +private@^0.1.6, private@^0.1.7, private@^0.1.8, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -7129,6 +8205,13 @@ prompt@0.2.14: utile "0.2.x" winston "0.8.x" +prompts@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.13.tgz#7fad7ee1c6cafe49834ca0b2a6a471262de57620" + dependencies: + kleur "^2.0.1" + sisteransi "^0.1.1" + prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.5.9, prop-types@^15.6.1: version "15.6.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" @@ -7177,6 +8260,10 @@ pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +psl@^1.1.24: + version "1.1.29" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" + public-encrypt@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" @@ -7420,6 +8507,15 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-apollo@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-2.1.6.tgz#13be92689009eda9023948c78532f4102cbc3d57" @@ -7635,6 +8731,13 @@ react@^16.3.0: object-assign "^4.1.1" prop-types "^15.6.0" +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" @@ -7642,6 +8745,14 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" @@ -7716,6 +8827,12 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" +realpath-native@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.1.tgz#07f40a0cce8f8261e2e8b7ebebf5c95965d7b633" + dependencies: + util.promisify "^1.0.0" + recast@^0.12.6: version "0.12.9" resolved "https://registry.yarnpkg.com/recast/-/recast-0.12.9.tgz#e8e52bdb9691af462ccbd7c15d5a5113647a15f1" @@ -7821,6 +8938,13 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + regexp.prototype.flags@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" @@ -7875,7 +8999,7 @@ repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" -repeat-string@^1.5.2: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" @@ -7953,6 +9077,31 @@ request@2.x, request@^2.61.0, request@^2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" +request@^2.87.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -7984,6 +9133,12 @@ reselect@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + dependencies: + resolve-from "^3.0.0" + resolve-dir@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" @@ -7999,10 +9154,22 @@ resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + resolve-pathname@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + resolve@^1.1.6, resolve@^1.1.7, resolve@^1.4.0, resolve@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" @@ -8028,6 +9195,10 @@ resumer@~0.0.0: dependencies: through "~2.3.4" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + revalidator@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" @@ -8060,6 +9231,10 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^2.0.0" inherits "^2.0.1" +rsvp@^3.3.3: + version "3.6.2" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -8094,6 +9269,16 @@ safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +safe-buffer@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -8102,6 +9287,21 @@ samsam@1.x: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" +sane@^2.0.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" + dependencies: + anymatch "^2.0.0" + capture-exit "^1.2.0" + exec-sh "^0.2.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + watch "~0.18.0" + optionalDependencies: + fsevents "^1.2.3" + sax@0.5.x: version "0.5.8" resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" @@ -8127,7 +9327,7 @@ scroll-frame@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scroll-frame/-/scroll-frame-1.0.0.tgz#f562eb69d7ece50a06466f0e3cb2ef7bc3713b27" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -8217,6 +9417,24 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -8342,6 +9560,10 @@ sinon@*: supports-color "^5.1.0" type-detect "^4.0.5" +sisteransi@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -8352,6 +9574,33 @@ slice-ansi@1.0.0: dependencies: is-fullwidth-code-point "^2.0.0" +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -8395,19 +9644,40 @@ 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-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: source-map "^0.5.6" +source-map-support@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + source-map@0.1.x, source-map@~0.1.7: version "0.1.43" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" dependencies: amdefine ">=0.0.4" -source-map@0.4.x: +source-map@0.4.x, source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: @@ -8417,11 +9687,11 @@ source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.6: +source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" -source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -8445,6 +9715,12 @@ 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" +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + sprintf-js@^1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" @@ -8477,6 +9753,10 @@ stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" +stack-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" + stackframe@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-0.3.1.tgz#33aa84f1177a5548c8935533cbfeb3420975f5a4" @@ -8485,6 +9765,13 @@ stackframe@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + "statuses@>= 1.3.1 < 2", statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -8497,6 +9784,12 @@ stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" +storybook-react-router@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/storybook-react-router/-/storybook-react-router-1.0.1.tgz#a33af1cb0c16f0e755f420296352c8f8709cb674" + dependencies: + prop-types "^15.6.1" + stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -8547,6 +9840,13 @@ string-length@^1.0.1: dependencies: strip-ansi "^3.0.0" +string-length@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" + dependencies: + astral-regex "^1.0.0" + strip-ansi "^4.0.0" + string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -8620,10 +9920,16 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-bom@^3.0.0: +strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -8731,7 +10037,7 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.2.3: +supports-color@^3.1.2, supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: @@ -8838,6 +10144,28 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +tar@^4: + version "4.4.6" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +test-exclude@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" + dependencies: + arrify "^1.0.1" + micromatch "^3.1.8" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + text-encoding@^0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" @@ -8846,6 +10174,10 @@ text-table@0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +throat@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + throng@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/throng/-/throng-4.0.0.tgz#983c6ba1993b58eae859998aa687ffe88df84c17" @@ -8887,6 +10219,10 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -8903,6 +10239,28 @@ to-iso-string@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + toggle-selection@^1.0.3: version "1.0.6" resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" @@ -8925,7 +10283,14 @@ tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.0, tough-cookie@~2. dependencies: punycode "^1.4.1" -tr46@^1.0.0: +tough-cookie@^2.3.4: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tr46@^1.0.0, tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" dependencies: @@ -9003,7 +10368,7 @@ uglify-js@3.3.x: commander "~2.15.0" source-map "~0.6.1" -uglify-js@^2.4.19, uglify-js@^2.6.1, uglify-js@^2.6.2, uglify-js@^2.8.29: +uglify-js@^2.4.19, uglify-js@^2.6, uglify-js@^2.6.1, uglify-js@^2.6.2, uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: @@ -9071,6 +10436,15 @@ underscore@*, underscore@>=1.8.3, underscore@^1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" @@ -9095,6 +10469,13 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" @@ -9105,6 +10486,10 @@ uri-js@^4.2.1: dependencies: punycode "^2.1.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + url-join@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728" @@ -9141,10 +10526,21 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" +util.promisify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + util@0.10.3, util@^0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" @@ -9238,12 +10634,25 @@ w3c-hr-time@^1.0.1: dependencies: browser-process-hrtime "^0.1.2" +walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + dependencies: + makeerror "1.0.x" + warning@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" dependencies: loose-envify "^1.0.0" +watch@~0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" + dependencies: + exec-sh "^0.2.0" + minimist "^1.2.0" + watchpack@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" @@ -9372,6 +10781,10 @@ whatwg-fetch@>=0.10.0: version "2.0.4" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" +whatwg-mimetype@^2.0.0, whatwg-mimetype@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" + whatwg-url@^6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.4.0.tgz#08fdf2b9e872783a7a1f6216260a1d66cc722e08" @@ -9380,6 +10793,14 @@ whatwg-url@^6.4.0: tr46 "^1.0.0" webidl-conversions "^4.0.1" +whatwg-url@^6.4.1: + version "6.5.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" @@ -9388,7 +10809,7 @@ which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" -which@^1.2.14: +which@^1.2.12, which@^1.2.14: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: @@ -9480,6 +10901,14 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +write-file-atomic@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -9494,6 +10923,12 @@ ws@^4.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" +ws@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + dependencies: + async-limiter "~1.0.0" + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -9540,6 +10975,10 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"