Merge branch 'master' into tslib

This commit is contained in:
Anton Zinovyev 2019-10-14 21:59:47 +03:00 committed by GitHub
commit 317c81eba5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 1179 additions and 165 deletions

View File

@ -3,7 +3,7 @@ version: 2
refs:
container: &container
docker:
- image: node:12.9.1
- image: node:12.11.1
working_directory: ~/repo
steps:
- &Versions

View File

@ -1,3 +1,59 @@
# [12.5.0](https://github.com/streamich/react-use/compare/v12.4.0...v12.5.0) (2019-10-13)
### Features
* useList allow pushing multiple items ([#621](https://github.com/streamich/react-use/issues/621)) ([a624364](https://github.com/streamich/react-use/commit/a624364))
# [12.4.0](https://github.com/streamich/react-use/compare/v12.3.2...v12.4.0) (2019-10-12)
### Features
* useIntersection ([#652](https://github.com/streamich/react-use/issues/652)) ([d5f359f](https://github.com/streamich/react-use/commit/d5f359f))
## [12.3.2](https://github.com/streamich/react-use/compare/v12.3.1...v12.3.2) (2019-10-12)
### Bug Fixes
* improve use of refs in dependency lists ([#655](https://github.com/streamich/react-use/issues/655)) ([ed8e26d](https://github.com/streamich/react-use/commit/ed8e26d))
## [12.3.1](https://github.com/streamich/react-use/compare/v12.3.0...v12.3.1) (2019-10-10)
### Bug Fixes
* move [@types](https://github.com/types)/react-wait to dependencies, closes [#661](https://github.com/streamich/react-use/issues/661) ([#662](https://github.com/streamich/react-use/issues/662)) ([6bdd74e](https://github.com/streamich/react-use/commit/6bdd74e))
# [12.3.0](https://github.com/streamich/react-use/compare/v12.2.3...v12.3.0) (2019-10-07)
### Features
* reset util callback for useList ([#654](https://github.com/streamich/react-use/issues/654)) ([9ea3548](https://github.com/streamich/react-use/commit/9ea3548))
## [12.2.3](https://github.com/streamich/react-use/compare/v12.2.2...v12.2.3) (2019-10-05)
### Bug Fixes
* move react-wait types to dev dependencies, closes [#644](https://github.com/streamich/react-use/issues/644) ([49372ac](https://github.com/streamich/react-use/commit/49372ac))
## [12.2.2](https://github.com/streamich/react-use/compare/v12.2.1...v12.2.2) (2019-09-26)
### Bug Fixes
* useDebounce remove deps from function arguments ([#623](https://github.com/streamich/react-use/issues/623)) ([23d6a5a](https://github.com/streamich/react-use/commit/23d6a5a))
## [12.2.1](https://github.com/streamich/react-use/compare/v12.2.0...v12.2.1) (2019-09-23)
### Bug Fixes
* remove attempt from deps of retry in useAsyncRetry ([#614](https://github.com/streamich/react-use/issues/614)) ([adce59e](https://github.com/streamich/react-use/commit/adce59e))
# [12.2.0](https://github.com/streamich/react-use/compare/v12.1.0...v12.2.0) (2019-09-02)

View File

@ -49,6 +49,7 @@
- [`useGeolocation`](./docs/useGeolocation.md) — tracks geo location state of user's device. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usegeolocation--demo)
- [`useHover` and `useHoverDirty`](./docs/useHover.md) — tracks mouse hover state of some element. [![][img-demo]](https://codesandbox.io/s/zpn583rvx)
- [`useIdle`](./docs/useIdle.md) — tracks whether user is being inactive.
- [`useIntersection`](./docs/useIntersection.md) — tracks an HTML element's intersection. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-useintersection--demo)
- [`useKey`](./docs/useKey.md), [`useKeyPress`](./docs/useKeyPress.md), [`useKeyboardJs`](./docs/useKeyboardJs.md), and [`useKeyPressEvent`](./docs/useKeyPressEvent.md) — track keys. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usekeypressevent--demo)
- [`useLocation`](./docs/useLocation.md) and [`useSearchParam`](./docs/useSearchParam.md) — tracks page navigation bar location state.
- [`useMedia`](./docs/useMedia.md) — tracks state of a CSS media query. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemedia--demo)
@ -60,11 +61,11 @@
- [`usePageLeave`](./docs/usePageLeave.md) — triggers when mouse leaves page boundaries.
- [`useScroll`](./docs/useScroll.md) — tracks an HTML element's scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usescroll--docs)
- [`useScrolling`](./docs/useScrolling.md) — tracks whether HTML element is scrolling.
- [`useSize`](./docs/useSize.md) — tracks an HTML element's dimensions.
- [`useSize`](./docs/useSize.md) — tracks an HTML element's size.
- [`useStartTyping`](./docs/useStartTyping.md) — detects when user starts typing.
- [`useWindowScroll`](./docs/useWindowScroll.md) — tracks `Window` scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usewindowscroll--docs)
- [`useWindowSize`](./docs/useWindowSize.md) — tracks `Window` dimensions. [![][img-demo]](https://codesandbox.io/s/m7ln22668)
- [`useMeasure`](./docs/useMeasure.md) — tracks an HTML element's dimensions by [Resize Observer](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver).[![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemeasure--demo)
- [`useMeasure`](./docs/useMeasure.md) — tracks an HTML element's dimensions using the Resize Observer API.[![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemeasure--demo)
<br/>
<br/>
- [**UI**](./docs/UI.md)
@ -104,7 +105,7 @@
- [`useTitle`](./docs/useTitle.md) &mdash; sets title of the page.
- [`usePermission`](./docs/usePermission.md) &mdash; query permission status for browser APIs.
<br/>
<br/>
<br/>
- [**Lifecycles**](./docs/Lifecycles.md)
- [`useEffectOnce`](./docs/useEffectOnce.md) &mdash; a modified [`useEffect`](https://reactjs.org/docs/hooks-reference.html#useeffect) hook that only runs once.
- [`useEvent`](./docs/useEvent.md) &mdash; subscribe to events.
@ -125,15 +126,15 @@
- [`useDefault`](./docs/useDefault.md) &mdash; returns the default value when state is `null` or `undefined`.
- [`useGetSet`](./docs/useGetSet.md) &mdash; returns state getter `get()` instead of raw state.
- [`useGetSetState`](./docs/useGetSetState.md) &mdash; as if [`useGetSet`](./docs/useGetSet.md) and [`useSetState`](./docs/useSetState.md) had a baby.
- [`usePrevious`](./docs/usePrevious.md) &mdash; returns the previous state or props.
- [`usePrevious`](./docs/usePrevious.md) &mdash; returns the previous state or props. [![][img-demo]](https://codesandbox.io/s/fervent-galileo-krgx6)
- [`useObservable`](./docs/useObservable.md) &mdash; tracks latest value of an `Observable`.
- [`useSetState`](./docs/useSetState.md) &mdash; creates `setState` method which works like `this.setState`. [![][img-demo]](https://codesandbox.io/s/n75zqn1xp0)
- [`useStateList`](./docs/useStateList.md) &mdash; circularly iterates over an array.
- [`useToggle` and `useBoolean`](./docs/useToggle.md) &mdash; tracks state of a boolean.
- [`useStateList`](./docs/useStateList.md) &mdash; circularly iterates over an array. [![][img-demo]](https://codesandbox.io/s/bold-dewdney-pjzkd)
- [`useToggle` and `useBoolean`](./docs/useToggle.md) &mdash; tracks state of a boolean. [![][img-demo]](https://codesandbox.io/s/focused-sammet-brw2d)
- [`useCounter` and `useNumber`](./docs/useCounter.md) &mdash; tracks state of a number. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usecounter--demo)
- [`useList`](./docs/useList.md) &mdash; tracks state of an array.
- [`useMap`](./docs/useMap.md) &mdash; tracks state of an object.
- [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) &mdash; tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w)
- [`useMap`](./docs/useMap.md) &mdash; tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161)
- [`useStateValidator`](./docs/useStateValidator.md) &mdash; tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo)
<br />
<br />
@ -159,7 +160,6 @@
[img-demo]: https://img.shields.io/badge/demo-%20%20%20%F0%9F%9A%80-green.svg
<div align="center">
<h1>Contributors</h1>
</div>

36
docs/useIntersection.md Normal file
View File

@ -0,0 +1,36 @@
# `useIntersection`
React sensor hook that tracks the changes in the intersection of a target element with an ancestor element or with a top-level document's viewport. Uses the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) and returns a [IntersectionObserverEntry](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry).
## Usage
```jsx
import * as React from 'react';
import { useIntersection } from 'react-use';
const Demo = () => {
const intersectionRef = React.useRef(null);
const intersection = useIntersection(intersectionRef, {
root: null,
rootMargin: '0px',
threshold: 1
});
return (
<div ref={intersectionRef}>
{intersection && intersection.intersectionRatio < 1
? 'Obscured'
: 'Fully in view'}
</div>
);
};
```
## Reference
```ts
useIntersection(
ref: RefObject<HTMLElement>,
options: IntersectionObserverInit,
): IntersectionObserverEntry | null;
```

View File

@ -1,6 +1,6 @@
# `useInterval`
React hook that allow you using declarative `setInterval`.
A declarative interval hook based on [Dan Abramov's article on overreacted.io](https://overreacted.io/making-setinterval-declarative-with-react-hooks). The interval can be paused by setting the delay to `null`.
## Usage
@ -11,32 +11,31 @@ import {useInterval} from 'react-use';
const Demo = () => {
const [count, setCount] = React.useState(0);
const [delay, setDelay] = React.useState(1000);
const [isRunning, toggleIsRunning] = useBoolean(true);
useInterval(() => {
setCount(count + 1);
}, delay);
function handleDelayChange(e) {
setDelay(Number(e.target.value));
}
useInterval(
() => {
setCount(count + 1);
},
isRunning ? delay : null
);
return (
<div>
<div>
delay: <input value={delay} onChange={handleDelayChange} />
delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
</div>
<h1>count: {count}</h1>
<div>
<button onClick={() => setDelay(delay ? null : 1000)}>{delay ? 'stop' : 'start'}</button>
<button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
</div>
</div>
);
};
```
## Reference
```js
useInterval(fn, delay?: number)
useInterval(callback, delay?: number)
```

View File

@ -2,21 +2,31 @@
React state hook that tracks a value of an array.
## Usage
```jsx
import {useList} from 'react-use';
const Demo = () => {
const [list, {set, push}] = useList();
const [list, { clear, filter, push, remove, set, sort, updateAt, reset }] = useList();
return (
<div>
<div>{list.join(',')}</div>
<button onClick={() => set([])}>Reset</button>
<button onClick={() => push(Date.now())}>Push</button>
<button onClick={() => set([1, 2, 3])}>Set to [1, 2, 3]</button>
<button onClick={() => push(Date.now())}>Push timestamp</button>
<button onClick={() => updateAt(1, Date.now())}>Update value at index 1</button>
<button onClick={() => remove(1)}>Remove element at index 1</button>
<button onClick={() => filter(item => item % 2 === 0)}>Filter even values</button>
<button onClick={() => sort((a, b) => a - b)}>Sort ascending</button>
<button onClick={() => sort((a, b) => b - a)}>Sort descending</button>
<button onClick={clear}>Clear</button>
<button onClick={reset}>Reset</button>
<pre>{JSON.stringify(list, null, 2)}</pre>
</div>
);
};
```
## Related hooks
- [useUpsert](./useUpsert.md)

View File

@ -2,22 +2,28 @@
React state hook that tracks a value of an object.
## Usage
```jsx
import {useMap} from 'react-use';
const Demo = () => {
const [map, {set, reset}] = useMap({
const [map, {set, remove, reset}] = useMap({
hello: 'there',
});
return (
<div>
<button onClick={() => set(String(Date.now()), new Date().toJSON())}>
Add
</button>
<button onClick={() => reset()}>
Reset
</button>
<button onClick={() => remove('hello')} disabled={!map.hello}>
Remove 'hello'
</button>
<pre>{JSON.stringify(map, null, 2)}</pre>
<button onClick={() => set(String(Date.now()), (new Date()).toJSON())}>Add</button>
<button onClick={() => reset()}>Reset</button>
</div>
);
};

View File

@ -1,6 +1,6 @@
# `useMeasure`
React sensor hook that reacts to changes in size of any of the observed elements.
React sensor hook that tracks dimensions of an HTML element using the [Resize Observer API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
## Usage
@ -8,12 +8,18 @@ React sensor hook that reacts to changes in size of any of the observed elements
import { useMeasure } from "react-use";
const Demo = () => {
const [ref, { width, height }] = useMeasure();
const [ref, { x, y, width, height, top, right, bottom, left }] = useMeasure();
return (
<div ref={ref}>
<div>x: {x}</div>
<div>y: {y}</div>
<div>width: {width}</div>
<div>height: {height}</div>
<div>top: {top}</div>
<div>right: {right}</div>
<div>bottom: {bottom}</div>
<div>left: {left}</div>
</div>
);
};
@ -21,4 +27,4 @@ const Demo = () => {
## Related hooks
- [useSize](./useSize.md)
- [useSize](./useSize.md)

View File

@ -13,7 +13,11 @@ const Demo = () => {
return (
<p>
Now: {count}, before: {prevCount}
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
<p>
Now: {count}, before: {prevCount}
</p>
</p>
);
};

View File

@ -2,7 +2,6 @@
React sensor hook that tracks browser's location search param.
## Usage
```jsx
@ -27,3 +26,7 @@ const Demo = () => {
);
};
```
## Caveats/Gotchas
When using a hash router, like `react-router`'s [`<HashRouter>`](https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/HashRouter.md), this hook won't be able to read the search parameters as they are considered part of the hash of the URL by browsers.

View File

@ -9,7 +9,8 @@ import {useSize} from 'react-use';
const Demo = () => {
const [sized, {width, height}] = useSize(
({width}) => <div style={{border: '1px solid red'}}>Size me up! ({width}px)</div>
({width}) => <div style={{background: 'red'}}>Size me up! ({width}px)</div>,
{ width: 100, height: 100 }
);
return (
@ -21,3 +22,16 @@ const Demo = () => {
);
};
```
## Reference
```js
useSize(element, initialSize);
```
- `element` &mdash; sized element.
- `initialSize` &mdash; initial size containing a `width` and `height` key.
## Related hooks
- [useMeasure](./useMeasure.md)

47
docs/useStateValidator.md Normal file
View File

@ -0,0 +1,47 @@
# `useStateValidator`
Each time given state changes - validator function is invoked.
## Usage
```ts
import * as React from 'react';
import { useCallback } from 'react';
import { useStateValidator } from 'react-use';
const DemoStateValidator = s => [s === '' ? null : (s * 1) % 2 === 0];
const Demo = () => {
const [state, setState] = React.useState<string | number>(0);
const [[isValid]] = useStateValidator(state, DemoStateValidator);
return (
<div>
<div>Below field is valid only if number is even</div>
<input
type="number"
min="0"
max="10"
value={state}
onChange={(ev: React.ChangeEvent<HTMLInputElement>) => {
setState(ev.target.value);
}}
/>
{isValid !== null && <span>{isValid ? 'Valid!' : 'Invalid'}</span>}
</div>
);
};
```
## Reference
```ts
const [validity, revalidate] = useStateValidator(
state: any,
validator: (state, setValidity?)=>[boolean|null, ...any[]],
initialValidity: any
);
```
- **`validity`**_`: [boolean|null, ...any[]]`_ result of validity check. First element is strictly nullable boolean, but others can contain arbitrary data;
- **`revalidate`**_`: ()=>void`_ runs validator once again
- **`validator`**_`: (state, setValidity?)=>[boolean|null, ...any[]]`_ should return an array suitable for validity state described above;
- `state` - current state;
- `setValidity` - if defined hook will not trigger validity change automatically. Useful for async validators;
- `initialValidity` - validity value which set when validity is nt calculated yet;

View File

@ -7,7 +7,7 @@ React state hook that tracks value of a boolean.
## Usage
```jsx
import {useToggle, useBoolean} from 'react-use';
import {useToggle} from 'react-use';
const Demo = () => {
const [on, toggle] = useToggle(true);

View File

@ -1,6 +1,7 @@
# `useUpsert`
Superset of `useList`. Provides an additional method to upsert (update or insert) an element into the list.
Superset of [`useList`](./useList.md). Provides an additional method to upsert (update or insert) an element into the list.
## Usage
```jsx
@ -26,3 +27,7 @@ const Demo = () => {
);
};
```
## Related hooks
- [useList](./useList.md)

View File

@ -1,6 +1,6 @@
{
"name": "react-use",
"version": "12.2.0",
"version": "12.5.0",
"description": "Collection of React Hooks",
"main": "lib/index.js",
"module": "esm/index.js",
@ -51,7 +51,7 @@
"react-fast-compare": "^2.0.4",
"react-wait": "^0.3.0",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^4.1.0",
"screenfull": "^5.0.0",
"set-harmonic-interval": "^1.0.0",
"throttle-debounce": "^2.0.1",
"ts-easing": "^0.2.0",
@ -62,52 +62,53 @@
"react-dom": "^16.8.0"
},
"devDependencies": {
"@babel/core": "7.6.0",
"@babel/core": "7.6.4",
"@babel/plugin-syntax-dynamic-import": "7.2.0",
"@babel/preset-env": "7.6.0",
"@babel/preset-react": "7.0.0",
"@babel/preset-env": "7.6.3",
"@babel/preset-react": "7.6.3",
"@babel/preset-typescript": "7.6.0",
"@semantic-release/changelog": "3.0.4",
"@semantic-release/git": "7.0.16",
"@semantic-release/npm": "5.1.13",
"@shopify/jest-dom-mocks": "2.8.2",
"@storybook/addon-actions": "5.1.11",
"@storybook/addon-knobs": "5.1.11",
"@storybook/addon-notes": "5.1.11",
"@storybook/addon-options": "5.1.11",
"@storybook/react": "5.1.11",
"@testing-library/react-hooks": "2.0.1",
"@testing-library/react-hooks": "2.0.3",
"@types/jest": "24.0.18",
"@types/react": "16.9.2",
"babel-core": "6.26.3",
"babel-loader": "8.0.6",
"babel-plugin-dynamic-import-node": "2.3.0",
"fork-ts-checker-webpack-plugin": "1.5.0",
"fork-ts-checker-webpack-plugin": "1.5.1",
"gh-pages": "2.1.1",
"husky": "3.0.5",
"husky": "3.0.9",
"jest": "24.9.0",
"keyboardjs": "2.5.1",
"lint-staged": "9.2.5",
"lint-staged": "9.4.2",
"markdown-loader": "5.1.0",
"prettier": "1.18.2",
"raf-stub": "3.0.0",
"react": "16.9.0",
"react-dom": "16.9.0",
"react": "16.10.2",
"react-dom": "16.10.2",
"react-frame-component": "4.1.1",
"react-spring": "8.0.27",
"react-test-renderer": "16.9.0",
"react-test-renderer": "16.10.2",
"rebound": "0.1.0",
"redux-logger": "3.0.6",
"redux-thunk": "2.3.0",
"rimraf": "3.0.0",
"rxjs": "6.5.3",
"semantic-release": "15.13.24",
"ts-loader": "6.1.0",
"ts-node": "8.3.0",
"ts-loader": "6.2.0",
"ts-node": "8.4.1",
"tslint": "5.20.0",
"tslint-config-prettier": "1.18.0",
"tslint-eslint-rules": "5.4.0",
"tslint-plugin-prettier": "2.0.1",
"tslint-react": "4.0.0",
"tslint-react": "4.1.0",
"typescript": "3.5.3"
},
"config": {
@ -141,8 +142,8 @@
]
},
"volta": {
"node": "10.16.0",
"yarn": "1.16.0"
"node": "10.16.3",
"yarn": "1.19.1"
},
"collective": {
"type": "opencollective",

View File

@ -0,0 +1,53 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { useIntersection } from '..';
import ShowDocs from './util/ShowDocs';
const Spacer = () => (
<div
style={{
width: '200px',
height: '300px',
backgroundColor: 'whitesmoke',
}}
/>
);
const Demo = () => {
const intersectionRef = React.useRef(null);
const intersection = useIntersection(intersectionRef, {
root: null,
rootMargin: '0px',
threshold: 1,
});
return (
<div
style={{
width: '400px',
height: '400px',
backgroundColor: 'whitesmoke',
overflow: 'scroll',
}}
>
Scroll me
<Spacer />
<div
ref={intersectionRef}
style={{
width: '100px',
height: '100px',
padding: '20px',
backgroundColor: 'palegreen',
}}
>
{intersection && intersection.intersectionRatio < 1 ? 'Obscured' : 'Fully in view'}
</div>
<Spacer />
</div>
);
};
storiesOf('Sensors/useIntersection', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useIntersection.md')} />)
.add('Demo', () => <Demo />);

View File

@ -1,28 +1,28 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { useInterval } from '..';
import { useInterval, useBoolean } from '..';
import ShowDocs from './util/ShowDocs';
const Demo = () => {
const [count, setCount] = React.useState(0);
const [delay, setDelay] = React.useState(1000);
const [isRunning, toggleIsRunning] = useBoolean(true);
useInterval(() => {
setCount(count + 1);
}, delay);
function handleDelayChange(e) {
setDelay(Number(e.target.value));
}
useInterval(
() => {
setCount(count + 1);
},
isRunning ? delay : null
);
return (
<div>
<div>
delay: <input value={delay} onChange={handleDelayChange} />
delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
</div>
<h1>count: {count}</h1>
<div>
<button onClick={() => setDelay(delay ? null : 1000)}>{delay ? 'stop' : 'start'}</button>
<button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
</div>
</div>
);

View File

@ -4,13 +4,20 @@ import { useList } from '..';
import ShowDocs from './util/ShowDocs';
const Demo = () => {
const [list, { set, push }] = useList();
const [list, { clear, filter, push, remove, set, sort, updateAt, reset }] = useList([1, 2, 3, 4, 5]);
return (
<div>
<div>{list.join(',')}</div>
<button onClick={() => set([])}>Reset</button>
<button onClick={() => push(Date.now())}>Push</button>
<button onClick={() => set([1, 2, 3])}>Set to [1, 2, 3]</button>
<button onClick={() => push(Date.now())}>Push timestamp</button>
<button onClick={() => updateAt(1, Date.now())}>Update value at index 1</button>
<button onClick={() => remove(1)}>Remove element at index 1</button>
<button onClick={() => filter(item => item % 2 === 0)}>Filter even values</button>
<button onClick={() => sort((a, b) => a - b)}>Sort ascending</button>
<button onClick={() => sort((a, b) => b - a)}>Sort descending</button>
<button onClick={clear}>Clear</button>
<button onClick={reset}>Reset</button>
<pre>{JSON.stringify(list, null, 2)}</pre>
</div>
);
};

View File

@ -4,15 +4,18 @@ import { useMap } from '..';
import ShowDocs from './util/ShowDocs';
const Demo = () => {
const [map, { set, reset }] = useMap({
const [map, { set, remove, reset }] = useMap({
hello: 'there',
});
return (
<div>
<pre>{JSON.stringify(map, null, 2)}</pre>
<button onClick={() => set(String(Date.now()), new Date().toJSON())}>Add</button>
<button onClick={() => reset()}>Reset</button>
<button onClick={() => remove('hello')} disabled={!map.hello}>
Remove 'hello'
</button>
<pre>{JSON.stringify(map, null, 2)}</pre>
</div>
);
};

View File

@ -4,18 +4,12 @@ import { useMeasure } from '..';
import ShowDocs from './util/ShowDocs';
const Demo = () => {
const [ref, { width, height }] = useMeasure();
const [ref, state] = useMeasure();
return (
<>
<div>width: {width}</div>
<div>height: {height}</div>
<div
style={{
background: 'red',
}}
ref={ref}
>
<pre>{JSON.stringify(state, null, 2)}</pre>
<div ref={ref} style={{ background: 'red' }}>
resize me
</div>
</>

View File

@ -4,15 +4,14 @@ import { useSize } from '..';
import ShowDocs from './util/ShowDocs';
const Demo = () => {
const [sized, { width, height }] = useSize(({ width: currentWidth }) => (
<div style={{ border: '1px solid red' }}>Size me up! ({currentWidth}px)</div>
const [sized, state] = useSize(({ width: currentWidth }) => (
<div style={{ background: 'red' }}>Size me up! ({currentWidth}px)</div>
));
return (
<div>
<pre>{JSON.stringify(state, null, 2)}</pre>
{sized}
<div>width: {width}</div>
<div>height: {height}</div>
</div>
);
};

View File

@ -0,0 +1,30 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import useStateValidator from '../useStateValidator';
import ShowDocs from './util/ShowDocs';
const DemoStateValidator = s => [s === '' ? null : (s * 1) % 2 === 0];
const Demo = () => {
const [state, setState] = React.useState<string | number>(0);
const [[isValid]] = useStateValidator(state, DemoStateValidator);
return (
<div>
<div>Below field is valid only if number is even</div>
<input
type="number"
min="0"
max="10"
value={state}
onChange={(ev: React.ChangeEvent<HTMLInputElement>) => {
setState(ev.target.value);
}}
/>
{isValid !== null && <span>{isValid ? 'Valid!' : 'Invalid'}</span>}
</div>
);
};
storiesOf('State|useStateValidator', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useStateValidator.md')} />)
.add('Demo', () => <Demo />);

View File

@ -0,0 +1,39 @@
import { renderHook } from '@testing-library/react-hooks';
import { useDeepCompareEffect } from '..';
import { useEffect } from 'react';
let options = { max: 10 };
const mockEffectNormal = jest.fn();
const mockEffectDeep = jest.fn();
const mockEffectCleanup = jest.fn();
const mockEffectCallback = jest.fn().mockReturnValue(mockEffectCleanup);
it('should run provided object once', () => {
const { rerender: rerenderNormal } = renderHook(() => useEffect(mockEffectNormal, [options]));
const { rerender: rerenderDeep } = renderHook(() => useDeepCompareEffect(mockEffectDeep, [options]));
expect(mockEffectNormal).toHaveBeenCalledTimes(1);
expect(mockEffectDeep).toHaveBeenCalledTimes(1);
options = { max: 10 };
rerenderDeep();
rerenderNormal();
expect(mockEffectNormal).toHaveBeenCalledTimes(2);
expect(mockEffectDeep).toHaveBeenCalledTimes(1);
options = { max: 10 };
rerenderNormal();
rerenderDeep();
expect(mockEffectNormal).toHaveBeenCalledTimes(3);
expect(mockEffectDeep).toHaveBeenCalledTimes(1);
});
it('should run clean-up provided on unmount', () => {
const { unmount } = renderHook(() => useDeepCompareEffect(mockEffectCallback, [options]));
expect(mockEffectCleanup).not.toHaveBeenCalled();
unmount();
expect(mockEffectCleanup).toHaveBeenCalledTimes(1);
});

View File

@ -0,0 +1,55 @@
import { renderHook } from '@testing-library/react-hooks';
import useFavicon from '../useFavicon';
afterEach(() => {
const favicon = document.querySelector("link[rel*='icon']");
if (favicon) {
favicon.remove();
}
});
describe('useFavicon', () => {
it('should be defined', () => {
expect(useFavicon).toBeDefined();
});
it('should create a HTMLLinkElement', () => {
const faviconBeforeHook = document.querySelector("link[rel*='icon']");
expect(faviconBeforeHook).toBe(null);
renderHook(() => useFavicon('My-favicon'));
const faviconAfterHook = document.querySelector("link[rel*='icon']");
expect(faviconAfterHook).toBeInstanceOf(HTMLLinkElement);
});
it('should set the elements type to "image/x-icon"', () => {
renderHook(() => useFavicon('My-favicon'));
const favicon = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
expect(favicon.type).toBe('image/x-icon');
});
it('should set the elements rel to "shortcut icon"', () => {
renderHook(() => useFavicon('My-favicon'));
const favicon = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
expect(favicon.rel).toBe('shortcut icon');
});
it('should set the elements href to the provided string', () => {
renderHook(() => useFavicon('https://github.com/streamich/react-use'));
const favicon = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
expect(favicon.href).toBe('https://github.com/streamich/react-use');
});
it('should update an existing favicon', () => {
const hook = renderHook(props => useFavicon(props), { initialProps: 'https://github.com/streamich/react-use' });
const favicon = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
expect(favicon.href).toBe('https://github.com/streamich/react-use');
hook.rerender('https://en.wikipedia.org/wiki/Favicon');
expect(favicon.href).toBe('https://en.wikipedia.org/wiki/Favicon');
});
});

View File

@ -0,0 +1,119 @@
import React, { createRef } from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-dom/test-utils';
import TestRenderer from 'react-test-renderer';
import { intersectionObserver } from '@shopify/jest-dom-mocks';
import { renderHook } from '@testing-library/react-hooks';
import { useIntersection } from '..';
beforeEach(() => {
intersectionObserver.mock();
});
afterEach(() => {
intersectionObserver.restore();
});
describe('useIntersection', () => {
const container = document.createElement('div');
let targetRef;
it('should be defined', () => {
expect(useIntersection).toBeDefined();
});
it('should setup an IntersectionObserver targeting the ref element and using the options provided', () => {
TestUtils.act(() => {
targetRef = createRef();
ReactDOM.render(<div ref={targetRef} />, container);
});
expect(intersectionObserver.observers).toHaveLength(0);
const observerOptions = { root: null, threshold: 0.8 };
renderHook(() => useIntersection(targetRef, observerOptions));
expect(intersectionObserver.observers).toHaveLength(1);
expect(intersectionObserver.observers[0].target).toEqual(targetRef.current);
expect(intersectionObserver.observers[0].options).toEqual(observerOptions);
});
it('should return null if a ref without a current value is provided', () => {
targetRef = createRef();
const { result } = renderHook(() => useIntersection(targetRef, { root: null, threshold: 1 }));
expect(result.current).toBe(null);
});
it('should return the first IntersectionObserverEntry when the IntersectionObserver registers an intersection', () => {
TestUtils.act(() => {
targetRef = createRef();
ReactDOM.render(<div ref={targetRef} />, container);
});
const { result } = renderHook(() => useIntersection(targetRef, { root: container, threshold: 0.8 }));
const mockIntersectionObserverEntry = {
boundingClientRect: targetRef.current.getBoundingClientRect(),
intersectionRatio: 0.81,
intersectionRect: container.getBoundingClientRect(),
isIntersecting: true,
rootBounds: container.getBoundingClientRect(),
target: targetRef.current,
time: 300,
};
TestRenderer.act(() => {
intersectionObserver.simulate(mockIntersectionObserverEntry);
});
expect(result.current).toEqual(mockIntersectionObserverEntry);
});
it('should setup a new IntersectionObserver when the ref changes', () => {
let newRef;
TestUtils.act(() => {
targetRef = createRef();
newRef = createRef();
ReactDOM.render(
<div ref={targetRef}>
<span ref={newRef} />
</div>,
container
);
});
const observerOptions = { root: null, threshold: 0.8 };
const { rerender } = renderHook(({ ref, options }) => useIntersection(ref, options), {
initialProps: { ref: targetRef, options: observerOptions },
});
expect(intersectionObserver.observers[0].target).toEqual(targetRef.current);
TestRenderer.act(() => {
rerender({ ref: newRef, options: observerOptions });
});
expect(intersectionObserver.observers[0].target).toEqual(newRef.current);
});
it('should setup a new IntersectionObserver when the options change', () => {
TestUtils.act(() => {
targetRef = createRef();
ReactDOM.render(<div ref={targetRef} />, container);
});
const initialObserverOptions = { root: null, threshold: 0.8 };
const { rerender } = renderHook(({ ref, options }) => useIntersection(ref, options), {
initialProps: { ref: targetRef, options: initialObserverOptions },
});
expect(intersectionObserver.observers[0].options).toEqual(initialObserverOptions);
const newObserverOptions = { root: container, threshold: 1 };
TestRenderer.act(() => {
rerender({ ref: targetRef, options: newObserverOptions });
});
expect(intersectionObserver.observers[0].options).toEqual(newObserverOptions);
});
});

View File

@ -16,6 +16,7 @@ it('should init list and utils', () => {
push: expect.any(Function),
filter: expect.any(Function),
sort: expect.any(Function),
reset: expect.any(Function),
});
});
@ -103,6 +104,19 @@ it('should push duplicated element at the end of the list', () => {
expect(result.current[0]).not.toBe(initList); // checking immutability
});
it('should push multiple elements at the end of the list', () => {
const initList = [1, 2, 3];
const { result } = setUp(initList);
const [, utils] = result.current;
act(() => {
utils.push(4, 5, 6);
});
expect(result.current[0]).toEqual([1, 2, 3, 4, 5, 6]);
expect(result.current[0]).not.toBe(initList); // checking immutability
});
it('should filter current list by provided function', () => {
const initList = [1, -1, 2, -2, 3, -3];
const { result } = setUp(initList);
@ -150,3 +164,43 @@ it('should sort current list by provided function', () => {
expect(result.current[0]).toEqual(['March', 'Jan', 'Feb', 'Dec']);
expect(result.current[0]).not.toBe(initList); // checking immutability
});
it('should reset the list to initial list provided', () => {
const initList = [1, 2, 3];
const { result } = setUp(initList);
const [, utils] = result.current;
act(() => {
utils.push(4);
});
expect(result.current[0]).toEqual([1, 2, 3, 4]);
act(() => {
utils.reset();
});
expect(result.current[0]).toEqual([1, 2, 3]);
expect(result.current[0]).not.toBe(initList); // checking immutability
});
it('should memoized its utils methods', () => {
const initList = [1, 2, 3];
const { result } = setUp(initList);
const [, utils] = result.current;
const { set, clear, updateAt, remove, push, filter, sort, reset } = utils;
act(() => {
push(4);
});
expect(result.current[1]).toBe(utils);
expect(result.current[1].set).toBe(set);
expect(result.current[1].clear).toBe(clear);
expect(result.current[1].updateAt).toBe(updateAt);
expect(result.current[1].remove).toBe(remove);
expect(result.current[1].push).toBe(push);
expect(result.current[1].filter).toBe(filter);
expect(result.current[1].sort).toBe(sort);
expect(result.current[1].reset).toBe(reset);
});

View File

@ -0,0 +1,41 @@
import { renderHook } from '@testing-library/react-hooks';
import useLogger from '../useLogger';
const logSpy = jest.spyOn(global.console, 'log').mockImplementation(() => {});
describe('useLogger', () => {
it('should be defined', () => {
expect(useLogger).toBeDefined();
});
it('should log the provided props on mount', () => {
const props = { question: 'What is the meaning?', answer: 42 };
renderHook(() => useLogger('Test', props));
expect(logSpy).toBeCalledTimes(1);
expect(logSpy).toHaveBeenLastCalledWith('Test mounted', props);
});
it('should log when the component has unmounted', () => {
const props = { question: 'What is the meaning?', answer: 42 };
const { unmount } = renderHook(() => useLogger('Test', props));
unmount();
expect(logSpy).toHaveBeenLastCalledWith('Test unmounted');
});
it('should log updates as props change', () => {
const { rerender } = renderHook(
({ componentName, props }: { componentName: string; props: any }) => useLogger(componentName, props),
{
initialProps: { componentName: 'Test', props: { one: 1 } },
}
);
const newProps = { one: 1, two: 2 };
rerender({ componentName: 'Test', props: newProps });
expect(logSpy).toHaveBeenLastCalledWith('Test updated', newProps);
});
});

View File

@ -0,0 +1,100 @@
import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks';
import { useState } from 'react';
import useStateValidator, { UseValidatorReturn, Validator } from '../useStateValidator';
interface Mock extends jest.Mock {}
describe('useStateValidator', () => {
it('should be defined', () => {
expect(useStateValidator).toBeDefined();
});
function getHook(
fn: Validator<any> = jest.fn(state => [!!(state % 2)])
): [jest.Mock | Function, RenderHookResult<any, [Function, UseValidatorReturn<any>]>] {
return [
fn,
renderHook(() => {
const [state, setState] = useState(1);
return [setState, useStateValidator(state, fn)];
}),
];
}
it('should return an array of two elements', () => {
const [, hook] = getHook();
const res = hook.result.current[1];
expect(Array.isArray(res)).toBe(true);
expect(res[0]).toEqual([true]);
expect(typeof res[1]).toBe('function');
});
it('first element should represent current validity state', () => {
const [, hook] = getHook();
let [setState, [validity]] = hook.result.current;
expect(validity).toEqual([true]);
act(() => setState(3));
[setState, [validity]] = hook.result.current;
expect(validity).toEqual([true]);
act(() => setState(4));
[setState, [validity]] = hook.result.current;
expect(validity).toEqual([false]);
});
it('second element should re-call validation', () => {
const [spy, hook] = getHook();
const [, [, revalidate]] = hook.result.current;
expect(spy).toHaveBeenCalledTimes(1);
act(() => revalidate());
expect(spy).toHaveBeenCalledTimes(2);
});
it('validator have to be called on init plus on each state update', () => {
const [spy, hook] = getHook(jest.fn());
const [setState] = hook.result.current;
expect(spy).toHaveBeenCalledTimes(1);
act(() => setState(4));
expect(spy).toHaveBeenCalledTimes(2);
act(() => setState(prevState => prevState + 1));
expect(spy).toHaveBeenCalledTimes(3);
});
it('should pass to validator one parameter - current state', () => {
const [spy, hook] = getHook(jest.fn());
const [setState] = hook.result.current;
act(() => setState(4));
act(() => setState(5));
expect((spy as Mock).mock.calls[0].length).toBe(1);
expect((spy as Mock).mock.calls[0].length).toBe(1);
expect((spy as Mock).mock.calls[0][0]).toBe(1);
expect((spy as Mock).mock.calls[1].length).toBe(1);
expect((spy as Mock).mock.calls[1][0]).toBe(4);
expect((spy as Mock).mock.calls[2].length).toBe(1);
expect((spy as Mock).mock.calls[2][0]).toBe(5);
});
it('if validator expects 2nd parameters it should pass a validity setter there', () => {
const [spy, hook] = getHook(jest.fn((state, setValidity) => setValidity!([state % 2 === 0])));
let [setState, [[isValid]]] = hook.result.current;
expect((spy as Mock).mock.calls[0].length).toBe(2);
expect(typeof (spy as Mock).mock.calls[0][1]).toBe('function');
expect(isValid).toBe(false);
act(() => setState(prevState => prevState + 1));
[setState, [[isValid]]] = hook.result.current;
expect(isValid).toBe(true);
act(() => setState(5));
[setState, [[isValid]]] = hook.result.current;
expect(isValid).toBe(false);
});
});

View File

@ -0,0 +1,13 @@
import { renderHook } from '@testing-library/react-hooks';
import { useUpdateEffect } from '..';
const mockEffectCleanup = jest.fn();
const mockEffectCallback = jest.fn().mockReturnValue(mockEffectCleanup);
it('should run effect on update', () => {
const { rerender } = renderHook(() => useUpdateEffect(mockEffectCallback));
expect(mockEffectCallback).not.toHaveBeenCalled();
rerender();
expect(mockEffectCallback).toHaveBeenCalledTimes(1);
});

View File

@ -27,6 +27,7 @@ export { default as useHarmonicIntervalFn } from './useHarmonicIntervalFn';
export { default as useHover } from './useHover';
export { default as useHoverDirty } from './useHoverDirty';
export { default as useIdle } from './useIdle';
export { default as useIntersection } from './useIntersection';
export { default as useInterval } from './useInterval';
export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
export { default as useKey } from './useKey';
@ -86,6 +87,7 @@ export { default as useUpdate } from './useUpdate';
export { default as useUpdateEffect } from './useUpdateEffect';
export { default as useUpsert } from './useUpsert';
export { default as useVideo } from './useVideo';
export { default as useStateValidator } from './useStateValidator';
export { useWait, Waiter } from './useWait';
export { default as useWindowScroll } from './useWindowScroll';
export { default as useWindowSize } from './useWindowSize';

View File

@ -20,7 +20,7 @@ const useAsyncRetry = <T>(fn: () => Promise<T>, deps: DependencyList = []) => {
}
setAttempt(currentAttempt => currentAttempt + 1);
}, [...deps, stateLoading, attempt]);
}, [...deps, stateLoading]);
return { ...state, retry };
};

View File

@ -1,14 +1,14 @@
import { DependencyList } from 'react';
import useUpdateEffect from './useUpdateEffect';
const useDebounce = (fn: () => any, ms: number = 0, args: any[] = []) => {
const useDebounce = (fn: () => any, ms: number = 0, deps: DependencyList = []) => {
useUpdateEffect(() => {
const handle = setTimeout(fn.bind(null, args), ms);
const timeout = setTimeout(fn, ms);
return () => {
// if args change then clear timeout
clearTimeout(handle);
clearTimeout(timeout);
};
}, args);
}, deps);
};
export default useDebounce;

View File

@ -26,7 +26,7 @@ const useFullscreen = (ref: RefObject<Element>, on: boolean, options: FullScreen
};
const onChange = () => {
if (screenfull) {
if (screenfull.isEnabled) {
const isScreenfullFullscreen = screenfull.isFullscreen;
setIsFullscreen(isScreenfullFullscreen);
if (!isScreenfullFullscreen) {
@ -35,7 +35,7 @@ const useFullscreen = (ref: RefObject<Element>, on: boolean, options: FullScreen
}
};
if (screenfull && screenfull.enabled) {
if (screenfull.isEnabled) {
try {
screenfull.request(ref.current);
setIsFullscreen(true);
@ -55,7 +55,7 @@ const useFullscreen = (ref: RefObject<Element>, on: boolean, options: FullScreen
return () => {
setIsFullscreen(false);
if (screenfull && screenfull.enabled) {
if (screenfull.isEnabled) {
try {
screenfull.off('change', onChange);
screenfull.exit();
@ -65,7 +65,7 @@ const useFullscreen = (ref: RefObject<Element>, on: boolean, options: FullScreen
video.current.webkitExitFullscreen();
}
};
}, [ref.current, video, on]);
}, [on, video, ref]);
return isFullscreen;
};

30
src/useIntersection.ts Normal file
View File

@ -0,0 +1,30 @@
import { RefObject, useEffect, useState } from 'react';
const useIntersection = (
ref: RefObject<HTMLElement>,
options: IntersectionObserverInit
): IntersectionObserverEntry | null => {
const [intersectionObserverEntry, setIntersectionObserverEntry] = useState<IntersectionObserverEntry | null>(null);
useEffect(() => {
if (ref.current) {
const handler = (entries: IntersectionObserverEntry[]) => {
setIntersectionObserverEntry(entries[0]);
};
const observer = new IntersectionObserver(handler, options);
observer.observe(ref.current);
return () => {
if (ref.current) {
observer.disconnect();
}
};
}
return () => {};
}, [ref, options.threshold, options.root, options.rootMargin]);
return intersectionObserverEntry;
};
export default useIntersection;

View File

@ -1,17 +1,18 @@
import { useEffect, useRef } from 'react';
const useInterval = (callback: Function, delay?: number | null) => {
const latestCallback = useRef<Function>(() => {});
const savedCallback = useRef<Function>(() => {});
useEffect(() => {
latestCallback.current = callback;
savedCallback.current = callback;
});
useEffect(() => {
if (delay !== null) {
const interval = setInterval(() => latestCallback.current(), delay || 0);
const interval = setInterval(() => savedCallback.current(), delay || 0);
return () => clearInterval(interval);
}
return undefined;
}, [delay]);
};

View File

@ -1,31 +1,35 @@
import { useState } from 'react';
import { useState, useMemo } from 'react';
export interface Actions<T> {
set: (list: T[]) => void;
clear: () => void;
updateAt: (index: number, item: T) => void;
remove: (index: number) => void;
push: (item: T) => void;
push: (...items: T[]) => void;
filter: (fn: (value: T) => boolean) => void;
sort: (fn?: (a: T, b: T) => number) => void;
reset: () => void;
}
const useList = <T>(initialList: T[] = []): [T[], Actions<T>] => {
const [list, set] = useState<T[]>(initialList);
return [
list,
{
const utils = useMemo<Actions<T>>(
() => ({
set,
clear: () => set([]),
updateAt: (index, entry) =>
set(currentList => [...currentList.slice(0, index), entry, ...currentList.slice(index + 1)]),
remove: index => set(currentList => [...currentList.slice(0, index), ...currentList.slice(index + 1)]),
push: entry => set(currentList => [...currentList, entry]),
push: (...entry) => set(currentList => [...currentList, ...entry]),
filter: fn => set(currentList => currentList.filter(fn)),
sort: (fn?) => set(currentList => [...currentList].sort(fn)),
},
];
reset: () => set([...initialList]),
}),
[set]
);
return [list, utils];
};
export default useList;

View File

@ -62,7 +62,7 @@ const useMouse = (ref: RefObject<Element>): State => {
cancelAnimationFrame(frame.current);
document.removeEventListener('mousemove', moveHandler);
};
}, [ref.current]);
}, [ref]);
return state;
};

View File

@ -48,7 +48,7 @@ const useScroll = (ref: RefObject<HTMLElement>): State => {
ref.current.removeEventListener('scroll', handler);
}
};
}, [ref.current]);
}, [ref]);
return state;
};

View File

@ -25,7 +25,7 @@ const useScrolling = (ref: RefObject<HTMLElement>): boolean => {
};
}
return () => {};
}, [ref.current]);
}, [ref]);
return scrolling;
};

36
src/useStateValidator.ts Normal file
View File

@ -0,0 +1,36 @@
import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react';
export type ValidityState = [boolean | undefined, ...any[]];
export type DispatchValidity<V extends ValidityState> = Dispatch<SetStateAction<V>>;
export type Validator<V extends ValidityState, S = any> =
| {
(state?: S): V;
(state?: S, dispatch?: DispatchValidity<V>): void;
}
| Function;
export type UseValidatorReturn<V extends ValidityState> = [V, () => void];
export default function useStateValidator<V extends ValidityState, S = any>(
state: S,
validator: Validator<V, S>,
initialValidity: V = [undefined] as V
): UseValidatorReturn<V> {
const validatorFn = useRef(validator);
const [validity, setValidity] = useState(initialValidity);
const validate = useCallback(() => {
if (validatorFn.current.length === 2) {
validatorFn.current(state, setValidity);
} else {
setValidity(validatorFn.current(state));
}
}, [state]);
useEffect(() => {
validate();
}, [state]);
return [validity, validate];
}

357
yarn.lock
View File

@ -42,12 +42,12 @@
integrity sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==
dependencies:
"@babel/code-frame" "^7.5.5"
"@babel/generator" "^7.6.0"
"@babel/helpers" "^7.6.0"
"@babel/parser" "^7.6.0"
"@babel/generator" "^7.6.4"
"@babel/helpers" "^7.6.2"
"@babel/parser" "^7.6.4"
"@babel/template" "^7.6.0"
"@babel/traverse" "^7.6.0"
"@babel/types" "^7.6.0"
"@babel/traverse" "^7.6.3"
"@babel/types" "^7.6.3"
convert-source-map "^1.1.0"
debug "^4.1.0"
json5 "^2.1.0"
@ -264,6 +264,21 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.3.tgz#9eff8b9c3eeae16a74d8d4ff30da2bd0d6f0487e"
integrity sha512-sUZdXlva1dt2Vw2RqbMkmfoImubO0D0gaCrNngV6Hi0DA4x3o4mlrq0tbfY0dZEUIccH8I6wQ4qgEtwcpOR6Qg==
"@babel/parser@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1"
integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==
"@babel/parser@^7.6.3":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.3.tgz#9eff8b9c3eeae16a74d8d4ff30da2bd0d6f0487e"
integrity sha512-sUZdXlva1dt2Vw2RqbMkmfoImubO0D0gaCrNngV6Hi0DA4x3o4mlrq0tbfY0dZEUIccH8I6wQ4qgEtwcpOR6Qg==
"@babel/parser@^7.6.4":
version "7.6.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81"
integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e"
@ -322,6 +337,14 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
"@babel/plugin-proposal-object-rest-spread@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096"
integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
"@babel/plugin-proposal-optional-catch-binding@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5"
@ -339,6 +362,15 @@
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.5.4"
"@babel/plugin-proposal-unicode-property-regex@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802"
integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.6.0"
"@babel/plugin-syntax-async-generators@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f"
@ -491,6 +523,15 @@
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.5.4"
"@babel/plugin-transform-dotall-regex@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9"
integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.6.0"
"@babel/plugin-transform-duplicate-keys@^7.2.0", "@babel/plugin-transform-duplicate-keys@^7.5.0":
version "7.5.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853"
@ -695,6 +736,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-spread@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd"
integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-sticky-regex@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1"
@ -736,6 +784,15 @@
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.5.4"
"@babel/plugin-transform-unicode-regex@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698"
integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.6.0"
"@babel/preset-env@7.4.3":
version "7.4.3"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.3.tgz#e71e16e123dc0fbf65a52cbcbcefd072fbd02880"
@ -800,9 +857,9 @@
"@babel/plugin-proposal-async-generator-functions" "^7.2.0"
"@babel/plugin-proposal-dynamic-import" "^7.5.0"
"@babel/plugin-proposal-json-strings" "^7.2.0"
"@babel/plugin-proposal-object-rest-spread" "^7.5.5"
"@babel/plugin-proposal-object-rest-spread" "^7.6.2"
"@babel/plugin-proposal-optional-catch-binding" "^7.2.0"
"@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
"@babel/plugin-proposal-unicode-property-regex" "^7.6.2"
"@babel/plugin-syntax-async-generators" "^7.2.0"
"@babel/plugin-syntax-dynamic-import" "^7.2.0"
"@babel/plugin-syntax-json-strings" "^7.2.0"
@ -811,11 +868,11 @@
"@babel/plugin-transform-arrow-functions" "^7.2.0"
"@babel/plugin-transform-async-to-generator" "^7.5.0"
"@babel/plugin-transform-block-scoped-functions" "^7.2.0"
"@babel/plugin-transform-block-scoping" "^7.6.0"
"@babel/plugin-transform-block-scoping" "^7.6.3"
"@babel/plugin-transform-classes" "^7.5.5"
"@babel/plugin-transform-computed-properties" "^7.2.0"
"@babel/plugin-transform-destructuring" "^7.6.0"
"@babel/plugin-transform-dotall-regex" "^7.4.4"
"@babel/plugin-transform-dotall-regex" "^7.6.2"
"@babel/plugin-transform-duplicate-keys" "^7.5.0"
"@babel/plugin-transform-exponentiation-operator" "^7.2.0"
"@babel/plugin-transform-for-of" "^7.4.4"
@ -826,7 +883,7 @@
"@babel/plugin-transform-modules-commonjs" "^7.6.0"
"@babel/plugin-transform-modules-systemjs" "^7.5.0"
"@babel/plugin-transform-modules-umd" "^7.2.0"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.6.3"
"@babel/plugin-transform-new-target" "^7.4.4"
"@babel/plugin-transform-object-super" "^7.5.5"
"@babel/plugin-transform-parameters" "^7.4.4"
@ -834,12 +891,12 @@
"@babel/plugin-transform-regenerator" "^7.4.5"
"@babel/plugin-transform-reserved-words" "^7.2.0"
"@babel/plugin-transform-shorthand-properties" "^7.2.0"
"@babel/plugin-transform-spread" "^7.2.0"
"@babel/plugin-transform-spread" "^7.6.2"
"@babel/plugin-transform-sticky-regex" "^7.2.0"
"@babel/plugin-transform-template-literals" "^7.4.4"
"@babel/plugin-transform-typeof-symbol" "^7.2.0"
"@babel/plugin-transform-unicode-regex" "^7.4.4"
"@babel/types" "^7.6.0"
"@babel/plugin-transform-unicode-regex" "^7.6.2"
"@babel/types" "^7.6.3"
browserslist "^4.6.0"
core-js-compat "^3.1.1"
invariant "^2.2.2"
@ -865,6 +922,17 @@
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
"@babel/preset-react@7.6.3":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.6.3.tgz#d5242c828322520205ae4eda5d4f4f618964e2f6"
integrity sha512-07yQhmkZmRAfwREYIQgW0HEwMY9GBJVuPY4Q12UC72AbfaawuupVWa8zQs2tlL+yun45Nv/1KreII/0PLfEsgA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-react-display-name" "^7.0.0"
"@babel/plugin-transform-react-jsx" "^7.0.0"
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
"@babel/preset-typescript@7.3.3":
version "7.3.3"
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz#88669911053fa16b2b276ea2ede2ca603b3f307a"
@ -935,6 +1003,15 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@babel/types@^7.6.3":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09"
integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@cnakazawa/watch@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
@ -1414,6 +1491,37 @@
into-stream "^4.0.0"
lodash "^4.17.4"
"@shopify/async@^2.0.7":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@shopify/async/-/async-2.0.7.tgz#944992bc1721df6c363b3f0f31be1dad0e75e929"
integrity sha512-wYGjqPhpna4ShYbUmlD2fPv5ZkjNlCZtU7huUU8/snnyPmdgL/Rn5M5FPP6Apr7/hU5RgqMj2tJFs37ORz/VaQ==
"@shopify/decorators@^1.1.5":
version "1.1.5"
resolved "https://registry.yarnpkg.com/@shopify/decorators/-/decorators-1.1.5.tgz#b8da0bd5fffb04cde9730898fc04428f964cab1c"
integrity sha512-cFAwd7T5IjkPs1ef11dbA6cbJA+CtgCDanbalPlQdl5ItwDzqJXGpvbhbQXw7zPyNMLijrgrpQqltalqAy9wnQ==
dependencies:
"@shopify/function-enhancers" "^1.0.5"
"@shopify/function-enhancers@^1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@shopify/function-enhancers/-/function-enhancers-1.0.5.tgz#7c3e516e26ce7a9b63c263679bdcf5121d994a10"
integrity sha512-34ML8DX4RmmA9hXDlf2BAz4SA37unShZxoBRPz585a+FaEzNcMvw5NzLD+Ih9XrP/wrxTUcN+p6pazvoS+jB7w==
"@shopify/jest-dom-mocks@2.8.2":
version "2.8.2"
resolved "https://registry.yarnpkg.com/@shopify/jest-dom-mocks/-/jest-dom-mocks-2.8.2.tgz#477c3159897807cc8d7797c33e8a79e787051779"
integrity sha512-4drt+S1cQ1ZSP1DaEHAj5XPPCiI2R8IIt+ZnH9h08Ngy8PjtjFFNHNcSJ6bKBmk7eO2c6+5UaJQzNcg56nt7gg==
dependencies:
"@shopify/async" "^2.0.7"
"@shopify/decorators" "^1.1.5"
"@types/fetch-mock" "^6.0.1"
"@types/lolex" "^2.1.3"
fetch-mock "^6.3.0"
lolex "^2.7.5"
promise "^8.0.3"
tslib "^1.9.3"
"@storybook/addon-actions@5.1.11":
version "5.1.11"
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.1.11.tgz#ebc299b9dfe476b5c65eb5d148c4b064f682ca08"
@ -1875,14 +1983,13 @@
"@svgr/plugin-svgo" "^4.3.1"
loader-utils "^1.2.3"
"@testing-library/react-hooks@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-2.0.1.tgz#1c3ec40882d0830df3078ddae0056fdf7366c81d"
integrity sha512-MLTvWX7/csq/uQzP4WJntGz0QJDq6H4EzjV0VTL5YJE7KBZbaQ9DGT0IbtjuB33L4R4YKZ55rGZQ5eL+WiZtQA==
"@testing-library/react-hooks@2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-2.0.3.tgz#305a6c76facb5fa1d185792b9eb11b1ca1b63fb7"
integrity sha512-adm+7b1gcysGka8VuYq/ObBrIBJTT9QmCEIqPpuxozWFfVDgxSbzBGc44ia/WYLGVt2dqFIOc6/DmAmu/pa0gQ==
dependencies:
"@babel/runtime" "^7.5.4"
"@types/react" ">=16.9.0"
"@types/react-test-renderer" ">=16.9.0"
"@types/testing-library__react-hooks" "^2.0.0"
"@types/babel__core@^7.1.0":
version "7.1.0"
@ -1922,6 +2029,11 @@
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/fetch-mock@^6.0.1":
version "6.0.5"
resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-6.0.5.tgz#acbc6771d43d7ebc1f0a8b7e3d57147618f8eacb"
integrity sha512-rV8O2j/TIi0PtFCOlK55JnfKpE8Hm6PKFgrUZY/3FNHw4uBEMHnM+5ZickDO1duOyKxbpY3VES5T4NIwZXvodA==
"@types/glob@^7.1.1":
version "7.1.1"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
@ -1963,6 +2075,11 @@
dependencies:
"@types/jest-diff" "*"
"@types/lolex@^2.1.3":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@types/lolex/-/lolex-2.1.3.tgz#793557c9b8ad319b4c8e4c6548b90893f4aa5f69"
integrity sha512-nEipOLYyZJ4RKHCg7tlR37ewFy91oggmip2MBzPdVQ8QhTFqjcRhE8R0t4tfpDnSlxGWHoEGJl0UCC4kYhqoiw==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@ -1988,7 +2105,7 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
"@types/react-test-renderer@>=16.9.0":
"@types/react-test-renderer@*":
version "16.9.0"
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.0.tgz#d60f530ecf4c906721511603cca711b4fa830d41"
integrity sha512-bN5EyjtuTY35xX7N5j0KP1vg5MpUXHpFTX6tGsqkNOthjNvet4VQOYRxFh+NT5cDSJrATmAFK9NLeYZ4mp/o0Q==
@ -2023,6 +2140,14 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
"@types/testing-library__react-hooks@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/testing-library__react-hooks/-/testing-library__react-hooks-2.0.0.tgz#7b289d64945517ae8ba9cbcb0c5b282432aaeffa"
integrity sha512-YUVqXGCChJKEJ4aAnMXqPCq0NfPAFVsJeGIb2y/iiMjxwyu+45+vR+AHOwjJHHKEHeC0ZhOGrZ5gSEmaJe4tyQ==
dependencies:
"@types/react" "*"
"@types/react-test-renderer" "*"
"@types/yargs-parser@*":
version "13.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.0.0.tgz#453743c5bbf9f1bed61d959baab5b06be029b2d0"
@ -2560,7 +2685,7 @@ arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
asap@^2.0.0, asap@~2.0.3:
asap@^2.0.0, asap@~2.0.3, asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
@ -3020,6 +3145,15 @@ babel-plugin-transform-undefined-to-void@^6.9.4:
resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz#be241ca81404030678b748717322b89d0c8fe280"
integrity sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=
babel-polyfill@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=
dependencies:
babel-runtime "^6.26.0"
core-js "^2.5.0"
regenerator-runtime "^0.10.5"
babel-preset-jest@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc"
@ -5347,6 +5481,15 @@ fbjs@^0.8.0, fbjs@^0.8.1:
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
fetch-mock@^6.3.0:
version "6.5.2"
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-6.5.2.tgz#b3842b305c13ea0f81c85919cfaa7de387adfa3e"
integrity sha512-EIvbpCLBTYyDLu4HJiqD7wC8psDwTUaPaWXNKZbhNO/peUYKiNp5PkZGKRJtnTxaPQu71ivqafvjpM7aL+MofQ==
dependencies:
babel-polyfill "^6.26.0"
glob-to-regexp "^0.4.0"
path-to-regexp "^2.2.1"
figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
@ -5554,10 +5697,10 @@ fork-ts-checker-webpack-plugin@1.1.1:
tapable "^1.0.0"
worker-rpc "^0.1.0"
fork-ts-checker-webpack-plugin@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.5.0.tgz#ce1d77190b44d81a761b10b6284a373795e41f0c"
integrity sha512-zEhg7Hz+KhZlBhILYpXy+Beu96gwvkROWJiTXOCyOOMMrdBIRPvsBpBqgTI4jfJGrJXcqGwJR8zsBGDmzY0jsA==
fork-ts-checker-webpack-plugin@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.5.1.tgz#f82d078ba8911c7b2c70703ffb3cbe588b33fbaa"
integrity sha512-IbVh1Z46dmCXJMg6We8s9jYwCAzzSv2Tgj+G2Sg/8pFantHDBrAg/rQyPnmAWLS/djW7n4VEltoEglbtTvt0wQ==
dependencies:
babel-code-frame "^6.22.0"
chalk "^2.4.1"
@ -5848,6 +5991,11 @@ glob-to-regexp@^0.3.0:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
glob-to-regexp@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.1.4"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
@ -6286,20 +6434,20 @@ humanize-url@^1.0.0:
normalize-url "^1.0.0"
strip-url-auth "^1.0.0"
husky@3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.5.tgz#d7db27c346645a8dc52df02aa534a377ad7925e0"
integrity sha512-cKd09Jy9cDyNIvAdN2QQAP/oA21sle4FWXjIMDttailpLAYZuBE7WaPmhrkj+afS8Sj9isghAtFvWSQ0JiwOHg==
husky@3.0.9:
version "3.0.9"
resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.9.tgz#a2c3e9829bfd6b4957509a9500d2eef5dbfc8044"
integrity sha512-Yolhupm7le2/MqC1VYLk/cNmYxsSsqKkTyBhzQHhPK1jFnC89mmmNVuGtLNabjDI6Aj8UNIr0KpRNuBkiC4+sg==
dependencies:
chalk "^2.4.2"
ci-info "^2.0.0"
cosmiconfig "^5.2.1"
execa "^1.0.0"
get-stdin "^7.0.0"
is-ci "^2.0.0"
opencollective-postinstall "^2.0.2"
pkg-dir "^4.2.0"
please-upgrade-node "^3.2.0"
read-pkg "^5.1.1"
read-pkg "^5.2.0"
run-node "^1.0.0"
slash "^3.0.0"
@ -7746,10 +7894,10 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
lint-staged@9.2.5:
version "9.2.5"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-9.2.5.tgz#5a3e1e0a539a403bd7f88542bc3d34ce52efdbb3"
integrity sha512-d99gTBFMJ29159+9iRvaMEQstmNcPAbQbhHSYw6D/1FncvFdIj8lWHztaq3Uq+tbZPABHXQ/fyN7Rp1QwF8HIw==
lint-staged@9.4.2:
version "9.4.2"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-9.4.2.tgz#14cb577a9512f520691f8b5aefce6a8f7ead6c04"
integrity sha512-OFyGokJSWTn2M6vngnlLXjaHhi8n83VIZZ5/1Z26SULRUWgR3ITWpAEQC9Pnm3MC/EpCxlwts/mQWDHNji2+zA==
dependencies:
chalk "^2.4.2"
commander "^2.20.0"
@ -8003,6 +8151,11 @@ log-update@^2.3.0:
cli-cursor "^2.0.0"
wrap-ansi "^3.0.1"
lolex@^2.7.5:
version "2.7.5"
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733"
integrity sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@ -9419,6 +9572,16 @@ parse-json@^4.0.0:
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
parse-json@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f"
integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==
dependencies:
"@babel/code-frame" "^7.0.0"
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
lines-and-columns "^1.1.6"
parse5@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
@ -9479,6 +9642,11 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-to-regexp@^2.2.1:
version "2.4.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704"
integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==
path-type@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
@ -9799,6 +9967,13 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
promise@^8.0.3:
version "8.0.3"
resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.3.tgz#f592e099c6cddc000d538ee7283bb190452b0bf6"
integrity sha512-HeRDUL1RJiLhyA0/grn+PTShlBAcLuh/1BJGtrvjwbvRDCTLLMEz9rOGCV+R3vHY4MixIuoMEd9Yq/XvsTPcjw==
dependencies:
asap "~2.0.6"
prompts@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.4.tgz#179f9d4db3128b9933aa35f93a800d8fce76a682"
@ -10113,7 +10288,17 @@ react-docgen@^4.1.0:
node-dir "^0.1.10"
recast "^0.17.3"
react-dom@16.9.0, react-dom@^16.8.3:
react-dom@16.10.2:
version "16.10.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.10.2.tgz#4840bce5409176bc3a1f2bd8cb10b92db452fda6"
integrity sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.16.2"
react-dom@^16.8.3:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962"
integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ==
@ -10195,6 +10380,11 @@ react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.10.2.tgz#984120fd4d16800e9a738208ab1fba422d23b5ab"
integrity sha512-INBT1QEgtcCCgvccr5/86CfD71fw9EPmDxgiJX4I2Ddr6ZsV6iFXsuby+qWJPtmNuMY0zByTsG4468P7nHuNWA==
react-is@^16.8.6:
version "16.10.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.10.0.tgz#3d6a031e57fff73c3cfa0347feb3e8f40c5141e5"
integrity sha512-WRki2sBb7MTpYp7FtDEmSeGKX2vamYyq3rc9o7fKUG+/DHVyJu69NnvJsiSwwhh2Tt8XN40MQHkDBEXwyfxncQ==
react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@ -10263,15 +10453,15 @@ react-syntax-highlighter@^8.0.1:
prismjs "^1.8.4"
refractor "^2.4.1"
react-test-renderer@16.9.0:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.9.0.tgz#7ed657a374af47af88f66f33a3ef99c9610c8ae9"
integrity sha512-R62stB73qZyhrJo7wmCW9jgl/07ai+YzvouvCXIJLBkRlRqLx4j9RqcLEAfNfU3OxTGucqR2Whmn3/Aad6L3hQ==
react-test-renderer@16.10.2:
version "16.10.2"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.10.2.tgz#4d8492f8678c9b43b721a7d79ed0840fdae7c518"
integrity sha512-k9Qzyev6cTIcIfrhgrFlYQAFxh5EEDO6ALNqYqmKsWVA7Q/rUMTay5nD3nthi6COmYsd4ghVYyi8U86aoeMqYQ==
dependencies:
object-assign "^4.1.1"
prop-types "^15.6.2"
react-is "^16.9.0"
scheduler "^0.15.0"
react-is "^16.8.6"
scheduler "^0.16.2"
react-textarea-autosize@^7.1.0:
version "7.1.0"
@ -10296,7 +10486,16 @@ react-wait@^0.3.0:
resolved "https://registry.yarnpkg.com/react-wait/-/react-wait-0.3.0.tgz#0cdd4d919012451a5bc3ab0a16d00c6fd9a8c10b"
integrity sha512-kB5x/kMKWcn0uVr9gBdNz21/oGbQwEQnF3P9p6E9yLfJ9DRcKS0fagbgYMFI0YFOoyKDj+2q6Rwax0kTYJF37g==
react@16.9.0, react@^16.8.3:
react@16.10.2:
version "16.10.2"
resolved "https://registry.yarnpkg.com/react/-/react-16.10.2.tgz#a5ede5cdd5c536f745173c8da47bda64797a4cf0"
integrity sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
react@^16.8.3:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa"
integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==
@ -10400,6 +10599,16 @@ read-pkg@^5.0.0, read-pkg@^5.1.1:
parse-json "^4.0.0"
type-fest "^0.4.1"
read-pkg@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
dependencies:
"@types/normalize-package-data" "^2.4.0"
normalize-package-data "^2.5.0"
parse-json "^5.0.0"
type-fest "^0.6.0"
read@1, read@~1.0.1, read@~1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
@ -10559,11 +10768,23 @@ regenerate-unicode-properties@^8.0.2, regenerate-unicode-properties@^8.1.0:
dependencies:
regenerate "^1.4.0"
regenerate-unicode-properties@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==
dependencies:
regenerate "^1.4.0"
regenerate@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
regenerator-runtime@^0.10.5:
version "0.10.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=
regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
@ -10618,6 +10839,18 @@ regexpu-core@^4.5.4, regexpu-core@^4.6.0:
unicode-match-property-ecmascript "^1.0.4"
unicode-match-property-value-ecmascript "^1.1.0"
regexpu-core@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==
dependencies:
regenerate "^1.4.0"
regenerate-unicode-properties "^8.1.0"
regjsgen "^0.5.0"
regjsparser "^0.6.0"
unicode-match-property-ecmascript "^1.0.4"
unicode-match-property-value-ecmascript "^1.1.0"
registry-auth-token@^3.0.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20"
@ -10940,6 +11173,14 @@ scheduler@^0.15.0:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler@^0.16.2:
version "0.16.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.16.2.tgz#f74cd9d33eff6fc554edfb79864868e4819132c1"
integrity sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
schema-utils@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
@ -12119,10 +12360,10 @@ ts-easing@^0.2.0:
resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec"
integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==
ts-loader@6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.1.0.tgz#999cb0a7644f9c7c6c0901802dce50ceb0a76e5b"
integrity sha512-7JedeOu2rsYHQDEr2fwmMozABwbQTZXEaEMZPSIWG7gpzRefOLJCqwdazcegHtyaxp04PeEgs/b0m08WMpnIzQ==
ts-loader@6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.0.tgz#52d3993ecbc5474c1513242388e1049da0fce880"
integrity sha512-Da8h3fD+HiZ9GvZJydqzk3mTC9nuOKYlJcpuk+Zv6Y1DPaMvBL+56GRzZFypx2cWrZFMsQr869+Ua2slGoLxvQ==
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"
@ -12130,10 +12371,10 @@ ts-loader@6.1.0:
micromatch "^4.0.0"
semver "^6.0.0"
ts-node@8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.3.0.tgz#e4059618411371924a1fb5f3b125915f324efb57"
integrity sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ==
ts-node@8.4.1:
version "8.4.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.4.1.tgz#270b0dba16e8723c9fa4f9b4775d3810fd994b4f"
integrity sha512-5LpRN+mTiCs7lI5EtbXmF/HfMeCjzt7DH9CZwtkr6SywStrNQC723wG+aOWFiLNn7zT3kD/RnFqi3ZUfr4l5Qw==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
@ -12179,10 +12420,10 @@ tslint-plugin-prettier@2.0.1:
lines-and-columns "^1.1.6"
tslib "^1.7.1"
tslint-react@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-4.0.0.tgz#b4bb4c01c32448cb14d23f143a2f5e4989bb961e"
integrity sha512-9fNE0fm9zNDx1+b6hgy8rgDN2WsQLRiIrn3+fbqm0tazBVF6jiaCFAITxmU+WSFWYE03Xhp1joCircXOe1WVAQ==
tslint-react@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-4.1.0.tgz#7153b724a8cfbea52423d0ffa469e8eba3bcc834"
integrity sha512-Y7CbFn09X7Mpg6rc7t/WPbmjx9xPI8p1RsQyiGCLWgDR6sh3+IBSlT+bEkc0PSZcWwClOkqq2wPsID8Vep6szQ==
dependencies:
tsutils "^3.9.1"
@ -12258,6 +12499,11 @@ type-fest@^0.5.0:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2"
integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
type-is@~1.6.17, type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
@ -12949,3 +13195,4 @@ yn@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.0.0.tgz#0073c6b56e92aed652fbdfd62431f2d6b9a7a091"
integrity sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q==