Removed some old ui/ components

Summary: Removing old components that are no longer used, and cleaning up index.tsx to prevent future for some of those

Reviewed By: nikoant

Differential Revision: D29428621

fbshipit-source-id: 78ae51c09510738cf2d75982fdae35b9ef6d2d7e
This commit is contained in:
Michel Weststrate
2021-06-30 10:40:50 -07:00
committed by Facebook GitHub Bot
parent 1dafe351f7
commit 8e0d3cf779
32 changed files with 25 additions and 1461 deletions

View File

@@ -49,7 +49,6 @@
"p-map": "^4.0.0",
"promise-retry": "^2.0.1",
"promisify-child-process": "^4.1.0",
"prop-types": "^15.6.0",
"react": "17.0.2",
"react-async": "^10.0.0",
"react-debounce-render": "^7.0.0",

View File

@@ -20,7 +20,6 @@ import {
ACTIVE_SHEET_CHANGELOG,
} from './reducers/application';
import {setStaticView} from './reducers/connections';
import SupportRequestFormV2 from './fb-stubs/SupportRequestFormV2';
import {Store} from './reducers/';
import electron, {MenuItemConstructorOptions} from 'electron';
import {notNull} from './utils/typeUtils';
@@ -270,7 +269,9 @@ function getTemplate(
label: 'Create...',
click: function () {
// Dispatch an action to open the export screen of Support Request form
store.dispatch(setStaticView(SupportRequestFormV2));
store.dispatch(
setStaticView(require('./fb-stubs/SupportRequestFormV2').default),
);
},
},
];

View File

