Merge pull request #17 from sharetribe/auth-pages

Auth forms
This commit is contained in:
Kimmo Puputti 2017-01-25 13:10:19 +02:00 committed by GitHub
commit 1fe434bbda
34 changed files with 628 additions and 48 deletions

View file

@ -18,6 +18,8 @@
"react-router": "4.0.0-alpha.6",
"react-test-renderer": "^15.4.2",
"redux": "^3.6.0",
"redux-form": "^6.4.3",
"sanitize.css": "^4.1.0",
"sharetribe-scripts": "0.8.6",
"source-map-support": "^0.4.10"
},

View file

@ -48,7 +48,6 @@ const MatchWithSubRoutes = props => {
);
};
/* eslint-enable arrow-body-style */
MatchWithSubRoutes.defaultProps = { auth: false, exactly: false };
const { any, array, bool, func, node, oneOfType, string } = PropTypes;

View file

@ -1,13 +0,0 @@
import Hello from './Hello';
export const HelloWorld = {
component: Hello,
description: 'Hello to world',
props: { name: 'world' },
};
export const HelloMars = {
component: Hello,
description: 'Hello to mars',
props: { name: 'mars' },
};

View file

@ -1,9 +0,0 @@
import React, { PropTypes } from 'react';
const Hello = ({ name }) => <p>hello, {name}!</p>;
const { string } = PropTypes;
Hello.propTypes = { name: string.isRequired };
export default Hello;

View file

@ -1,4 +0,0 @@
/* eslint-disable import/prefer-default-export*/
import * as Hello from './Hello/Hello.example';
export { Hello };

View file

@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import NamedLink from './NamedLink/NamedLink';
import PageLayout from './PageLayout/PageLayout';
import RouterProvider from './RouterProvider/RouterProvider';

View file

@ -0,0 +1,11 @@
/* eslint-disable no-console, import/prefer-default-export */
import ChangeAccountPasswordForm from './ChangeAccountPasswordForm';
export const Empty = {
component: ChangeAccountPasswordForm,
props: {
onSubmit(values) {
console.log('submit new password form values:', values);
},
},
};

View file

@ -0,0 +1,24 @@
import React from 'react';
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
const ChangeAccountPasswordForm = props => {
const { handleSubmit, pristine, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" />
<label htmlFor="newPassword1">New password</label>
<Field name="newPassword1" component="input" type="password" />
<label htmlFor="newPassword2">New password, again</label>
<Field name="newPassword2" component="input" type="password" />
<label htmlFor="password">Current password</label>
<Field name="password" component="input" type="password" />
<p>Delete account (module)</p>
<button type="submit" disabled={pristine || submitting}>Save changes</button>
</form>
);
};
ChangeAccountPasswordForm.propTypes = { ...formPropTypes };
export default reduxForm({ form: 'changeAccountPassword' })(ChangeAccountPasswordForm)

View file

