From 26cab31f10a995ec45d6c1e2a2f724d9994d801f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=BD=E9=BE=99?= Date: Mon, 19 Aug 2019 14:14:35 +0800 Subject: [PATCH 001/213] feat: useDebounce add cancel --- docs/useDebounce.md | 2 +- src/useDebounce.ts | 17 +++++++++++++++-- src/useUpdateEffect.ts | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/useDebounce.md b/docs/useDebounce.md index 20a25b27e6..4dc06b324b 100644 --- a/docs/useDebounce.md +++ b/docs/useDebounce.md @@ -45,5 +45,5 @@ const Demo = () => { ## Reference ```ts -useDebounce(fn, ms: number, args: any[]); +const { cancel } = useDebounce(fn, ms: number, args: any[]); ``` diff --git a/src/useDebounce.ts b/src/useDebounce.ts index 3c7d4664ca..eded395d30 100644 --- a/src/useDebounce.ts +++ b/src/useDebounce.ts @@ -1,14 +1,27 @@ +import { useCallback, useRef } from 'react'; import useUpdateEffect from './useUpdateEffect'; + const useDebounce = (fn: () => any, ms: number = 0, args: any[] = []) => { + + const timer = useRef(); + useUpdateEffect(() => { - const handle = setTimeout(fn.bind(null, args), ms); + timer.current = window.setTimeout(fn.bind(null, args), ms); return () => { // if args change then clear timeout - clearTimeout(handle); + window.clearTimeout(timer.current); }; }, args); + + const cancel = useCallback(() => { + if (timer.current) { + window.clearTimeout(timer.current); + } + }, []); + + return { cancel }; }; export default useDebounce; diff --git a/src/useUpdateEffect.ts b/src/useUpdateEffect.ts index 47678266bc..63fbc80c66 100644 --- a/src/useUpdateEffect.ts +++ b/src/useUpdateEffect.ts @@ -7,7 +7,7 @@ const useUpdateEffect: typeof useEffect = (effect, deps) => { if (isInitialMount.current) { isInitialMount.current = false; } else { - effect(); + return effect(); } }, deps); }; From 693aec8307c378697c88c635a401832f24d3531a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=BD=E9=BE=99?= Date: Mon, 19 Aug 2019 14:18:40 +0800 Subject: [PATCH 002/213] feat: useDebounce add cancel --- src/useDebounce.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/useDebounce.ts b/src/useDebounce.ts index eded395d30..73e3ca6ed7 100644 --- a/src/useDebounce.ts +++ b/src/useDebounce.ts @@ -1,13 +1,9 @@ import { useCallback, useRef } from 'react'; import useUpdateEffect from './useUpdateEffect'; - const useDebounce = (fn: () => any, ms: number = 0, args: any[] = []) => { - const timer = useRef(); - useUpdateEffect(() => { - timer.current = window.setTimeout(fn.bind(null, args), ms); return () => { // if args change then clear timeout From 66f06905819184fcda2d1753182b73faf7788a19 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Mon, 26 Aug 2019 00:52:57 +0300 Subject: [PATCH 003/213] Way simpler with `useTimeoutFn`; --- src/useDebounce.ts | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/useDebounce.ts b/src/useDebounce.ts index 73e3ca6ed7..6f183ffb65 100644 --- a/src/useDebounce.ts +++ b/src/useDebounce.ts @@ -1,23 +1,9 @@ -import { useCallback, useRef } from 'react'; -import useUpdateEffect from './useUpdateEffect'; +import { DependencyList, useCallback } from 'react'; +import useTimeoutFn from './useTimeoutFn'; -const useDebounce = (fn: () => any, ms: number = 0, args: any[] = []) => { - const timer = useRef(); - useUpdateEffect(() => { - timer.current = window.setTimeout(fn.bind(null, args), ms); - return () => { - // if args change then clear timeout - window.clearTimeout(timer.current); - }; - }, args); +export default function useDebounce(fn: (...args: any[]) => any, ms: number = 0, args: DependencyList = []) { + const cb = useCallback(fn, args); + const [, cancel] = useTimeoutFn(cb, ms); - const cancel = useCallback(() => { - if (timer.current) { - window.clearTimeout(timer.current); - } - }, []); - - return { cancel }; -}; - -export default useDebounce; + return [cancel]; +} From bb0ab036a37be63b97891023c491e5f38a6d27f8 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Mon, 26 Aug 2019 01:04:28 +0300 Subject: [PATCH 004/213] Added state checker; Updated story; Updated docs; --- docs/useDebounce.md | 24 ++++++++++++++++++------ src/__stories__/useDebounce.story.tsx | 7 +++++-- src/useDebounce.ts | 4 ++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/docs/useDebounce.md b/docs/useDebounce.md index 4dc06b324b..a7ef2206e7 100644 --- a/docs/useDebounce.md +++ b/docs/useDebounce.md @@ -7,15 +7,12 @@ The third argument is the array of values that the debounce depends on, in the s ## Usage ```jsx -import React, { useState } from 'react'; -import { useDebounce } from 'react-use'; - const Demo = () => { const [state, setState] = React.useState('Typing stopped'); const [val, setVal] = React.useState(''); const [debouncedValue, setDebouncedValue] = React.useState(''); - useDebounce( + const [, cancel] = useDebounce( () => { setState('Typing stopped'); setDebouncedValue(val); @@ -36,7 +33,10 @@ const Demo = () => { }} />
{state}
-
Debounced value: {debouncedValue}
+
+ Debounced value: {debouncedValue} + +
); }; @@ -45,5 +45,17 @@ const Demo = () => { ## Reference ```ts -const { cancel } = useDebounce(fn, ms: number, args: any[]); +const [ + isReady: () => boolean | null, + cancel: () => void, +] = useDebounce(fn: Function, ms: number, args: DependencyList = []); ``` + +- **`fn`**_`: Function`_ - function that will be called; +- **`ms`**_`: number`_ - delay in milliseconds; +- **`args`**_`: DependencyList`_ - array of values that the debounce depends on, in the same manner as useEffect; +- **`isReady`**_`: ()=>boolean|null`_ - function returning current debounce state: + - `false` - pending + - `true` - called + - `null` - cancelled +- **`cancel`**_`: ()=>void`_ - cancel the debounce diff --git a/src/__stories__/useDebounce.story.tsx b/src/__stories__/useDebounce.story.tsx index 788f33e07d..4e3ba3f41d 100644 --- a/src/__stories__/useDebounce.story.tsx +++ b/src/__stories__/useDebounce.story.tsx @@ -8,7 +8,7 @@ const Demo = () => { const [val, setVal] = React.useState(''); const [debouncedValue, setDebouncedValue] = React.useState(''); - useDebounce( + const [, cancel] = useDebounce( () => { setState('Typing stopped'); setDebouncedValue(val); @@ -29,7 +29,10 @@ const Demo = () => { }} />
{state}
-
Debounced value: {debouncedValue}
+
+ Debounced value: {debouncedValue} + +
); }; diff --git a/src/useDebounce.ts b/src/useDebounce.ts index 6f183ffb65..59af877653 100644 --- a/src/useDebounce.ts +++ b/src/useDebounce.ts @@ -3,7 +3,7 @@ import useTimeoutFn from './useTimeoutFn'; export default function useDebounce(fn: (...args: any[]) => any, ms: number = 0, args: DependencyList = []) { const cb = useCallback(fn, args); - const [, cancel] = useTimeoutFn(cb, ms); + const [isReady, cancel] = useTimeoutFn(cb, ms); - return [cancel]; + return [isReady, cancel]; } From 00e0c2691bd9194c62a91243e7efffa2bf32b389 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Mon, 26 Aug 2019 09:58:28 +0300 Subject: [PATCH 005/213] make useTimeoutFn work properly: - reset function should clear previous timeout; - function change should not reset the timeout; --- docs/useTimeoutFn.md | 11 +++++++---- src/__tests__/useTimeoutFn.test.ts | 24 ++++++++++++++++++++---- src/useTimeoutFn.ts | 15 +++++++++++++-- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/docs/useTimeoutFn.md b/docs/useTimeoutFn.md index 52d259be9f..48e4bc2d99 100644 --- a/docs/useTimeoutFn.md +++ b/docs/useTimeoutFn.md @@ -1,10 +1,13 @@ # `useTimeoutFn` -Calls given function after specified amount of milliseconds. -**Note:** this hook does not re-render component by itself. +Calls given function after specified amount of milliseconds. -Automatically cancels timeout on component unmount. -Automatically resets timeout on delay change. +Several thing about it's work: +- does not re-render component; +- automatically cancel timeout on cancel; +- automatically reset timeout on delay change; +- reset function call will cancel previous timeout; +- timeout will NOT be reset on function change. It will be called within the timeout, you have to reset it on your own when needed. ## Usage diff --git a/src/__tests__/useTimeoutFn.test.ts b/src/__tests__/useTimeoutFn.test.ts index 8164bcdc62..c87739f5e7 100644 --- a/src/__tests__/useTimeoutFn.test.ts +++ b/src/__tests__/useTimeoutFn.test.ts @@ -28,9 +28,11 @@ describe('useTimeoutFn', () => { expect(typeof hook.result.current[2]).toBe('function'); }); - function getHook(ms: number = 5): [jest.Mock, RenderHookResult<{ delay: number }, UseTimeoutFnReturn>] { - const spy = jest.fn(); - return [spy, renderHook(({ delay = 5 }) => useTimeoutFn(spy, delay), { initialProps: { delay: ms } })]; + function getHook( + ms: number = 5, + fn: Function = jest.fn() + ): [Function, RenderHookResult<{ delay: number; cb: Function }, UseTimeoutFnReturn>] { + return [fn, renderHook(({ delay = 5, cb }) => useTimeoutFn(cb, delay), { initialProps: { delay: ms, cb: fn } })]; } it('should call passed function after given amount of time', () => { @@ -108,9 +110,23 @@ describe('useTimeoutFn', () => { const [spy, hook] = getHook(50); expect(spy).not.toHaveBeenCalled(); - hook.rerender({ delay: 5 }); + hook.rerender({ delay: 5, cb: spy }); jest.advanceTimersByTime(5); expect(spy).toHaveBeenCalledTimes(1); }); + + it('should NOT reset timeout on function change', () => { + const [spy, hook] = getHook(50); + + jest.advanceTimersByTime(25); + expect(spy).not.toHaveBeenCalled(); + + const spy2 = jest.fn(); + hook.rerender({ delay: 5, cb: spy2 }); + + jest.advanceTimersByTime(25); + expect(spy).not.toHaveBeenCalled(); + expect(spy2).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/useTimeoutFn.ts b/src/useTimeoutFn.ts index 8bede34f9d..4f9e8c50d5 100644 --- a/src/useTimeoutFn.ts +++ b/src/useTimeoutFn.ts @@ -5,20 +5,31 @@ export type UseTimeoutFnReturn = [() => boolean | null, () => void, () => void]; export default function useTimeoutFn(fn: Function, ms: number = 0): UseTimeoutFnReturn { const ready = useRef(false); const timeout = useRef>(); + const callback = useRef(fn); const isReady = useCallback(() => ready.current, []); + const set = useCallback(() => { ready.current = false; + timeout.current && clearTimeout(timeout.current); + timeout.current = setTimeout(() => { ready.current = true; - fn(); + callback.current(); }, ms); - }, [ms, fn]); + }, [ms]); + const clear = useCallback(() => { ready.current = null; timeout.current && clearTimeout(timeout.current); }, []); + // update ref when function changes + useEffect(() => { + callback.current = fn; + }, [fn]); + + // set on mount, clear on unmount useEffect(() => { set(); From 42fdec140b5a16ed828bf9b1718655dd485b40e7 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Mon, 26 Aug 2019 09:39:22 +0300 Subject: [PATCH 006/213] useDebounce: - tests; - fix function change debounce clear and reset; - declare return type; --- docs/useDebounce.md | 4 +- src/__tests__/useDebounce.test.ts | 116 ++++++++++++++++++++++++++++++ src/useDebounce.ts | 15 ++-- 3 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 src/__tests__/useDebounce.test.ts diff --git a/docs/useDebounce.md b/docs/useDebounce.md index a7ef2206e7..151e9a2af8 100644 --- a/docs/useDebounce.md +++ b/docs/useDebounce.md @@ -48,12 +48,12 @@ const Demo = () => { const [ isReady: () => boolean | null, cancel: () => void, -] = useDebounce(fn: Function, ms: number, args: DependencyList = []); +] = useDebounce(fn: Function, ms: number, deps: DependencyList = []); ``` - **`fn`**_`: Function`_ - function that will be called; - **`ms`**_`: number`_ - delay in milliseconds; -- **`args`**_`: DependencyList`_ - array of values that the debounce depends on, in the same manner as useEffect; +- **`deps`**_`: DependencyList`_ - array of values that the debounce depends on, in the same manner as useEffect; - **`isReady`**_`: ()=>boolean|null`_ - function returning current debounce state: - `false` - pending - `true` - called diff --git a/src/__tests__/useDebounce.test.ts b/src/__tests__/useDebounce.test.ts new file mode 100644 index 0000000000..128f68a95b --- /dev/null +++ b/src/__tests__/useDebounce.test.ts @@ -0,0 +1,116 @@ +import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks'; +import { DependencyList } from 'react'; +import { useDebounce } from '../index'; +import { UseDebounceReturn } from '../useDebounce'; + +describe('useDebounce', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + it('should be defined', () => { + expect(useDebounce).toBeDefined(); + }); + + it('should return three functions', () => { + const hook = renderHook(() => useDebounce(() => {}, 5)); + + expect(hook.result.current.length).toBe(2); + expect(typeof hook.result.current[0]).toBe('function'); + expect(typeof hook.result.current[1]).toBe('function'); + }); + + function getHook( + ms: number = 5, + dep: DependencyList = [] + ): [jest.Mock, RenderHookResult<{ delay: number; deps: DependencyList }, UseDebounceReturn>] { + const spy = jest.fn(); + return [ + spy, + renderHook(({ delay = 5, deps = [] }) => useDebounce(spy, delay, deps), { + initialProps: { + delay: ms, + deps: dep, + }, + }), + ]; + } + + it('should call passed function after given amount of time', () => { + const [spy] = getHook(); + + expect(spy).not.toHaveBeenCalled(); + jest.advanceTimersByTime(5); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should cancel function call on unmount', () => { + const [spy, hook] = getHook(); + + expect(spy).not.toHaveBeenCalled(); + hook.unmount(); + jest.advanceTimersByTime(5); + expect(spy).not.toHaveBeenCalled(); + }); + + it('first function should return actual state of debounce', () => { + let [, hook] = getHook(); + let [isReady] = hook.result.current; + + expect(isReady()).toBe(false); + hook.unmount(); + expect(isReady()).toBe(null); + + [, hook] = getHook(); + [isReady] = hook.result.current; + jest.advanceTimersByTime(5); + expect(isReady()).toBe(true); + }); + + it('second function should cancel debounce', () => { + const [spy, hook] = getHook(); + const [isReady, cancel] = hook.result.current; + + expect(spy).not.toHaveBeenCalled(); + expect(isReady()).toBe(false); + + act(() => { + cancel(); + }); + jest.advanceTimersByTime(5); + + expect(spy).not.toHaveBeenCalled(); + expect(isReady()).toBe(null); + }); + + it('should reset timeout on delay change', () => { + const [spy, hook] = getHook(50); + + expect(spy).not.toHaveBeenCalled(); + hook.rerender({ delay: 5, deps: [] }); + + jest.advanceTimersByTime(5); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should reset timeout on deps change', () => { + const [spy, hook] = getHook(50, [5, 6]); + + jest.advanceTimersByTime(45); + expect(spy).not.toHaveBeenCalled(); + hook.rerender({ delay: 50, deps: [6, 6] }); + + jest.advanceTimersByTime(45); + expect(spy).not.toHaveBeenCalled(); + jest.advanceTimersByTime(5); + expect(spy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/useDebounce.ts b/src/useDebounce.ts index 59af877653..c9fc77331a 100644 --- a/src/useDebounce.ts +++ b/src/useDebounce.ts @@ -1,9 +1,16 @@ -import { DependencyList, useCallback } from 'react'; +import { DependencyList, useEffect } from 'react'; import useTimeoutFn from './useTimeoutFn'; -export default function useDebounce(fn: (...args: any[]) => any, ms: number = 0, args: DependencyList = []) { - const cb = useCallback(fn, args); - const [isReady, cancel] = useTimeoutFn(cb, ms); +export type UseDebounceReturn = [() => boolean | null, () => void]; + +export default function useDebounce( + fn: (...args: any[]) => any, + ms: number = 0, + deps: DependencyList = [] +): UseDebounceReturn { + const [isReady, cancel, reset] = useTimeoutFn(fn, ms); + + useEffect(reset, deps); return [isReady, cancel]; } From 664b071d2d8aaeb80f27fdead39049be2755fadf Mon Sep 17 00:00:00 2001 From: Rogdham Date: Tue, 3 Sep 2019 16:14:28 +0200 Subject: [PATCH 007/213] Improve useThrottleFn type definition --- src/useThrottleFn.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/useThrottleFn.ts b/src/useThrottleFn.ts index fafbe7b883..c0c0aa7753 100644 --- a/src/useThrottleFn.ts +++ b/src/useThrottleFn.ts @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import useUnmount from './useUnmount'; -const useThrottleFn = (fn: (...args: any[]) => T, ms: number = 200, args: any[]) => { +const useThrottleFn = (fn: (...args: U) => T, ms: number = 200, args: U) => { const [state, setState] = useState(null as any); const timeout = useRef>(); const nextArgs = useRef(null) as any; From fd8905a25ec036c35a6fe766e703713ba778182e Mon Sep 17 00:00:00 2001 From: macinjoke Date: Wed, 4 Sep 2019 02:48:21 +0900 Subject: [PATCH 008/213] add useEvent test --- src/__tests__/useEvent.test.ts | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/__tests__/useEvent.test.ts diff --git a/src/__tests__/useEvent.test.ts b/src/__tests__/useEvent.test.ts new file mode 100644 index 0000000000..ec124600ba --- /dev/null +++ b/src/__tests__/useEvent.test.ts @@ -0,0 +1,118 @@ +import { renderHook } from '@testing-library/react-hooks'; +import useEvent, { ListenerType1, ListenerType2 } from '../useEvent'; + +interface Props { + name: string; + handler: (...args: any[]) => void; + target: ListenerType1 | ListenerType2; + options: any; +} + +const propsList1 = [ + { + name: 'name1', + handler: () => {}, + target: { + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + }, + options: { a: 'opt1' }, + }, + { + name: 'name2', + handler: () => {}, + target: { + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + }, + options: { a: 'opt2' }, + }, +]; + +const propsList2 = [ + { + ...propsList1[0], + target: { + on: jest.fn(), + off: jest.fn(), + }, + }, + { + ...propsList1[1], + target: { + on: jest.fn(), + off: jest.fn(), + }, + }, +]; + +it('should call addEventListener/removeEventListener on mount/unmount', () => { + checkOnMountAndUnmount(propsList1[0], 'addEventListener', 'removeEventListener'); +}); + +it('should call on/off on mount/unmount', () => { + checkOnMountAndUnmount(propsList2[0], 'on', 'off'); +}); + +it('should call addEventListener/removeEventListener on deps changes', () => { + checkOnDepsChanges(propsList1[0], propsList1[1], 'addEventListener', 'removeEventListener'); +}); + +it('should call on/off on deps changes', () => { + checkOnDepsChanges(propsList2[0], propsList2[1], 'on', 'off'); +}); + +const checkOnMountAndUnmount = (props: Props, addEventListenerName: string, removeEventListenerName: string) => { + const { unmount } = renderHook((p: Props) => useEvent(p.name, p.handler, p.target, p.options), { + initialProps: props, + }); + expect(props.target[addEventListenerName]).toHaveBeenCalledTimes(1); + expect(props.target[addEventListenerName]).toHaveBeenLastCalledWith(props.name, props.handler, props.options); + unmount(); + expect(props.target[removeEventListenerName]).toHaveBeenCalledTimes(1); + expect(props.target[removeEventListenerName]).toHaveBeenLastCalledWith(props.name, props.handler, props.options); +}; + +const checkOnDepsChanges = ( + props1: Props, + props2: Props, + addEventListenerName: string, + removeEventListenerName: string +) => { + const { rerender } = renderHook((p: Props) => useEvent(p.name, p.handler, p.target, p.options), { + initialProps: props1, + }); + expect(props1.target[addEventListenerName]).toHaveBeenCalledTimes(1); + expect(props1.target[addEventListenerName]).toHaveBeenLastCalledWith(props1.name, props1.handler, props1.options); + + // deps are same as previous + rerender({ name: props1.name, handler: props1.handler, target: props1.target, options: props1.options }); + expect(props1.target[removeEventListenerName]).not.toHaveBeenCalled(); + + // name is different from previous + rerender({ name: props2.name, handler: props1.handler, target: props1.target, options: props1.options }); + expect(props1.target[removeEventListenerName]).toHaveBeenCalledTimes(1); + expect(props1.target[removeEventListenerName]).toHaveBeenLastCalledWith(props1.name, props1.handler, props1.options); + + // handler is different from previous + rerender({ name: props2.name, handler: props2.handler, target: props1.target, options: props1.options }); + expect(props1.target[removeEventListenerName]).toHaveBeenCalledTimes(2); + expect(props1.target[removeEventListenerName]).toHaveBeenLastCalledWith(props2.name, props1.handler, props1.options); + + // options contents is same as previous + rerender({ name: props2.name, handler: props2.handler, target: props1.target, options: { a: 'opt1' } }); + expect(props1.target[removeEventListenerName]).toHaveBeenCalledTimes(2); + + // options is different from previous + rerender({ name: props2.name, handler: props2.handler, target: props1.target, options: props2.options }); + expect(props1.target[removeEventListenerName]).toHaveBeenCalledTimes(3); + expect(props1.target[removeEventListenerName]).toHaveBeenLastCalledWith(props2.name, props2.handler, props1.options); + + // target is different from previous + rerender({ name: props2.name, handler: props2.handler, target: props2.target, options: props2.options }); + expect(props1.target[removeEventListenerName]).toHaveBeenCalledTimes(4); + expect(props1.target[removeEventListenerName]).toHaveBeenLastCalledWith(props2.name, props2.handler, props2.options); + + expect(props2.target[addEventListenerName]).toHaveBeenCalledTimes(1); + expect(props2.target[addEventListenerName]).toHaveBeenLastCalledWith(props2.name, props2.handler, props2.options); +}; From 0fb314863eacaf80772631626a5db416e5f4c698 Mon Sep 17 00:00:00 2001 From: macinjoke Date: Fri, 6 Sep 2019 23:14:34 +0900 Subject: [PATCH 009/213] improve useEvent type inference --- src/useEvent.ts | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/useEvent.ts b/src/useEvent.ts index 3074df6ddc..b9c1ec4c36 100644 --- a/src/useEvent.ts +++ b/src/useEvent.ts @@ -3,25 +3,32 @@ import { isClient } from './util'; export interface ListenerType1 { addEventListener(name: string, handler: (event?: any) => void, ...args: any[]); - - removeEventListener(name: string, handler: (event?: any) => void); + removeEventListener(name: string, handler: (event?: any) => void, ...args: any[]); } export interface ListenerType2 { on(name: string, handler: (event?: any) => void, ...args: any[]); - - off(name: string, handler: (event?: any) => void); + off(name: string, handler: (event?: any) => void, ...args: any[]); } export type UseEventTarget = ListenerType1 | ListenerType2; const defaultTarget = isClient ? window : null; -const useEvent = ( - name: string, - handler?: null | undefined | ((event?: any) => void), - target: null | UseEventTarget = defaultTarget, - options?: any +const isListenerType1 = (target: any): target is ListenerType1 => { + return !!target.addEventListener; +}; +const isListenerType2 = (target: any): target is ListenerType2 => { + return !!target.on; +}; + +type AddEventListener = T extends ListenerType1 ? T['addEventListener'] : T extends ListenerType2 ? T['on'] : never; + +const useEvent = ( + name: Parameters>[0], + handler?: null | undefined | Parameters>[1], + target: null | T | Window = defaultTarget, + options?: Parameters>[2] ) => { useEffect(() => { if (!handler) { @@ -30,11 +37,17 @@ const useEvent = ( if (!target) { return; } - const fn: any = (target as ListenerType1).addEventListener || (target as ListenerType2).on; - fn.call(target, name, handler, options); + if (isListenerType1(target)) { + target.addEventListener(name, handler, options); + } else if (isListenerType2(target)) { + target.on(name, handler, options); + } return () => { - const cleanFn: any = (target as ListenerType1).removeEventListener || (target as ListenerType2).off; - cleanFn.call(target, name, handler, options); + if (isListenerType1(target)) { + target.removeEventListener(name, handler, options); + } else if (isListenerType2(target)) { + target.off(name, handler, options); + } }; }, [name, handler, target, JSON.stringify(options)]); }; From a8b41f5e6510a319d742facfe9ac961d598ab9ce Mon Sep 17 00:00:00 2001 From: Sergei Droganov Date: Wed, 18 Sep 2019 15:47:23 +0300 Subject: [PATCH 010/213] useQueue hook --- README.md | 1 + docs/useQueue.md | 26 +++++++++++++++++++++ src/__stories__/useQueue.story.tsx | 23 +++++++++++++++++++ src/__tests__/useQueue.test.ts | 33 ++++++++++++++++++++++++++ src/index.ts | 1 + src/useQueue.ts | 37 ++++++++++++++++++++++++++++++ 6 files changed, 121 insertions(+) create mode 100644 docs/useQueue.md create mode 100644 src/__stories__/useQueue.story.tsx create mode 100644 src/__tests__/useQueue.test.ts create mode 100644 src/useQueue.ts diff --git a/README.md b/README.md index f54afa21d6..358a7f329c 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ - [`useCounter` and `useNumber`](./docs/useCounter.md) — tracks state of a number. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usecounter--demo) - [`useList`](./docs/useList.md) — tracks state of an array. - [`useMap`](./docs/useMap.md) — tracks state of an object. + - [`useQueue`](./docs/useQueue.md) — implements simple queue.
diff --git a/docs/useQueue.md b/docs/useQueue.md new file mode 100644 index 0000000000..6ba34ba238 --- /dev/null +++ b/docs/useQueue.md @@ -0,0 +1,26 @@ +# `useQueue` + +React state hook implements simple queue. + + +## Usage + +```jsx +import { useQueue } from 'react-use'; + +const Demo = () => { + const { add, pop, first, last, size } = useQueue(); + + return ( +
+
    +
  • first: {first}
  • +
  • last: {last}
  • +
  • size: {size}
  • +