@@ -10,13 +10,11 @@
import React, {
Component,
ReactElement,
RefObject,
useCallback,
useEffect,
useState,
} from 'react';
import {
Glyph,
FlexColumn,
FlexRow,
Button,
@@ -25,7 +23,6 @@ import {
Input,
Link,
} from '../ui';
import LegacyPopover from '../ui/components/Popover2';
import {LeftRailButton} from '../sandy-chrome/LeftRail';
import GK from '../fb-stubs/GK';
import * as UserFeedback from '../fb-stubs/UserFeedback';
@@ -36,16 +33,6 @@ import {useStore} from '../utils/useStore';
import {isLoggedIn} from '../fb-stubs/user';
import {useValue} from 'flipper-plugin';
type PropsFromState = {
sessionId: string | null;
};
type State = {
promptData: FeedbackPrompt | null;
isShown: boolean;
hasTriggered: boolean;
};
type NextAction = 'select-rating' | 'leave-comment' | 'finished';
class PredefinedComment extends Component<{
@@ -277,100 +264,6 @@ class FeedbackComponent extends Component<
}
}
class RatingButton extends Component<PropsFromState, State> {
state: State = {
promptData: null,
isShown: false,
hasTriggered: false,
};
glyphRef: RefObject<HTMLDivElement> = React.createRef();
constructor(props: PropsFromState) {
super(props);
if (GK.get('flipper_enable_star_ratiings')) {
UserFeedback.getPrompt().then((prompt) => {
this.setState({promptData: prompt});
setTimeout(this.triggerPopover.bind(this), 30000);
});
}
}
onClick() {
const willBeShown = !this.state.isShown;
this.setState({isShown: willBeShown, hasTriggered: true});
if (!willBeShown) {
UserFeedback.dismiss(this.props.sessionId);
}
}
submitRating(rating: number) {
UserFeedback.submitRating(rating, this.props.sessionId);
}
submitComment(
rating: number,
comment: string,
selectedPredefinedComments: Array<string>,
allowUserInfoSharing: boolean,
) {
UserFeedback.submitComment(
rating,
comment,
selectedPredefinedComments,
allowUserInfoSharing,
this.props.sessionId,
);
}
triggerPopover() {
if (!this.state.hasTriggered) {
this.setState({isShown: true, hasTriggered: true});
}
}
render() {
const promptData = this.state.promptData;
if (!promptData) {
return null;
}
if (
!promptData.shouldPopup ||
(this.state.hasTriggered && !this.state.isShown)
) {
return null;
}
return (
<div style={{position: 'relative'}}>
<div
role="button"
tabIndex={0}
onClick={this.onClick.bind(this)}
ref={this.glyphRef}>
<Glyph
name="star"
color="grey"
variant={this.state.isShown ? 'filled' : 'outline'}
/>
</div>
{this.state.isShown ? (
<LegacyPopover id="rating-button" targetRef={this.glyphRef}>
<FeedbackComponent
submitRating={this.submitRating.bind(this)}
submitComment={this.submitComment.bind(this)}
close={() => {
this.setState({isShown: false});
}}
dismiss={this.onClick.bind(this)}
promptData={promptData}
/>
</LegacyPopover>
) : null}
</div>
);
}
}
export function SandyRatingButton() {
const [promptData, setPromptData] =
useState<UserFeedback.FeedbackPrompt | null>(null);

View File

@@ -12,7 +12,7 @@ import Client from '../../Client';
import {TableBodyRow} from '../../ui/components/table/types';
import React, {Component, Fragment} from 'react';
import {connect} from 'react-redux';
import {Text, ManagedTable, styled, colors, Link, Bordered} from '../../ui';
import {Text, ManagedTable, styled, colors, Link} from '../../ui';
import StatusIndicator from '../../ui/components/StatusIndicator';
import {State as Store} from '../../reducers';
import {PluginDefinition} from '../../plugin';
@@ -28,7 +28,7 @@ const Ellipsis = styled(Text)({
whiteSpace: 'nowrap',
});
const TableContainer = styled(Bordered)({
const TableContainer = styled.div({
marginTop: 10,
height: 400,
});

View File

@@ -12,7 +12,7 @@ export {keyframes} from '@emotion/css';
export {produce} from 'immer';
export * from './ui/index';
export {getStringFromErrorLike, textContent, sleep} from './utils/index';
export {textContent, sleep} from './utils/index';
export * from './utils/jsonTypes';
export {default as GK, loadGKs, loadDistilleryGK} from './fb-stubs/GK';
export {default as createPaste} from './fb-stubs/createPaste';
@@ -22,48 +22,32 @@ export {
graphQLQuery,
isLoggedIn,
} from './fb-stubs/user';
export {
FlipperBasePlugin,
FlipperPlugin,
FlipperDevicePlugin,
callClient,
BaseAction,
} from './plugin';
export {FlipperPlugin, FlipperDevicePlugin, BaseAction} from './plugin';
export {PluginClient, Props} from './plugin';
export {default as Client} from './Client';
export {reportUsage} from './utils/metrics';
export {default as promiseTimeout} from './utils/promiseTimeout';
export {clipboard, remote, OpenDialogOptions} from 'electron';
export {default as SupportRequestFormV2} from './fb-stubs/SupportRequestFormV2';
export {default as constants} from './fb-stubs/constants';
export {connect} from 'react-redux';
export {selectPlugin, StaticView} from './reducers/connections';
export {writeBufferToFile, bufferToBlob} from './utils/screenshot';
export {bufferToBlob} from './utils/screenshot';
export {getPluginKey} from './utils/pluginUtils';
export {Notification, Idler} from 'flipper-plugin';
export {IdlerImpl} from './utils/Idler';
export {Store, MiddlewareAPI, State as ReduxState} from './reducers/index';
export {Store, State as ReduxState} from './reducers/index';
export {default as BaseDevice} from './devices/BaseDevice';
export {DeviceLogEntry, LogLevel, DeviceLogListener} from 'flipper-plugin';
export {deconstructClientId} from './utils/clientUtils';
export {default as isProduction} from './utils/isProduction';
export {DetailSidebar} from 'flipper-plugin';
export {default as Device} from './devices/BaseDevice';
export {default as AndroidDevice} from './devices/AndroidDevice';
export {default as MetroDevice} from './devices/MetroDevice';
export {default as ArchivedDevice} from './devices/ArchivedDevice';
export {default as IOSDevice} from './devices/IOSDevice';
export {default as KaiOSDevice} from './devices/KaiOSDevice';
export {OS} from './devices/BaseDevice';
export {default as Button} from './ui/components/Button';
export {default as ToggleButton} from './ui/components/ToggleSwitch';
export {default as ButtonNavigationGroup} from './ui/components/ButtonNavigationGroup';
export {default as ButtonGroup} from './ui/components/ButtonGroup';
export {default as ButtonGroupChain} from './ui/components/ButtonGroupChain';
export {colors, darkColors, brandColors} from './ui/components/colors';
export {colors, brandColors} from './ui/components/colors';
export {default as Glyph} from './ui/components/Glyph';
export {default as LoadingIndicator} from './ui/components/LoadingIndicator';
export {default as Popover} from './ui/components/Popover';
export {
TableColumns,
TableRows,
@@ -72,20 +56,13 @@ export {
TableHighlightedRows,
TableRowSortOrder,
TableColumnOrder,
TableColumnOrderVal,
TableColumnSizes,
} from './ui/components/table/types';
export {
default as ManagedTable,
ManagedTable as ManagedTableClass,
} from './ui/components/table/ManagedTable';
export {default as ManagedTable} from './ui/components/table/ManagedTable';
export {ManagedTableProps} from './ui/components/table/ManagedTable';
export {
DataValueExtractor,
DataInspectorExpanded,
DataDescriptionType,
DataDescription,
DataInspector,
MarkerTimeline,
} from 'flipper-plugin';
export {DataInspector as ManagedDataInspector} from 'flipper-plugin';
@@ -96,35 +73,13 @@ export {default as Input} from './ui/components/Input';
export {default as Textarea} from './ui/components/Textarea';
export {default as Select} from './ui/components/Select';
export {default as Checkbox} from './ui/components/Checkbox';
export {default as CodeBlock} from './ui/components/CodeBlock';
export {default as ErrorBlock} from './ui/components/ErrorBlock';
export {ErrorBlockContainer} from './ui/components/ErrorBlock';
export {default as ErrorBoundary} from './ui/components/ErrorBoundary';
export {OrderableOrder} from './ui/components/Orderable';
export {_Interactive as Interactive} from 'flipper-plugin';
export {default as Orderable} from './ui/components/Orderable';
export {default as VirtualList} from './ui/components/VirtualList';
export {Component, PureComponent} from 'react';
export {default as ContextMenuProvider} from './ui/components/ContextMenuProvider';
export {
default as ContextMenu,
MenuTemplate,
} from './ui/components/ContextMenu';
export {FileListFile, FileListFiles} from './ui/components/FileList';
export {default as ContextMenu} from './ui/components/ContextMenu';
export {FileListFiles} from './ui/components/FileList';
export {default as FileList} from './ui/components/FileList';
export {default as File} from './ui/components/File';
export {
DesktopDropdownItem,
DesktopDropdownSelectedItem,
DesktopDropdown,
} from './ui/components/desktop-toolbar';
export {default as View} from './ui/components/View';
export {default as ViewWithSize} from './ui/components/ViewWithSize';
export {default as Block} from './ui/components/Block';
export {default as FocusableBox} from './ui/components/FocusableBox';
export {default as Sidebar} from './ui/components/Sidebar';
export {default as SidebarLabel} from './ui/components/SidebarLabel';
export {default as Box} from './ui/components/Box';
export {default as FlexBox} from './ui/components/FlexBox';
export {default as FlexRow} from './ui/components/FlexRow';
export {default as FlexColumn} from './ui/components/FlexColumn';
@@ -134,16 +89,10 @@ export {Spacer} from './ui/components/Toolbar';
export {default as ToolbarIcon} from './ui/components/ToolbarIcon';
export {default as Panel} from './ui/components/Panel';
export {default as Text} from './ui/components/Text';
export {default as TextParagraph} from './ui/components/TextParagraph';
export {default as Link} from './ui/components/Link';
export {default as PathBreadcrumbs} from './ui/components/PathBreadcrumbs';
export {default as ModalOverlay} from './ui/components/ModalOverlay';
export {default as Tooltip} from './ui/components/Tooltip';
export {default as TooltipProvider} from './ui/components/TooltipProvider';
export {default as ResizeSensor} from './ui/components/ResizeSensor';
export {default as StatusIndicator} from './ui/components/StatusIndicator';
export {default as HorizontalRule} from './ui/components/HorizontalRule';
export {default as VerticalRule} from './ui/components/VerticalRule';
export {default as Label} from './ui/components/Label';
export {default as Heading} from './ui/components/Heading';
export {Filter} from './ui/components/filter/types';
@@ -164,7 +113,6 @@ export {
ElementsInspectorElement as Element,
// TODO: clean up or create namespace
ElementsInspectorProps,
ElementExtraInfo,
ElementAttribute,
ElementData,
ElementSearchResultSet,
@@ -179,8 +127,7 @@ export {getFlipperMediaCDN, appendAccessTokenToUrl} from './fb-stubs/user';
export {Rect} from './utils/geometry';
export {Logger} from './fb-interfaces/Logger';
export {getInstance as getLogger} from './fb-stubs/Logger';
export {callVSCode, getVSCodeUrl} from './utils/vscodeUtils';
export {useLocalStorageState as useLocalStorage} from 'flipper-plugin';
export {callVSCode} from './utils/vscodeUtils';
export {checkIdbIsInstalled} from './utils/iOSContainerUtility';
export {IDEFileResolver, IDEType} from './fb-stubs/IDEFileResolver';
export {renderMockFlipperWithPlugin} from './test-utils/createMockFlipperWithPlugin';

View File

@@ -29,7 +29,6 @@ import {cache} from '@emotion/css';
import {CacheProvider} from '@emotion/react';
import {enableMapSet} from 'immer';
import os from 'os';
import {PopoverProvider} from './ui/components/PopoverProvider';
import {initializeFlipperLibImplementation} from './utils/flipperLibImplementation';
import {enableConsoleHook} from './chrome/ConsoleLogs';
import {sideEffect} from './utils/sideEffect';
@@ -131,13 +130,11 @@ class AppFrame extends React.Component<
<PersistGate persistor={persistor}>
<CacheProvider value={cache}>
<TooltipProvider>
<PopoverProvider>
<ContextMenuProvider>
<_NuxManagerContext.Provider value={_createNuxManager()}>
<SandyApp />
</_NuxManagerContext.Provider>
</ContextMenuProvider>
</PopoverProvider>
<ContextMenuProvider>
<_NuxManagerContext.Provider value={_createNuxManager()}>
<SandyApp />
</_NuxManagerContext.Provider>
</ContextMenuProvider>
</TooltipProvider>
</CacheProvider>
</PersistGate>

View File

@@ -1,36 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import React from 'react';
import Bordered from './Bordered';
import {colors} from './colors';
/**
* Displays all children in a bordered, zebra styled vertical layout
* @deprecated use Layout.Container gap
*/
const AlternatingRows: React.FC<{
children: React.ReactNode[] | React.ReactNode;
}> = ({children}) => (
<Bordered style={{flexDirection: 'column'}}>
{(Array.isArray(children) ? children : [children]).map((child, idx) => (
<div
key={idx}
style={{
padding: 8,
background: idx % 2 === 0 ? colors.light02 : colors.white,
}}>
{child}
</div>
))}
</Bordered>
);
export default AlternatingRows;

View File

@@ -1,21 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
/**
* A Block styled div
* @deprecated use Layout.Container
*/
const Block = styled.div({
display: 'block',
});
Block.displayName = 'Block';
export default Block;

View File

@@ -1,26 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
import {colors} from './colors';
/**
* Puts a gray border around something
* @deprecated use Layout.Container
*/
const Bordered = styled.div({
borderRadius: 4,
overflow: 'hidden',
border: `1px solid ${colors.macOSTitleBarButtonBorder}`,
backgroundColor: colors.white,
display: 'flex',
});
Bordered.displayName = 'bordered';
export default Bordered;

View File

@@ -1,24 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import FlexBox from './FlexBox';
import styled from '@emotion/styled';
/**
* @deprecated use Layout.Container
*/
const Box = styled(FlexBox)({
height: '100%',
overflow: 'auto',
position: 'relative',
width: '100%',
});
Box.displayName = 'Box';
export default Box;

View File

@@ -1,93 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import React from 'react';
import styled from '@emotion/styled';
import Glyph from './Glyph';
import {ButtonGroupContext} from './ButtonGroup';
const IconContainer = styled.div({
width: 0,
zIndex: 1,
display: 'inline-flex',
alignItems: 'center',
pointerEvents: 'none',
});
IconContainer.displayName = 'ButtonGroupChain:IconContainer';
const ButtonGroupChainContainer = styled.div<{iconSize: number}>((props) => ({
display: 'inline-flex',
marginLeft: 10,
'&:first-child>*:not(:first-child):nth-child(odd)': {
paddingLeft: props.iconSize + 6,
},
'&:first-child>*': {
borderRightStyle: 'none',
borderLeftStyle: 'none',
},
'&:first-child>:first-child': {
borderLeftStyle: 'solid',
},
'&:first-child>:last-child': {
borderRightStyle: 'solid',
},
}));
IconContainer.displayName = 'ButtonGroupChain:ButtonGroupChainContainer';
type Props = {
/**
* Children.
*/
children: React.ReactNode;
/**
* Size of the button seperator icon in pixels.
*/
iconSize: 8 | 10 | 12 | 16 | 18 | 20 | 24 | 32;
/**
* Name of the icon seperating the buttons. Defaults to 'chevron-right'.
*/
icon?: string;
};
/**
* Groups a series of buttons together with
* a right-chevron icon to seperate them.
* Used to create a navigation heirarchy.
*
* ```jsx
* <ButtonGroupChain iconSize={12}>
* <Button>One</Button>
* <Button>Two</Button>
* <Button>Three</Button>
* </ButtonGroupChain>
* ```
*
* @deprecated use Layout.Horizontal with flags: gap pad wrap
*/
export default function ButtonGroupChain({children, iconSize, icon}: Props) {
return (
<ButtonGroupContext.Provider value>
<ButtonGroupChainContainer iconSize={iconSize}>
{React.Children.map(children, (child, idx) => {
if (idx === 0) {
return child;
}
return (
<>
<IconContainer>
<Glyph name={icon || 'chevron-right'} size={iconSize} />
</IconContainer>
{child}
</>
);
})}
</ButtonGroupChainContainer>
</ButtonGroupContext.Provider>
);
}

View File

@@ -1,39 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import ButtonGroup from './ButtonGroup';
import Button from './Button';
import React from 'react';
/**
* Button group to navigate back and forth.
* @deprecated
*/
export default function ButtonNavigationGroup(props: {
/** Back button is enabled */
canGoBack: boolean;
/** Forwards button is enabled */
canGoForward: boolean;
/** Callback when back button is clicked */
onBack: () => void;
/** Callback when forwards button is clicked */
onForward: () => void;
}) {
return (
<ButtonGroup>
<Button disabled={!props.canGoBack} onClick={props.onBack}>
{'<'}
</Button>
<Button disabled={!props.canGoForward} onClick={props.onForward}>
{'<'}
</Button>
</ButtonGroup>
);
}

View File

@@ -1,20 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
/**
* @deprecated, use CodeBlock from flipper-plugin instead
*/
const CodeBlock = styled.div({
fontFamily: 'monospace',
});
CodeBlock.displayName = 'CodeBlock';
export default CodeBlock;

View File

@@ -9,7 +9,7 @@
import styled from '@emotion/styled';
import React from 'react';
import CodeBlock from './CodeBlock';
import {CodeBlock} from 'flipper-plugin';
export const ErrorBlockContainer = styled(CodeBlock)({
backgroundColor: '#f2dede',

View File

@@ -7,7 +7,7 @@
* @format
*/
import ErrorBlock from './ErrorBlock';
import {CodeBlock} from 'flipper-plugin';
import {Component} from 'react';
import Heading from './Heading';
import Button from './Button';
@@ -21,7 +21,7 @@ const ErrorBoundaryContainer = styled(View)({
});
ErrorBoundaryContainer.displayName = 'ErrorBoundary:ErrorBoundaryContainer';
const ErrorBoundaryStack = styled(ErrorBlock)({
const ErrorBoundaryStack = styled(CodeBlock)({
marginBottom: 10,
whiteSpace: 'pre',
});
@@ -79,7 +79,7 @@ export default class ErrorBoundary extends Component<
<ErrorBoundaryContainer grow>
<Heading>{heading}</Heading>
{this.props.showStack !== false && (
<ErrorBoundaryStack error={error} />
<ErrorBoundaryStack>{error}</ErrorBoundaryStack>
)}
<Button onClick={this.clearError}>Clear error and try again</Button>
</ErrorBoundaryContainer>

View File

@@ -1,93 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import React, {Component} from 'react';
import fs from 'fs';
type FileProps = {
/** Path to the file in the file system */
src: string;
/** Initial content that should be shown while the file is loading */
buffer?: string | null | undefined;
/** Encoding to parse the contents of the file. Defaults to UTF-8. */
encoding: string;
/** Content that should be rendered, when the file loading failed. */
onError?: (err: Error) => React.ReactNode;
/** Content that should be rendered, while the file is loaded. */
onLoading?: () => React.ReactNode;
/** Callback when the data is successfully loaded. */
onData?: (content: string) => void;
/** Content that should be rendered, when the file is successfully loaded. This ususally should render the file's contents. */
onLoad: (content: string) => React.ReactNode;
};
type FileState = {
error: Error | null | undefined;
loaded: boolean;
content: string;
};
/**
* Wrapper for loading file content from the file system.
*/
export default class File extends Component<FileProps, FileState> {
constructor(props: FileProps, context: Object) {
super(props, context);
this.state = {
content: props.buffer || '',
error: null,
loaded: props.buffer != null,
};
}
static defaultProps = {
encoding: 'utf8',
};
static getDerivedStateFromProps(nextProps: FileProps) {
if (nextProps.buffer != null) {
return {content: nextProps.buffer, loaded: true};
}
return null;
}
componentDidMount() {
if (this.state.loaded) {
return;
}
fs.readFile(this.props.src, this.props.encoding, (err, content) => {
if (err) {
this.setState({error: err});
return;
}
this.setState({content, loaded: true});
if (this.props.onData) {
this.props.onData(content);
}
});
}
render() {
const {onError, onLoad, onLoading} = this.props;
const {content, error, loaded} = this.state;
if (error && onError) {
return onError(error);
} else if (loaded) {
return onLoad(content);
} else if (onLoading) {
return onLoading();
} else {
return null;
}
}
}

View File

@@ -1,78 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Component} from 'react';
import Box from './Box';
import {colors} from './colors';
import styled from '@emotion/styled';
import React from 'react';
const FocusableBoxBorder = styled(Box)({
border: `1px solid ${colors.highlight}`,
bottom: '0',
left: '0',
pointerEvents: 'none',
position: 'absolute',
right: '0',
top: '0',
});
FocusableBoxBorder.displayName = 'FocusableBox:FocusableBoxBorder';
type Props = {
onBlur?: (e: React.FocusEvent) => void;
onFocus?: (e: React.FocusEvent) => void;
focusable?: boolean;
};
export default class FocusableBox extends Component<
Props,
{
focused: boolean;
}
> {
constructor(props: Props, context: Object) {
super(props, context);
this.state = {focused: false};
}
static defaultProps = {
focusable: true,
};
onBlur = (e: React.FocusEvent) => {
const {onBlur} = this.props;
if (onBlur) {
onBlur(e);
}
if (this.state.focused) {
this.setState({focused: false});
}
};
onFocus = (e: React.FocusEvent) => {
const {onFocus} = this.props;
if (onFocus) {
onFocus(e);
}
if (this.props.focusable) {
this.setState({focused: true});
}
};
render() {
const {props} = this;
return (
<Box {...props} onFocus={this.onFocus} onBlur={this.onBlur} tabIndex={0}>
{props.children}
{this.state.focused && <FocusableBoxBorder />}
</Box>
);
}
}

View File

@@ -9,7 +9,6 @@
import React from 'react';
import styled from '@emotion/styled';
import PropTypes from 'prop-types';
import {getIconURL} from '../../utils/icons';
export type IconSize = 8 | 10 | 12 | 16 | 18 | 20 | 24 | 32;
@@ -94,9 +93,6 @@ function ColoredIcon(
}
}
ColoredIcon.displayName = 'Glyph:ColoredIcon';
ColoredIcon.contextTypes = {
glyphColor: PropTypes.string,
};
export default class Glyph extends React.PureComponent<{
name: string;

View File

@@ -1,55 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import ButtonGroup from './ButtonGroup';
import {Component} from 'react';
import Button from './Button';
import path from 'path';
import React from 'react';
class PathBreadcrumbsItem extends Component<{
name: string;
path: string;
isFolder: boolean;
onClick: (path: string) => void;
}> {
onClick = () => {
this.props.onClick(this.props.path);
};
render() {
return <Button onClick={this.onClick}>{this.props.name}</Button>;
}
}
export default function PathBreadcrumbs(props: {
path: string;
isFile?: boolean;
onClick: (path: string) => void;
}) {
const parts = props.path === path.sep ? [''] : props.path.split(path.sep);
const {onClick} = props;
return (
<ButtonGroup>
{parts.map((part, i) => {
const fullPath = parts.slice(0, i + 1).join(path.sep) || path.sep;
return (
<PathBreadcrumbsItem
key={`${i}:${part}`}
name={part || fullPath}
path={fullPath}
isFolder={!(props.isFile === true && i === parts.length - 1)}
onClick={onClick}
/>
);
})}
</ButtonGroup>
);
}

View File

@@ -1,113 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import React, {PureComponent} from 'react';
import FlexColumn from './FlexColumn';
import styled from '@emotion/styled';
import {colors} from './colors';
const Anchor = styled.img({
zIndex: 6,
position: 'absolute',
bottom: 0,
left: '50%',
transform: 'translate(-50%, calc(100% + 2px))',
});
Anchor.displayName = 'Popover.Anchor';
type Opts = {
minWidth?: number;
skewLeft?: boolean;
};
const PopoverContainer = styled(FlexColumn)<{opts?: Opts}>((props) => ({
backgroundColor: colors.white,
borderRadius: 7,
border: '1px solid rgba(0,0,0,0.3)',
boxShadow: '0 2px 10px 0 rgba(0,0,0,0.3)',
position: 'absolute',
zIndex: 5,
bottom: 0,
marginTop: 15,
left: '50%',
minWidth: (props.opts && props.opts.minWidth) || 'auto',
transform:
props.opts && props.opts.skewLeft
? 'translate(calc(-100% + 22px), calc(100% + 15px))'
: 'translate(-50%, calc(100% + 15px))',
overflow: 'hidden',
'&::before': {
content: '""',
display: 'block',
position: 'absolute',
left: '50%',
transform:
props.opts && props.opts.skewLeft
? 'translateX(calc(-100% + 22px))'
: 'translateX(-50%)',
height: 13,
top: -13,
width: 26,
backgroundColor: colors.white,
},
}));
PopoverContainer.displayName = 'Popover:PopoverContainer';
type Props = {
children: React.ReactNode;
onDismiss: Function;
forceOpts?: Opts;
};
/**
* @deprecated use Popover from antd
*/
export default class Popover extends PureComponent<Props> {
_ref?: Element | null;
componentDidMount() {
window.document.addEventListener('click', this.handleClick);
window.document.addEventListener('keydown', this.handleKeydown);
}
componentWillUnmount() {
window.document.addEventListener('click', this.handleClick);
window.document.addEventListener('keydown', this.handleKeydown);
}
handleClick = (e: MouseEvent) => {
if (this._ref && !this._ref.contains(e.target as Node)) {
this.props.onDismiss();
}
};
handleKeydown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
this.props.onDismiss();
}
};
_setRef = (ref: Element | null) => {
this._ref = ref;
};
render() {
return (
<>
<Anchor src="./anchor.svg" key="anchor" />
<PopoverContainer
ref={this._setRef}
key="popup"
opts={this.props.forceOpts || {}}>
{this.props.children}
</PopoverContainer>
</>
);
}
}

View File

@@ -1,38 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import React, {useEffect, ReactNode} from 'react';
import {useContext} from 'react';
import {PopoverContext} from './PopoverProvider';
/**
* Popover element to be used as a stopgap until we adopt a
* UI framework.
* I don't recommend using this, as it will likely be removed in future.
* Must be nested under a PopoverProvider at some level, usually it is at the top level app so you shouldn't need to add it.
* @deprecated use Popover from Antd
*/
export default function Popover2(props: {
id: string;
targetRef: React.RefObject<HTMLElement | null>;
children: ReactNode;
}) {
const popoverManager = useContext(PopoverContext);
useEffect(() => {
if (props.targetRef.current) {
popoverManager.open(props.id, props.targetRef, props.children);
return () => {
popoverManager.close(props.id);
};
}
});
return null;
}

View File

@@ -1,158 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {
createContext,
useMemo,
useState,
ReactNode,
useEffect,
useRef,
RefObject,
} from 'react';
import React from 'react';
import {colors, styled} from '../../ui';
import {useWindowSize} from '../../utils/useWindowSize';
type PopoverManager = {
open(
id: string,
targetRef: RefObject<HTMLElement | null>,
content: ReactNode,
): void;
close(id: string): void;
};
type Popover = {
id: string;
targetRef: RefObject<HTMLElement | null>;
content: ReactNode;
};
const Anchor = styled.img((props: {top: number; left: number}) => ({
zIndex: 9999999,
position: 'absolute',
top: props.top,
left: props.left,
}));
Anchor.displayName = 'Popover.Anchor';
const ANCHOR_WIDTH = 34;
const PopoverContainer = styled('div')(
(props: {left: number; top: number; hidden: boolean}) => ({
position: 'absolute',
top: props.top,
left: props.left,
zIndex: 9999998,
backgroundColor: colors.white,
borderRadius: 7,
border: '1px solid rgba(0,0,0,0.3)',
boxShadow: '0 2px 10px 0 rgba(0,0,0,0.3)',
display: props.hidden ? 'none' : 'visible',
}),
);
PopoverContainer.displayName = 'Popover.PopoverContainer';
const PopoverElement = (props: {
targetRef: RefObject<HTMLElement | null>;
children: ReactNode;
}) => {
const ref = useRef<HTMLDivElement | null>(null);
const [dimensions, setDimensions] = useState<{
width: number;
height: number;
} | null>(null);
useEffect(() => {
if (!ref.current) {
return;
}
if (
dimensions?.width !== ref.current.clientWidth ||
dimensions?.height !== ref.current.clientHeight
) {
setDimensions({
width: ref.current?.clientWidth,
height: ref.current?.clientHeight,
});
}
});
const windowSize = useWindowSize();
if (
windowSize.height == null ||
windowSize.width == null ||
props.targetRef.current?.getBoundingClientRect() == null
) {
return null;
}
// target is the point that the anchor points to.
// It is defined as the center of the bottom edge of the target element.
const targetXCoord =
props.targetRef.current?.getBoundingClientRect().left +
props.targetRef.current?.getBoundingClientRect().width / 2;
const targetYCoord = props.targetRef.current?.getBoundingClientRect().bottom;
return (
<>
<Anchor
top={targetYCoord}
left={targetXCoord - ANCHOR_WIDTH / 2}
src="./anchor.svg"
key="anchor"
/>
<PopoverContainer
ref={ref}
hidden={ref.current === null}
top={
Math.min(
targetYCoord,
windowSize.height - (dimensions?.height ?? 0),
) + 13
}
left={Math.min(
targetXCoord - (dimensions?.width ?? 0) / 2,
windowSize.width - (dimensions?.width ?? 0),
)}>
{props.children}
</PopoverContainer>
</>
);
};
export const PopoverContext = createContext<PopoverManager>(undefined as any);
export function PopoverProvider({children}: {children: React.ReactNode}) {
const [popovers, setPopovers] = useState<Popover[]>([]);
const popoverManager = useMemo(
() => ({
open: (
id: string,
targetRef: RefObject<HTMLElement | null>,
content: ReactNode,
) => {
setPopovers((s) => [...s, {id, targetRef: targetRef, content}]);
},
close: (id: string) => {
setPopovers((s) => s.filter((p) => p.id !== id));
},
}),
[],
);
return (
<>
{popovers.map((p, index) => (
<PopoverElement key={index} targetRef={p.targetRef}>
{p.content}
</PopoverElement>
))}
<PopoverContext.Provider value={popoverManager}>
{children}
</PopoverContext.Provider>
</>
);
}

View File

@@ -1,60 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
import {Component} from 'react';
import React from 'react';
const IFrame = styled.iframe({
height: '100%',
width: '100%',
border: 'none',
background: 'transparent',
position: 'absolute',
zIndex: -1,
top: 0,
left: 0,
});
IFrame.displayName = 'ResizeSensor:IFrame';
/**
* Listener for resize events.
*/
export default class ResizeSensor extends Component<{
/** Callback when resize happened */
onResize: (e: UIEvent) => void;
}> {
iframe: HTMLIFrameElement | undefined | null;
setRef = (ref: HTMLIFrameElement | null) => {
this.iframe = ref;
};
render() {
return <IFrame ref={this.setRef} />;
}
componentDidMount() {
const {iframe} = this;
if (iframe && iframe.contentWindow != null) {
iframe.contentWindow.addEventListener('resize', this.handleResize);
}
}
componentWillUnmount() {
const {iframe} = this;
if (iframe && iframe.contentWindow != null) {
iframe.contentWindow.removeEventListener('resize', this.handleResize);
}
}
handleResize = (e: UIEvent) => {
window.requestAnimationFrame(() => this.props.onResize(e));
};
}

View File

@@ -1,21 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {colors} from './colors';
import Label from './Label';
import styled from '@emotion/styled';
const SidebarLabel = styled(Label)({
color: colors.blackAlpha30,
fontSize: 12,
padding: 10,
});
SidebarLabel.displayName = 'SidebarLabel';
export default SidebarLabel;

View File

@@ -1,24 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
/**
* A TextParagraph component.
*/
const TextParagraph = styled.div({
marginBottom: 10,
'&:last-child': {
marginBottom: 0,
},
});
TextParagraph.displayName = 'TextParagraph';
export default TextParagraph;

View File

@@ -1,20 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
const VerticalRule = styled.div({
backgroundColor: '#c9ced4',
width: 3,
margin: '0',
flexShrink: 0,
});
VerticalRule.displayName = 'VerticalRule';
export default VerticalRule;

View File

@@ -1,45 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Component} from 'react';
type ViewWithSizeProps = {
onSize: (width: number, height: number) => any;
};
type ViewWithSizeState = {
width: number;
height: number;
};
export default class ViewWithSize extends Component<
ViewWithSizeProps,
ViewWithSizeState
> {
constructor(props: ViewWithSizeProps, context: Object) {
super(props, context);
this.state = {height: window.innerHeight, width: window.innerWidth};
}
_onResize = () => {
this.setState({height: window.innerHeight, width: window.innerWidth});
};
componentDidMount() {
window.addEventListener('resize', this._onResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this._onResize);
}
render() {
return this.props.onSize(this.state.width, this.state.height);
}
}

View File

@@ -1,141 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import FlexColumn from './FlexColumn';
import {Component} from 'react';
import View from './View';
import styled from '@emotion/styled';
import React from 'react';
import {Property} from 'csstype';
const Inner = styled(FlexColumn)<{height: Property.Height<number>}>(
({height}) => ({
alignItems: 'flex-start',
height,
minHeight: '100%',
minWidth: '100%',
overflow: 'visible',
width: '100%',
}),
);
Inner.displayName = 'VirtualList:Inner';
const Content = styled(FlexColumn)<{top: Property.Top<number>}>(({top}) => ({
alignItems: 'flex-start',
height: '100%',
marginTop: top,
minWidth: '100%',
overflow: 'visible',
}));
Content.displayName = 'VirtualList:Content';
type VirtualListProps = {
data: Array<any>;
renderRow: (data: any, i: number) => any;
rowHeight: number;
overscanCount: number;
sync?: boolean;
wrapInner?: (data: any) => any;
};
type VirtualListState = {
offset: number;
height: number;
};
export default class VirtualList extends Component<
VirtualListProps,
VirtualListState
> {
constructor(props: VirtualListProps, context: Object) {
super(props, context);
this.state = {
height: 0,
offset: 0,
};
}
static defaultProps = {
overscanCount: 10,
};
ref: HTMLElement | undefined | null;
setRef = (ref: HTMLElement | null) => {
this.ref = ref;
};
resize = () => {
if (this.ref && this.state.height !== this.ref.offsetHeight) {
this.setState({height: this.ref.offsetHeight});
}
};
handleScroll = () => {
this.setState({offset: this.ref ? this.ref.scrollTop : 0});
if (this.props.sync === true) {
this.forceUpdate();
}
};
componentDidUpdate() {
this.resize();
}
componentDidMount() {
this.resize();
window.addEventListener('resize', this.resize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.resize);
}
render() {
const {data, overscanCount, renderRow, rowHeight, wrapInner} = this.props;
const {height, offset} = this.state;
// first visible row index
// eslint-disable-next-line no-bitwise
let start = (offset / rowHeight) | 0;
// actual number of visible rows (without overscan)
// eslint-disable-next-line no-bitwise
let visibleRowCount = (height / rowHeight) | 0;
// Overscan: render blocks of rows modulo an overscan row count
// This dramatically reduces DOM writes during scrolling
if (overscanCount) {
start = Math.max(0, start - (start % overscanCount));
visibleRowCount += overscanCount;
}
// last visible + overscan row index
const end = start + 1 + visibleRowCount;
// data slice currently in viewport plus overscan items
const selection = data.slice(start, end);
let inner = (
<Inner height={data.length * rowHeight}>
<Content top={start * rowHeight}>{selection.map(renderRow)}</Content>
</Inner>
);
if (wrapInner) {
inner = wrapInner(inner);
}
return (
<View grow onScroll={this.handleScroll} ref={this.setRef} scrollable>
{inner}
</View>
);
}
}

View File

@@ -1,133 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import styled from '@emotion/styled';
import {colors, darkColors} from './colors';
import React from 'react';
const DesktopDropdownContainer = styled.div({
borderBottom: `1px solid ${darkColors.dividers}`,
lineHeight: '25px',
marginTop: 5,
maxHeight: 600,
minWidth: 180,
overflow: 'auto',
padding: 0,
paddingBottom: 5,
textAlign: 'left',
width: 'auto',
'&:last-child': {
borderBottom: 'none',
},
});
DesktopDropdownContainer.displayName =
'DesktopDropdown:DesktopDropdownContainer';
export function DesktopDropdown(props: {
deactivate?: () => void;
children?: any;
}) {
return (
<DesktopDropdownContainer>
{React.Children.map(props.children, (child) => {
return (
child &&
React.cloneElement(child, {
deactivate: props.deactivate,
})
);
})}
</DesktopDropdownContainer>
);
}
const DesktopDropdownItemContainer = styled.div(
(props: {onClick?: Function; onHover?: Function}) => ({
listStyle: 'none',
opacity: props.onClick || props.onHover ? 1 : 0.5,
padding: '0 20px',
'&:hover': {
backgroundColor: props.onClick || props.onHover ? colors.highlight : '',
color: props.onClick || props.onHover ? '#fff' : 'inherit',
},
}),
);
DesktopDropdownItemContainer.displayName =
'DesktopDropdownItem:DesktopDropdownItemContainer';
type DesktopDropdownItemState = {hovered: boolean};
type DesktopDropdownItemProps = {
onClick?: false | ((event: React.MouseEvent) => void);
onHover?: false | (() => React.ReactNode);
children?: React.ReactNode;
deactivate?: () => void;
};
export class DesktopDropdownItem extends React.Component<
DesktopDropdownItemProps,
DesktopDropdownItemState
> {
constructor(props: DesktopDropdownItemProps, context: Object) {
super(props, context);
this.state = {hovered: false};
}
onMouseEnter = () => {
this.setState({hovered: true});
};
onMouseLeave = () => {
this.setState({hovered: false});
};
onClick = (event: React.MouseEvent) => {
const {deactivate, onClick} = this.props;
if (typeof onClick === 'function') {
if (deactivate) {
deactivate();
}
onClick(event);
}
};
render() {
const {hovered} = this.state;
const {
children,
deactivate: _deactivate,
onClick,
onHover,
...props
} = this.props;
return (
<DesktopDropdownItemContainer
{...props}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onClick={typeof onClick === 'function' ? this.onClick : undefined}>
{children}
{hovered && typeof onHover === 'function' && onHover()}
</DesktopDropdownItemContainer>
);
}
}
export const DesktopDropdownSelectedItem = styled(DesktopDropdownItem)({
position: 'relative',
'&::before': {
content: "'✔'",
marginLeft: '-15px',
position: 'absolute',
},
});
DesktopDropdownSelectedItem.displayName = 'DesktopDropdownSelectedItem';

View File

@@ -10,9 +10,7 @@
export {default as styled} from '@emotion/styled';
export {default as Button} from './components/Button';
export {default as ToggleButton} from './components/ToggleSwitch';
export {default as ButtonNavigationGroup} from './components/ButtonNavigationGroup';
export {default as ButtonGroup} from './components/ButtonGroup';
export {default as ButtonGroupChain} from './components/ButtonGroupChain';
export {colors, darkColors, brandColors} from './components/colors';
@@ -20,8 +18,6 @@ export {default as Glyph, IconSize} from './components/Glyph';
export {default as LoadingIndicator} from './components/LoadingIndicator';
export {default as Popover} from './components/Popover';
// tables
export {
TableColumns,
@@ -53,18 +49,12 @@ export {default as Select} from './components/Select';
export {default as Checkbox} from './components/Checkbox';
export {default as Radio} from './components/Radio';
// code
export {default as CodeBlock} from './components/CodeBlock';
// error
export {default as ErrorBlock} from './components/ErrorBlock';
export {ErrorBlockContainer} from './components/ErrorBlock';
export {default as ErrorBoundary} from './components/ErrorBoundary';
// interactive components
export {OrderableOrder} from './components/Orderable';
export {default as Orderable} from './components/Orderable';
export {default as VirtualList} from './components/VirtualList';
// base components
export {Component, PureComponent} from 'react';
@@ -76,23 +66,9 @@ export {default as ContextMenu} from './components/ContextMenu';
// file
export {FileListFile, FileListFiles} from './components/FileList';
export {default as FileList} from './components/FileList';
export {default as File} from './components/File';
// context menu items
export {
DesktopDropdownItem,
DesktopDropdownSelectedItem,
DesktopDropdown,
} from './components/desktop-toolbar';
// utility elements
export {default as View} from './components/View';
export {default as ViewWithSize} from './components/ViewWithSize';
export {default as Block} from './components/Block';
export {default as FocusableBox} from './components/FocusableBox';
export {default as Sidebar} from './components/Sidebar';
export {default as SidebarLabel} from './components/SidebarLabel';
export {default as Box} from './components/Box';
export {default as FlexBox} from './components/FlexBox';
export {default as FlexRow} from './components/FlexRow';
export {default as FlexColumn} from './components/FlexColumn';
@@ -101,18 +77,14 @@ export {Spacer} from './components/Toolbar';
export {default as ToolbarIcon} from './components/ToolbarIcon';
export {default as Panel} from './components/Panel';
export {default as Text} from './components/Text';
export {default as TextParagraph} from './components/TextParagraph';
export {default as Link} from './components/Link';
export {default as PathBreadcrumbs} from './components/PathBreadcrumbs';
export {default as ModalOverlay} from './components/ModalOverlay';
export {default as Tooltip} from './components/Tooltip';
export {default as TooltipProvider} from './components/TooltipProvider';
export {default as ResizeSensor} from './components/ResizeSensor';
export {default as StatusIndicator} from './components/StatusIndicator';
export {default as Line} from './components/Line';
// typography
export {default as HorizontalRule} from './components/HorizontalRule';
export {default as VerticalRule} from './components/VerticalRule';
export {default as Label} from './components/Label';
export {default as Heading} from './components/Heading';
@@ -137,7 +109,6 @@ export {InspectorSidebar} from './components/elements-inspector/sidebar';
export {VisualizerPortal} from './components/elements-inspector/Visualizer';
export {default as Sheet} from './components/Sheet';
export {StarButton} from './components/StarButton';
export {Markdown} from './components/Markdown';
export {default as VBox} from './components/VBox';
@@ -147,8 +118,6 @@ export {default as Labeled} from './components/Labeled';
export {default as RoundedSection} from './components/RoundedSection';
export {default as CenteredView} from './components/CenteredView';
export {default as Info} from './components/Info';
export {default as Bordered} from './components/Bordered';
export {default as AlternatingRows} from './components/AlternatingRows';
export {Layout} from 'flipper-plugin';
export {default as Scrollable} from './components/Scrollable';

View File

@@ -7,7 +7,7 @@
* @format
*/
import {PluginDefinition} from '../plugin';
import type {PluginDefinition} from '../plugin';
import type {State} from '../reducers';
import type {State as PluginsState} from '../reducers/plugins';
import type BaseDevice from '../devices/BaseDevice';

View File

@@ -11051,7 +11051,7 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.4"
prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@^15.0.0, prop-types@^15.5.10, 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==