diff --git a/package.json b/package.json index d4931f8..e498e0e 100644 --- a/package.json +++ b/package.json @@ -83,8 +83,8 @@ "npm-run-all": "^4.1.5", "parcel-bundler": "^1.12.4", "prettier": "^1.19.1", - "react": "^16.12.0", - "react-dom": "^16.12.0", + "react": "16.13.1", + "react-dom": "16.13.1", "rimraf": "^3.0.0", "source-map-loader": "^0.2.4", "ts-jest": "^24.2.0", @@ -93,12 +93,12 @@ "webpack-cli": "^3.3.10" }, "peerDependencies": { - "react": "^15.0.1 || ^16.0.1", - "react-dom": "^15.0.1 || ^16.0.1" + "react": "^16.8", + "react-dom": "^16.8" }, "dependencies": { "cxs": "^6.2.0", "react-fast-compare": "2.0.4", - "react-motion": "^0.5.2" + "react-spring": "^9.5.2" } } diff --git a/src/components/TextLoop.tsx b/src/components/TextLoop.tsx index 51866ba..2d1e7e7 100644 --- a/src/components/TextLoop.tsx +++ b/src/components/TextLoop.tsx @@ -1,295 +1,169 @@ -import React from "react"; -import { - TransitionMotion, - spring, - OpaqueConfig, - TransitionStyle, -} from "react-motion"; -import cxs from "cxs"; -import isEqual from "react-fast-compare"; -import { requestTimeout, clearRequestTimeout, RequestTimeout } from "../utils"; +import React, { useState, useRef, useMemo } from 'react' +import { animated, useTransition } from 'react-spring' +import cxs from 'cxs' +import { useRequestTimeout } from '../utils' type Props = { - children?: (JSX.Element | string)[]; - interval: number | number[]; - delay: number; - adjustingSpeed: number; - springConfig: { - stiffness: number; - damping: number; - }; - fade: boolean; - mask: boolean; - noWrap: boolean; - className?: string; - onChange?: Function; -}; - -type State = { - elements: (JSX.Element | string | undefined)[]; - currentEl: JSX.Element | string | undefined; - currentWordIndex: number; - wordCount: number; - currentInterval: number; -}; - -class TextLoop extends React.PureComponent { - isUnMounting = false; - - tickDelay: RequestTimeout = 0; - - tickLoop: RequestTimeout = 0; - - wordBox: HTMLDivElement | null = null; - - static defaultProps: Props = { - interval: 3000, - delay: 0, - adjustingSpeed: 150, - springConfig: { stiffness: 340, damping: 30 }, - fade: true, - mask: false, - noWrap: true, - }; - - constructor(props: Props) { - super(props); - const elements = React.Children.toArray(props.children); - - this.state = { - elements, - currentEl: elements[0], - currentWordIndex: 0, - wordCount: 0, - currentInterval: Array.isArray(props.interval) - ? props.interval[0] - : props.interval, - }; - } - - componentDidMount(): void { - // Starts animation - const { delay } = this.props; - const { currentInterval, elements } = this.state; - - if (currentInterval > 0 && elements.length > 1) { - this.tickDelay = requestTimeout(() => { - this.tickLoop = requestTimeout(this.tick, currentInterval); - }, delay); - } - } - - componentDidUpdate(prevProps: Props, prevState: State): void { - const { interval, children, delay } = this.props as Props; - const { currentWordIndex } = this.state; - - const currentInterval = Array.isArray(interval) - ? interval[currentWordIndex % interval.length] - : interval; - - if (prevState.currentInterval !== currentInterval) { - this.clearTimeouts(); - - if (currentInterval > 0 && React.Children.count(children) > 1) { - this.tickDelay = requestTimeout(() => { - this.tickLoop = requestTimeout(this.tick, currentInterval); - }, delay); - } else { - this.setState((state, props) => { - const { currentWordIndex: _currentWordIndex } = state; - - return { - currentInterval: Array.isArray(props.interval) - ? props.interval[ - _currentWordIndex % props.interval.length - ] - : props.interval, - }; - }); - } - } - - if (!isEqual(prevProps.children, children)) { - // eslint-disable-next-line react/no-did-update-set-state - this.setState({ - elements: React.Children.toArray(children), - }); - } - } - - componentWillUnmount(): void { - this.isUnMounting = true; - this.clearTimeouts(); - } - - clearTimeouts(): void { - if (this.tickLoop != null) { - clearRequestTimeout(this.tickLoop); - } - - if (this.tickDelay != null) { - clearRequestTimeout(this.tickDelay); - } - } - - // Fade out animation - willLeave = (): { opacity: OpaqueConfig; translate: OpaqueConfig } => { - const { height } = this.getDimensions(); - - return { - opacity: spring(this.getOpacity(), this.props.springConfig), - translate: spring(-height, this.props.springConfig), - }; - }; - - // Fade in animation - willEnter = (): { opacity: 0 | 1; translate: number } => { - const { height } = this.getDimensions(); - - return { - opacity: this.getOpacity(), - translate: height, - }; - }; - - tick = (): void => { - if (!this.isUnMounting) { - this.setState( - (state, props) => { - const currentWordIndex = - (state.currentWordIndex + 1) % state.elements.length; - - const currentEl = state.elements[currentWordIndex]; - const updatedState = { - currentWordIndex, - currentEl, - wordCount: (state.wordCount + 1) % 1000, // just a safe value to avoid infinite counts, - currentInterval: Array.isArray(props.interval) - ? props.interval[ - currentWordIndex % props.interval.length - ] - : props.interval, - }; - if (props.onChange) { - props.onChange(updatedState); - } - - return updatedState; - }, - () => { - if (this.state.currentInterval > 0) { - this.clearTimeouts(); - this.tickLoop = requestTimeout( - this.tick, - this.state.currentInterval - ); - } - } - ); - } - }; - - getOpacity(): 0 | 1 { - return this.props.fade ? 0 : 1; - } - - getDimensions(): ClientRect | DOMRect | { width: 0; height: 0 } { - if (this.wordBox == null) { - return { - width: 0, - height: 0, - }; - } + children?: (JSX.Element | string)[] + interval?: number | number[] + delay?: number + adjustingSpeed?: number + springConfig?: { + stiffness: number + damping: number + } + fade?: boolean + mask?: boolean + noWrap?: boolean + className?: string + onChange?: Function +} - return this.wordBox.getBoundingClientRect(); +function TextLoop({ + children, + interval = 3000, + delay = 0, + adjustingSpeed = 150, + springConfig = { stiffness: 340, damping: 30 }, + fade = true, + mask = false, + noWrap = true, + className = '', + onChange, +}: Props) { + const elements = useMemo(() => React.Children.toArray(children), [children]) + + const [state, setState] = useState({ + currentEl: elements[0], + currentWordIndex: 0, + wordCount: 0, + usedDelay: false, + }) + const wordBoxRef = useRef(null) + // We set this state each time we get a new wordBoxRef in order to re-render immediately + const [, setWordBoxRefKey] = useState(null) + + const currentInterval = Array.isArray(interval) + ? interval[state.currentWordIndex % interval.length] + : interval + + const currentItem = { + el: state.currentEl, + key: `step-${state.wordCount}`, + } + const transitions = useTransition([currentItem], { + from: () => { + // Fade in animation + const { height } = getDimensions() + return { + opacity: getOpacity(), + translate: height, + } + }, + enter: { + // At rest values + opacity: 1, + translate: 0, + }, + leave: () => { + // Fade out animation + const { height } = getDimensions() + return { + opacity: getOpacity(), + translate: -height, + } + }, + config: springConfig, + keys: (item) => item.key, + }) + + let nextTickInterval: number | null = state.usedDelay ? currentInterval : currentInterval + delay + const needsTick = currentInterval > 0 && React.Children.count(children) > 1 + if (!needsTick) { + nextTickInterval = null // Disable the timeout + } + + // TODO: componentDidUpdate includes some code for currentInterval == 0 I think + function tick() { + const newWordIndex = (state.currentWordIndex + 1) % elements.length + const nextEl = elements[newWordIndex] + + const newState = { + usedDelay: true, // Next tick won't have a delay + currentWordIndex: newWordIndex, + currentEl: nextEl, + wordCount: (state.wordCount + 1) % 1000, // just a safe value to avoid infinite counts } + setState(newState) - wrapperStyles = cxs({ - ...(this.props.mask && { overflow: "hidden" }), - ...{ - display: "inline-block", - position: "relative", - verticalAlign: "top", - }, - }); - - elementStyles = cxs({ - display: "inline-block", - left: 0, - top: 0, - whiteSpace: this.props.noWrap ? "nowrap" : "normal", - }); - - getTransitionMotionStyles(): TransitionStyle[] { - const { springConfig } = this.props; - const { wordCount, currentEl } = this.state; - - return [ - { - key: `step-${wordCount}`, - data: { - currentEl, - }, - style: { - opacity: spring(1, springConfig), - translate: spring(0, springConfig), - }, - }, - ]; + if (onChange) { + onChange(newState) // TODO: This used to be a different format } - - render(): JSX.Element { - const { className = "" } = this.props; - return ( -
- - {(interpolatedStyles): JSX.Element => { - const { height, width } = this.getDimensions(); - - const parsedWidth = - this.wordBox == null ? "auto" : width; - - const parsedHeight = - this.wordBox == null ? "auto" : height; - - return ( -
- {interpolatedStyles.map(config => ( -
{ - this.wordBox = n; - }} - key={config.key} - style={{ - opacity: config.style.opacity, - transform: `translateY(${config.style.translate}px)`, - position: - this.wordBox == null - ? "relative" - : "absolute", - }} - > - {config.data.currentEl} -
- ))} -
- ); - }} -
-
- ); + } + useRequestTimeout(tick, nextTickInterval, state.wordCount) + + function getDimensions() { + if (wordBoxRef.current == null) { + return { + width: 0, + height: 0, + } } + return wordBoxRef.current.getBoundingClientRect() + } + + function getOpacity(): 0 | 1 { + return fade ? 0 : 1 + } + + const wrapperStyles = cxs({ + ...(mask && { overflow: 'hidden' }), + ...{ + display: 'inline-block', + position: 'relative', + verticalAlign: 'top', + }, + }) + + const elementStyles = cxs({ + display: 'inline-block', + left: 0, + top: 0, + whiteSpace: noWrap ? 'nowrap' : 'normal', + }) + + const { height, width } = getDimensions() + const parsedWidth = wordBoxRef.current == null ? 'auto' : width + const parsedHeight = wordBoxRef.current == null ? 'auto' : height + + return ( +
+
+ {transitions(({ opacity, translate }, item) => ( + { + if (n && item.key === currentItem.key) { + wordBoxRef.current = n + setWordBoxRefKey(item.key) + } + }} + style={{ + opacity: opacity, + transform: translate.to((y) => `translateY(${y}px)`), + position: wordBoxRef.current === null ? 'relative' : 'absolute', + }}> + {item.el} + + ))} +
+
+ ) } -export default TextLoop; +export default TextLoop diff --git a/src/utils.ts b/src/utils.ts index 2f39e06..6598c86 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,5 @@ +import { useEffect, useRef } from "react"; + declare global { interface Window { mozRequestAnimationFrame; @@ -97,3 +99,21 @@ export const clearRequestTimeout = function(handle): void { ? window.msCancelRequestAnimationFrame(handle.value) : clearTimeout(handle); }; + +export function useRequestTimeout(callback: () => void, delay: number | null, identifier: any) { + const savedCallback = useRef(callback) + useEffect(() => { + savedCallback.current = callback + }, [callback]) + + useEffect(() => { + if (!delay && delay !== 0) { + return + } + + const handle = requestTimeout(() => savedCallback.current(), delay) + + return () => clearRequestTimeout(handle) + }, [delay, identifier]) +} + diff --git a/yarn.lock b/yarn.lock index 381a6a6..a583c6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1656,6 +1656,92 @@ "@parcel/utils" "^1.11.0" physical-cpu-count "^2.0.0" +"@react-spring/animated@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.5.2.tgz#42785b4f369d9715e9ee32c04b78483e7bb85489" + integrity sha512-oRlX+MmYLbK8IuUZR7SQUnRjXxJ4PMIZeBkBd1SUWVgVJAHMTfJzPltzm+I6p59qX+qLlklYHfnWaonQKDqLuQ== + dependencies: + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/core@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.5.2.tgz#c8450783ce87a82d3f9ab21e2650e42922398ff7" + integrity sha512-UMRtFH6EfebMp/NMDGCUY5+hZFXsg9iT9hzt/iPzJSz2WMXKBjLoFZHJXcmiVOrIhzHmg1O0pFECn1Wp6pZ5Gw== + dependencies: + "@react-spring/animated" "~9.5.2" + "@react-spring/rafz" "~9.5.2" + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/konva@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.5.2.tgz#cbc7c75c55c7946481f86c7392a6656bb5b1bf4a" + integrity sha512-FN8LpbGQtm2pllU9mOyYjYwvLtA9EiIPWk2NVuhhX+5lJZrdCWuEY7EyFpK8PtgZXBdVj8bj7eIu1LlTnARW/A== + dependencies: + "@react-spring/animated" "~9.5.2" + "@react-spring/core" "~9.5.2" + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/native@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.5.2.tgz#218fa228a746cb2f535ea59b317d2e99cdfed02d" + integrity sha512-G9BCAKVADLweLR43uyMnTrOnYDb4BboYvqKY+0X1fLs45PNrfbBXnSLot4g+5x3HjblypJgNq7CjHlqZKI980g== + dependencies: + "@react-spring/animated" "~9.5.2" + "@react-spring/core" "~9.5.2" + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/rafz@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.5.2.tgz#1264d5df09717cf46d55055da2c55ff84f59073f" + integrity sha512-xHSRXKKBI/wDUkZGrspkOm4VlgN6lZi8Tw9Jzibp9QKf3neoof+U2mDNgklvnLaasymtUwAq9o4ZfFvQIVNgPQ== + +"@react-spring/shared@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.5.2.tgz#e0a252e06daa3927964460fef05d8092e7d78ffc" + integrity sha512-/OSf2sjwY4BUnjZL6xMC+H3WxOOhMUCk+yZwgdj40XuyUpk6E6tYyiPeD9Yq5GLsZHodkvE1syVMRVReL4ndAg== + dependencies: + "@react-spring/rafz" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/three@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.5.2.tgz#965ff4e729929ebbb9a1f8e84f3f4acb6acec4f9" + integrity sha512-3H7Lv8BJZ3dajh0yJA3m9rEbqz5ZNrTCAkhVOeLqgvBlcWU5qVs4luYA1Z7H4vZnLqVtzv+kHAyg3XIpuTOXhQ== + dependencies: + "@react-spring/animated" "~9.5.2" + "@react-spring/core" "~9.5.2" + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/types@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.5.2.tgz#cce1b03afbafb23edfb9cd8c517cc7462abffb65" + integrity sha512-n/wBRSHPqTmEd4BFWY6TeR1o/UY+3ujoqMxLjqy90CcY/ozJzDRuREL3c+pxMeTF2+B7dX33dTPCtFMX51nbxg== + +"@react-spring/web@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.5.2.tgz#762ee6b3c8fea40281e1298f5cf1c0515ad6a794" + integrity sha512-cusTjbOGTgtbsnpBDjb6Ia+B0lQLE0Fk5rGDog6Sww7hWnLIQ521PMiOBnAWtkntB9eXDUfj7L91nwJviEC0lw== + dependencies: + "@react-spring/animated" "~9.5.2" + "@react-spring/core" "~9.5.2" + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + +"@react-spring/zdog@~9.5.2": + version "9.5.2" + resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.5.2.tgz#a3e451378c23caa4381b5821d3d52c3017740c55" + integrity sha512-zUX8RzX8gM51g8NJ5Qaf15KNKQgN3qN/8m5FvqmiqZ5ZGqjoHkbCoMD3o2MICTUN1l+d4eUu9TYrmiO2bgJo/g== + dependencies: + "@react-spring/animated" "~9.5.2" + "@react-spring/core" "~9.5.2" + "@react-spring/shared" "~9.5.2" + "@react-spring/types" "~9.5.2" + "@sheerun/mutationobserver-shim@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b" @@ -6808,11 +6894,6 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -7300,7 +7381,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.3" -prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7410,13 +7491,6 @@ quote-stream@^1.0.1, quote-stream@~1.0.2: minimist "^1.1.3" through2 "^2.0.0" -raf@^3.1.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" - integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== - dependencies: - performance-now "^2.1.0" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -7447,15 +7521,15 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-dom@^16.12.0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" - integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== +react-dom@16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" + integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.18.0" + scheduler "^0.19.1" react-fast-compare@2.0.4: version "2.0.4" @@ -7467,19 +7541,22 @@ react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== -react-motion@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316" - integrity sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ== +react-spring@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.5.2.tgz#b9929ad2806e56e6408b27189ec9cdf1dc003873" + integrity sha512-OGWNgKi2TSjpqsK67NCUspaCgEvWcG7HcpO9KAaDLFzFGNxWdGdN3YTXhhWUqCsLAx9I6LxPzmRuUPsMNqTgrw== dependencies: - performance-now "^0.2.0" - prop-types "^15.5.8" - raf "^3.1.0" + "@react-spring/core" "~9.5.2" + "@react-spring/konva" "~9.5.2" + "@react-spring/native" "~9.5.2" + "@react-spring/three" "~9.5.2" + "@react-spring/web" "~9.5.2" + "@react-spring/zdog" "~9.5.2" -react@^16.12.0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" - integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA== +react@16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" + integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -7908,10 +7985,10 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" -scheduler@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" - integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -8751,9 +8828,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^3.7.3: - version "3.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" - integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== uglify-js@^3.1.4: version "3.6.9"