+ + +
+ ); +}; +``` diff --git a/src/__stories__/useQueue.story.tsx b/src/__stories__/useQueue.story.tsx new file mode 100644 index 0000000000..1c201df6bb --- /dev/null +++ b/src/__stories__/useQueue.story.tsx @@ -0,0 +1,23 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { useQueue } from '..'; +import ShowDocs from './util/ShowDocs'; + +const Demo = () => { + const { add, pop, first, last, size } = useQueue(); + return ( +
+
    +
  • first: {first}
  • +
  • last: {last}
  • +
  • size: {size}
  • +
+ + +
+ ); +}; + +storiesOf('State|useQueue', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/__tests__/useQueue.test.ts b/src/__tests__/useQueue.test.ts new file mode 100644 index 0000000000..9b53f73ec7 --- /dev/null +++ b/src/__tests__/useQueue.test.ts @@ -0,0 +1,33 @@ +import { act, renderHook } from '@testing-library/react-hooks'; +import useQueue from '../useQueue'; + +const setUp = (initialQueue?: any[]) => renderHook(() => useQueue(initialQueue)); + +it('takes initial state', () => { + const { result } = setUp([1, 2, 3]); + const { first, last, size } = result.current; + expect(first).toEqual(1); + expect(last).toEqual(3); + expect(size).toEqual(3); +}); + +it('appends new member', () => { + const { result } = setUp([1, 2]); + act(() => { + result.current.add(3); + }); + const { first, last, size } = result.current; + expect(first).toEqual(1); + expect(last).toEqual(3); + expect(size).toEqual(3); +}); + +it('pops oldest member', () => { + const { result } = setUp([1, 2]); + act(() => { + result.current.pop(); + }); + const { first, size } = result.current; + expect(first).toEqual(2); + expect(size).toEqual(1); +}); diff --git a/src/index.ts b/src/index.ts index b3514a7179..cc1fd945cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,6 +57,7 @@ export { default as usePermission } from './usePermission'; export { default as usePrevious } from './usePrevious'; export { default as usePreviousDistinct } from './usePreviousDistinct'; export { default as usePromise } from './usePromise'; +export { default as useQueue } from './useQueue'; export { default as useRaf } from './useRaf'; export { default as useRafLoop } from './useRafLoop'; /** diff --git a/src/useQueue.ts b/src/useQueue.ts new file mode 100644 index 0000000000..795e2735d9 --- /dev/null +++ b/src/useQueue.ts @@ -0,0 +1,37 @@ +import { useState } from 'react'; + +export interface QueueMethods { + add: (item: T) => void; + pop: () => T; + first: T; + last: T; + size: number; +} + +const useQueue = (initialValue: T[] = []): QueueMethods => { + const [state, set] = useState(initialValue); + return { + add: value => { + set(queue => [...queue, value]); + }, + pop: () => { + let result; + set(([first, ...rest]) => { + result = first; + return rest; + }); + return result; + }, + get first() { + return state[0]; + }, + get last() { + return state[state.length - 1]; + }, + get size() { + return state.length; + }, + }; +}; + +export default useQueue; From 15e9bd2bd5e8877fe84561774622aebe43d32af5 Mon Sep 17 00:00:00 2001 From: Sergei Droganov Date: Sun, 22 Sep 2019 15:10:27 +0300 Subject: [PATCH 011/213] rename pop ro remove --- docs/useQueue.md | 6 +++--- src/__stories__/useQueue.story.tsx | 4 ++-- src/__tests__/useQueue.test.ts | 2 +- src/useQueue.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/useQueue.md b/docs/useQueue.md index 6ba34ba238..ab05d2f78d 100644 --- a/docs/useQueue.md +++ b/docs/useQueue.md @@ -1,6 +1,6 @@ # `useQueue` -React state hook implements simple queue. +React state hook implements simple FIFO queue. ## Usage @@ -9,7 +9,7 @@ React state hook implements simple queue. import { useQueue } from 'react-use'; const Demo = () => { - const { add, pop, first, last, size } = useQueue(); + const { add, remove, first, last, size } = useQueue(); return (
@@ -19,7 +19,7 @@ const Demo = () => {
  • size: {size}
  • - +
    ); }; diff --git a/src/__stories__/useQueue.story.tsx b/src/__stories__/useQueue.story.tsx index 1c201df6bb..ecb7ab43c8 100644 --- a/src/__stories__/useQueue.story.tsx +++ b/src/__stories__/useQueue.story.tsx @@ -4,7 +4,7 @@ import { useQueue } from '..'; import ShowDocs from './util/ShowDocs'; const Demo = () => { - const { add, pop, first, last, size } = useQueue(); + const { add, remove, first, last, size } = useQueue(); return (
      @@ -13,7 +13,7 @@ const Demo = () => {
    • size: {size}
    - +
    ); }; diff --git a/src/__tests__/useQueue.test.ts b/src/__tests__/useQueue.test.ts index 9b53f73ec7..4a155ff3b2 100644 --- a/src/__tests__/useQueue.test.ts +++ b/src/__tests__/useQueue.test.ts @@ -25,7 +25,7 @@ it('appends new member', () => { it('pops oldest member', () => { const { result } = setUp([1, 2]); act(() => { - result.current.pop(); + result.current.remove(); }); const { first, size } = result.current; expect(first).toEqual(2); diff --git a/src/useQueue.ts b/src/useQueue.ts index 795e2735d9..97a8372dce 100644 --- a/src/useQueue.ts +++ b/src/useQueue.ts @@ -2,7 +2,7 @@ import { useState } from 'react'; export interface QueueMethods { add: (item: T) => void; - pop: () => T; + remove: () => T; first: T; last: T; size: number; @@ -14,7 +14,7 @@ const useQueue = (initialValue: T[] = []): QueueMethods => { add: value => { set(queue => [...queue, value]); }, - pop: () => { + remove: () => { let result; set(([first, ...rest]) => { result = first; From da0e66bb89af309f0da4f21c837f438a8b447331 Mon Sep 17 00:00:00 2001 From: qianL93 Date: Thu, 10 Oct 2019 14:14:54 +0800 Subject: [PATCH 012/213] fix: useSize avoid crash in Safari 11 --- src/useSize.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/useSize.tsx b/src/useSize.tsx index c0f8776fa0..214ceaf16c 100644 --- a/src/useSize.tsx +++ b/src/useSize.tsx @@ -67,7 +67,7 @@ const useSize = ( } return () => { - if (window) { + if (window && window.removeEventListener) { window.removeEventListener('resize', setSize); } }; From 9df69c6e00a600d597a4d88a3ab7ded4b8695738 Mon Sep 17 00:00:00 2001 From: Ward Oosterlijnck Date: Wed, 27 Mar 2019 08:19:44 +1100 Subject: [PATCH 013/213] useVibrate --- docs/useVibrate.md | 0 src/__stories__/useVibrate.story.tsx | 20 +++++++++++++++ src/index.ts | 1 + src/useVibrate.ts | 37 ++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 docs/useVibrate.md create mode 100644 src/__stories__/useVibrate.story.tsx create mode 100644 src/useVibrate.ts diff --git a/docs/useVibrate.md b/docs/useVibrate.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/__stories__/useVibrate.story.tsx b/src/__stories__/useVibrate.story.tsx new file mode 100644 index 0000000000..f521771ceb --- /dev/null +++ b/src/__stories__/useVibrate.story.tsx @@ -0,0 +1,20 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { useVibrate, useToggle } from '..'; +import ShowDocs from './util/ShowDocs'; + +const Demo = () => { + const [vibrating, toggleVibrating] = useToggle(false); + + useVibrate(vibrating, [300, 100, 200, 100, 1000, 300]); + + return ( +
    + +
    + ); +}; + +storiesOf('UI|useVibrate', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/index.ts b/src/index.ts index 65872134d6..745dae63b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -86,6 +86,7 @@ export { default as useUnmount } from './useUnmount'; export { default as useUpdate } from './useUpdate'; export { default as useUpdateEffect } from './useUpdateEffect'; export { default as useUpsert } from './useUpsert'; +export { default as useVibrate } from './useVibrate'; export { default as useVideo } from './useVideo'; export { default as useStateValidator } from './useStateValidator'; export { useWait, Waiter } from './useWait'; diff --git a/src/useVibrate.ts b/src/useVibrate.ts new file mode 100644 index 0000000000..23f7c619a8 --- /dev/null +++ b/src/useVibrate.ts @@ -0,0 +1,37 @@ +import { useEffect } from 'react'; + +export type VibrationPattern = number | number[]; + +const isVibrationApiSupported = typeof navigator === 'object' && 'vibrate' in navigator; + +const useVibrateMock = () => {}; + +function useVibrate(enabled: boolean = true, pattern: VibrationPattern = [1000, 1000], loop: boolean = true): void { + useEffect(() => { + let interval; + + if (enabled) { + navigator.vibrate(pattern); + + if (loop) { + const duration = pattern instanceof Array ? pattern.reduce((a, b) => a + b) : (pattern as number); + + interval = setInterval(() => { + navigator.vibrate(pattern); + }, duration); + } + } + + return () => { + if (enabled) { + navigator.vibrate(0); + + if (loop) { + clearInterval(interval); + } + } + }; + }, [enabled]); +} + +export default isVibrationApiSupported ? useVibrate : useVibrateMock; From 24ae8f392cc07024d93ba8508ea8bcdfd7f146eb Mon Sep 17 00:00:00 2001 From: Ward Oosterlijnck Date: Sun, 13 Oct 2019 22:28:58 +1100 Subject: [PATCH 014/213] useVibrate docs --- README.md | 1 + docs/useVibrate.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/README.md b/README.md index ebe6c734db..15a1823a0f 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ - [`useDrop` and `useDropArea`](./docs/useDrop.md) — tracks file, link and copy-paste drops. - [`useFullscreen`](./docs/useFullscreen.md) — display an element or video full-screen. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-usefullscreen--demo) - [`useSpeech`](./docs/useSpeech.md) — synthesizes speech from a text string. [![][img-demo]](https://codesandbox.io/s/n090mqz69m) + - [`useVibrate`](./docs/useVibrate.md) — provide physical feedback using the [Vibration API](https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API). [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-usevibrate--demo) - [`useVideo`](./docs/useVideo.md) — plays video, tracks its state, and exposes playback controls. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-usevideo--demo) - [`useWait`](./docs/useWait.md) — complex waiting management for UIs.
    diff --git a/docs/useVibrate.md b/docs/useVibrate.md index e69de29bb2..957d01149f 100644 --- a/docs/useVibrate.md +++ b/docs/useVibrate.md @@ -0,0 +1,31 @@ +# `useVibrate` + +React UI hook to provide physical feedback with device vibration hardware using the [Vibration API](https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API). + +## Usage + +```jsx +import {useVibrate} from 'react-use'; + +const Demo = () => { + const [vibrating, toggleVibrating] = useToggle(false); + + useVibrate(vibrating, [300, 100, 200, 100, 1000, 300], false); + + return ( +
    + +
    + ); +}; +``` + +## Reference + +```ts +useVibrate( + enabled: boolean = true, + pattern: number | number[] = [1000, 1000], + loop: boolean = true +): void; +``` From cb4a735b84efeaee711de97b0cf00a0db8ee7193 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Mon, 14 Oct 2019 20:30:07 +0300 Subject: [PATCH 015/213] useMediatedState implementation, tests and docs; --- README.md | 1 + docs/useMediatedState.md | 42 +++++++++++++ src/__stories__/useMediatedState.story.tsx | 28 +++++++++ src/__tests__/useMediatedState.test.ts | 68 ++++++++++++++++++++++ src/index.ts | 1 + src/useMediatedState.ts | 32 ++++++++++ 6 files changed, 172 insertions(+) create mode 100644 docs/useMediatedState.md create mode 100644 src/__stories__/useMediatedState.story.tsx create mode 100644 src/__tests__/useMediatedState.test.ts create mode 100644 src/useMediatedState.ts diff --git a/README.md b/README.md index ebe6c734db..502864511c 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ - [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w) - [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161) - [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo) + - [`useMedisatedState`](./docs/useMediatedState.md) — like the regular `useState` but with mediation by custom function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemediatedstate--demo)

    diff --git a/docs/useMediatedState.md b/docs/useMediatedState.md new file mode 100644 index 0000000000..34a5cdb590 --- /dev/null +++ b/docs/useMediatedState.md @@ -0,0 +1,42 @@ +# `useMediatedState` + +A lot like the standard `useState`, but with mediation process. + +## Usage +```ts +import * as React from 'react'; +import { useMediatedState } from '../useMediatedState'; + +const InputMediator = s => s.replace(/[\s]+/, ' '); +const Demo = () => { + const [state, setState] = useMediatedState('', InputMediator); + + return ( +
    +
    You will not be able to enter more than one space
    + ) => { + setState(ev.target.value); + }} + /> +
    + ); +}; +``` + +## Reference +```ts +const [state, setState] = useMediatedState( + mediator: StateMediator, + initialState?: S +); +``` + +> Initial state will be set as-is. + +In case mediator expects 2 arguments it will receive the `setState` function as second argument, it is useful for async mediators. +>This hook will not cancel previous mediation when new one been invoked, you have to handle it yourself._ diff --git a/src/__stories__/useMediatedState.story.tsx b/src/__stories__/useMediatedState.story.tsx new file mode 100644 index 0000000000..d3c946f6dd --- /dev/null +++ b/src/__stories__/useMediatedState.story.tsx @@ -0,0 +1,28 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { useMediatedState } from '../useMediatedState'; +import ShowDocs from './util/ShowDocs'; + +const InputMediator = s => s.replace(/[\s]+/, ' '); +const Demo = () => { + const [state, setState] = useMediatedState(InputMediator, ''); + + return ( +
    +
    You will not be able to enter more than one space
    + ) => { + setState(ev.target.value); + }} + /> +
    + ); +}; + +storiesOf('State|useMediatedState', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/__tests__/useMediatedState.test.ts b/src/__tests__/useMediatedState.test.ts new file mode 100644 index 0000000000..ef9838a9de --- /dev/null +++ b/src/__tests__/useMediatedState.test.ts @@ -0,0 +1,68 @@ +import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks'; +import { Dispatch, SetStateAction } from 'react'; +import { useMediatedState } from '../'; +import { StateMediator, UseMediatedStateReturn } from '../useMediatedState'; + +describe('useMediatedState', () => { + it('should be defined', () => { + expect(useMediatedState).toBeDefined(); + }); + + function getHook( + initialState: number = 2, + fn: StateMediator = jest.fn(newState => newState / 2) + ): [jest.Mock | StateMediator, RenderHookResult>] { + return [fn, renderHook(() => useMediatedState(fn, initialState))]; + } + + it('should return array of two elements', () => { + const [, hook] = getHook(); + + expect(Array.isArray(hook.result.current)).toBe(true); + expect(hook.result.current[0]).toBe(2); + expect(typeof hook.result.current[1]).toBe('function'); + }); + + it('should act like regular useState but with mediator call on each setState', () => { + const [spy, hook] = getHook(); + + expect(hook.result.current[0]).toBe(2); + + act(() => hook.result.current[1](3)); + expect(hook.result.current[0]).toBe(1.5); + expect(spy).toHaveBeenCalledTimes(1); + + act(() => hook.result.current[1](4)); + expect(hook.result.current[0]).toBe(2); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('should not call mediator on init', () => { + const [spy] = getHook(); + + expect(spy).toHaveBeenCalledTimes(0); + }); + + it('mediator should receive setState argument as first argument', () => { + let val; + const spy = jest.fn(newState => { + val = newState; + return newState * 2; + }); + const [, hook] = getHook(1, spy); + + act(() => hook.result.current[1](3)); + expect(val).toBe(3); + expect(hook.result.current[0]).toBe(6); + }); + + it('if mediator expects 2 args, second should be a function setting the state', () => { + const spy = (jest.fn((newState: number, setState: Dispatch>): void => { + setState(newState * 2); + }) as unknown) as StateMediator; + const [, hook] = getHook(1, spy); + + act(() => hook.result.current[1](3)); + expect(hook.result.current[0]).toBe(6); + }); +}); diff --git a/src/index.ts b/src/index.ts index 65872134d6..e1e9b33781 100644 --- a/src/index.ts +++ b/src/index.ts @@ -44,6 +44,7 @@ export { default as useLogger } from './useLogger'; export { default as useMap } from './useMap'; export { default as useMedia } from './useMedia'; export { default as useMediaDevices } from './useMediaDevices'; +export { useMediatedState } from './useMediatedState'; export { default as useMotion } from './useMotion'; export { default as useMount } from './useMount'; export { default as useMountedState } from './useMountedState'; diff --git a/src/useMediatedState.ts b/src/useMediatedState.ts new file mode 100644 index 0000000000..708b2ecf92 --- /dev/null +++ b/src/useMediatedState.ts @@ -0,0 +1,32 @@ +import { Dispatch, SetStateAction, useCallback, useRef, useState } from 'react'; + +export interface StateMediator { + (newState: any): S; + + (newState: any, dispatch: Dispatch>): void; +} + +export type UseMediatedStateReturn = [S, Dispatch>]; + +export function useMediatedState( + mediator: StateMediator +): UseMediatedStateReturn; +export function useMediatedState(mediator: StateMediator, initialState: S): UseMediatedStateReturn; + +export function useMediatedState(mediator: StateMediator, initialState?: S): UseMediatedStateReturn { + const mediatorFn = useRef(mediator); + + const [state, setMediatedState] = useState(initialState!); + const setState = useCallback( + (newState: any) => { + if (mediatorFn.current.length === 2) { + mediatorFn.current(newState, setMediatedState); + } else { + setMediatedState(mediatorFn.current(newState)); + } + }, + [state] + ); + + return [state, setState]; +} From ae2698891be952f45d2ea9af0027497d1030f0ae Mon Sep 17 00:00:00 2001 From: xobotyi Date: Wed, 16 Oct 2019 12:14:41 +0300 Subject: [PATCH 016/213] feat: useMultiStateValidator --- README.md | 1 + docs/useMultiStateValidator.md | 55 ++++++++ .../useMultiStateValidator.story.tsx | 51 +++++++ src/__tests__/useMultiStateValidator.ts | 125 ++++++++++++++++++ src/index.ts | 1 + src/useMultiStateValidator.ts | 41 ++++++ 6 files changed, 274 insertions(+) create mode 100644 docs/useMultiStateValidator.md create mode 100644 src/__stories__/useMultiStateValidator.story.tsx create mode 100644 src/__tests__/useMultiStateValidator.ts create mode 100644 src/useMultiStateValidator.ts diff --git a/README.md b/README.md index ebe6c734db..33f88b1bcd 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ - [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w) - [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161) - [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo) + - [`useMultiStateValidator`](./docs/useMultiStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemultistatevalidator--demo)

    diff --git a/docs/useMultiStateValidator.md b/docs/useMultiStateValidator.md new file mode 100644 index 0000000000..42de5b1e88 --- /dev/null +++ b/docs/useMultiStateValidator.md @@ -0,0 +1,55 @@ +# `useMultiStateValidator` + +Each time any of given states changes - validator function is invoked. + +## Usage +```ts +import * as React from 'react'; +import { useMultiStateValidator } from 'react-use'; + +const DemoStateValidator = (s: number[]) => [s.every((num: number) => !(num % 2))] as [boolean]; +const Demo = () => { + const [state1, setState1] = React.useState(1); + const [state2, setState2] = React.useState(1); + const [state3, setState3] = React.useState(1); + const [[isValid]] = useMultiStateValidator([state1, state2, state3], DemoStateValidator); + + return ( +
    +
    Below fields will be valid if all of them is even
    + ) => { + setState1((ev.target.value as unknown) as number); + }} + /> + ) => { + setState2((ev.target.value as unknown) as number); + }} + /> + ) => { + setState3((ev.target.value as unknown) as number); + }} + /> + {isValid !== null && {isValid ? 'Valid!' : 'Invalid'}} +
    + ); +}; +``` + +## Reference +```ts +const [validity, revalidate] = useStateValidator( + state: any[] | { [p: string]: any } | { [p: number]: any }, + validator: (state, setValidity?)=>[boolean|null, ...any[]], + initialValidity: any = [undefined] +); +``` +- **`state`**_`: any[] | { [p: string]: any } | { [p: number]: any }`_ can be both an array or object. It's _values_ will be used as a deps for inner `useEffect`. +- **`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; + - `states` - current states values as the've been passed to the hook; + - `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; diff --git a/src/__stories__/useMultiStateValidator.story.tsx b/src/__stories__/useMultiStateValidator.story.tsx new file mode 100644 index 0000000000..91eb619401 --- /dev/null +++ b/src/__stories__/useMultiStateValidator.story.tsx @@ -0,0 +1,51 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { useMultiStateValidator } from '../'; +import ShowDocs from './util/ShowDocs'; + +const DemoStateValidator = (s: number[]) => [s.every((num: number) => !(num % 2))] as [boolean]; +const Demo = () => { + const [state1, setState1] = React.useState(1); + const [state2, setState2] = React.useState(1); + const [state3, setState3] = React.useState(1); + const [[isValid]] = useMultiStateValidator([state1, state2, state3], DemoStateValidator); + + return ( +
    +
    Below fields will be valid if all of them is even
    +
    + ) => { + setState1((ev.target.value as unknown) as number); + }} + /> + ) => { + setState2((ev.target.value as unknown) as number); + }} + /> + ) => { + setState3((ev.target.value as unknown) as number); + }} + /> + {isValid !== null && {isValid ? 'Valid!' : 'Invalid'}} +
    + ); +}; + +storiesOf('State|useMultiStateValidator', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/__tests__/useMultiStateValidator.ts b/src/__tests__/useMultiStateValidator.ts new file mode 100644 index 0000000000..392af53d1d --- /dev/null +++ b/src/__tests__/useMultiStateValidator.ts @@ -0,0 +1,125 @@ +import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks'; +import { useState } from 'react'; +import { MultiStateValidator, useMultiStateValidator } from '../useMultiStateValidator'; +import { UseValidatorReturn, ValidityState } from '../useStateValidator'; + +interface Mock extends jest.Mock {} + +describe('useMultiStateValidator', () => { + it('should be defined', () => { + expect(useMultiStateValidator).toBeDefined(); + }); + + const defaultStatesValidator = (states: number[]) => [states.every(num => !(num % 2))]; + + function getHook( + fn: MultiStateValidator = jest.fn(defaultStatesValidator), + initialStates = [1, 2], + initialValidity = [false] + ): [MultiStateValidator, RenderHookResult]>] { + return [ + fn, + renderHook( + ({ initStates, validator, initValidity }) => { + const [states, setStates] = useState(initStates); + + return [setStates, useMultiStateValidator(states, validator, initValidity)]; + }, + { + initialProps: { + initStates: initialStates, + initValidity: initialValidity, + validator: 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.length).toBe(2); + }); + + it('should call validator on init', () => { + const [spy] = getHook(); + + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should call validator on any of states changed', () => { + const [spy, hook] = getHook(); + + expect(spy).toHaveBeenCalledTimes(1); + act(() => hook.result.current[0]([4, 2])); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it("should NOT call validator on it's change", () => { + const [spy, hook] = getHook(); + const newValidator: MultiStateValidator = jest.fn(states => [states!.every(num => !!(num % 2))]); + + expect(spy).toHaveBeenCalledTimes(1); + hook.rerender({ validator: newValidator }); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should throw if states is not an object', () => { + try { + // @ts-ignore + getHook(defaultStatesValidator, 123); + } catch (err) { + expect(err).toBeDefined(); + expect(err instanceof Error).toBe(true); + expect(err.message).toBe('states expected to be an object or array, got number'); + } + }); + + it('first returned element should represent current validity state', () => { + const [, hook] = getHook(); + let [setState, [validity]] = hook.result.current; + expect(validity).toEqual([false]); + + act(() => setState([4, 2])); + [setState, [validity]] = hook.result.current; + expect(validity).toEqual([true]); + + act(() => setState([4, 5])); + [setState, [validity]] = hook.result.current; + expect(validity).toEqual([false]); + }); + + it('second returned 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 should receive states as a firs argument', () => { + const [spy, hook] = getHook(); + const [setState] = hook.result.current; + + expect((spy as Mock).mock.calls[0].length).toBe(1); + expect((spy as Mock).mock.calls[0][0]).toEqual([1, 2]); + act(() => setState([4, 6])); + expect((spy as Mock).mock.calls[1][0]).toEqual([4, 6]); + }); + + it('if validator expects 2nd parameters it should pass a validity setter there', () => { + const spy = (jest.fn((states: number[], done) => { + done([states.every(num => !!(num % 2))]); + }) as unknown) as MultiStateValidator; + const [, hook] = getHook(spy, [1, 3]); + const [, [validity]] = hook.result.current; + + expect((spy as Mock).mock.calls[0].length).toBe(2); + expect((spy as Mock).mock.calls[0][0]).toEqual([1, 3]); + expect(validity).toEqual([true]); + }); +}); diff --git a/src/index.ts b/src/index.ts index 65872134d6..69a7deefc8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,6 +88,7 @@ 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 { useMultiStateValidator } from './useMultiStateValidator'; export { useWait, Waiter } from './useWait'; export { default as useWindowScroll } from './useWindowScroll'; export { default as useWindowSize } from './useWindowSize'; diff --git a/src/useMultiStateValidator.ts b/src/useMultiStateValidator.ts new file mode 100644 index 0000000000..19ed9f2108 --- /dev/null +++ b/src/useMultiStateValidator.ts @@ -0,0 +1,41 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { DispatchValidity, UseValidatorReturn, ValidityState } from './useStateValidator'; + +export type MultiStateValidatorStates = any[] | { [p: string]: any } | { [p: number]: any }; + +export interface MultiStateValidator< + V extends ValidityState = ValidityState, + S extends MultiStateValidatorStates = MultiStateValidatorStates +> { + (states: S): V; + + (states: S, done: DispatchValidity): void; +} + +export function useMultiStateValidator< + V extends ValidityState = ValidityState, + S extends MultiStateValidatorStates = MultiStateValidatorStates +>(states: S, validator: MultiStateValidator, initialValidity: V = [undefined] as V): UseValidatorReturn { + if (typeof states !== 'object') { + throw Error('states expected to be an object or array, got ' + typeof states); + } + + const validatorFn = useRef(validator); + + const [validity, setValidity] = useState(initialValidity); + + const deps = Array.isArray(states) ? states : Object.values(states); + const validate = useCallback(() => { + if (validatorFn.current.length === 2) { + validatorFn.current(states, setValidity); + } else { + setValidity(validatorFn.current(states)); + } + }, deps); + + useEffect(() => { + validate(); + }, deps); + + return [validity, validate]; +} From 8c7f7f5b729bce9be1f41096324517b8fc630666 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Wed, 16 Oct 2019 14:32:11 +0300 Subject: [PATCH 017/213] fix: useMultiStateValidator readme description; --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33f88b1bcd..14541732d2 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ - [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w) - [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161) - [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo) - - [`useMultiStateValidator`](./docs/useMultiStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemultistatevalidator--demo) + - [`useMultiStateValidator`](./docs/useMultiStateValidator.md) — alike the `useStateValidator`, but tracks multiple states at a time. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemultistatevalidator--demo)

    From 652b31890560becc38d9feadb57afea14360291b Mon Sep 17 00:00:00 2001 From: xobotyi Date: Wed, 16 Oct 2019 12:21:56 +0300 Subject: [PATCH 018/213] fix: rename story's mediator and add `g` flag to it's regex; fix: typo in readme; --- README.md | 2 +- src/__stories__/useMediatedState.story.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 502864511c..e3b9393c48 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ - [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w) - [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161) - [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo) - - [`useMedisatedState`](./docs/useMediatedState.md) — like the regular `useState` but with mediation by custom function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemediatedstate--demo) + - [`useMediatedState`](./docs/useMediatedState.md) — like the regular `useState` but with mediation by custom function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemediatedstate--demo)

    diff --git a/src/__stories__/useMediatedState.story.tsx b/src/__stories__/useMediatedState.story.tsx index d3c946f6dd..96ee1a13e5 100644 --- a/src/__stories__/useMediatedState.story.tsx +++ b/src/__stories__/useMediatedState.story.tsx @@ -3,9 +3,9 @@ import * as React from 'react'; import { useMediatedState } from '../useMediatedState'; import ShowDocs from './util/ShowDocs'; -const InputMediator = s => s.replace(/[\s]+/, ' '); +const inputMediator = s => s.replace(/[\s]+/g, ' '); const Demo = () => { - const [state, setState] = useMediatedState(InputMediator, ''); + const [state, setState] = useMediatedState(inputMediator, ''); return (
    From 7f54cad64248575366d6154ad7dff68905c17ec5 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Wed, 16 Oct 2019 15:07:33 +0300 Subject: [PATCH 019/213] fix: example in the docs; --- docs/useMediatedState.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/docs/useMediatedState.md b/docs/useMediatedState.md index 34a5cdb590..0779a2e97d 100644 --- a/docs/useMediatedState.md +++ b/docs/useMediatedState.md @@ -7,21 +7,18 @@ A lot like the standard `useState`, but with mediation process. import * as React from 'react'; import { useMediatedState } from '../useMediatedState'; -const InputMediator = s => s.replace(/[\s]+/, ' '); +const inputMediator = s => s.replace(/[\s]+/g, ' '); const Demo = () => { - const [state, setState] = useMediatedState('', InputMediator); + const [state, setState] = useMediatedState(inputMediator, ''); return (
    You will not be able to enter more than one space
    - ) => { - setState(ev.target.value); - }} + ) => { + setState(ev.target.value); + }} />
    ); From b256bb2b5c9eed5a69f68c1e47f4b0438dd7d703 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 16 Oct 2019 20:09:21 +0000 Subject: [PATCH 020/213] chore(deps): update dependency @shopify/jest-dom-mocks to v2.8.3 --- package.json | 2 +- yarn.lock | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index ee8f3a41d2..b502f85017 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@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", + "@shopify/jest-dom-mocks": "2.8.3", "@storybook/addon-actions": "5.1.11", "@storybook/addon-knobs": "5.1.11", "@storybook/addon-notes": "5.1.11", diff --git a/yarn.lock b/yarn.lock index 0fb8905df9..558545f821 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1712,10 +1712,10 @@ 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/async@^2.0.8": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@shopify/async/-/async-2.0.8.tgz#6ecded5fe8c5f6f20a74f212e4cd8f307e9e5138" + integrity sha512-jiqVW8SA79eO3dWwJCCcLTch6TJK30i796WKyF1bGjIhwAaD6qRlspj5Ffzfg3r4RQbGMJheOVMdWhzctwxgKg== "@shopify/decorators@^1.1.5": version "1.1.5" @@ -1729,16 +1729,17 @@ 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== +"@shopify/jest-dom-mocks@2.8.3": + version "2.8.3" + resolved "https://registry.yarnpkg.com/@shopify/jest-dom-mocks/-/jest-dom-mocks-2.8.3.tgz#3c00872c1b996290dc2a8222d2701c131150b305" + integrity sha512-K544qSPkjlf/ze0urmgbN50ti4wcF+Vy1IQP8tbnkqA362slMXjdLokuB7oSIkntYLL9TmlEkWCxSRC17LXtnQ== dependencies: - "@shopify/async" "^2.0.7" + "@shopify/async" "^2.0.8" "@shopify/decorators" "^1.1.5" "@types/fetch-mock" "^6.0.1" "@types/lolex" "^2.1.3" fetch-mock "^6.3.0" + lodash ">=4.0.0 <5.0.0" lolex "^2.7.5" promise "^8.0.3" tslib "^1.9.3" @@ -8336,7 +8337,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@>4.17.4, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1: +lodash@>4.17.4, "lodash@>=4.0.0 <5.0.0", lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== From 056875ba535bd601f04e4365914064583aa52a07 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Thu, 17 Oct 2019 10:47:44 +0300 Subject: [PATCH 021/213] fix: error throw tests; fix: better throw already `new Error`; --- src/__tests__/useMultiStateValidator.ts | 14 +++++++------- src/useMultiStateValidator.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/__tests__/useMultiStateValidator.ts b/src/__tests__/useMultiStateValidator.ts index 392af53d1d..cf191ca697 100644 --- a/src/__tests__/useMultiStateValidator.ts +++ b/src/__tests__/useMultiStateValidator.ts @@ -68,14 +68,14 @@ describe('useMultiStateValidator', () => { }); it('should throw if states is not an object', () => { - try { + expect(() => { // @ts-ignore - getHook(defaultStatesValidator, 123); - } catch (err) { - expect(err).toBeDefined(); - expect(err instanceof Error).toBe(true); - expect(err.message).toBe('states expected to be an object or array, got number'); - } + const [, hook] = getHook(defaultStatesValidator, 123); + + if (hook.result.error) { + throw hook.result.error; + } + }).toThrowError('states expected to be an object or array, got number'); }); it('first returned element should represent current validity state', () => { diff --git a/src/useMultiStateValidator.ts b/src/useMultiStateValidator.ts index 19ed9f2108..29cb12b338 100644 --- a/src/useMultiStateValidator.ts +++ b/src/useMultiStateValidator.ts @@ -17,7 +17,7 @@ export function useMultiStateValidator< S extends MultiStateValidatorStates = MultiStateValidatorStates >(states: S, validator: MultiStateValidator, initialValidity: V = [undefined] as V): UseValidatorReturn { if (typeof states !== 'object') { - throw Error('states expected to be an object or array, got ' + typeof states); + throw new Error('states expected to be an object or array, got ' + typeof states); } const validatorFn = useRef(validator); From 6e26237b5e428905e63501497a20a44a890bfe36 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 17 Oct 2019 13:39:31 +0000 Subject: [PATCH 022/213] chore(release): 12.7.0 [skip ci] # [12.7.0](https://github.com/streamich/react-use/compare/v12.6.0...v12.7.0) (2019-10-17) ### Bug Fixes * error throw tests; ([056875b](https://github.com/streamich/react-use/commit/056875b)) * useMultiStateValidator readme description; ([8c7f7f5](https://github.com/streamich/react-use/commit/8c7f7f5)) ### Features * useMultiStateValidator ([ae26988](https://github.com/streamich/react-use/commit/ae26988)) --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78784e127d..2bdc286658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [12.7.0](https://github.com/streamich/react-use/compare/v12.6.0...v12.7.0) (2019-10-17) + + +### Bug Fixes + +* error throw tests; ([056875b](https://github.com/streamich/react-use/commit/056875b)) +* useMultiStateValidator readme description; ([8c7f7f5](https://github.com/streamich/react-use/commit/8c7f7f5)) + + +### Features + +* useMultiStateValidator ([ae26988](https://github.com/streamich/react-use/commit/ae26988)) + # [12.6.0](https://github.com/streamich/react-use/compare/v12.5.0...v12.6.0) (2019-10-16) diff --git a/package.json b/package.json index b502f85017..da12c654d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-use", - "version": "12.6.0", + "version": "12.7.0", "description": "Collection of React Hooks", "main": "lib/index.js", "module": "esm/index.js", From e59f63a1f6190a08617e09e8ae8f094bc7f95917 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 17 Oct 2019 13:45:01 +0000 Subject: [PATCH 023/213] chore(release): 12.7.1 [skip ci] ## [12.7.1](https://github.com/streamich/react-use/compare/v12.7.0...v12.7.1) (2019-10-17) ### Bug Fixes * example in the docs; ([7f54cad](https://github.com/streamich/react-use/commit/7f54cad)) * rename story's mediator and add `g` flag to it's regex; ([652b318](https://github.com/streamich/react-use/commit/652b318)) --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bdc286658..6d33219bf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [12.7.1](https://github.com/streamich/react-use/compare/v12.7.0...v12.7.1) (2019-10-17) + + +### Bug Fixes + +* example in the docs; ([7f54cad](https://github.com/streamich/react-use/commit/7f54cad)) +* rename story's mediator and add `g` flag to it's regex; ([652b318](https://github.com/streamich/react-use/commit/652b318)) + # [12.7.0](https://github.com/streamich/react-use/compare/v12.6.0...v12.7.0) (2019-10-17) diff --git a/package.json b/package.json index da12c654d7..3c4ad4286a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-use", - "version": "12.7.0", + "version": "12.7.1", "description": "Collection of React Hooks", "main": "lib/index.js", "module": "esm/index.js", From a1144741ea9786c987478415e0c89a4e83207669 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 17 Oct 2019 16:13:13 +0000 Subject: [PATCH 024/213] chore(deps): update dependency @shopify/jest-dom-mocks to v2.8.4 --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3c4ad4286a..917a196663 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@semantic-release/changelog": "3.0.4", "@semantic-release/git": "7.0.16", "@semantic-release/npm": "5.1.13", - "@shopify/jest-dom-mocks": "2.8.3", + "@shopify/jest-dom-mocks": "2.8.4", "@storybook/addon-actions": "5.1.11", "@storybook/addon-knobs": "5.1.11", "@storybook/addon-notes": "5.1.11", diff --git a/yarn.lock b/yarn.lock index 558545f821..51d61cc736 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1712,10 +1712,10 @@ into-stream "^4.0.0" lodash "^4.17.4" -"@shopify/async@^2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@shopify/async/-/async-2.0.8.tgz#6ecded5fe8c5f6f20a74f212e4cd8f307e9e5138" - integrity sha512-jiqVW8SA79eO3dWwJCCcLTch6TJK30i796WKyF1bGjIhwAaD6qRlspj5Ffzfg3r4RQbGMJheOVMdWhzctwxgKg== +"@shopify/async@^2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@shopify/async/-/async-2.0.9.tgz#d097b99eb17c9368cdf0761870a162bfb93322c9" + integrity sha512-SAY9z9CXSZM/wQ5pSySpZ+MjiDwQiTdlXkCi8BiMUUgFRhEZ8CSgBQdy8R5pF64tqX1Iurmiwn+pl3sthWVyTQ== "@shopify/decorators@^1.1.5": version "1.1.5" @@ -1729,12 +1729,12 @@ 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.3": - version "2.8.3" - resolved "https://registry.yarnpkg.com/@shopify/jest-dom-mocks/-/jest-dom-mocks-2.8.3.tgz#3c00872c1b996290dc2a8222d2701c131150b305" - integrity sha512-K544qSPkjlf/ze0urmgbN50ti4wcF+Vy1IQP8tbnkqA362slMXjdLokuB7oSIkntYLL9TmlEkWCxSRC17LXtnQ== +"@shopify/jest-dom-mocks@2.8.4": + version "2.8.4" + resolved "https://registry.yarnpkg.com/@shopify/jest-dom-mocks/-/jest-dom-mocks-2.8.4.tgz#065e770884f2853debf90647ba13d69d84153aa0" + integrity sha512-GjHl1SIuMe7RD1C1izKEt3kmSDKGbLzwx3sFmsbh/ov1XKAhQa4I8AFqkW5CadO2GylVVefANd+sd4WgMcQuaQ== dependencies: - "@shopify/async" "^2.0.8" + "@shopify/async" "^2.0.9" "@shopify/decorators" "^1.1.5" "@types/fetch-mock" "^6.0.1" "@types/lolex" "^2.1.3" From 9099f98f57717b6661a354b568c2516416ef3a9d Mon Sep 17 00:00:00 2001 From: Behnam Mohammadi Date: Mon, 21 Oct 2019 21:21:34 +0330 Subject: [PATCH 025/213] Added ActionsTabStory for log --- src/__stories__/useMount.story.tsx | 7 ++++--- src/__stories__/useUnmount.story.tsx | 7 ++++--- src/__stories__/util/ActionsTabStory.tsx | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 src/__stories__/util/ActionsTabStory.tsx diff --git a/src/__stories__/useMount.story.tsx b/src/__stories__/useMount.story.tsx index 966ab737e5..da6bcb8da2 100644 --- a/src/__stories__/useMount.story.tsx +++ b/src/__stories__/useMount.story.tsx @@ -1,13 +1,14 @@ import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; import * as React from 'react'; import { useMount } from '..'; -import ConsoleStory from './util/ConsoleStory'; +import ActionsTabStory from './util/ActionsTabStory'; import ShowDocs from './util/ShowDocs'; const Demo = () => { - useMount(() => console.log('MOUNTED')); + useMount(action('MOUNTED')); - return ; + return ; }; storiesOf('Lifecycle|useMount', module) diff --git a/src/__stories__/useUnmount.story.tsx b/src/__stories__/useUnmount.story.tsx index 87d58e3595..fda353e768 100644 --- a/src/__stories__/useUnmount.story.tsx +++ b/src/__stories__/useUnmount.story.tsx @@ -1,13 +1,14 @@ import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; import * as React from 'react'; import { useUnmount } from '..'; -import ConsoleStory from './util/ConsoleStory'; +import ActionsTabStory from './util/ActionsTabStory'; import ShowDocs from './util/ShowDocs'; const Demo = () => { - useUnmount(() => console.log('UNMOUNTED')); + useUnmount(action('UNMOUNTED')); - return ; + return ; }; storiesOf('Lifecycle|useUnmount', module) diff --git a/src/__stories__/util/ActionsTabStory.tsx b/src/__stories__/util/ActionsTabStory.tsx new file mode 100644 index 0000000000..8309618628 --- /dev/null +++ b/src/__stories__/util/ActionsTabStory.tsx @@ -0,0 +1,5 @@ +import * as React from 'react'; + +const ActionsTabStory = ({ message = 'Open actions tab to see logs' }) =>

    {message}

    ; + +export default ActionsTabStory; From 8cdcfddae4d951a5f5d1f5ca067c30a2bf436b94 Mon Sep 17 00:00:00 2001 From: Jakkapat Boonroj Date: Tue, 22 Oct 2019 22:35:25 +0700 Subject: [PATCH 026/213] :sparkles: create useBreakpoint --- docs/useBreakpoint.md | 37 +++++++++++++++++++++++++ src/__stories__/useBreakpoint.story.tsx | 25 +++++++++++++++++ src/index.ts | 2 +- src/useBreakpoint.ts | 24 ++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 docs/useBreakpoint.md create mode 100644 src/__stories__/useBreakpoint.story.tsx create mode 100644 src/useBreakpoint.ts diff --git a/docs/useBreakpoint.md b/docs/useBreakpoint.md new file mode 100644 index 0000000000..de346a46f7 --- /dev/null +++ b/docs/useBreakpoint.md @@ -0,0 +1,37 @@ +# `useBreakpoint` + +## Usage + +### use default breakpoint + +laptopL: 1440, laptop: 1024, tablet: 768 + +```jsx +import React from "react"; +import { useBreakpoint } from "react-use"; + +const Demo = () => { + const breakpoint = useBreakpoint(); + if (breakpoint === "laptopL") return
    This is very big Laptop
    ; + else if (breakpoint == "laptop") return
    This is Laptop
    ; + else if (breakpoint == "tablet") return
    This is Tablet
    ; + else return
    Too small!
    ; +}; +``` + +### use custom breakpoint + +XL: 1280, L: 768, S: 350 + +```jsx +import React from "react"; +import { useBreakpoint } from "react-use"; + +const Demo = () => { + const breakpoint = useBreakpoint(); + if (breakpoint === "XL") return
    XL
    ; + else if (breakpoint == "L") return
    LoL
    ; + else if (breakpoint == "S") return
    Sexyy
    ; + else return
    Wth
    ; +}; +``` diff --git a/src/__stories__/useBreakpoint.story.tsx b/src/__stories__/useBreakpoint.story.tsx new file mode 100644 index 0000000000..2fef483782 --- /dev/null +++ b/src/__stories__/useBreakpoint.story.tsx @@ -0,0 +1,25 @@ +import { number, withKnobs } from "@storybook/addon-knobs"; +import { storiesOf } from "@storybook/react"; +import React from "react"; +import { useBreakpoint } from ".."; +import ShowDocs from "./util/ShowDocs"; +const Demo = () => { + const breakpoint = useBreakpoint(); + const breakpointB = useBreakpoint({ mobileM: 350, laptop: 1024, tablet: 768 }); + return ( +
    +

    {"try resize your window"}

    +

    {"useBreakpoint() #default : { laptopL: 1440, laptop: 1024, tablet: 768 }"}

    +

    {breakpoint}

    +

    {"useBreakpoint({ mobileM: 350, laptop: 1024, tablet: 768 })"}

    +

    {breakpointB}

    +
    + ); +}; + +storiesOf("sensors|useBreakpoint", module) + .addDecorator(withKnobs) + .add("Docs", () => ) + .add("Demo", () => { + return ; + }); diff --git a/src/index.ts b/src/index.ts index 9c660296a2..772f69fb17 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,6 +31,7 @@ export { default as useIntersection } from './useIntersection'; export { default as useInterval } from './useInterval'; export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'; export { default as useKey } from './useKey'; +export { default as useBreakpoint } from './useBreakpoint'; // not exported because of peer dependency // export { default as useKeyboardJs } from './useKeyboardJs'; export { default as useKeyPress } from './useKeyPress'; @@ -62,7 +63,6 @@ export { default as usePromise } from './usePromise'; export { default as useRaf } from './useRaf'; export { default as useRafLoop } from './useRafLoop'; export { default as useRafState } from './useRafState'; - /** * @deprecated This hook is obsolete, use `useMountedState` instead */ diff --git a/src/useBreakpoint.ts b/src/useBreakpoint.ts new file mode 100644 index 0000000000..6b9f4e0268 --- /dev/null +++ b/src/useBreakpoint.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react' + +function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) { + const [useScreen, setScreen] = useState(0) + + useEffect(() => { + const setSideScreen = (): void => { + setScreen(window.innerWidth) + } + setSideScreen() + window.addEventListener('resize', setSideScreen) + return () => { + window.removeEventListener('resize', setSideScreen) + } + }) + const sortedBreakpoints = Object.entries(breakpoints).sort((a, b) => a[1] >= b[1] ? 1 : -1) + const result = sortedBreakpoints.reduce((acc, [name, width]) => { + if (useScreen >= width) return name + else return acc + }, sortedBreakpoints[0][0]) + return result +} + +export default useBreakpoint From 43ac4129dab37cf039be2b395ed04396b4895660 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 22 Oct 2019 21:33:49 +0000 Subject: [PATCH 027/213] chore(deps): update node.js to v10.17.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 917a196663..9ea159c4a4 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ ] }, "volta": { - "node": "10.16.3", + "node": "10.17.0", "yarn": "1.19.1" }, "collective": { From aa9090a1d319f83b6380302b1f881d7d24e7df3d Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 22 Oct 2019 21:34:02 +0000 Subject: [PATCH 028/213] chore(deps): update react monorepo to v16.11.0 --- package.json | 6 +++--- yarn.lock | 36 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 9ea159c4a4..8c78c1869b 100644 --- a/package.json +++ b/package.json @@ -92,11 +92,11 @@ "markdown-loader": "5.1.0", "prettier": "1.18.2", "raf-stub": "3.0.0", - "react": "16.10.2", - "react-dom": "16.10.2", + "react": "16.11.0", + "react-dom": "16.11.0", "react-frame-component": "4.1.1", "react-spring": "8.0.27", - "react-test-renderer": "16.10.2", + "react-test-renderer": "16.11.0", "rebound": "0.1.0", "redux-logger": "3.0.6", "redux-thunk": "2.3.0", diff --git a/yarn.lock b/yarn.lock index 51d61cc736..d06e07c7b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10502,15 +10502,15 @@ react-docgen@^4.1.0: node-dir "^0.1.10" recast "^0.17.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== +react-dom@16.11.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.11.0.tgz#7e7c4a5a85a569d565c2462f5d345da2dd849af5" + integrity sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.16.2" + scheduler "^0.17.0" react-dom@^16.8.3: version "16.9.0" @@ -10667,15 +10667,15 @@ react-syntax-highlighter@^8.0.1: prismjs "^1.8.4" refractor "^2.4.1" -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== +react-test-renderer@16.11.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.11.0.tgz#72574566496462c808ac449b0287a4c0a1a7d8f8" + integrity sha512-nh9gDl8R4ut+ZNNb2EeKO5VMvTKxwzurbSMuGBoKtjpjbg8JK/u3eVPVNi1h1Ue+eYK9oSzJjb+K3lzLxyA4ag== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" react-is "^16.8.6" - scheduler "^0.16.2" + scheduler "^0.17.0" react-textarea-autosize@^7.1.0: version "7.1.0" @@ -10700,10 +10700,10 @@ 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.10.2: - version "16.10.2" - resolved "https://registry.yarnpkg.com/react/-/react-16.10.2.tgz#a5ede5cdd5c536f745173c8da47bda64797a4cf0" - integrity sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw== +react@16.11.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" + integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -11394,10 +11394,10 @@ 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== +scheduler@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" + integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" From 9c779b256b0a6fecaa9df0a999c372e37ac6c097 Mon Sep 17 00:00:00 2001 From: Jakkapat Boonroj Date: Wed, 23 Oct 2019 10:11:29 +0700 Subject: [PATCH 029/213] rename variable --- src/useBreakpoint.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/useBreakpoint.ts b/src/useBreakpoint.ts index 6b9f4e0268..696902d2f5 100644 --- a/src/useBreakpoint.ts +++ b/src/useBreakpoint.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) { - const [useScreen, setScreen] = useState(0) + const [screen, setScreen] = useState(0) useEffect(() => { const setSideScreen = (): void => { @@ -15,7 +15,7 @@ function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440 }) const sortedBreakpoints = Object.entries(breakpoints).sort((a, b) => a[1] >= b[1] ? 1 : -1) const result = sortedBreakpoints.reduce((acc, [name, width]) => { - if (useScreen >= width) return name + if (screen >= width) return name else return acc }, sortedBreakpoints[0][0]) return result From 20bdd507883ce41307a27df5d5c4b58c3a4078a5 Mon Sep 17 00:00:00 2001 From: Jakkapat Boonroj Date: Wed, 23 Oct 2019 10:13:25 +0700 Subject: [PATCH 030/213] add useMemo --- src/useBreakpoint.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/useBreakpoint.ts b/src/useBreakpoint.ts index 696902d2f5..f4a685cb36 100644 --- a/src/useBreakpoint.ts +++ b/src/useBreakpoint.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useState, useMemo } from 'react' function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) { const [screen, setScreen] = useState(0) @@ -13,7 +13,7 @@ function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440 window.removeEventListener('resize', setSideScreen) } }) - const sortedBreakpoints = Object.entries(breakpoints).sort((a, b) => a[1] >= b[1] ? 1 : -1) + const sortedBreakpoints = useMemo(() => Object.entries(breakpoints).sort((a, b) => a[1] >= b[1] ? 1 : -1), [breakpoints]) const result = sortedBreakpoints.reduce((acc, [name, width]) => { if (screen >= width) return name else return acc From fa08f930046ac05911ada1ed9813eabe8c3e079a Mon Sep 17 00:00:00 2001 From: Jakkapat Boonroj Date: Wed, 23 Oct 2019 10:15:38 +0700 Subject: [PATCH 031/213] rename to createBreakpoint --- docs/{useBreakpoint.md => createBreakpoint.md} | 0 .../{useBreakpoint.story.tsx => createBreakpoint.story.tsx} | 4 ++-- src/{useBreakpoint.ts => createBreakpoint.ts} | 4 ++-- src/index.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename docs/{useBreakpoint.md => createBreakpoint.md} (100%) rename src/__stories__/{useBreakpoint.story.tsx => createBreakpoint.story.tsx} (85%) rename src/{useBreakpoint.ts => createBreakpoint.ts} (83%) diff --git a/docs/useBreakpoint.md b/docs/createBreakpoint.md similarity index 100% rename from docs/useBreakpoint.md rename to docs/createBreakpoint.md diff --git a/src/__stories__/useBreakpoint.story.tsx b/src/__stories__/createBreakpoint.story.tsx similarity index 85% rename from src/__stories__/useBreakpoint.story.tsx rename to src/__stories__/createBreakpoint.story.tsx index 2fef483782..6e810e99df 100644 --- a/src/__stories__/useBreakpoint.story.tsx +++ b/src/__stories__/createBreakpoint.story.tsx @@ -17,9 +17,9 @@ const Demo = () => { ); }; -storiesOf("sensors|useBreakpoint", module) +storiesOf("sensors|createBreakpoint", module) .addDecorator(withKnobs) - .add("Docs", () => ) + .add("Docs", () => ) .add("Demo", () => { return ; }); diff --git a/src/useBreakpoint.ts b/src/createBreakpoint.ts similarity index 83% rename from src/useBreakpoint.ts rename to src/createBreakpoint.ts index f4a685cb36..a0542e75d4 100644 --- a/src/useBreakpoint.ts +++ b/src/createBreakpoint.ts @@ -1,6 +1,6 @@ import { useEffect, useState, useMemo } from 'react' -function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) { +function createBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) { const [screen, setScreen] = useState(0) useEffect(() => { @@ -21,4 +21,4 @@ function useBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440 return result } -export default useBreakpoint +export default createBreakpoint diff --git a/src/index.ts b/src/index.ts index 772f69fb17..241f91db48 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,7 +31,7 @@ export { default as useIntersection } from './useIntersection'; export { default as useInterval } from './useInterval'; export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'; export { default as useKey } from './useKey'; -export { default as useBreakpoint } from './useBreakpoint'; +export { default as useBreakpoint } from './createBreakpoint'; // not exported because of peer dependency // export { default as useKeyboardJs } from './useKeyboardJs'; export { default as useKeyPress } from './useKeyPress'; From 75827fd497d69dca17c39fe39a6374fd44002231 Mon Sep 17 00:00:00 2001 From: Jakkapat Boonroj Date: Wed, 23 Oct 2019 10:21:55 +0700 Subject: [PATCH 032/213] add createBreakpoint in readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 76fd92c187..b0f21b0f71 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ - [`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 using the Resize Observer API.[![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemeasure--demo) + - [`createBreakpoint`](./doc/createBreakpoint.md) — tracks `innerWidth`

    - [**UI**](./docs/UI.md) From 13ac976b0d30788e8ee8a760c4e9dcf3aef8e725 Mon Sep 17 00:00:00 2001 From: Jakkapat Boonroj Date: Wed, 23 Oct 2019 10:33:36 +0700 Subject: [PATCH 033/213] change word --- docs/createBreakpoint.md | 12 +++++++++--- src/__stories__/createBreakpoint.story.tsx | 16 ++++++++++------ src/createBreakpoint.ts | 2 +- src/index.ts | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/createBreakpoint.md b/docs/createBreakpoint.md index de346a46f7..a07cb68b15 100644 --- a/docs/createBreakpoint.md +++ b/docs/createBreakpoint.md @@ -1,4 +1,4 @@ -# `useBreakpoint` +# `createBreakpoint` ## Usage @@ -8,10 +8,13 @@ laptopL: 1440, laptop: 1024, tablet: 768 ```jsx import React from "react"; -import { useBreakpoint } from "react-use"; +import { createBreakpoint } from "react-use"; + +const useBreakpoint = createBreakpoint(); const Demo = () => { const breakpoint = useBreakpoint(); + if (breakpoint === "laptopL") return
    This is very big Laptop
    ; else if (breakpoint == "laptop") return
    This is Laptop
    ; else if (breakpoint == "tablet") return
    This is Tablet
    ; @@ -25,10 +28,13 @@ XL: 1280, L: 768, S: 350 ```jsx import React from "react"; -import { useBreakpoint } from "react-use"; +import { createBreakpoint } from "react-use"; + +const useBreakpoint = createBreakpoint({ XL: 1280, L: 768, S: 350 }); const Demo = () => { const breakpoint = useBreakpoint(); + if (breakpoint === "XL") return
    XL
    ; else if (breakpoint == "L") return
    LoL
    ; else if (breakpoint == "S") return
    Sexyy
    ; diff --git a/src/__stories__/createBreakpoint.story.tsx b/src/__stories__/createBreakpoint.story.tsx index 6e810e99df..92068f79b5 100644 --- a/src/__stories__/createBreakpoint.story.tsx +++ b/src/__stories__/createBreakpoint.story.tsx @@ -1,17 +1,21 @@ import { number, withKnobs } from "@storybook/addon-knobs"; import { storiesOf } from "@storybook/react"; import React from "react"; -import { useBreakpoint } from ".."; +import { createBreakpoint } from ".."; import ShowDocs from "./util/ShowDocs"; + +const useBreakpointA = createBreakpoint(); +const useBreakpointB = createBreakpoint({ mobileM: 350, laptop: 1024, tablet: 768 }); + const Demo = () => { - const breakpoint = useBreakpoint(); - const breakpointB = useBreakpoint({ mobileM: 350, laptop: 1024, tablet: 768 }); + const breakpointA = useBreakpointA(); + const breakpointB = useBreakpointB(); return (

    {"try resize your window"}

    -

    {"useBreakpoint() #default : { laptopL: 1440, laptop: 1024, tablet: 768 }"}

    -

    {breakpoint}

    -

    {"useBreakpoint({ mobileM: 350, laptop: 1024, tablet: 768 })"}

    +

    {"createBreakpoint() #default : { laptopL: 1440, laptop: 1024, tablet: 768 }"}

    +

    {breakpointA}

    +

    {"createBreakpoint({ mobileM: 350, laptop: 1024, tablet: 768 })"}

    {breakpointB}

    ); diff --git a/src/createBreakpoint.ts b/src/createBreakpoint.ts index a0542e75d4..966a03558c 100644 --- a/src/createBreakpoint.ts +++ b/src/createBreakpoint.ts @@ -1,6 +1,6 @@ import { useEffect, useState, useMemo } from 'react' -function createBreakpoint(breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) { +const createBreakpoint = (breakpoints: { [name: string]: number } = { laptopL: 1440, laptop: 1024, tablet: 768 }) => () => { const [screen, setScreen] = useState(0) useEffect(() => { diff --git a/src/index.ts b/src/index.ts index 241f91db48..88cd19a6e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,7 +31,7 @@ export { default as useIntersection } from './useIntersection'; export { default as useInterval } from './useInterval'; export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'; export { default as useKey } from './useKey'; -export { default as useBreakpoint } from './createBreakpoint'; +export { default as createBreakpoint } from './createBreakpoint'; // not exported because of peer dependency // export { default as useKeyboardJs } from './useKeyboardJs'; export { default as useKeyPress } from './useKeyPress'; From ad1da8463b4606e03e216a6e6f16b5f2b79e8caf Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 23 Oct 2019 06:28:18 +0000 Subject: [PATCH 034/213] chore(deps): update dependency ts-loader to v6.2.1 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8c78c1869b..38d72de52d 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "rimraf": "3.0.0", "rxjs": "6.5.3", "semantic-release": "15.13.24", - "ts-loader": "6.2.0", + "ts-loader": "6.2.1", "ts-node": "8.4.1", "tslint": "5.20.0", "tslint-config-prettier": "1.18.0", diff --git a/yarn.lock b/yarn.lock index d06e07c7b3..4446cde0d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12581,10 +12581,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.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== +ts-loader@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.1.tgz#67939d5772e8a8c6bdaf6277ca023a4812da02ef" + integrity sha512-Dd9FekWuABGgjE1g0TlQJ+4dFUfYGbYcs52/HQObE0ZmUNjQlmLAS7xXsSzy23AMaMwipsx5sNHvoEpT2CZq1g== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" From f7c709afce7834d1430e2cef58ad4892e60c340d Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 23 Oct 2019 10:08:51 +0200 Subject: [PATCH 035/213] =?UTF-8?q?fix:=20=F0=9F=90=9B=20bump=20set-harmon?= =?UTF-8?q?ic-interval=20package=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 38d72de52d..8972e043fb 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "react-wait": "^0.3.0", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.0.0", - "set-harmonic-interval": "^1.0.0", + "set-harmonic-interval": "^1.0.1", "throttle-debounce": "^2.0.1", "ts-easing": "^0.2.0", "tslib": "^1.10.0" diff --git a/yarn.lock b/yarn.lock index 4446cde0d5..b84e46863c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11540,10 +11540,10 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-harmonic-interval@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.0.tgz#2759658395579fc336b9cd026eefe1ad9e742f9b" - integrity sha512-RJtrhB5G10e5A1auBv/jHGq0KWfHH8PAb4ln4+kjiHS46aAP12rSdarSj9GDlxQ3QULA2pefEDpm9Y1Xnz+eng== +set-harmonic-interval@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" + integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== set-value@^0.4.3: version "0.4.3" From 1ed849490706fb8cccce3bd864cf8b77a2aedaab Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 23 Oct 2019 08:11:24 +0000 Subject: [PATCH 036/213] chore(release): 12.7.2 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [12.7.2](https://github.com/streamich/react-use/compare/v12.7.1...v12.7.2) (2019-10-23) ### Bug Fixes * 🐛 bump set-harmonic-interval package version ([f7c709a](https://github.com/streamich/react-use/commit/f7c709a)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d33219bf7..87d3f0ed09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [12.7.2](https://github.com/streamich/react-use/compare/v12.7.1...v12.7.2) (2019-10-23) + + +### Bug Fixes + +* 🐛 bump set-harmonic-interval package version ([f7c709a](https://github.com/streamich/react-use/commit/f7c709a)) + ## [12.7.1](https://github.com/streamich/react-use/compare/v12.7.0...v12.7.1) (2019-10-17) diff --git a/package.json b/package.json index 8972e043fb..7aaed5003c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-use", - "version": "12.7.1", + "version": "12.7.2", "description": "Collection of React Hooks", "main": "lib/index.js", "module": "esm/index.js", From 711b48cfd1af7dfc3dbb4c52691c50b9226bd50a Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 23 Oct 2019 10:23:26 +0200 Subject: [PATCH 037/213] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20use=20aler?= =?UTF-8?q?t()=20in=20useMount()=20and=20useUnmount()=20stories?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/useMount.md | 2 +- docs/useUnmount.md | 2 +- src/__stories__/useMount.story.tsx | 10 ++++++---- src/__stories__/useUnmount.story.tsx | 11 +++++++---- src/__stories__/util/ActionsTabStory.tsx | 5 ----- 5 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 src/__stories__/util/ActionsTabStory.tsx diff --git a/docs/useMount.md b/docs/useMount.md index 95b53ae8b9..7b357c55ff 100644 --- a/docs/useMount.md +++ b/docs/useMount.md @@ -8,7 +8,7 @@ React lifecycle hook that calls a function after the component is mounted. Use ` import {useMount} from 'react-use'; const Demo = () => { - useMount(() => console.log('MOUNTED')); + useMount(() => alert('MOUNTED')); return null; }; ``` diff --git a/docs/useUnmount.md b/docs/useUnmount.md index 83dc772219..c0a3e6c85b 100644 --- a/docs/useUnmount.md +++ b/docs/useUnmount.md @@ -8,7 +8,7 @@ React lifecycle hook that calls a function when the component will unmount. Use import {useUnmount} from 'react-use'; const Demo = () => { - useUnmount(() => console.log('UNMOUNTED')); + useUnmount(() => alert('UNMOUNTED')); return null; }; ``` diff --git a/src/__stories__/useMount.story.tsx b/src/__stories__/useMount.story.tsx index da6bcb8da2..31c16c5ca7 100644 --- a/src/__stories__/useMount.story.tsx +++ b/src/__stories__/useMount.story.tsx @@ -1,14 +1,16 @@ import { storiesOf } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; import * as React from 'react'; import { useMount } from '..'; -import ActionsTabStory from './util/ActionsTabStory'; import ShowDocs from './util/ShowDocs'; const Demo = () => { - useMount(action('MOUNTED')); + useMount(() => alert('MOUNTED')); - return ; + return ( +
    + useMount() hook can be used to perform a side-effect when component is mounted. +
    + ); }; storiesOf('Lifecycle|useMount', module) diff --git a/src/__stories__/useUnmount.story.tsx b/src/__stories__/useUnmount.story.tsx index fda353e768..a08dfbb336 100644 --- a/src/__stories__/useUnmount.story.tsx +++ b/src/__stories__/useUnmount.story.tsx @@ -1,14 +1,17 @@ import { storiesOf } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; import * as React from 'react'; import { useUnmount } from '..'; -import ActionsTabStory from './util/ActionsTabStory'; import ShowDocs from './util/ShowDocs'; const Demo = () => { - useUnmount(action('UNMOUNTED')); + useUnmount(() => alert('UNMOUNTED')); - return ; + return ( +
    + useUnmount() hook can be used to perform side-effects when component unmounts. This component will + alert you when it is un-mounted. +
    + ); }; storiesOf('Lifecycle|useUnmount', module) diff --git a/src/__stories__/util/ActionsTabStory.tsx b/src/__stories__/util/ActionsTabStory.tsx deleted file mode 100644 index 8309618628..0000000000 --- a/src/__stories__/util/ActionsTabStory.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; - -const ActionsTabStory = ({ message = 'Open actions tab to see logs' }) =>

    {message}

    ; - -export default ActionsTabStory; From c494aa3c3b993352f9cec0e4e834343d411ac52b Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 23 Oct 2019 10:59:39 +0200 Subject: [PATCH 038/213] =?UTF-8?q?chore:=20=F0=9F=A4=96=20upgrade=20Story?= =?UTF-8?q?book=20to=205.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 10 +- yarn.lock | 892 +++++++++++++++++++++++++++------------------------ 2 files changed, 474 insertions(+), 428 deletions(-) diff --git a/package.json b/package.json index 7aaed5003c..bf911645fa 100644 --- a/package.json +++ b/package.json @@ -72,11 +72,11 @@ "@semantic-release/git": "7.0.16", "@semantic-release/npm": "5.1.13", "@shopify/jest-dom-mocks": "2.8.4", - "@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", + "@storybook/addon-actions": "5.2.5", + "@storybook/addon-knobs": "5.2.5", + "@storybook/addon-notes": "5.2.5", + "@storybook/addon-options": "5.2.5", + "@storybook/react": "5.2.5", "@testing-library/react-hooks": "2.0.3", "@types/jest": "24.0.19", "@types/react": "16.9.2", diff --git a/yarn.lock b/yarn.lock index b84e46863c..9dc9186e24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1136,13 +1136,20 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.3", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.5.5": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.3.tgz#935122c74c73d2240cafd32ddb5fc2a6cd35cf1f" + integrity sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" @@ -1241,17 +1248,15 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@emotion/babel-utils@^0.6.4": - version "0.6.10" - resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc" - integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow== +"@emotion/cache@^10.0.17": + version "10.0.19" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.19.tgz#d258d94d9c707dcadaf1558def968b86bb87ad71" + integrity sha512-BoiLlk4vEsGBg2dAqGSJu0vJl/PgVtCYLBFJaEO8RmQzPugXewQCXZJNXTDFaRlfCs0W+quesayav4fvaif5WQ== dependencies: - "@emotion/hash" "^0.6.6" - "@emotion/memoize" "^0.6.6" - "@emotion/serialize" "^0.9.1" - convert-source-map "^1.5.1" - find-root "^1.1.0" - source-map "^0.7.2" + "@emotion/sheet" "0.9.3" + "@emotion/stylis" "0.8.4" + "@emotion/utils" "0.11.2" + "@emotion/weak-memoize" "0.2.4" "@emotion/cache@^10.0.9": version "10.0.9" @@ -1263,6 +1268,18 @@ "@emotion/utils" "0.11.1" "@emotion/weak-memoize" "0.2.2" +"@emotion/core@^10.0.14": + version "10.0.21" + resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.21.tgz#2e8398d2b92fd90d4ed6ac4d0b66214971de3458" + integrity sha512-U9zbc7ovZ2ceIwbLXYZPJy6wPgnOdTNT4jENZ31ee6v2lojetV5bTbCVk6ciT8G3wQRyVaTTfUCH9WCrMzpRIw== + dependencies: + "@babel/runtime" "^7.5.5" + "@emotion/cache" "^10.0.17" + "@emotion/css" "^10.0.14" + "@emotion/serialize" "^0.11.10" + "@emotion/sheet" "0.9.3" + "@emotion/utils" "0.11.2" + "@emotion/core@^10.0.9": version "10.0.10" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.10.tgz#8d3114e5a2f8b178a7067c603a2937516f180b08" @@ -1274,6 +1291,15 @@ "@emotion/sheet" "0.9.2" "@emotion/utils" "0.11.1" +"@emotion/css@^10.0.14": + version "10.0.14" + resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.14.tgz#95dacabdd0e22845d1a1b0b5968d9afa34011139" + integrity sha512-MozgPkBEWvorcdpqHZE5x1D/PLEHUitALQCQYt2wayf4UNhpgQs2tN0UwHYS4FMy5ROBH+0ALyCFVYJ/ywmwlg== + dependencies: + "@emotion/serialize" "^0.11.8" + "@emotion/utils" "0.11.2" + babel-plugin-emotion "^10.0.14" + "@emotion/css@^10.0.9": version "10.0.9" resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.9.tgz#ea0df431965a308f6cb1d61386df8ad61e5befb5" @@ -1288,27 +1314,38 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.1.tgz#9833722341379fb7d67f06a4b00ab3c37913da53" integrity sha512-OYpa/Sg+2GDX+jibUfpZVn1YqSVRpYmTLF2eyAfrFTIJSbwyIrc+YscayoykvaOME/wV4BV0Sa0yqdMrgse6mA== -"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44" - integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ== - -"@emotion/is-prop-valid@0.7.3": +"@emotion/hash@0.7.3": version "0.7.3" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc" - integrity sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA== + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.3.tgz#a166882c81c0c6040975dd30df24fae8549bd96f" + integrity sha512-14ZVlsB9akwvydAdaEnVnvqu6J2P6ySv39hYyl/aoB6w/V+bXX0tay8cF6paqbgZsN2n5Xh15uF4pE+GvE+itw== + +"@emotion/is-prop-valid@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.3.tgz#cbe62ddbea08aa022cdf72da3971570a33190d29" + integrity sha512-We7VBiltAJ70KQA0dWkdPMXnYoizlxOXpvtjmu5/MBnExd+u0PGgV27WCYanmLAbCwAU30Le/xA0CQs/F/Otig== dependencies: - "@emotion/memoize" "0.7.1" + "@emotion/memoize" "0.7.3" "@emotion/memoize@0.7.1": version "0.7.1" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f" integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg== -"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b" - integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ== +"@emotion/memoize@0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.3.tgz#5b6b1c11d6a6dddf1f2fc996f74cf3b219644d78" + integrity sha512-2Md9mH6mvo+ygq1trTeVp2uzAKwE2P7In0cRpD/M9Q70aH8L+rxMLbb3JCN2JoSWsV2O+DdFjfbbXoMoLBczow== + +"@emotion/serialize@^0.11.10", "@emotion/serialize@^0.11.11", "@emotion/serialize@^0.11.8": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.11.tgz#c92a5e5b358070a7242d10508143306524e842a4" + integrity sha512-YG8wdCqoWtuoMxhHZCTA+egL0RSGdHEc+YCsmiSBPBEDNuVeMWtjEWtGrhUterSChxzwnWBXvzSxIFQI/3sHLw== + dependencies: + "@emotion/hash" "0.7.3" + "@emotion/memoize" "0.7.3" + "@emotion/unitless" "0.7.4" + "@emotion/utils" "0.11.2" + csstype "^2.5.7" "@emotion/serialize@^0.11.6": version "0.11.6" @@ -1321,78 +1358,73 @@ "@emotion/utils" "0.11.1" csstype "^2.5.7" -"@emotion/serialize@^0.9.1": - version "0.9.1" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145" - integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ== - dependencies: - "@emotion/hash" "^0.6.6" - "@emotion/memoize" "^0.6.6" - "@emotion/unitless" "^0.6.7" - "@emotion/utils" "^0.8.2" - "@emotion/sheet@0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.2.tgz#74e5c6b5e489a1ba30ab246ab5eedd96916487c4" integrity sha512-pVBLzIbC/QCHDKJF2E82V2H/W/B004mDFQZiyo/MSR+VC4pV5JLG0TF/zgQDFvP3fZL/5RTPGEmXlYJBMUuJ+A== -"@emotion/styled-base@^10.0.9": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.9.tgz#634b43d1f0309c35c5b342c775b01610517d2529" - integrity sha512-uXOPP2V7g8lYWsqBfYGmEOXHMUPleOujFWusQyXezxe1VGlZjGJIQj+YmzkwzGBmFx2nAun0OKMYCBJMeGKojw== +"@emotion/sheet@0.9.3": + version "0.9.3" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a" + integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A== + +"@emotion/styled-base@^10.0.17": + version "10.0.19" + resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.19.tgz#53655274797194d86453354fdb2c947b46032db6" + integrity sha512-Sz6GBHTbOZoeZQKvkE9gQPzaJ6/qtoQ/OPvyG2Z/6NILlYk60Es1cEcTgTkm26H8y7A0GSgp4UmXl+srvsnFPg== dependencies: - "@emotion/is-prop-valid" "0.7.3" - "@emotion/serialize" "^0.11.6" - "@emotion/utils" "0.11.1" - object-assign "^4.1.1" + "@babel/runtime" "^7.5.5" + "@emotion/is-prop-valid" "0.8.3" + "@emotion/serialize" "^0.11.11" + "@emotion/utils" "0.11.2" -"@emotion/styled@^10.0.7": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.9.tgz#3d940ec8b989853fd422dab6278a2803e1c4a608" - integrity sha512-V+BT+KE4NKCANS18TL0yGueIyVbL5qXbgKarLcIhxmz0/dEk2k6kA18sKguJpHYa0RpgkggdhUPWWohTu3DRPw== +"@emotion/styled@^10.0.14": + version "10.0.17" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.17.tgz#0cd38b8b36259541f2c6717fc22607a120623654" + integrity sha512-zHMgWjHDMNjD+ux64POtDnjLAObniu3znxFBLSdV/RiEhSLjHIowfvSbbd/C33/3uwtI6Uzs2KXnRZtka/PpAQ== dependencies: - "@emotion/styled-base" "^10.0.9" - babel-plugin-emotion "^10.0.9" + "@emotion/styled-base" "^10.0.17" + babel-plugin-emotion "^10.0.17" "@emotion/stylis@0.8.3": version "0.8.3" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.3.tgz#3ca7e9bcb31b3cb4afbaeb66156d86ee85e23246" integrity sha512-M3nMfJ6ndJMYloSIbYEBq6G3eqoYD41BpDOxreE8j0cb4fzz/5qvmqU9Mb2hzsXcCnIlGlWhS03PCzVGvTAe0Q== -"@emotion/stylis@^0.7.0": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5" - integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ== +"@emotion/stylis@0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c" + integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ== "@emotion/unitless@0.7.3": version "0.7.3" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f" integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg== -"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7": - version "0.6.7" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397" - integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg== +"@emotion/unitless@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677" + integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ== "@emotion/utils@0.11.1": version "0.11.1" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.1.tgz#8529b7412a6eb4b48bdf6e720cc1b8e6e1e17628" integrity sha512-8M3VN0hetwhsJ8dH8VkVy7xo5/1VoBsDOk/T4SJOeXwTO1c4uIqVNx2qyecLFnnUWD5vvUqHQ1gASSeUN6zcTg== -"@emotion/utils@^0.8.2": - version "0.8.2" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc" - integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw== +"@emotion/utils@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183" + integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA== "@emotion/weak-memoize@0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.2.tgz#63985d3d8b02530e0869962f4da09142ee8e200e" integrity sha512-n/VQ4mbfr81aqkx/XmVicOLjviMuy02eenSdJY33SVA7S2J42EU0P1H0mOogfYedb3wXA0d/LVtBrgTSm04WEA== -"@emotion/weak-memoize@0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.3.tgz#dfa0c92efe44a1d1a7974fb49ffeb40ef2da5a27" - integrity sha512-zVgvPwGK7c1aVdUVc9Qv7SqepOGRDrqCw7KZPSZziWGxSlbII3gmvGLPzLX4d0n0BMbamBacUrN22zOMyFFEkQ== +"@emotion/weak-memoize@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" + integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== "@icons/material@^0.2.4": version "0.2.4" @@ -1744,161 +1776,169 @@ 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" - integrity sha512-Fp4b8cBYrl9zudvamVYTxE1XK2tzg91hgBDoVxIbDvSMZ2aQXSq8B5OFS4eSdvg+ldEOBbvIgUNS1NIw+FGntQ== - dependencies: - "@storybook/addons" "5.1.11" - "@storybook/api" "5.1.11" - "@storybook/components" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/theming" "5.1.11" +"@storybook/addon-actions@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.2.5.tgz#e8279907367392387d5c3c6af6031f9da2be9816" + integrity sha512-81N+M1GX4XB7Mirhhu3kiZJkjspfk2e1ysoJtwULjWeZfo2CLYLUAil4onr08Os2LH4RLJaj2hpS3hLflBio4g== + dependencies: + "@storybook/addons" "5.2.5" + "@storybook/api" "5.2.5" + "@storybook/client-api" "5.2.5" + "@storybook/components" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/theming" "5.2.5" core-js "^3.0.1" fast-deep-equal "^2.0.1" global "^4.3.2" - lodash "^4.17.11" polished "^3.3.1" prop-types "^15.7.2" react "^16.8.3" react-inspector "^3.0.2" uuid "^3.3.2" -"@storybook/addon-knobs@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.1.11.tgz#a7e7d986b45e8addb25151b81008af1648ef1f2a" - integrity sha512-16GY8IPxVBcmq5TqPtP6254Qw5FvdefDZjIQd+ByJJliQjXZMQKxEl6JhRq98iUfSxEB+6JCPnpKPa666jmCMA== - dependencies: - "@storybook/addons" "5.1.11" - "@storybook/client-api" "5.1.11" - "@storybook/components" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/theming" "5.1.11" +"@storybook/addon-knobs@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.2.5.tgz#cb3c617d2f017fc98c22b6db4384c90556cc074c" + integrity sha512-jr8HvtGciYaJqWgsl8CVYemcvC0Apw9YaLCV/ez8wmB4im94lmotE4llE+ZgpyIn6U6ikUYjQEeNzUMvEn25Xg== + dependencies: + "@storybook/addons" "5.2.5" + "@storybook/api" "5.2.5" + "@storybook/client-api" "5.2.5" + "@storybook/components" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/theming" "5.2.5" + "@types/react-color" "^3.0.1" copy-to-clipboard "^3.0.8" core-js "^3.0.1" escape-html "^1.0.3" fast-deep-equal "^2.0.1" global "^4.3.2" - lodash "^4.17.11" + lodash "^4.17.15" prop-types "^15.7.2" qs "^6.6.0" react-color "^2.17.0" react-lifecycles-compat "^3.0.4" - react-select "^2.2.0" - -"@storybook/addon-notes@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/addon-notes/-/addon-notes-5.1.11.tgz#ad68fd7f3eb8edc1a2f1de26364e777cbe61bf91" - integrity sha512-C+PV8vpS6g2bN96d88imQbi1RFn8wmNGaKUsncyz9ScdX9FhQwlbV8Lv1Lthholw0DwpcOjJVaf3pPml7XssGw== - dependencies: - "@storybook/addons" "5.1.11" - "@storybook/api" "5.1.11" - "@storybook/client-logger" "5.1.11" - "@storybook/components" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/router" "5.1.11" - "@storybook/theming" "5.1.11" + react-select "^3.0.0" + +"@storybook/addon-notes@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-notes/-/addon-notes-5.2.5.tgz#bd5564dcee415f22f259721b5ee4f2faced625ed" + integrity sha512-5zfJNVNN0OuIYmtsyucLtwKt9d8fNNNk1Vm/gDFF0gQvS5MxrK7rbHqiODBJzBRY2KBG4bBQZqbKQ3Eqq/7Zxw== + dependencies: + "@storybook/addons" "5.2.5" + "@storybook/api" "5.2.5" + "@storybook/client-logger" "5.2.5" + "@storybook/components" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/router" "5.2.5" + "@storybook/theming" "5.2.5" core-js "^3.0.1" global "^4.3.2" - markdown-to-jsx "^6.9.3" + markdown-to-jsx "^6.10.3" memoizerific "^1.11.3" prop-types "^15.7.2" util-deprecate "^1.0.2" -"@storybook/addon-options@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/addon-options/-/addon-options-5.1.11.tgz#c93249359f4c3586dc707611392cd342df911125" - integrity sha512-sqquPt/5FBroqsqFrAmHacxS2Bjh9ZmVLJgN7tCBR0be99q5cAJA3o0QNLIG9dS22NRR2qhG3HHOtwUqj+nXpA== +"@storybook/addon-options@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-options/-/addon-options-5.2.5.tgz#eab986dfa9a5716490b5efa4f709fad3467ff9f9" + integrity sha512-uDQmsmI/GcxWF2NecZdBB85g2P3alDqdIauaiFobUGVhYlBKVDyF59RXTh9Xqy0rTaTiiTkWO9Z0UiBywwp6hw== dependencies: - "@storybook/addons" "5.1.11" + "@storybook/addons" "5.2.5" core-js "^3.0.1" util-deprecate "^1.0.2" -"@storybook/addons@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.1.11.tgz#27f9cfed8d7f7c8a3fc341cdba3b0bdf608f02aa" - integrity sha512-714Xg6pX4rjDY1urL94w4oOxIiK6jCFSp4oKvqLj7dli5CG7d34Yt9joyTgOb2pkbrgmbMWAZJq0L0iOjHzpzw== +"@storybook/addons@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.2.5.tgz#e3e23d5ea6eb221df31e1a5d125be47454e9a0e8" + integrity sha512-CvMj7Bs3go9tv5rZuAvFwuwe8p/16LDCHS7+5nVFosvcL8nuN339V3rzakw8nLy/S6XKeZ1ACu4t3vYkreRE3w== dependencies: - "@storybook/api" "5.1.11" - "@storybook/channels" "5.1.11" - "@storybook/client-logger" "5.1.11" + "@storybook/api" "5.2.5" + "@storybook/channels" "5.2.5" + "@storybook/client-logger" "5.2.5" + "@storybook/core-events" "5.2.5" core-js "^3.0.1" global "^4.3.2" util-deprecate "^1.0.2" -"@storybook/api@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.1.11.tgz#71ef00285cd8602aad24cdb26c60c5d3c76631e5" - integrity sha512-zzPZM6W67D4YKCbUN4RhC/w+/CtnH/hFbSh/QUBdwXFB1aLh2qA1UTyB8i6m6OA6JgVHBqEkl10KhmeILLv/eA== +"@storybook/api@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.2.5.tgz#dcc68c873820485372a47c095a8fc5e4fb53a34c" + integrity sha512-JvLafqFVgA3dIWpLMoGNk4sRuogE5imhD6/g0d8DOwnCID9xowj5xIptSrCTKvGGGxuN3wWRGn6I2lEbY6969g== dependencies: - "@storybook/channels" "5.1.11" - "@storybook/client-logger" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/router" "5.1.11" - "@storybook/theming" "5.1.11" + "@storybook/channels" "5.2.5" + "@storybook/client-logger" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/router" "5.2.5" + "@storybook/theming" "5.2.5" core-js "^3.0.1" fast-deep-equal "^2.0.1" global "^4.3.2" - lodash "^4.17.11" + lodash "^4.17.15" memoizerific "^1.11.3" prop-types "^15.6.2" react "^16.8.3" semver "^6.0.0" shallow-equal "^1.1.0" store2 "^2.7.1" - telejson "^2.2.1" + telejson "^3.0.2" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.1.11.tgz#e75ab7d59ba19476eb631cdb69ee713c3b956c2b" - integrity sha512-S7Uq7+c9kOJ9BB4H9Uro2+dVhqoMchYCipQzAkD4jIIwK99RNzGdAaRipDC1k0k/C+v2SOa+D5xBbb3XVYPSrg== +"@storybook/channel-postmessage@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.2.5.tgz#47397e543a87ea525cbe93f7d85bd8533edc9127" + integrity sha512-GoiC6dUM3YfNKpvj3syxQIQJLHBnH61CfLJzz4xygmn+3keHtjtz6yPHaU4+00MSSP2uDzqePkjgXx4DcLedHA== dependencies: - "@storybook/channels" "5.1.11" - "@storybook/client-logger" "5.1.11" + "@storybook/channels" "5.2.5" + "@storybook/client-logger" "5.2.5" core-js "^3.0.1" global "^4.3.2" - telejson "^2.2.1" + telejson "^3.0.2" -"@storybook/channels@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.1.11.tgz#77ddf9d777891f975ac10095772c840fed4c4620" - integrity sha512-MlrjVGNvYOnDvv2JDRhr4wikbnZ8HCFCpVsFqKPFxj7I3OYBR417RvFkydX3Rtx4kwB9rmZEgLhfAfsSytkALg== +"@storybook/channels@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.2.5.tgz#d6ca2b490281dacb272096563fe760ccb353c4bb" + integrity sha512-I+zB3ym5ozBcNBqyzZbvB6gRIG/ZKKkqy5k6LwKd5NMx7NU7zU74+LQUBBOcSIrigj8kCArZz7rlgb0tlSKXxQ== dependencies: core-js "^3.0.1" -"@storybook/client-api@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.1.11.tgz#30d82c09c6c40aa70d932e77b1d1e65526bddc0c" - integrity sha512-znzSxZ1ZCqtEKrFoW7xT8iBbdiAXaQ8RNxQFKHuYPqWX+RLol6S3duEOxu491X2SzUg0StUmrX5qL9Rnth8dRQ== - dependencies: - "@storybook/addons" "5.1.11" - "@storybook/client-logger" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/router" "5.1.11" +"@storybook/client-api@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.2.5.tgz#53151a236b6ffc2088acc4535a08e010013e3278" + integrity sha512-n7CAZ3+DZ7EUdmXbq8mXRb+stOavC8GMw3CzjGSo8O6t4rFcMpZQAzjS0YRX1RG/CGFSv9d3R3TNvEBcBGTwRg== + dependencies: + "@storybook/addons" "5.2.5" + "@storybook/channel-postmessage" "5.2.5" + "@storybook/channels" "5.2.5" + "@storybook/client-logger" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/router" "5.2.5" common-tags "^1.8.0" core-js "^3.0.1" - eventemitter3 "^3.1.0" + eventemitter3 "^4.0.0" global "^4.3.2" is-plain-object "^3.0.0" - lodash "^4.17.11" + lodash "^4.17.15" memoizerific "^1.11.3" qs "^6.6.0" + util-deprecate "^1.0.2" -"@storybook/client-logger@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.1.11.tgz#9509af3021b7a9977f9dba1f2ff038fd3c994437" - integrity sha512-je4To+9zD3SEJsKe9R4u15N4bdXFBR7pdBToaRIur+XSvvShLFehZGseQi+4uPAj8vyG34quGTCeUC/BKY0LwQ== +"@storybook/client-logger@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.2.5.tgz#6f386ac6f81b4a783c57d54bb328281abbea1bab" + integrity sha512-6DyYUrMgAvF+th0foH7UNz+2JJpRdvNbpvYKtvi/+hlvRIaI6AqANgLkPUgMibaif5TLzjCr0bLdAYcjeJz03w== dependencies: core-js "^3.0.1" -"@storybook/components@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.1.11.tgz#da253af0a8cb1b063c5c2e8016c4540c983f717d" - integrity sha512-EQgD7HL2CWnnY968KrwUSU2dtKFGTGRJVc4vwphYEeZwAI0lX6qbTMuwEP22hDZ2OSRBxcvcXT8cvduDlZlFng== +"@storybook/components@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.2.5.tgz#40190dafbee34f083182255d26c19a0ea50789c8" + integrity sha512-6NVaBJm5wY53e9k+2ZiL2ABsHghE1ssQciLTG3jJPahnM6rfkM8ue66rhxhP88jE9isT48JgOZOJepEyxDz/fg== dependencies: - "@storybook/client-logger" "5.1.11" - "@storybook/theming" "5.1.11" + "@storybook/client-logger" "5.2.5" + "@storybook/theming" "5.2.5" + "@types/react-syntax-highlighter" "10.1.0" + "@types/react-textarea-autosize" "^4.3.3" core-js "^3.0.1" global "^4.3.2" markdown-to-jsx "^6.9.1" @@ -1913,39 +1953,39 @@ react-popper-tooltip "^2.8.3" react-syntax-highlighter "^8.0.1" react-textarea-autosize "^7.1.0" - recompose "^0.30.0" simplebar-react "^1.0.0-alpha.6" -"@storybook/core-events@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.1.11.tgz#9d00503a936d30398f7a64336eb956303d053765" - integrity sha512-m+yIFRdB47+IPBFBGS2OUXrSLkoz5iAXvb3c0lGAePf5wSR+o/Ni/9VD5l6xBf+InxHLSc9gcDEJehrT0fJAaQ== +"@storybook/core-events@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.2.5.tgz#62881164a4a01aa99ff0691e70eaed2dd58e229e" + integrity sha512-O5GM8XEBbYNbM6Z7a4H1bbnbO2cxQrXMhEwansC7a7YinQdkTPiuGxke3NiyK+7pLDh778kpQyjoCjXq6UfAoQ== dependencies: core-js "^3.0.1" -"@storybook/core@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.1.11.tgz#d7c4b14b02f74c183ab5baffe9b3e5ec8289b320" - integrity sha512-LkSoAJlLEtrzFcoINX3dz4oT6xUPEHEp2/WAXLqUFeCnzJHAxIsRvbVxB49Kh/2TrgDFZpL9Or8XXMzZtE6KYw== +"@storybook/core@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.2.5.tgz#cc04313480a1847aa6881420c675517cc400dc2e" + integrity sha512-R6A6VzSh++pB1a+9DsywW5Mlp0/eauQz1A8m2DrllWcTHTjbn0ZovlG5HBrKjpknFXpCWxkUKE4eTAE2tWsryA== dependencies: "@babel/plugin-proposal-class-properties" "^7.3.3" "@babel/plugin-proposal-object-rest-spread" "^7.3.2" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-env" "^7.4.5" - "@storybook/addons" "5.1.11" - "@storybook/channel-postmessage" "5.1.11" - "@storybook/client-api" "5.1.11" - "@storybook/client-logger" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/node-logger" "5.1.11" - "@storybook/router" "5.1.11" - "@storybook/theming" "5.1.11" - "@storybook/ui" "5.1.11" + "@storybook/addons" "5.2.5" + "@storybook/channel-postmessage" "5.2.5" + "@storybook/client-api" "5.2.5" + "@storybook/client-logger" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/node-logger" "5.2.5" + "@storybook/router" "5.2.5" + "@storybook/theming" "5.2.5" + "@storybook/ui" "5.2.5" airbnb-js-shims "^1 || ^2" + ansi-to-html "^0.6.11" autoprefixer "^9.4.9" babel-plugin-add-react-displayname "^0.0.5" - babel-plugin-emotion "^10.0.9" + babel-plugin-emotion "^10.0.14" babel-plugin-macros "^2.4.5" babel-preset-minify "^0.5.0 || 0.6.0-alpha.5" boxen "^3.0.0" @@ -1955,8 +1995,8 @@ commander "^2.19.0" common-tags "^1.8.0" core-js "^3.0.1" - corejs-upgrade-webpack-plugin "^2.0.0" - css-loader "^2.1.1" + corejs-upgrade-webpack-plugin "^2.2.0" + css-loader "^3.0.0" detect-port "^1.3.0" dotenv-webpack "^1.7.0" ejs "^2.6.1" @@ -1971,7 +2011,7 @@ interpret "^1.2.0" ip "^1.1.5" json5 "^2.1.0" - lazy-universal-dotenv "^3.0.0" + lazy-universal-dotenv "^3.0.1" node-fetch "^2.6.0" open "^6.1.0" pnp-webpack-plugin "1.4.3" @@ -1990,16 +2030,16 @@ style-loader "^0.23.1" terser-webpack-plugin "^1.2.4" unfetch "^4.1.0" - url-loader "^1.1.2" + url-loader "^2.0.1" util-deprecate "^1.0.2" webpack "^4.33.0" webpack-dev-middleware "^3.7.0" webpack-hot-middleware "^2.25.0" -"@storybook/node-logger@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.1.11.tgz#bbf5ad0d148e6c9a9b7cf6f62ad4df4e9fa19e5d" - integrity sha512-LG0KM4lzb9LEffcO3Ps9FcHHsVgQUc/oG+kz3p0u9fljFoL3cJHF1Mb4o+HrSydtdWZs/spwZ/BLEo5n/AByDw== +"@storybook/node-logger@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.2.5.tgz#87f53de795db6eed912b54d3cca82fd7b7857771" + integrity sha512-UNyXGOhOr4Bn9wKwBTZABTBXQzrgvGxPLSmvAFZuMx9ZhqoT/EXAuLUl0/wiJtkyuYpoOOskNwIdKxLBdTKS2w== dependencies: chalk "^2.4.2" core-js "^3.0.1" @@ -2007,17 +2047,19 @@ pretty-hrtime "^1.0.3" regenerator-runtime "^0.12.1" -"@storybook/react@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.1.11.tgz#227e13670098e52d1537daf9dc349755cea17e0c" - integrity sha512-y8/L2OWvev3fGREhAmToLVDPf8YEZMs5+vzSdzXlVlPkqHyAmWPtLY4sRB6K+TsEF0gwaC5F2BvMnKxbNYwd/Q== +"@storybook/react@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.2.5.tgz#f0082d75b14a10642986c7934fcbc8ff855b07fe" + integrity sha512-yPOL0jBEfYo3YkRJkXnIzAQ3L9lTju27mg+0bW+y3lpJAM23ffAxrRyOGV7bzj99EA7dak2lw8Hj4yVHTplBdg== dependencies: "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-flow" "^7.0.0" "@babel/preset-react" "^7.0.0" - "@storybook/core" "5.1.11" - "@storybook/node-logger" "5.1.11" + "@storybook/addons" "5.2.5" + "@storybook/core" "5.2.5" + "@storybook/node-logger" "5.2.5" "@svgr/webpack" "^4.0.3" + "@types/webpack-env" "^1.13.7" babel-plugin-add-react-displayname "^0.0.5" babel-plugin-named-asset-import "^0.3.1" babel-plugin-react-docgen "^3.0.0" @@ -2025,7 +2067,7 @@ common-tags "^1.8.0" core-js "^3.0.1" global "^4.3.2" - lodash "^4.17.11" + lodash "^4.17.15" mini-css-extract-plugin "^0.7.0" prop-types "^15.7.2" react-dev-utils "^9.0.0" @@ -2033,56 +2075,58 @@ semver "^6.0.0" webpack "^4.33.0" -"@storybook/router@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.1.11.tgz#75089e9e623482e52ed894c3f0cb0fc6a5372da9" - integrity sha512-Xt7R1IOWLlIxis6VKV9G8F+e/G4G8ng1zXCqoDq+/RlWzlQJ5ccO4bUm2/XGS1rEgY4agMzmzjum18HoATpLGA== +"@storybook/router@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.2.5.tgz#a005332bc6aa1e7849503187ad50c41b3f3bef92" + integrity sha512-e6ElDAWSoEW1KSnsTbVwbpzaZ8CNWYw0Ok3b5AHfY2fuSH5L4l6s6k/bP7QSYqvWUeTvkFQYux7A2rOFCriAgA== dependencies: "@reach/router" "^1.2.1" + "@types/reach__router" "^1.2.3" core-js "^3.0.1" global "^4.3.2" + lodash "^4.17.15" memoizerific "^1.11.3" qs "^6.6.0" -"@storybook/theming@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.1.11.tgz#0d1af46535f2e601293c999a314905069a93ec3b" - integrity sha512-PtRPfiAWx5pQbTm45yyPB+CuW/vyDmcmNOt+xnDzK52omeWaSD7XK2RfadN3u4QXCgha7zs35Ppx1htJio2NRA== +"@storybook/theming@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.2.5.tgz#9579e7944f61ded637d1d79be5fb859a617620f5" + integrity sha512-PGZNYrRgAhXFJKnktFpyyKlaDXEhtTi5XPq5ASVJrsPW6l963Mk2EMKSm4TCTxIJhs0Kx4cv2MnNZFDqHf47eg== dependencies: - "@emotion/core" "^10.0.9" - "@emotion/styled" "^10.0.7" - "@storybook/client-logger" "5.1.11" + "@emotion/core" "^10.0.14" + "@emotion/styled" "^10.0.14" + "@storybook/client-logger" "5.2.5" common-tags "^1.8.0" core-js "^3.0.1" deep-object-diff "^1.1.0" - emotion-theming "^10.0.9" + emotion-theming "^10.0.14" global "^4.3.2" memoizerific "^1.11.3" polished "^3.3.1" prop-types "^15.7.2" resolve-from "^5.0.0" -"@storybook/ui@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.1.11.tgz#02246f7656f644a36908430de12abbdf4e2a8a72" - integrity sha512-mopuFSwtodvH4HRdaSBlgYxzYca1qyvzZ0BxOPocXhiFfFR+V9NyNJqKKRA3vinWuuZWpYcnPTu3h8skmjMirg== - dependencies: - "@storybook/addons" "5.1.11" - "@storybook/api" "5.1.11" - "@storybook/channels" "5.1.11" - "@storybook/client-logger" "5.1.11" - "@storybook/components" "5.1.11" - "@storybook/core-events" "5.1.11" - "@storybook/router" "5.1.11" - "@storybook/theming" "5.1.11" +"@storybook/ui@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.2.5.tgz#0c2c67216e4c808e39cdb48301cafde81b77d074" + integrity sha512-C+5KmeTtdG6xkGXPmFDHPxTcSvVohuFD1399fnzjYhfLlRJ04ix3g16rcyDTxRtrFgFidOyGHdzCypgkdaN8dQ== + dependencies: + "@storybook/addons" "5.2.5" + "@storybook/api" "5.2.5" + "@storybook/channels" "5.2.5" + "@storybook/client-logger" "5.2.5" + "@storybook/components" "5.2.5" + "@storybook/core-events" "5.2.5" + "@storybook/router" "5.2.5" + "@storybook/theming" "5.2.5" copy-to-clipboard "^3.0.8" core-js "^3.0.1" core-js-pure "^3.0.1" - emotion-theming "^10.0.10" + emotion-theming "^10.0.14" fast-deep-equal "^2.0.1" fuse.js "^3.4.4" global "^4.3.2" - lodash "^4.17.11" + lodash "^4.17.15" markdown-to-jsx "^6.9.3" memoizerific "^1.11.3" polished "^3.3.1" @@ -2090,16 +2134,15 @@ qs "^6.6.0" react "^16.8.3" react-dom "^16.8.3" - react-draggable "^3.1.1" + react-draggable "^4.0.3" react-helmet-async "^1.0.2" react-hotkeys "2.0.0-pre4" - react-resize-detector "^4.0.5" - recompose "^0.30.0" + react-sizeme "^2.6.7" regenerator-runtime "^0.13.2" resolve-from "^5.0.0" semver "^6.0.0" store2 "^2.7.1" - telejson "^2.2.1" + telejson "^3.0.2" util-deprecate "^1.0.2" "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": @@ -2265,6 +2308,16 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/history@*": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.3.tgz#856c99cdc1551d22c22b18b5402719affec9839a" + integrity sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw== + +"@types/is-function@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/is-function/-/is-function-1.0.0.tgz#1b0b819b1636c7baf0d6785d030d12edf70c3e83" + integrity sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -2327,6 +2380,28 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== +"@types/reach__router@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.2.6.tgz#b14cf1adbd1a365d204bbf6605cd9dd7b8816c87" + integrity sha512-Oh5DAVr/L2svBvubw6QEFpXGu295Y406BPs4i9t1n2pp7M+q3pmCmhzb9oZV5wncR41KCD3NHl1Yhi7uKnTPsA== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-color@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.1.tgz#5433e2f503ea0e0831cbc6fd0c20f8157d93add0" + integrity sha512-J6mYm43Sid9y+OjZ7NDfJ2VVkeeuTPNVImNFITgQNXodHteKfl/t/5pAR5Z9buodZ2tCctsZjgiMlQOpfntakw== + dependencies: + "@types/react" "*" + +"@types/react-syntax-highlighter@10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-10.1.0.tgz#9c534e29bbe05dba9beae1234f3ae944836685d4" + integrity sha512-dF49hC4FZp1dIKyzacOrHvqMUe8U2IXyQCQXOcT1e6n64gLBp+xM6qGtPsThIT9XjiIHSg2W5Jc2V5IqekBfnA== + dependencies: + "@types/react" "*" + "@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" @@ -2334,6 +2409,13 @@ dependencies: "@types/react" "*" +"@types/react-textarea-autosize@^4.3.3": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/react-textarea-autosize/-/react-textarea-autosize-4.3.4.tgz#9a93f751c91ad5e86387bce75e3b7e11ed195813" + integrity sha512-LLqG27BJGt8ja9x4umQXbnK9pRd0dI23X/GXBcuf476feOZ+e5QiKJYmWOHwAJC3YLl3YixDSigzfF4gzVQZ5w== + dependencies: + "@types/react" "*" + "@types/react-wait@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@types/react-wait/-/react-wait-0.3.0.tgz#6f7ef17571a17e72c7864ede8cf7d3aa525a005e" @@ -2362,6 +2444,11 @@ "@types/react" "*" "@types/react-test-renderer" "*" +"@types/webpack-env@^1.13.7": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.1.tgz#0d8a53f308f017c53a5ddc3d07f4d6fa76b790d7" + integrity sha512-0Ki9jAAhKDSuLDXOIMADg54Hu60SuBTEsWaJGGy5cV+SSUQ63J2a+RrYYGrErzz39fXzTibhKrAQJAb8M7PNcA== + "@types/yargs-parser@*": version "13.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.0.0.tgz#453743c5bbf9f1bed61d959baab5b06be029b2d0" @@ -2723,6 +2810,13 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-to-html@^0.6.11: + version "0.6.12" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.12.tgz#9dcd1646f17770d02ec065615e97f979f4e313cb" + integrity sha512-qBkIqLW979675mP76yB7yVkzeAWtATegdnDQ0RA3CZzknx0yUlNxMSML4xFdBfTs2GWYFQ1FELfbGbVSPzJ+LA== + dependencies: + entities "^1.1.2" + ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" @@ -3143,15 +3237,15 @@ babel-plugin-dynamic-import-node@2.3.0, babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" -babel-plugin-emotion@^10.0.9: - version "10.0.9" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.9.tgz#04a0404d5a4084d5296357a393d344c0f8303ae4" - integrity sha512-IfWP12e9/wHtWHxVTzD692Nbcmrmcz2tip7acp6YUqtrP7slAyr5B+69hyZ8jd55GsyNSZwryNnmuDEVe0j+7w== +babel-plugin-emotion@^10.0.14, babel-plugin-emotion@^10.0.17: + version "10.0.21" + resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.21.tgz#9ebeb12edeea3e60a5476b0e07c9868605e65968" + integrity sha512-03o+T6sfVAJhNDcSdLapgv4IeewcFPzxlvBUVdSf7o5PI57ZSxoDvmy+ZulVWSu+rOWAWkEejNcsb29TuzJHbg== dependencies: "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.7.1" - "@emotion/memoize" "0.7.1" - "@emotion/serialize" "^0.11.6" + "@emotion/hash" "0.7.3" + "@emotion/memoize" "0.7.3" + "@emotion/serialize" "^0.11.11" babel-plugin-macros "^2.0.0" babel-plugin-syntax-jsx "^6.18.0" convert-source-map "^1.5.0" @@ -3159,23 +3253,21 @@ babel-plugin-emotion@^10.0.9: find-root "^1.1.0" source-map "^0.5.7" -babel-plugin-emotion@^9.2.11: - version "9.2.11" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728" - integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ== +babel-plugin-emotion@^10.0.9: + version "10.0.9" + resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.9.tgz#04a0404d5a4084d5296357a393d344c0f8303ae4" + integrity sha512-IfWP12e9/wHtWHxVTzD692Nbcmrmcz2tip7acp6YUqtrP7slAyr5B+69hyZ8jd55GsyNSZwryNnmuDEVe0j+7w== dependencies: "@babel/helper-module-imports" "^7.0.0" - "@emotion/babel-utils" "^0.6.4" - "@emotion/hash" "^0.6.2" - "@emotion/memoize" "^0.6.1" - "@emotion/stylis" "^0.7.0" + "@emotion/hash" "0.7.1" + "@emotion/memoize" "0.7.1" + "@emotion/serialize" "^0.11.6" babel-plugin-macros "^2.0.0" babel-plugin-syntax-jsx "^6.18.0" convert-source-map "^1.5.0" + escape-string-regexp "^1.0.5" find-root "^1.1.0" - mkdirp "^0.5.1" source-map "^0.5.7" - touch "^2.0.1" babel-plugin-istanbul@^5.1.0: version "5.1.1" @@ -3514,6 +3606,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +batch-processor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" + integrity sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg= + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -3920,7 +4017,7 @@ camelcase@^4.0.0, camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= -camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -3985,11 +4082,6 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -change-emitter@^0.1.2: - version "0.1.6" - resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" - integrity sha1-6LL+PX8at9aaMhma/5HqaTFAlRU= - character-entities-legacy@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" @@ -4487,7 +4579,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -corejs-upgrade-webpack-plugin@^2.0.0: +corejs-upgrade-webpack-plugin@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/corejs-upgrade-webpack-plugin/-/corejs-upgrade-webpack-plugin-2.2.0.tgz#503293bf1fdcb104918eb40d0294e4776ad6923a" integrity sha512-J0QMp9GNoiw91Kj/dkIQFZeiCXgXoja/Wlht1SPybxerBWh4NCmb0pOgCv61lrlQZETwvVVfAFAA3IqoEO9aqQ== @@ -4513,19 +4605,6 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-emotion@^9.2.12: - version "9.2.12" - resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f" - integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA== - dependencies: - "@emotion/hash" "^0.6.2" - "@emotion/memoize" "^0.6.1" - "@emotion/stylis" "^0.7.0" - "@emotion/unitless" "^0.6.2" - csstype "^2.5.2" - stylis "^3.5.0" - stylis-rule-sheet "^0.0.10" - create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" @@ -4614,22 +4693,23 @@ css-in-js-utils@^2.0.0: hyphenate-style-name "^1.0.2" isobject "^3.0.1" -css-loader@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea" - integrity sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w== +css-loader@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.2.0.tgz#bb570d89c194f763627fcf1f80059c6832d009b2" + integrity sha512-QTF3Ud5H7DaZotgdcJjGMvyDj5F3Pn1j/sC6VBEOVp94cbwqyIBdcs/quzj4MC1BKQSrTpQznegH/5giYbhnCQ== dependencies: - camelcase "^5.2.0" - icss-utils "^4.1.0" + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" loader-utils "^1.2.3" normalize-path "^3.0.0" - postcss "^7.0.14" + postcss "^7.0.17" postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^2.0.6" + postcss-modules-local-by-default "^3.0.2" postcss-modules-scope "^2.1.0" - postcss-modules-values "^2.0.0" - postcss-value-parser "^3.3.0" - schema-utils "^1.0.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.0" + schema-utils "^2.0.0" css-select-base-adapter@^0.1.1: version "0.1.1" @@ -4701,7 +4781,7 @@ cssstyle@^1.0.0: dependencies: cssom "0.3.x" -csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.5, csstype@^2.5.7: +csstype@^2.2.0, csstype@^2.5.5, csstype@^2.5.7: version "2.6.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa" integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg== @@ -5180,6 +5260,13 @@ elegant-spinner@^1.0.1: resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= +element-resize-detector@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.1.15.tgz#48eba1a2eaa26969a4c998d972171128c971d8d2" + integrity sha512-16/5avDegXlUxytGgaumhjyQoM6hpp5j3+L79sYq5hlXfTNRy5WMMuTVWkZU3egp/CokCmTmvf18P3KeB57Iog== + dependencies: + batch-processor "^1.0.0" + elliptic@^6.0.0: version "6.5.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" @@ -5208,23 +5295,15 @@ emojis-list@^2.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= -emotion-theming@^10.0.10, emotion-theming@^10.0.9: - version "10.0.14" - resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.14.tgz#e548d388493d07bedbb0d9d3bbe221766174b1f4" - integrity sha512-zMGhPSYz48AAR6DYjQVaZHeO42cYKPq4VyB1XjxzgR62/NmO99679fx8qDDB1QZVYGkRWZtsOe+zJE/e30XdbA== +emotion-theming@^10.0.14: + version "10.0.19" + resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.19.tgz#66d13db74fccaefad71ba57c915b306cf2250295" + integrity sha512-dQRBPLAAQ6eA8JKhkLCIWC8fdjPbiNC1zNTdFF292h9amhZXofcNGUP7axHoHX4XesqQESYwZrXp53OPInMrKw== dependencies: - "@babel/runtime" "^7.4.3" - "@emotion/weak-memoize" "0.2.3" + "@babel/runtime" "^7.5.5" + "@emotion/weak-memoize" "0.2.4" hoist-non-react-statics "^3.3.0" -emotion@^9.1.2: - version "9.2.12" - resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9" - integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ== - dependencies: - babel-plugin-emotion "^9.2.11" - create-emotion "^9.2.12" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -5253,7 +5332,7 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: memory-fs "^0.4.0" tapable "^1.0.0" -entities@^1.1.1: +entities@^1.1.1, entities@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== @@ -5415,10 +5494,10 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -eventemitter3@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" - integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== +eventemitter3@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" + integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== events@^3.0.0: version "3.0.0" @@ -5682,7 +5761,7 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fbjs@^0.8.0, fbjs@^0.8.1: +fbjs@^0.8.0: version "0.8.17" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= @@ -6253,6 +6332,14 @@ global@^4.3.2: min-document "^2.19.0" process "~0.5.1" +global@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + globals@^11.1.0: version "11.11.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" @@ -6496,11 +6583,6 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^2.3.1: - version "2.5.5" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== - hoist-non-react-statics@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" @@ -6677,12 +6759,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" -icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= - -icss-utils@^4.1.0: +icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== @@ -7933,7 +8010,7 @@ lazy-property@~1.0.0: resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147" integrity sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc= -lazy-universal-dotenv@^3.0.0: +lazy-universal-dotenv@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" integrity sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ== @@ -8234,11 +8311,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash-es@^4.17.11: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" - integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -8277,11 +8349,6 @@ lodash.escaperegexp@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" @@ -8514,6 +8581,14 @@ markdown-loader@5.1.0: loader-utils "^1.2.3" marked "^0.7.0" +markdown-to-jsx@^6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.3.tgz#7f0946684acd321125ff2de7fd258a9b9c7c40b7" + integrity sha512-PSoUyLnW/xoW6RsxZrquSSz5eGEOTwa15H5eqp3enmrp8esmgDJmhzd6zmQ9tgAA9TxJzx1Hmf3incYU/IamoQ== + dependencies: + prop-types "^15.6.2" + unquote "^1.1.0" + markdown-to-jsx@^6.9.1, markdown-to-jsx@^6.9.3: version "6.10.2" resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.2.tgz#644f602b81d088f10aef1c3674874876146cf38b" @@ -8701,7 +8776,7 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.0.3, mime@^2.4.2: +mime@^2.0.3, mime@^2.4.2, mime@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== @@ -9073,13 +9148,6 @@ nopt@^4.0.1, nopt@~4.0.1: abbrev "1" osenv "^0.1.4" -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" - normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -10025,14 +10093,15 @@ postcss-modules-extract-imports@^2.0.0: dependencies: postcss "^7.0.5" -postcss-modules-local-by-default@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz#dd9953f6dd476b5fd1ef2d8830c8929760b56e63" - integrity sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA== +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" + integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" - postcss-value-parser "^3.3.1" + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" postcss-modules-scope@^2.1.0: version "2.1.0" @@ -10042,15 +10111,15 @@ postcss-modules-scope@^2.1.0: postcss "^7.0.6" postcss-selector-parser "^6.0.0" -postcss-modules-values@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz#479b46dc0c5ca3dc7fa5270851836b9ec7152f64" - integrity sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w== +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: - icss-replace-symbols "^1.1.0" + icss-utils "^4.0.0" postcss "^7.0.6" -postcss-selector-parser@^6.0.0: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== @@ -10059,11 +10128,6 @@ postcss-selector-parser@^6.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - postcss-value-parser@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.1.tgz#e3f6172cc91302912c89da55a42454025485250f" @@ -10078,6 +10142,15 @@ postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.5, postcss@^7.0.6 source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.16: + version "7.0.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" + integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -10368,23 +10441,11 @@ qw@~1.0.1: resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" integrity sha1-77/cdA+a0FQwRCassYNBLMi5ltQ= -raf-schd@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" - integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== - raf-stub@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/raf-stub/-/raf-stub-3.0.0.tgz#40e53dc3ad3b241311f914bbd41dc11a2c9ee0a9" integrity sha512-64wjDTI8NAkplC3WYF3DUBXmdx8AZF0ubxiicZi83BKW5hcdvMtbwDe6gpFBngTo6+XIJbfwmUP8lMa85UPK6A== -raf@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" - integrity sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw== - dependencies: - performance-now "^2.1.0" - ramda@^0.21.0: version "0.21.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" @@ -10522,10 +10583,10 @@ react-dom@^16.8.3: prop-types "^15.6.2" scheduler "^0.15.0" -react-draggable@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.3.0.tgz#2ed7ea3f92e7d742d747f9e6324860606cd4d997" - integrity sha512-U7/jD0tAW4T0S7DCPK0kkKLyL0z61sC/eqU+NUfDjnq+JtBKaYKDHpsK2wazctiA4alEzCXUnzkREoxppOySVw== +react-draggable@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.0.3.tgz#6b9f76f66431c47b9070e9b805bbc520df8ca481" + integrity sha512-4vD6zms+9QGeZ2RQXzlUBw8PBYUXy+dzYX5r22idjp9YwQKIIvD/EojL0rbjS1GK4C3P0rAJnmKa8gDQYWUDyA== dependencies: classnames "^2.2.5" prop-types "^15.6.0" @@ -10573,10 +10634,10 @@ react-hotkeys@2.0.0-pre4: dependencies: prop-types "^15.6.1" -react-input-autosize@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" - integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA== +react-input-autosize@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" + integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== dependencies: prop-types "^15.5.8" @@ -10599,7 +10660,7 @@ react-is@^16.8.6: 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: +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" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== @@ -10624,30 +10685,30 @@ react-popper@^1.3.3: typed-styles "^0.0.7" warning "^4.0.2" -react-resize-detector@^4.0.5: - version "4.2.0" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-4.2.0.tgz#b87aee6b37c9e8a52daca8736b3230cf6a2a8647" - integrity sha512-AtOaNIxs0ydua7tEoglXR3902/EdlIj9PXDu1Zj0ug2VAUnkSQjguLGzaG/N6CXLOhJSccTsUCZxjLayQ1mE9Q== +react-select@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.8.tgz#06ff764e29db843bcec439ef13e196865242e0c1" + integrity sha512-v9LpOhckLlRmXN5A6/mGGEft4FMrfaBFTGAnuPHcUgVId7Je42kTq9y0Z+Ye5z8/j0XDT3zUqza8gaRaI1PZIg== dependencies: - lodash "^4.17.11" - lodash-es "^4.17.11" - prop-types "^15.7.2" - raf-schd "^4.0.0" - resize-observer-polyfill "^1.5.1" - -react-select@^2.2.0: - version "2.4.4" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.4.tgz#ba72468ef1060c7d46fbb862b0748f96491f1f73" - integrity sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw== - dependencies: - classnames "^2.2.5" - emotion "^9.1.2" + "@babel/runtime" "^7.4.4" + "@emotion/cache" "^10.0.9" + "@emotion/core" "^10.0.9" + "@emotion/css" "^10.0.9" memoize-one "^5.0.0" prop-types "^15.6.0" - raf "^3.4.0" - react-input-autosize "^2.2.1" + react-input-autosize "^2.2.2" react-transition-group "^2.2.1" +react-sizeme@^2.6.7: + version "2.6.10" + resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.10.tgz#9993dcb5e67fab94a8e5d078a0d3820609010f17" + integrity sha512-OJAPQxSqbcpbsXFD+fr5ARw4hNSAOimWcaTOLcRkIqnTp9+IFWY0w3Qdw1sMez6Ao378aimVL/sW6TTsgigdOA== + dependencies: + element-resize-detector "^1.1.15" + invariant "^2.2.4" + shallowequal "^1.1.0" + throttle-debounce "^2.1.0" + react-spring@8.0.27: version "8.0.27" resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-8.0.27.tgz#97d4dee677f41e0b2adcb696f3839680a3aa356a" @@ -10920,18 +10981,6 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" -recompose@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.30.0.tgz#82773641b3927e8c7d24a0d87d65aeeba18aabd0" - integrity sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w== - dependencies: - "@babel/runtime" "^7.0.0" - change-emitter "^0.1.2" - fbjs "^0.8.1" - hoist-non-react-statics "^2.3.1" - react-lifecycles-compat "^3.0.2" - symbol-observable "^1.0.4" - recursive-readdir@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" @@ -11411,6 +11460,14 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +schema-utils@^2.0.0, schema-utils@^2.4.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.5.0.tgz#8f254f618d402cc80257486213c8970edfd7c22f" + integrity sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + screenfull@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.0.0.tgz#5c2010c0e84fd4157bf852877698f90b8cbe96f6" @@ -11846,11 +11903,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - sourcemap-codec@^1.4.1: version "1.4.3" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.3.tgz#0ba615b73ec35112f63c2f2d9e7c3f87282b0e33" @@ -12234,12 +12286,7 @@ style-loader@^0.23.1: loader-utils "^1.1.0" schema-utils "^1.0.0" -stylis-rule-sheet@^0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" - integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== - -stylis@3.5.0, stylis@^3.5.0: +stylis@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1" integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw== @@ -12295,7 +12342,7 @@ svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-observable@^1.0.4, symbol-observable@^1.1.0: +symbol-observable@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== @@ -12339,17 +12386,18 @@ tar@^4, tar@^4.4.8: safe-buffer "^5.1.2" yallist "^3.0.2" -telejson@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/telejson/-/telejson-2.2.1.tgz#d9ee7e7eba0c81d9378257342fde7142a03787e2" - integrity sha512-JtFAnITek+Z9t+uQjVl4Fxur9Z3Bi3flytBLc3KZVXmMUHLXdtAxiP0g8IBkHvKn1kQIYZC57IG0jjGH1s64HQ== +telejson@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-3.0.3.tgz#442af55f78d791d3744c9e7a696be6cdf789a4b5" + integrity sha512-gUOh6wox1zJjbGMg+e26NquZcp/F18EbIaqVvjiGqikRqVB4fYEAM8Nyin8smgwX30XhaRBOg+kCj4vInmvwAg== dependencies: - global "^4.3.2" + "@types/is-function" "^1.0.0" + global "^4.4.0" is-function "^1.0.1" is-regex "^1.0.4" is-symbol "^1.0.2" - isobject "^3.0.1" - lodash.get "^4.4.2" + isobject "^4.0.0" + lodash "^4.17.15" memoizerific "^1.11.3" term-size@^1.2.0: @@ -12413,6 +12461,11 @@ throttle-debounce@^2.0.1: resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.0.1.tgz#7307ddd6cd9acadb349132fbf6c18d78c88a5e62" integrity sha512-Sr6jZBlWShsAaSXKyNXyNicOrJW/KtkDqIEwHt4wYwWA2wa/q67Luhqoujg48V8hTk60wB56tYrJJn6jc2R7VA== +throttle-debounce@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" + integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== + through2@^2.0.0, through2@^2.0.2, through2@~2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" @@ -12522,13 +12575,6 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== -touch@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164" - integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A== - dependencies: - nopt "~1.0.10" - tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -12913,14 +12959,14 @@ url-join@^4.0.0: resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a" integrity sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo= -url-loader@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8" - integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg== +url-loader@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.2.0.tgz#af321aece1fd0d683adc8aaeb27829f29c75b46e" + integrity sha512-G8nk3np8ZAnwhHXas1JxJEwJyQdqFXAKJehfgZ/XrC48volFBRtO+FIKtF2u0Ma3bw+4vnDVjHPAQYlF9p2vsw== dependencies: - loader-utils "^1.1.0" - mime "^2.0.3" - schema-utils "^1.0.0" + loader-utils "^1.2.3" + mime "^2.4.4" + schema-utils "^2.4.1" url-parse-lax@^1.0.0: version "1.0.0" From 2b30566ad3a25d0e4267ac1050487b20073a1f0a Mon Sep 17 00:00:00 2001 From: Marcel Tinner Date: Wed, 23 Oct 2019 15:13:22 +0200 Subject: [PATCH 039/213] add typings for createReducer --- src/createReducer.ts | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/createReducer.ts b/src/createReducer.ts index 781900f45a..cee9ba867d 100644 --- a/src/createReducer.ts +++ b/src/createReducer.ts @@ -1,18 +1,35 @@ import { useCallback, useRef, useState } from 'react'; import useUpdateEffect from './useUpdateEffect'; -function composeMiddleware(chain) { - return (context, dispatch) => { +type Dispatch = (action: Action) => void; + +type Store = { + getState: () => State; + dispatch: Dispatch; +}; + +type Middleware = ( + store: Store +) => (next: Dispatch) => (action: Action) => void; + +function composeMiddleware(chain: Middleware[]) { + return (context: Store, dispatch: Dispatch) => { return chain.reduceRight((res, middleware) => { return middleware(context)(res); }, dispatch); }; } -const createReducer = (...middlewares) => { - const composedMiddleware = composeMiddleware(middlewares); +const createReducer = ( + ...middlewares: Middleware[] +) => { + const composedMiddleware = composeMiddleware(middlewares); - return (reducer, initialState, initializer = value => value) => { + return ( + reducer: (state: State, action: Action) => State, + initialState: State, + initializer = (value: State) => value + ): [State, Dispatch] => { const ref = useRef(initializer(initialState)); const [, setState] = useState(ref.current); @@ -25,11 +42,11 @@ const createReducer = (...middlewares) => { [reducer] ); - const dispatchRef = useRef( + const dispatchRef: { current: Dispatch } = useRef( composedMiddleware( { getState: () => ref.current, - dispatch: (...args) => dispatchRef.current(...args), + dispatch: (...args: [Action]) => dispatchRef.current(...args) }, dispatch ) @@ -39,7 +56,7 @@ const createReducer = (...middlewares) => { dispatchRef.current = composedMiddleware( { getState: () => ref.current, - dispatch: (...args) => dispatchRef.current(...args), + dispatch: (...args: [Action]) => dispatchRef.current(...args) }, dispatch ); From 0c20fb98fa3b93d2674a21a4b63e191af64e8bd1 Mon Sep 17 00:00:00 2001 From: Marcel Date: Thu, 24 Oct 2019 07:06:54 +0200 Subject: [PATCH 040/213] change dispatchRef to mutableRefObject --- src/createReducer.ts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/createReducer.ts b/src/createReducer.ts index cee9ba867d..7cece51cbc 100644 --- a/src/createReducer.ts +++ b/src/createReducer.ts @@ -1,18 +1,16 @@ -import { useCallback, useRef, useState } from 'react'; +import { MutableRefObject, useCallback, useRef, useState } from 'react'; import useUpdateEffect from './useUpdateEffect'; type Dispatch = (action: Action) => void; -type Store = { +interface Store { getState: () => State; dispatch: Dispatch; -}; +} -type Middleware = ( - store: Store -) => (next: Dispatch) => (action: Action) => void; +type Middleware = (store: Store) => (next: Dispatch) => (action: Action) => void; -function composeMiddleware(chain: Middleware[]) { +function composeMiddleware(chain: Array>) { return (context: Store, dispatch: Dispatch) => { return chain.reduceRight((res, middleware) => { return middleware(context)(res); @@ -20,9 +18,7 @@ function composeMiddleware(chain: Middleware[]) { }; } -const createReducer = ( - ...middlewares: Middleware[] -) => { +const createReducer = (...middlewares: Array>) => { const composedMiddleware = composeMiddleware(middlewares); return ( @@ -42,11 +38,11 @@ const createReducer = ( [reducer] ); - const dispatchRef: { current: Dispatch } = useRef( + const dispatchRef: MutableRefObject> = useRef( composedMiddleware( { getState: () => ref.current, - dispatch: (...args: [Action]) => dispatchRef.current(...args) + dispatch: (...args: [Action]) => dispatchRef.current(...args), }, dispatch ) @@ -56,7 +52,7 @@ const createReducer = ( dispatchRef.current = composedMiddleware( { getState: () => ref.current, - dispatch: (...args: [Action]) => dispatchRef.current(...args) + dispatch: (...args: [Action]) => dispatchRef.current(...args), }, dispatch ); From a80f3d01b3777ba3bd8e7146013ddf80e6a28471 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 24 Oct 2019 05:51:32 +0000 Subject: [PATCH 041/213] chore(deps): update dependency fork-ts-checker-webpack-plugin to v1.6.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index bf911645fa..99eaaa903a 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "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.1", + "fork-ts-checker-webpack-plugin": "1.6.0", "gh-pages": "2.1.1", "husky": "3.0.9", "jest": "24.9.0", diff --git a/yarn.lock b/yarn.lock index 9dc9186e24..08b2df992d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5990,10 +5990,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.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== +fork-ts-checker-webpack-plugin@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.6.0.tgz#a81fd1c6bf5258fa5318cf3e9a7e9bac006f7917" + integrity sha512-vqOY5gakcoon2s12V7MMe01OPwfgqulUWFzm+geQaPPOBKjW1I7aqqoBVlU0ECn97liMB0ECs16pRdIGe9qdRw== dependencies: babel-code-frame "^6.22.0" chalk "^2.4.1" From dc7fc55fe88f0c7a2a45ab3baca19356dc9732da Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 25 Oct 2019 12:40:50 +0000 Subject: [PATCH 042/213] chore(deps): update dependency fork-ts-checker-webpack-plugin to v2 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 99eaaa903a..9179858436 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "babel-core": "6.26.3", "babel-loader": "8.0.6", "babel-plugin-dynamic-import-node": "2.3.0", - "fork-ts-checker-webpack-plugin": "1.6.0", + "fork-ts-checker-webpack-plugin": "2.0.0", "gh-pages": "2.1.1", "husky": "3.0.9", "jest": "24.9.0", diff --git a/yarn.lock b/yarn.lock index 08b2df992d..0dd1ae2dbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5990,10 +5990,10 @@ fork-ts-checker-webpack-plugin@1.1.1: tapable "^1.0.0" worker-rpc "^0.1.0" -fork-ts-checker-webpack-plugin@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.6.0.tgz#a81fd1c6bf5258fa5318cf3e9a7e9bac006f7917" - integrity sha512-vqOY5gakcoon2s12V7MMe01OPwfgqulUWFzm+geQaPPOBKjW1I7aqqoBVlU0ECn97liMB0ECs16pRdIGe9qdRw== +fork-ts-checker-webpack-plugin@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-2.0.0.tgz#6b77f0ba7edbe03246721a9f0519e32eb5765f41" + integrity sha512-9FWDlYAkuJFvWW6/uykliAAbhneLOS1PK3z9DjFAt3BLaUsCcFHFFzICSot998J4VPvT6aA8F+XIlxE0q0G6Tg== dependencies: babel-code-frame "^6.22.0" chalk "^2.4.1" From 1bfe0636643a519bcbc3e620d9e384b4870a5a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oriol=20Colomer=20Aragon=C3=A9s?= Date: Thu, 24 Oct 2019 16:27:38 +0200 Subject: [PATCH 043/213] feat: add ensuredForwardRef and useEnsuredForwardedRef --- README.md | 5 ++ docs/useEnsuredForwardedRef.md | 63 +++++++++++++++ .../useEnsuredForwardedRef.story.tsx | 79 +++++++++++++++++++ src/__tests__/useEnsuredForwardedRef.test.tsx | 53 +++++++++++++ src/index.ts | 1 + src/useEnsuredForwardedRef.ts | 33 ++++++++ 6 files changed, 234 insertions(+) create mode 100644 docs/useEnsuredForwardedRef.md create mode 100644 src/__stories__/useEnsuredForwardedRef.story.tsx create mode 100644 src/__tests__/useEnsuredForwardedRef.test.tsx create mode 100644 src/useEnsuredForwardedRef.ts diff --git a/README.md b/README.md index 76fd92c187..d93ee9a387 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,11 @@ - [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo) - [`useMultiStateValidator`](./docs/useMultiStateValidator.md) — alike the `useStateValidator`, but tracks multiple states at a time. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemultistatevalidator--demo) - [`useMediatedState`](./docs/useMediatedState.md) — like the regular `useState` but with mediation by custom function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemediatedstate--demo) +
    +
    +- [**Miscellaneous**]() + - [`useEnsuredForwardedRef`](./docs/useEnsuredForwardedRef.md) and [`ensuredForwardRef`](./docs/useEnsuredForwardedRef.md) — use a React.forwardedRef safely. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-useensuredforwardedref--demo) +

    diff --git a/docs/useEnsuredForwardedRef.md b/docs/useEnsuredForwardedRef.md new file mode 100644 index 0000000000..b094a284bc --- /dev/null +++ b/docs/useEnsuredForwardedRef.md @@ -0,0 +1,63 @@ +# `useEnsuredForwardedRef` + +React hook to use a ForwardedRef safely. + +In some scenarios, you may need to use a _ref_ from inside and outside a component. If that's the case, you should use `React.forwardRef` to pass it through the child component. This is useful when you only want to forward that _ref_ and expose an internal `HTMLelement` to a parent component, for example. However, if you need to manipulate that reference inside a child's lifecycle hook... things get complicated, since you can't always ensure that the _ref_ is being sent by the parent component and if it is not, you will get `undefined` instead of a valid _ref_. + +This hook is useful in this specific case, it will __ensure__ that you get a valid reference on the other side. + +## Usage + +```jsx +import {ensuredForwardRef} from 'react-use'; + +const Demo = () => { + return ( + + ); +}; + +const Child = ensuredForwardRef((props, ref) => { + useEffect(() => { + console.log(ref.current.getBoundingClientRect()) + }, []) + + return ( +
    + ); +}); +``` + +## Alternative usage + +```jsx +import {useEnsuredForwardedRef} from 'react-use'; + +const Demo = () => { + return ( + + ); +}; + +const Child = React.forwardRef((props, ref) => { + // Here `ref` is undefined + const ensuredForwardRef = useEnsuredForwardedRef(ref); + // ensuredForwardRef will always be a valid reference. + + useEffect(() => { + console.log(ensuredForwardRef.current.getBoundingClientRect()) + }, []) + + return ( +
    + ); +}); +``` + +## Reference + +```ts +ensuredForwardRef(Component: RefForwardingComponent): ForwardRefExoticComponent & RefAttributes>; + +useEnsuredForwardedRef(ref: React.MutableRefObject): React.MutableRefObject; +``` diff --git a/src/__stories__/useEnsuredForwardedRef.story.tsx b/src/__stories__/useEnsuredForwardedRef.story.tsx new file mode 100644 index 0000000000..b2623f2fc4 --- /dev/null +++ b/src/__stories__/useEnsuredForwardedRef.story.tsx @@ -0,0 +1,79 @@ +import { storiesOf } from '@storybook/react'; +import React, { forwardRef, useRef, useState, useEffect, MutableRefObject } from 'react'; +import { useEnsuredForwardedRef } from '..'; +import ShowDocs from './util/ShowDocs'; + +import { boolean, withKnobs } from '@storybook/addon-knobs'; + +const INITIAL_SIZE = { + width: null, + height: null, +}; + +const Demo = ({ activeForwardRef }) => { + const ref = useRef(null); + + const [size, setSize] = useState(INITIAL_SIZE); + + useEffect(() => { + handleClick(); + }, [activeForwardRef]); + + const handleClick = () => { + if (activeForwardRef) { + const { width, height } = ref.current.getBoundingClientRect(); + setSize({ + width, + height, + }); + } else { + setSize(INITIAL_SIZE); + } + }; + + return ( + <> + +
    Parent component using external ref: (textarea size)
    +
    {JSON.stringify(size, null, 2)}
    + + + ); +}; + +const Child = forwardRef(({}, ref: MutableRefObject) => { + const ensuredForwardRef = useEnsuredForwardedRef(ref); + + const [size, setSize] = useState(INITIAL_SIZE); + + useEffect(() => { + handleMouseUp(); + }, []); + + const handleMouseUp = () => { + const { width, height } = ensuredForwardRef.current.getBoundingClientRect(); + setSize({ + width, + height, + }); + }; + + return ( + <> +
    Child forwardRef component using forwardRef: (textarea size)
    +
    {JSON.stringify(size, null, 2)}
    +
    You can resize this textarea:
    +