Feature/ switch explorer rendering to use react-virtualized (#2182)

* experiment with changing scrollIntoView fn in explorer

* switch to using react virtualized to render explorer

* add react virtualised list and typescript Styled components plugin

* add missing style item to rowrenderer which fixes scrolling

* add key as per docs example

* update snapshot test for explorer

* add ability to dynamically calculate row with inputs

* remove overscan rows

* re-add overscan re-trigger build

* use ui.fontSize for row sizing

* destructure vars (primarily to trigger re-test)

* switch scroll to alignment to end as center causes scroll lag

* add font size in px function switch to cell measurer

* add the definition file for units-css

* update jest mocks

* remove shadowed variable in explorer

* update react-virtualized and its types to fix type errors

* prettier lint fix for performance config

* lint fix

* merge upstream

* fix double border in sidebar item component
also recalculate height when component yanrk status changes

* separate should measure calculation into function
add iss selected check to it

* restructure comparison function to be more readable and work hopefully

* use cache clear and recompute row height for list resizing

* add is or was selected to props checked component did update check

* remove outline from List, separate out should measure

* switch to using _oni in explorer split

* prettier fix

* fix missing space on left edge of container component
add helper for quickly adding types for styled component oni props

* remove unnecessary type annotation

* use pixel function from common in sidebar items

* fix lint error

* remove unnecessary dependency and associated utility
use more thorough method for checking if props changed
simplify sidebar items components

* fix lint error

* remove references to unused fontsize prop

* remove measurement from node entirely
switch to invalidating the cache if yanking, pasting etc occur
This commit is contained in:
Akin 2018-09-01 22:23:50 +01:00 committed by GitHub
parent f5ca695205
commit c06df641ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 267 additions and 189 deletions

View File

@ -79,7 +79,7 @@ const DragCollect = (connect: DND.DragSourceConnector, monitor: DND.DragSourceMo
*
* @name props
* @function
* @param {String | String[]} >props.target The target Type that responds to the drop
* @param {String | String[]} props.target The target Type that responds to the drop
* @param {Object} DragSource Object with a beginDrag which return the dragged props
* @param {React.Component} A component which is dragged onto another
* @returns {React.Component<P>} A react class component

View File

@ -84,9 +84,9 @@ export class ExplorerSplit {
onCompleteCreate={this._completeCreation}
onCompleteRename={this._completeRename}
onCancelRename={this._cancelRename}
onSelectionChanged={id => this._onSelectionChanged(id)}
onClick={id => this._onOpenItem(id)}
moveFileOrFolder={this.moveFileOrFolder}
onSelectionChanged={id => this._onSelectionChanged(id)}
/>
</Provider>
)

View File

@ -7,17 +7,20 @@ import * as React from "react"
import * as DND from "react-dnd"
import HTML5Backend from "react-dnd-html5-backend"
import { connect } from "react-redux"
import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from "react-virtualized"
import { compose } from "redux"
import { CSSTransition, TransitionGroup } from "react-transition-group"
import { css, styled } from "./../../UI/components/common"
import { css, enableMouse, styled } from "./../../UI/components/common"
import { TextInputView } from "./../../UI/components/LightweightText"
import { SidebarEmptyPaneView } from "./../../UI/components/SidebarEmptyPaneView"
import { SidebarContainerView, SidebarItemView } from "./../../UI/components/SidebarItemView"
import { Sneakable } from "./../../UI/components/Sneakable"
import { VimNavigator } from "./../../UI/components/VimNavigator"
import { DragAndDrop, Droppeable } from "./../DragAndDrop"
import { commandManager } from "./../CommandManager"
import { FileIcon } from "./../FileIcon"
import * as ExplorerSelectors from "./ExplorerSelectors"
@ -38,20 +41,9 @@ export interface INodeViewProps {
updated?: string[]
isRenaming: Node
isCreating: boolean
children?: React.ReactNode
}
export const NodeWrapper = styled.div`
&:hover {
text-decoration: underline;
}
`
// tslint:disable-next-line
const noop = (elem: HTMLElement) => {}
const scrollIntoViewIfNeeded = (elem: HTMLElement) => {
// tslint:disable-next-line
elem && elem["scrollIntoViewIfNeeded"] && elem["scrollIntoViewIfNeeded"]()
}
const stopPropagation = (fn: () => void) => {
return (e?: React.MouseEvent<HTMLElement>) => {
if (e) {
@ -75,6 +67,13 @@ interface IMoveNode {
}
}
export const NodeWrapper = styled.div`
cursor: pointer;
&:hover {
text-decoration: underline;
}
`
const NodeTransitionWrapper = styled.div`
transition: all 400ms 50ms ease-in-out;
@ -94,12 +93,6 @@ interface ITransitionProps {
updated: boolean
}
const Transition = ({ children, updated }: ITransitionProps) => (
<CSSTransition in={updated} classNames="move" timeout={1000}>
<NodeTransitionWrapper className={updated && "move"}>{children}</NodeTransitionWrapper>
</CSSTransition>
)
const renameStyles = css`
width: 100%;
background-color: inherit;
@ -116,7 +109,13 @@ const createStyles = css`
margin-top: 0.2em;
`
export class NodeView extends React.PureComponent<INodeViewProps, {}> {
const Transition = ({ children, updated }: ITransitionProps) => (
<CSSTransition in={updated} classNames="move" timeout={1000}>
<NodeTransitionWrapper className={updated && "move"}>{children}</NodeTransitionWrapper>
</CSSTransition>
)
export class NodeView extends React.PureComponent<INodeViewProps> {
public moveFileOrFolder = ({ drag, drop }: IMoveNode) => {
this.props.moveFileOrFolder(drag.node, drop.node)
}
@ -125,15 +124,12 @@ export class NodeView extends React.PureComponent<INodeViewProps, {}> {
return !(drag.node.name === drop.node.name)
}
public render(): JSX.Element {
public render() {
const { isCreating, isRenaming, isSelected, node } = this.props
const renameInProgress = isRenaming.name === node.name && isSelected && !isCreating
const creationInProgress = isCreating && isSelected && !renameInProgress
return (
<NodeWrapper
style={{ cursor: "pointer" }}
innerRef={this.props.isSelected ? scrollIntoViewIfNeeded : noop}
>
<NodeWrapper>
{renameInProgress ? (
<TextInputView
styles={renameStyles}
@ -159,7 +155,7 @@ export class NodeView extends React.PureComponent<INodeViewProps, {}> {
public hasUpdated = (path: string) =>
!!this.props.updated && this.props.updated.some(nodePath => nodePath === path)
public getElement(): JSX.Element {
public getElement() {
const { node } = this.props
const yanked = this.props.yanked.includes(node.id)
@ -270,13 +266,67 @@ export interface IExplorerViewProps extends IExplorerViewContainerProps {
idToSelect: string
}
import { SidebarEmptyPaneView } from "./../../UI/components/SidebarEmptyPaneView"
interface ISneakableNode extends IExplorerViewProps {
node: Node
selectedId: string
}
import { commandManager } from "./../CommandManager"
const SneakableNode = ({ node, selectedId, ...props }: ISneakableNode) => (
<Sneakable callback={() => props.onClick(node.id)}>
<NodeView
node={node}
isSelected={node.id === selectedId}
isCreating={props.isCreating}
onCancelCreate={props.onCancelCreate}
onCompleteCreate={props.onCompleteCreate}
onCompleteRename={props.onCompleteRename}
isRenaming={props.isRenaming}
onCancelRename={props.onCancelRename}
updated={props.updated}
yanked={props.yanked}
moveFileOrFolder={props.moveFileOrFolder}
onClick={() => props.onClick(node.id)}
/>
</Sneakable>
)
export class ExplorerView extends React.PureComponent<IExplorerViewProps, {}> {
public render(): JSX.Element {
const ExplorerContainer = styled.div`
height: 100%;
${enableMouse};
`
export class ExplorerView extends React.PureComponent<IExplorerViewProps> {
private _list = React.createRef<List>()
private _cache = new CellMeasurerCache({
defaultHeight: 30,
fixedWidth: true,
})
public openWorkspaceFolder = () => {
commandManager.executeCommand("workspace.openFolder")
}
public getSelectedNode = (selectedId: string) => {
return this.props.nodes.findIndex(n => selectedId === n.id)
}
public propsChanged(keys: Array<keyof IExplorerViewProps>, prevProps: IExplorerViewProps) {
return keys.some(prop => this.props[prop] !== prevProps[prop])
}
public componentDidUpdate(prevProps: IExplorerViewProps) {
if (this.propsChanged(["isCreating", "isRenaming", "yanked"], prevProps)) {
// TODO: if we could determine which nodes actually were involved
// in the change this could potentially be optimised
this._cache.clearAll()
this._list.current.recomputeRowHeights()
}
}
public render() {
const ids = this.props.nodes.map(node => node.id)
const isActive = this.props.isActive && !this.props.isRenaming && !this.props.isCreating
if (!this.props.nodes || !this.props.nodes.length) {
return (
@ -284,43 +334,57 @@ export class ExplorerView extends React.PureComponent<IExplorerViewProps, {}> {
active={this.props.isActive}
contentsText="Nothing to show here, yet!"
actionButtonText="Open a Folder"
onClickButton={() => commandManager.executeCommand("workspace.openFolder")}
onClickButton={this.openWorkspaceFolder}
/>
)
}
return (
<TransitionGroup>
<TransitionGroup style={{ height: "100%" }}>
<VimNavigator
ids={ids}
active={this.props.isActive && !this.props.isRenaming && !this.props.isCreating}
active={isActive}
style={{ height: "100%" }}
idToSelect={this.props.idToSelect}
onSelectionChanged={this.props.onSelectionChanged}
onSelected={id => this.props.onClick(id)}
render={(selectedId: string) => {
const nodes = this.props.nodes.map(node => (
<Sneakable callback={() => this.props.onClick(node.id)} key={node.id}>
<NodeView
node={node}
isSelected={node.id === selectedId}
isCreating={this.props.isCreating}
onCancelCreate={this.props.onCancelCreate}
onCompleteCreate={this.props.onCompleteCreate}
onCompleteRename={this.props.onCompleteRename}
isRenaming={this.props.isRenaming}
onCancelRename={this.props.onCancelRename}
updated={this.props.updated}
yanked={this.props.yanked}
moveFileOrFolder={this.props.moveFileOrFolder}
onClick={() => this.props.onClick(node.id)}
/>
</Sneakable>
))
onSelectionChanged={this.props.onSelectionChanged}
render={selectedId => {
return (
<div className="explorer enable-mouse">
<div className="items">{nodes}</div>
</div>
<ExplorerContainer className="explorer">
<AutoSizer>
{measurements => (
<List
{...measurements}
ref={this._list}
scrollToAlignment="end"
style={{ outline: "none" }}
rowCount={this.props.nodes.length}
rowHeight={this._cache.rowHeight}
scrollToIndex={this.getSelectedNode(selectedId)}
rowRenderer={({ index, style, key, parent }) => (
<CellMeasurer
key={key}
cache={this._cache}
columnIndex={0}
parent={parent}
rowIndex={index}
>
<div
style={style}
key={this.props.nodes[index].id}
>
<SneakableNode
{...this.props}
selectedId={selectedId}
node={this.props.nodes[index]}
/>
</div>
</CellMeasurer>
)}
/>
)}
</AutoSizer>
</ExplorerContainer>
)
}}
/>
@ -329,6 +393,19 @@ export class ExplorerView extends React.PureComponent<IExplorerViewProps, {}> {
}
}
const getIdToSelect = (fileToSelect: string, nodes: ExplorerSelectors.ExplorerNode[]) => {
// If parent has told us to select a file, attempt to convert the file path into a node ID.
if (fileToSelect) {
const [nodeToSelect] = nodes.filter(node => {
const nodePath = getPathForNode(node)
return nodePath === fileToSelect
})
return nodeToSelect ? nodeToSelect.id : null
}
return null
}
const mapStateToProps = (
state: IExplorerState,
containerProps: IExplorerViewContainerProps,
@ -341,25 +418,13 @@ const mapStateToProps = (
const nodes: ExplorerSelectors.ExplorerNode[] = ExplorerSelectors.mapStateToNodeList(state)
let idToSelect: string = null
// If parent has told us to select a file, attempt to convert the file path into a node ID.
if (fileToSelect) {
const [nodeToSelect] = nodes.filter((node: ExplorerSelectors.ExplorerNode) => {
const nodePath: string = getPathForNode(node)
return nodePath === fileToSelect
})
if (nodeToSelect) {
idToSelect = nodeToSelect.id
}
}
return {
...containerProps,
isActive: state.hasFocus,
nodes,
updated,
yanked,
idToSelect,
idToSelect: getIdToSelect(fileToSelect, nodes),
isCreating: state.register.create.active,
isRenaming: rename.active && rename.target,
}

View File

@ -127,8 +127,8 @@ export class SidebarHeaderView extends React.PureComponent<ISidebarHeaderProps,
export const SidebarInnerPaneWrapper = withProps<{}>(styled.div)`
flex: 1 1 auto;
overflow-y: auto;
position: relative;
height: 100%;
`
export class SidebarContentView extends React.PureComponent<

View File

@ -6,34 +6,53 @@
import * as React from "react"
import { styled, withProps } from "./common"
import { OniStyledProps, pixel, styled, withProps } from "./common"
import Caret from "./../../UI/components/Caret"
import { Sneakable } from "./../../UI/components/Sneakable"
export interface ISidebarItemViewProps {
interface IItemProps {
yanked?: boolean
updated?: boolean
isOver?: boolean
canDrop?: boolean
didDrop?: boolean
text: string | JSX.Element
isFocused: boolean
isContainer?: boolean
indentationLevel: number
icon?: JSX.Element
text: string | JSX.Element
onClick: (e?: React.MouseEvent<HTMLElement>) => void
}
const px = (num: number): string => num.toString() + "px"
export interface ISidebarItemViewProps extends IItemProps {
indentationLevel: number
}
export interface ISidebarContainerViewProps extends IItemProps {
isExpanded: boolean
indentationLevel?: number
}
type SidebarStyleProps = OniStyledProps<ISidebarItemViewProps>
const INDENT_AMOUNT = 12
const getLeftBorder = (props: SidebarStyleProps) => {
switch (true) {
case props.isFocused:
return `4px solid ${props.theme["highlight.mode.normal.background"]}`
case !props.isContainer:
return "4px solid transparent"
case props.isContainer:
return `4px solid rgba(0, 0, 0, 0.2)`
default:
return ""
}
}
const SidebarItemStyleWrapper = withProps<ISidebarItemViewProps>(styled.div)`
padding-left: ${props => px(INDENT_AMOUNT * props.indentationLevel)};
border-left: ${props =>
props.isFocused
? `4px solid ${props.theme["highlight.mode.normal.background"]}`
: "4px solid transparent"};
padding-left: ${props => pixel(INDENT_AMOUNT * props.indentationLevel)};
border-left: ${getLeftBorder};
${p =>
(p.isOver || p.yanked) &&
`border: 3px solid ${p.theme["highlight.mode.insert.background"]};`};
@ -44,7 +63,6 @@ const SidebarItemStyleWrapper = withProps<ISidebarItemViewProps>(styled.div)`
padding-top: 4px;
padding-bottom: 3px;
position: relative;
cursor: pointer;
pointer-events: all;
@ -63,18 +81,19 @@ const SidebarItemStyleWrapper = withProps<ISidebarItemViewProps>(styled.div)`
}
`
const SidebarItemBackground = withProps<ISidebarItemViewProps>(styled.div)`
background-color: ${props => {
if (props.isFocused && !props.isContainer) {
return props.theme["highlight.mode.normal.background"]
} else if (props.isContainer) {
return "rgb(0, 0, 0)"
} else {
return "transparent"
}
}};
opacity: ${props => (props.isContainer || props.isFocused ? "0.2" : "0")};
const getSidebarBackground = (props: SidebarStyleProps) => {
if (props.isFocused && !props.isContainer) {
return props.theme["highlight.mode.normal.background"]
} else if (props.isContainer) {
return "rgb(0, 0, 0)"
} else {
return "transparent"
}
}
const SidebarItemBackground = withProps<ISidebarItemViewProps>(styled.div)`
background-color: ${getSidebarBackground};
opacity: ${props => (props.isContainer || props.isFocused ? "0.2" : "0")};
position: absolute;
top: 0px;
left: 0px;
@ -82,76 +101,38 @@ const SidebarItemBackground = withProps<ISidebarItemViewProps>(styled.div)`
bottom: 0px;
`
const INDENT_AMOUNT = 12
export class SidebarItemView extends React.PureComponent<ISidebarItemViewProps, {}> {
public render(): JSX.Element {
const icon = this.props.icon ? <div className="icon">{this.props.icon}</div> : null
return (
<Sneakable callback={this.props.onClick}>
<SidebarItemStyleWrapper
{...this.props}
className="item"
onClick={this.props.onClick}
>
<SidebarItemBackground {...this.props} />
{icon}
<div className="name">{this.props.text}</div>
</SidebarItemStyleWrapper>
</Sneakable>
)
}
export const SidebarItemView: React.SFC<ISidebarItemViewProps> = props => {
const icon = props.icon ? <div className="icon">{props.icon}</div> : null
return (
<Sneakable callback={props.onClick}>
<SidebarItemStyleWrapper {...props} className="item" onClick={props.onClick}>
<SidebarItemBackground {...props} />
{icon}
<div className="name">{props.text}</div>
</SidebarItemStyleWrapper>
</Sneakable>
)
}
const SidebarContainer = styled.div``
export interface ISidebarContainerViewProps extends IContainerProps {
yanked?: boolean
updated?: boolean
didDrop?: boolean
text: string
isExpanded: boolean
isFocused: boolean
indentationLevel?: number
isContainer?: boolean
onClick: (e: React.MouseEvent<HTMLElement>) => void
}
interface IContainerProps {
isOver?: boolean
canDrop?: boolean
yanked?: boolean
updated?: boolean
}
const SidebarContainer = withProps<IContainerProps>(styled.div)`
${p =>
(p.isOver || p.yanked) &&
`border: 3px solid ${p.theme["highlight.mode.insert.background"]};`};
`
export class SidebarContainerView extends React.PureComponent<ISidebarContainerViewProps, {}> {
public render(): JSX.Element {
const indentationlevel = this.props.indentationLevel || 0
return (
<SidebarContainer
updated={this.props.updated}
yanked={this.props.yanked}
canDrop={this.props.canDrop}
isOver={this.props.isOver}
>
<SidebarItemView
yanked={this.props.yanked}
updated={this.props.updated}
didDrop={this.props.didDrop}
indentationLevel={indentationlevel}
icon={<Caret active={this.props.isExpanded} />}
text={this.props.text}
isFocused={this.props.isFocused}
isContainer={this.props.isContainer}
onClick={this.props.onClick}
/>
{this.props.isExpanded ? this.props.children : null}
</SidebarContainer>
)
}
export const SidebarContainerView: React.SFC<ISidebarContainerViewProps> = ({
indentationLevel = 0,
...props
}) => {
return (
<SidebarContainer>
<SidebarItemView
yanked={props.yanked}
updated={props.updated}
didDrop={props.didDrop}
indentationLevel={indentationLevel}
icon={<Caret active={props.isExpanded} />}
text={props.text}
isFocused={props.isFocused}
isContainer={props.isContainer}
onClick={props.onClick}
/>
{props.isExpanded ? props.children : null}
</SidebarContainer>
)
}

View File

@ -18,6 +18,8 @@ import { Event } from "oni-types"
import { KeyboardInputView } from "./../../Input/KeyboardInput"
import { getInstance, IMenuBinding } from "./../../neovim/SharedNeovimInstance"
import styled from "./../../UI/components/common"
import { CallbackCommand, commandManager } from "./../../Services/CommandManager"
export interface IVimNavigatorProps {
@ -42,6 +44,10 @@ export interface IVimNavigatorState {
selectedId: string
}
const NavigatorContainer = styled.div`
height: 100%;
`
export class VimNavigator extends React.PureComponent<IVimNavigatorProps, IVimNavigatorState> {
private _activeBinding: IMenuBinding = null
private _activateEvent = new Event<void>()
@ -89,9 +95,9 @@ export class VimNavigator extends React.PureComponent<IVimNavigatorProps, IVimNa
return (
<div style={this.props.style}>
<div className="items">
<NavigatorContainer>
{this.props.render(this.state.selectedId, this.updateSelection)}
</div>
</NavigatorContainer>
{this.props.active ? inputElement : null}
</div>
)

View File

@ -162,6 +162,9 @@ const fallBackFonts = `
sans-serif
`.trim()
export type OniThemeProps = ThemeProps<IThemeColors>
export type OniStyledProps<T> = OniThemeProps & T
export {
css,
injectGlobal,

1
browser/src/units-css.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module "units-css"

View File

@ -1,6 +1,9 @@
var path = require("path")
var webpack = require("webpack")
const createStyledComponentsTransformer = require("typescript-plugin-styled-components").default
const styledComponentsTransformer = createStyledComponentsTransformer()
module.exports = {
mode: "development",
entry: [path.join(__dirname, "src/index.tsx")],
@ -48,7 +51,12 @@ module.exports = {
},
{
test: /\.tsx?$/,
use: "ts-loader",
use: {
loader: "ts-loader",
options: {
getCustomTransformers: () => ({ before: [styledComponentsTransformer] }),
},
},
exclude: /node_modules/,
},
],

View File

@ -919,7 +919,7 @@
"@types/react-redux": "5.0.12",
"@types/react-test-renderer": "^16.0.0",
"@types/react-transition-group": "^2.0.11",
"@types/react-virtualized": "^9.7.10",
"@types/react-virtualized": "^9.18.3",
"@types/redux-batched-subscribe": "^0.1.2",
"@types/redux-mock-store": "^1.0.0",
"@types/rimraf": "^2.0.2",
@ -980,7 +980,7 @@
"react-redux": "5.0.6",
"react-test-renderer": "^16.2.0",
"react-transition-group": "2.2.1",
"react-virtualized": "^9.18.0",
"react-virtualized": "^9.19.1",
"redux": "3.7.2",
"redux-mock-store": "^1.5.3",
"redux-observable": "0.17.0",
@ -995,6 +995,7 @@
"ts-jest": "^23.0.0",
"ts-loader": "^4.2.0",
"tslint": "5.9.1",
"typescript-plugin-styled-components": "^0.0.6",
"vscode-snippet-parser": "0.0.5",
"wcwidth": "1.0.1",
"webdriverio": "4.8.0",

View File

@ -1,9 +1,10 @@
// For more information on customizing Oni,
// check out our wiki page:
// https://github.com/onivim/oni/wiki/Configuration
// tslint:disable
module.exports = {
"sidebar.enabled": false,
"statusbar.enabled": false,
"tabs.mode": "hidden",
"ui.animations.enabled": false,
};
}

View File

@ -1,4 +1,4 @@
import { mount, shallow } from "enzyme"
import { shallow } from "enzyme"
import { shallowToJson } from "enzyme-to-json"
import * as React from "react"
@ -20,6 +20,8 @@ describe("<NodeView />", () => {
const Node = (
<NodeView
yanked={[] as string[]}
measure={() => null}
isCreating={false}
isRenaming={testNode}
moveFileOrFolder={() => ({})}
node={testNode}
@ -38,6 +40,8 @@ describe("<NodeView />", () => {
const wrapper = shallow(
<NodeView
yanked={[] as string[]}
measure={() => null}
isCreating={false}
isRenaming={testNode}
moveFileOrFolder={() => ({})}
node={testNode}

View File

@ -1,14 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<NodeView /> Should match the snapshot 1`] = `
<styled.div
innerRef={[Function]}
style={
Object {
"cursor": "pointer",
}
}
>
<styled.div>
<div>
<DropTarget(DragSource(DragAndDrop))
accepts={

View File

@ -220,9 +220,9 @@
dependencies:
"@types/react" "*"
"@types/react-virtualized@^9.7.10":
version "9.7.10"
resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.7.10.tgz#f55ee6138cef17a4adf2893494d32b8407f0103b"
"@types/react-virtualized@^9.18.3":
version "9.18.3"
resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.18.3.tgz#777b3c28bd2b972d0a402f2f9d11bacef550be1c"
dependencies:
"@types/prop-types" "*"
"@types/react" "*"
@ -8607,6 +8607,10 @@ react-lifecycles-compat@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-2.0.2.tgz#00a23160eec17a43b94dd74f95d44a1a2c3c5ec1"
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"
react-motion@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316"
@ -8654,15 +8658,16 @@ react-transition-group@2.2.1:
prop-types "^15.5.8"
warning "^3.0.0"
react-virtualized@^9.18.0:
version "9.18.0"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.18.0.tgz#d95ccdcfe82c7791da661be3ebc59f4bbc224f07"
react-virtualized@^9.19.1:
version "9.19.1"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.19.1.tgz#84b53253df2d9df61c85ce037141edccc70a73fd"
dependencies:
babel-runtime "^6.26.0"
classnames "^2.2.3"
dom-helpers "^2.4.0 || ^3.0.0"
loose-envify "^1.3.0"
prop-types "^15.5.4"
prop-types "^15.6.0"
react-lifecycles-compat "^3.0.4"
react@^16.3.2:
version "16.3.2"
@ -10328,6 +10333,10 @@ tryer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7"
ts-is-kind@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ts-is-kind/-/ts-is-kind-1.0.0.tgz#f9ca9c1af07ddb82d7a06744d8928952d4bd2426"
ts-jest@^23.0.0:
version "23.0.0"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-23.0.0.tgz#3216310fb51e40789c6e4aa20bfe80198d250e9b"
@ -10416,6 +10425,12 @@ typedarray@^0.0.6, typedarray@~0.0.5:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript-plugin-styled-components@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typescript-plugin-styled-components/-/typescript-plugin-styled-components-0.0.6.tgz#e8489b72436aa1780e859243b519230b2c6b53d1"
dependencies:
ts-is-kind "^1.0.0"
typescript@^2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"