@ -0,0 +1,20 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { Provider } from 'react-redux';
import configureStore from '../../store';
import ChangeAccountPasswordForm from './ChangeAccountPasswordForm';
describe('ChangeAccountPasswordForm', () => {
it('matches snapshot', () => {
const store = configureStore();
const component = renderer.create(
(
<Provider store={store}>
<ChangeAccountPasswordForm />
</Provider>
),
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View file

@ -0,0 +1,65 @@
exports[`ChangeAccountPasswordForm matches snapshot 1`] = `
<form
onSubmit={[Function]}>
<label
htmlFor="email">
Email
</label>
<input
name="email"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="email"
value="" />
<label
htmlFor="newPassword1">
New password
</label>
<input
name="newPassword1"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<label
htmlFor="newPassword2">
New password, again
</label>
<input
name="newPassword2"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<label
htmlFor="password">
Current password
</label>
<input
name="password"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<p>
Delete account (module)
</p>
<button
disabled={true}
type="submit">
Save changes
</button>
</form>
`;

View file

@ -0,0 +1,11 @@
/* eslint-disable no-console, import/prefer-default-export */
import ChangePasswordForm from './ChangePasswordForm';
export const Empty = {
component: ChangePasswordForm,
props: {
onSubmit(values) {
console.log('submit new password form values:', values);
},
},
};

View file

@ -0,0 +1,23 @@
import React from 'react';
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
const ChangePasswordForm = props => {
const { handleSubmit, pristine, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" />
<label htmlFor="newPassword1">New password</label>
<Field name="newPassword1" component="input" type="password" />
<label htmlFor="newPassword2">New password, again</label>
<Field name="newPassword2" component="input" type="password" />
<label htmlFor="password">Current password</label>
<Field name="password" component="input" type="password" />
<button type="submit" disabled={pristine || submitting}>Change password</button>
</form>
);
};
ChangePasswordForm.propTypes = { ...formPropTypes };
export default reduxForm({ form: 'changePassword' })(ChangePasswordForm)

View file

@ -0,0 +1,20 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { Provider } from 'react-redux';
import configureStore from '../../store';
import ChangePasswordForm from './ChangePasswordForm';
describe('ChangePasswordForm', () => {
it('matches snapshot', () => {
const store = configureStore();
const component = renderer.create(
(
<Provider store={store}>
<ChangePasswordForm />
</Provider>
),
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View file

@ -0,0 +1,62 @@
exports[`ChangePasswordForm matches snapshot 1`] = `
<form
onSubmit={[Function]}>
<label
htmlFor="email">
Email
</label>
<input
name="email"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="email"
value="" />
<label
htmlFor="newPassword1">
New password
</label>
<input
name="newPassword1"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<label
htmlFor="newPassword2">
New password, again
</label>
<input
name="newPassword2"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<label
htmlFor="password">
Current password
</label>
<input
name="password"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<button
disabled={true}
type="submit">
Change password
</button>
</form>
`;

View file

@ -0,0 +1,11 @@
/* eslint-disable no-console, import/prefer-default-export */
import LoginForm from './LoginForm';
export const Empty = {
component: LoginForm,
props: {
onSubmit(values) {
console.log('log in with form values:', values);
},
},
};

View file

@ -0,0 +1,20 @@
import React from 'react';
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
const LoginForm = props => {
const { handleSubmit, pristine, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" />
<label htmlFor="password">Password</label>
<Field name="password" component="input" type="password" />
<p>Forgot password?</p>
<button type="submit" disabled={pristine || submitting}>Log in</button>
</form>
);
};
LoginForm.propTypes = { ...formPropTypes };
export default reduxForm({ form: 'login' })(LoginForm)

View file

@ -0,0 +1,20 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { Provider } from 'react-redux';
import configureStore from '../../store';
import LoginForm from './LoginForm';
describe('LoginForm', () => {
it('matches snapshot', () => {
const store = configureStore();
const component = renderer.create(
(
<Provider store={store}>
<LoginForm />
</Provider>
),
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View file

@ -0,0 +1,39 @@
exports[`LoginForm matches snapshot 1`] = `
<form
onSubmit={[Function]}>
<label
htmlFor="email">
Email
</label>
<input
name="email"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="email"
value="" />
<label
htmlFor="password">
Password
</label>
<input
name="password"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<p>
Forgot password?
</p>
<button
disabled={true}
type="submit">
Log in
</button>
</form>
`;

View file

@ -0,0 +1,11 @@
/* eslint-disable no-console, import/prefer-default-export */
import PasswordForgottenForm from './PasswordForgottenForm';
export const Empty = {
component: PasswordForgottenForm,
props: {
onSubmit(values) {
console.log('submit forgotten password email:', values);
},
},
};

View file

@ -0,0 +1,18 @@
import React from 'react';
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
const PasswordForgottenForm = props => {
const { handleSubmit, pristine, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" />
<p>We will send you instructions to your email.</p>
<button type="submit" disabled={pristine || submitting}>Send</button>
</form>
);
};
PasswordForgottenForm.propTypes = { ...formPropTypes };
export default reduxForm({ form: 'passwordForgotten' })(PasswordForgottenForm)

View file

@ -0,0 +1,20 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { Provider } from 'react-redux';
import configureStore from '../../store';
import PasswordForgottenForm from './PasswordForgottenForm';
describe('PasswordForgottenForm', () => {
it('matches snapshot', () => {
const store = configureStore();
const component = renderer.create(
(
<Provider store={store}>
<PasswordForgottenForm />
</Provider>
),
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View file

@ -0,0 +1,26 @@
exports[`PasswordForgottenForm matches snapshot 1`] = `
<form
onSubmit={[Function]}>
<label
htmlFor="email">
Email
</label>
<input
name="email"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="email"
value="" />
<p>
We will send you instructions to your email.
</p>
<button
disabled={true}
type="submit">
Send
</button>
</form>
`;

View file

@ -0,0 +1,11 @@
/* eslint-disable no-console, import/prefer-default-export */
import SignUpForm from './SignUpForm';
export const Empty = {
component: SignUpForm,
props: {
onSubmit(values) {
console.log('sign up with form values:', values);
},
},
};

View file

@ -0,0 +1,24 @@
import React from 'react';
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
const SignUpForm = props => {
const { handleSubmit, pristine, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" />
<label htmlFor="firstName">First name</label>
<Field name="firstName" component="input" />
<label htmlFor="lastName">Last name</label>
<Field name="lastName" component="input" />
<label htmlFor="password">Password</label>
<Field name="password" component="input" type="password" />
<p>By confirming I accept the booking terms and conditions.</p>
<button type="submit" disabled={pristine || submitting}>Sign up</button>
</form>
);
};
SignUpForm.propTypes = { ...formPropTypes };
export default reduxForm({ form: 'signup' })(SignUpForm)

View file

@ -0,0 +1,20 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { Provider } from 'react-redux';
import configureStore from '../../store';
import SignUpForm from './SignUpForm';
describe('SignUpForm', () => {
it('matches snapshot', () => {
const store = configureStore();
const component = renderer.create(
(
<Provider store={store}>
<SignUpForm />
</Provider>
),
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View file

@ -0,0 +1,63 @@
exports[`SignUpForm matches snapshot 1`] = `
<form
onSubmit={[Function]}>
<label
htmlFor="email">
Email
</label>
<input
name="email"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="email"
value="" />
<label
htmlFor="firstName">
First name
</label>
<input
name="firstName"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
value="" />
<label
htmlFor="lastName">
Last name
</label>
<input
name="lastName"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
value="" />
<label
htmlFor="password">
Password
</label>
<input
name="password"
onBlur={[Function]}
onChange={[Function]}
onDragStart={[Function]}
onDrop={[Function]}
onFocus={[Function]}
type="password"
value="" />
<p>
By confirming I accept the booking terms and conditions.
</p>
<button
disabled={true}
type="submit">
Sign up
</button>
</form>
`;

View file

@ -1,6 +1,3 @@
.root {
& ul {
list-style: none;
padding: 0;
}
padding: 1rem;
}

View file

@ -1,7 +1,7 @@
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import { map, size } from 'lodash';
import * as allExamples from '../../components/examples';
import * as allExamples from '../../examples';
import css from './StyleguidePage.css';

View file

@ -1,41 +1,51 @@
import AuthenticationPage from './AuthenticationPage/AuthenticationPage';
import ChangeAccountPasswordForm from './ChangeAccountPasswordForm/ChangeAccountPasswordForm';
import ChangePasswordForm from './ChangePasswordForm/ChangePasswordForm';
import CheckoutPage from './CheckoutPage/CheckoutPage';
import ContactDetailsPage from './ContactDetailsPage/ContactDetailsPage';
import EditProfilePage from './EditProfilePage/EditProfilePage';
import InboxPage from './InboxPage/InboxPage';
import LandingPage from './LandingPage/LandingPage';
import ListingPage from './ListingPage/ListingPage';
import LoginForm from './LoginForm/LoginForm';
import ManageListingsPage from './ManageListingsPage/ManageListingsPage';
import NotFoundPage from './NotFoundPage/NotFoundPage';
import OrderPage from './OrderPage/OrderPage';
import PasswordChangePage from './PasswordChangePage/PasswordChangePage';
import PasswordForgottenForm from './PasswordForgottenForm/PasswordForgottenForm';
import PasswordForgottenPage from './PasswordForgottenPage/PasswordForgottenPage';
import PayoutPreferencesPage from './PayoutPreferencesPage/PayoutPreferencesPage';
import ProfilePage from './ProfilePage/ProfilePage';
import SalesConversationPage from './SalesConversationPage/SalesConversationPage';
import SearchPage from './SearchPage/SearchPage';
import SecurityPage from './SecurityPage/SecurityPage';
import SignUpForm from './SignUpForm/SignUpForm';
import StyleguidePage from './StyleguidePage/StyleguidePage';
import Topbar from './Topbar/Topbar';
export {
AuthenticationPage,
ChangeAccountPasswordForm,
ChangePasswordForm,
CheckoutPage,
ContactDetailsPage,
EditProfilePage,
InboxPage,
LandingPage,
ListingPage,
LoginForm,
ManageListingsPage,
NotFoundPage,
OrderPage,
PasswordChangePage,
PasswordForgottenForm,
PasswordForgottenPage,
PayoutPreferencesPage,
ProfilePage,
SalesConversationPage,
SearchPage,
SecurityPage,
SignUpForm,
StyleguidePage,
Topbar,
};

View file

@ -4,6 +4,7 @@
* https://github.com/erikras/ducks-modular-redux
*/
import { reducer as formReducer } from 'redux-form';
import FlashNotification from './FlashNotification.ducks';
export { FlashNotification }; // eslint-disable-line import/prefer-default-export
export { formReducer as form, FlashNotification };

13
src/examples.js Normal file
View file

@ -0,0 +1,13 @@
import * as ChangeAccountPasswordForm from './containers/ChangeAccountPasswordForm/ChangeAccountPasswordForm.example';
import * as ChangePasswordForm from './containers/ChangePasswordForm/ChangePasswordForm.example';
import * as LoginForm from './containers/LoginForm/LoginForm.example';
import * as PasswordForgottenForm from './containers/PasswordForgottenForm/PasswordForgottenForm.example';
import * as SignUpForm from './containers/SignUpForm/SignUpForm.example';
export {
ChangeAccountPasswordForm,
ChangePasswordForm,
LoginForm,
PasswordForgottenForm,
SignUpForm,
};

View file

@ -1,5 +1,46 @@
body {
margin: 0;
@import "sanitize.css";
ul {
list-style: none;
padding: 0;
font-family: sans-serif;
}
label {
display: block;
font-weight: bold;
margin-top: 1rem;
}
input {
display: block;
width: 100%;
font-size: 1.4rem;
border: 1px solid #ddd;
}
button {
display: block;
width: 100%;
font-size: 1.4rem;
padding: 0.5rem;
margin: 1rem 0;
background-color: #eee;
border: 1px solid #ddd;
cursor: pointer;
&:hover {
background-color: #ddd;
}
&:active {
background-color: #ccc;
}
&:disabled {
cursor: auto;
color: #aaa;
&:hover,
&:active {
background-color: #eee;
}
}
}

View file

@ -197,12 +197,7 @@ const routesConfiguration = [
},
],
},
{
pattern: '/styleguide',
exactly: true,
name: 'Styleguide',
component: StyleguidePage,
},
{ pattern: '/styleguide', exactly: true, name: 'Styleguide', component: StyleguidePage },
{
pattern: '/styleguide/:component',
exactly: true,

View file

@ -136,6 +136,10 @@ array-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
array-findindex-polyfill@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/array-findindex-polyfill/-/array-findindex-polyfill-0.1.0.tgz#c362665bec7645f22d7a3c3aac9793f71c3622ef"
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@ -1645,7 +1649,7 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
deep-equal@1.0.1:
deep-equal@1.0.1, deep-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
@ -1872,6 +1876,10 @@ es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.
es6-iterator "2"
es6-symbol "~3.1"
es6-error@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.0.1.tgz#eeb3e280f57e2ec48d72a9fccaf6247d3c1f5719"
es6-iterator@2:
version "2.0.0"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac"
@ -2632,7 +2640,7 @@ hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
hoist-non-react-statics@^1.0.3:
hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
@ -2849,7 +2857,7 @@ intl-relativeformat@^1.3.0:
dependencies:
intl-messageformat "1.3.0"
invariant@^2.0.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1:
invariant@^2.0.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies:
@ -2998,6 +3006,10 @@ is-primitive@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
is-promise@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
is-property@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
@ -3499,7 +3511,7 @@ loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.
json5 "^0.5.0"
object-assign "^4.0.1"
lodash-es@^4.2.0, lodash-es@^4.2.1:
lodash-es@^4.17.3, lodash-es@^4.2.0, lodash-es@^4.2.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
@ -3648,7 +3660,7 @@ lodash.uniq@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.14.0, lodash@^4.16.2, lodash@^4.16.4, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.14.0, lodash@^4.16.2, lodash@^4.16.4, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@ -5081,6 +5093,20 @@ reduce-function-call@^1.0.1:
dependencies:
balanced-match "^0.4.2"
redux-form@^6.4.3:
version "6.4.3"
resolved "https://registry.yarnpkg.com/redux-form/-/redux-form-6.4.3.tgz#bd83a77770d9805f7b595a4ff18f00fe4267d3c8"
dependencies:
array-findindex-polyfill "^0.1.0"
deep-equal "^1.0.1"
es6-error "^4.0.0"
hoist-non-react-statics "^1.2.0"
invariant "^2.2.2"
is-promise "^2.1.0"
lodash "^4.17.3"
lodash-es "^4.17.3"
shallowequal "^0.2.2"
redux@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-3.6.0.tgz#887c2b3d0b9bd86eca2be70571c27654c19e188d"
@ -5303,6 +5329,10 @@ sane@~1.4.1:
walker "~1.0.5"
watch "~0.10.0"
sanitize.css@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-4.1.0.tgz#0bafc3c513699f2fe8c7980c6d37edf21d3f5448"
sax@^1.1.4, sax@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"