Summary: _typescript_

Reviewed By: priteshrnandgaonkar

Differential Revision: D16807180

fbshipit-source-id: dcba794351eee69c0574dc224cf7bd2732bea447
This commit is contained in:
Daniel Büchele
2019-08-20 05:40:31 -07:00
committed by Facebook Github Bot
parent 62a204bdbe
commit 4c4169063d
22 changed files with 501 additions and 473 deletions

View File

@@ -58,6 +58,8 @@
"@types/react": "^16.8.24",
"@types/react-dom": "^16.8.5",
"@types/react-redux": "^7.1.1",
"@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.1",
"@types/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.2",
"@types/uuid": "^3.4.5",

View File

@@ -73,17 +73,17 @@ export {
TableColumnOrder,
TableColumnOrderVal,
TableColumnSizes,
} from './ui/components/table/types.js';
export {default as ManagedTable} from './ui/components/table/ManagedTable.js';
export {ManagedTableProps} from './ui/components/table/ManagedTable.js';
} from './ui/components/table/types.tsx';
export {default as ManagedTable} from './ui/components/table/ManagedTable.tsx';
export {ManagedTableProps} from './ui/components/table/ManagedTable.tsx';
export {
default as ManagedTable_immutable,
} from './ui/components/table/ManagedTable_immutable.js';
export {
ManagedTableProps_immutable,
} from './ui/components/table/ManagedTable_immutable.js';
export {Value} from './ui/components/table/TypeBasedValueRenderer.js';
export {renderValue} from './ui/components/table/TypeBasedValueRenderer.js';
} from './ui/components/table/ManagedTable_immutable.tsx';
export {
Value,
renderValue,
} from './ui/components/table/TypeBasedValueRenderer.tsx';
export {
DataValueExtractor,
DataInspectorExpanded,

View File

@@ -17,12 +17,14 @@ import Select from '../ui/components/Select';
import ErrorBlock from '../ui/components/ErrorBlock';
import FlexColumn from '../ui/components/FlexColumn';
import SearchableTable from '../ui/components/searchable/SearchableTable';
import TableHighlightedRows from '../ui/components/table/types';
import TableRows from '../ui/components/table/types';
import TableColumnSizes from '../ui/components/table/types';
import TableColumns from '../ui/components/table/types';
import TableColumnOrderVal from '../ui/components/table/types';
import TableBodyRow from '../ui/components/table/types';
import {
TableHighlightedRows,
TableRows,
TableColumnSizes,
TableColumns,
TableColumnOrderVal,
TableBodyRow,
} from '../ui/components/table/types';
import DetailSidebar from '../chrome/DetailSidebar';
import {FlipperPlugin} from '../plugin';
import textContent from '../utils/textContent';

View File

@@ -5,8 +5,7 @@
* @format
*/
import type {PluginClient} from '../../plugin.tsx';
import type {Value} from '../../ui/components/table/TypeBasedValueRenderer';
import type {PluginClient, Value} from 'flipper';
type ClientCall<Params, Response> = Params => Promise<Response>;

View File

@@ -25,10 +25,7 @@ import {
ManagedDataInspector,
} from 'flipper';
import {Component} from 'react';
import type {
TableBodyRow,
TableRowSortOrder,
} from '../../ui/components/table/types';
import type {TableBodyRow, TableRowSortOrder} from 'flipper';
import {FlipperPlugin} from 'flipper';
import {DatabaseClient} from './ClientProtocol';
import {renderValue} from 'flipper';

View File

@@ -21,7 +21,7 @@ type Props = {
children: React.ReactNode;
/** The component that is used to wrap the children. Defaults to `FlexColumn`. */
component: React.ComponentType<any> | string;
onMouseDown: (e: React.MouseEvent) => any;
onMouseDown?: (e: React.MouseEvent) => any;
};
/**

View File

@@ -60,8 +60,8 @@ type InteractiveProps = {
minLeft?: number;
width?: number | string;
height?: number | string;
minWidth: number;
minHeight: number;
minWidth?: number;
minHeight?: number;
maxWidth?: number;
maxHeight?: number;
onCanResize?: (sides: ResizingSides) => void;

View File

@@ -14,6 +14,7 @@ import Glyph from './Glyph';
import styled from 'react-emotion';
import React from 'react';
import {BackgroundColorProperty} from 'csstype';
import {TableBodyRow} from './table/types';
const Padder = styled('div')(
({
@@ -132,8 +133,8 @@ export default class StackTrace extends Component<{
return acc;
}, {});
const rows = children.map((l, i) => ({
key: i,
const rows: TableBodyRow[] = children.map((l, i) => ({
key: String(i),
columns: Object.keys(columns).reduce((acc, cv) => {
acc[cv] = {
align: cv === 'lineNumber' ? 'right' : 'left',

View File

@@ -6,8 +6,8 @@
*/
import {Filter} from '../filter/types';
import ManagedTable, {ManagedTableProps} from '../table/ManagedTable.js';
import {TableBodyRow} from '../table/types.js';
import ManagedTable, {ManagedTableProps} from '../table/ManagedTable';
import {TableBodyRow} from '../table/types';
import Searchable, {SearchableProps} from './Searchable';
import React, {PureComponent} from 'react';
import textContent from '../../../utils/textContent';

View File

@@ -6,11 +6,11 @@
*/
import {Filter} from '../filter/types';
import {ManagedTableProps_immutable} from '../table/ManagedTable_immutable.js';
import {TableBodyRow} from '../table/types.js';
import {ManagedTableProps_immutable} from '../table/ManagedTable_immutable';
import {TableBodyRow} from '../table/types';
import Searchable, {SearchableProps} from './Searchable';
import {PureComponent} from 'react';
import ManagedTable_immutable from '../table/ManagedTable_immutable.js';
import ManagedTable_immutable from '../table/ManagedTable_immutable';
import textContent from '../../../utils/textContent';
import deepEqual from 'deep-equal';
import React from 'react';

View File

@@ -5,7 +5,7 @@
* @format
*/
import type {
import {
TableColumnOrder,
TableColumnSizes,
TableColumns,
@@ -14,146 +14,143 @@ import type {
TableRows,
TableBodyRow,
TableOnAddFilter,
} from './types.js';
import type {MenuTemplate} from '../ContextMenu.tsx';
} from './types';
import {MenuTemplate} from '../ContextMenu';
import React from 'react';
import styled from '../../styled/index.js';
import styled from 'react-emotion';
import AutoSizer from 'react-virtualized-auto-sizer';
import {VariableSizeList as List} from 'react-window';
import {clipboard} from 'electron';
import TableHead from './TableHead.js';
import TableRow from './TableRow.js';
import ContextMenu from '../ContextMenu.tsx';
import FlexColumn from '../FlexColumn.tsx';
import createPaste from '../../../fb-stubs/createPaste.tsx';
import {clipboard, MenuItemConstructorOptions} from 'electron';
import TableHead from './TableHead';
import TableRow from './TableRow';
import ContextMenu from '../ContextMenu';
import FlexColumn from '../FlexColumn';
import createPaste from '../../../fb-stubs/createPaste';
import debounceRender from 'react-debounce-render';
import debounce from 'lodash.debounce';
import {DEFAULT_ROW_HEIGHT} from './types';
import textContent from '../../../utils/textContent.tsx';
import textContent from '../../../utils/textContent';
export type ManagedTableProps = {|
export type ManagedTableProps = {
/**
* Column definitions.
*/
columns: TableColumns,
columns: TableColumns;
/**
* Row definitions.
*/
rows: TableRows,
rows: TableRows;
/*
* Globally unique key for persisting data between uses of a table such as column sizes.
*/
tableKey?: string,
tableKey?: string;
/**
* Whether the table has a border.
*/
floating?: boolean,
floating?: boolean;
/**
* Whether a row can span over multiple lines. Otherwise lines cannot wrap and
* are truncated.
*/
multiline?: boolean,
multiline?: boolean;
/**
* Whether the body is scrollable. When this is set to `true` then the table
* is not scrollable.
*/
autoHeight?: boolean,
autoHeight?: boolean;
/**
* Order of columns.
*/
columnOrder?: TableColumnOrder,
columnOrder?: TableColumnOrder;
/**
* Initial size of the columns.
*/
columnSizes?: TableColumnSizes,
columnSizes?: TableColumnSizes;
/**
* Value to filter rows on. Alternative to the `filter` prop.
*/
filterValue?: string,
filterValue?: string;
/**
* Callback to filter rows.
*/
filter?: (row: TableBodyRow) => boolean,
filter?: (row: TableBodyRow) => boolean;
/**
* Callback when the highlighted rows change.
*/
onRowHighlighted?: (keys: TableHighlightedRows) => void,
onRowHighlighted?: (keys: TableHighlightedRows) => void;
/**
* Whether rows can be highlighted or not.
*/
highlightableRows?: boolean,
highlightableRows?: boolean;
/**
* Whether multiple rows can be highlighted or not.
*/
multiHighlight?: boolean,
multiHighlight?: boolean;
/**
* Height of each row.
*/
rowLineHeight?: number,
rowLineHeight?: number;
/**
* This makes it so the scroll position sticks to the bottom of the window.
* Useful for streaming data like requests, logs etc.
*/
stickyBottom?: boolean,
stickyBottom?: boolean;
/**
* Used by SearchableTable to add filters for rows.
*/
onAddFilter?: TableOnAddFilter,
onAddFilter?: TableOnAddFilter;
/**
* Enable or disable zebra striping.
*/
zebra?: boolean,
zebra?: boolean;
/**
* Whether to hide the column names at the top of the table.
*/
hideHeader?: boolean,
hideHeader?: boolean;
/**
* Rows that are highlighted initially.
*/
highlightedRows?: Set<string>,
highlightedRows?: Set<string>;
/**
* Allows to create context menu items for rows.
*/
buildContextMenuItems?: () => MenuTemplate,
initialSortOrder?: ?TableRowSortOrder,
buildContextMenuItems?: () => MenuTemplate;
/**
* Callback when sorting changes.
*/
onSort?: (order: TableRowSortOrder) => void,
onSort?: (order: TableRowSortOrder) => void;
/**
* Initial sort order of the table.
*/
initialSortOrder?: ?TableRowSortOrder,
initialSortOrder?: TableRowSortOrder;
/**
* Table scroll horizontally, if needed
*/
horizontallyScrollable?: boolean,
horizontallyScrollable?: boolean;
/**
* Whether to allow navigation via arrow keys. Default: true
*/
enableKeyboardNavigation?: boolean,
|};
enableKeyboardNavigation?: boolean;
};
type ManagedTableState = {|
highlightedRows: Set<string>,
sortOrder: ?TableRowSortOrder,
columnOrder: TableColumnOrder,
columnSizes: TableColumnSizes,
shouldScrollToBottom: boolean,
|};
type ManagedTableState = {
highlightedRows: Set<string>;
sortOrder?: TableRowSortOrder;
columnOrder: TableColumnOrder;
columnSizes: TableColumnSizes;
shouldScrollToBottom: boolean;
};
const Container = styled(FlexColumn)(props => ({
const Container = styled(FlexColumn)((props: {canOverflow?: boolean}) => ({
overflow: props.canOverflow ? 'scroll' : 'visible',
flexGrow: 1,
}));
const globalTableState: {[string]: TableColumnSizes} = {};
const globalTableState: {[key: string]: TableColumnSizes} = {};
class ManagedTable extends React.Component<
ManagedTableProps,
ManagedTableState,
ManagedTableState
> {
static defaultProps = {
highlightableRows: true,
@@ -188,10 +185,10 @@ class ManagedTable extends React.Component<
tableRef = React.createRef<List>();
scrollRef: {
current: null | HTMLDivElement,
current: null | HTMLDivElement;
} = React.createRef();
dragStartIndex: ?number = null;
dragStartIndex: number | null = null;
// We want to call scrollToHighlightedRows on componentDidMount. However, at
// this time, tableRef is still null, because AutoSizer needs one render to
@@ -225,7 +222,7 @@ class ManagedTable extends React.Component<
// if columnOrder has changed
if (nextProps.columnOrder !== this.props.columnOrder) {
if (this.tableRef && this.tableRef.current) {
this.tableRef.current.resetAfterIndex(0);
this.tableRef.current.resetAfterIndex(0, true);
}
this.setState({
columnOrder: nextProps.columnOrder,
@@ -238,7 +235,7 @@ class ManagedTable extends React.Component<
this.tableRef.current
) {
// rows were filtered, we need to recalculate heights
this.tableRef.current.resetAfterIndex(0);
this.tableRef.current.resetAfterIndex(0, true);
}
}
@@ -336,7 +333,7 @@ class ManagedTable extends React.Component<
}
};
onRowHighlighted = (highlightedRows: Set<string>, cb?: Function) => {
onRowHighlighted = (highlightedRows: Set<string>, cb?: () => void) => {
if (!this.props.highlightableRows) {
return;
}
@@ -385,11 +382,7 @@ class ManagedTable extends React.Component<
}
}
onHighlight = (
e: SyntheticMouseEvent<>,
row: TableBodyRow,
index: number,
) => {
onHighlight = (e: React.MouseEvent, row: TableBodyRow, index: number) => {
if (e.shiftKey) {
// prevents text selection
e.preventDefault();
@@ -468,11 +461,7 @@ class ManagedTable extends React.Component<
return selected;
};
onMouseEnterRow = (
e: SyntheticMouseEvent<>,
row: TableBodyRow,
index: number,
) => {
onMouseEnterRow = (e: React.MouseEvent, row: TableBodyRow, index: number) => {
const {dragStartIndex} = this;
const {current} = this.tableRef;
if (
@@ -585,9 +574,9 @@ class ManagedTable extends React.Component<
scrollDirection,
scrollOffset,
}: {
scrollDirection: 'forward' | 'backward',
scrollOffset: number,
scrollUpdateWasRequested: boolean,
scrollDirection: 'forward' | 'backward';
scrollOffset: number;
scrollUpdateWasRequested: boolean;
}) => {
const {current} = this.scrollRef;
const parent = current ? current.parentElement : null;
@@ -612,13 +601,7 @@ class ManagedTable extends React.Component<
);
getRow = ({index, style}) => {
const {
onAddFilter,
multiline,
zebra,
rows,
horizontallyScrollable,
} = this.props;
const {onAddFilter, multiline, zebra, rows} = this.props;
const {columnOrder, columnSizes, highlightedRows} = this.state;
const columnKeys = columnOrder
.map(k => (k.visible ? k.key : null))
@@ -639,7 +622,6 @@ class ManagedTable extends React.Component<
style={style}
onAddFilter={onAddFilter}
zebra={zebra}
horizontallyScrollable={horizontallyScrollable}
/>
);
};
@@ -664,12 +646,12 @@ class ManagedTable extends React.Component<
}
const width = columnSizes[col.key];
if (isNaN(width)) {
if (typeof width === 'number' && isNaN(width)) {
// non-numeric columns with, can't caluclate
computedWidth = 0;
break;
} else {
computedWidth += parseInt(width, 10);
computedWidth += parseInt(String(width), 10);
}
}
}

View File

@@ -5,7 +5,7 @@
* @format
*/
import type {
import {
TableColumnOrder,
TableColumnSizes,
TableColumns,
@@ -14,142 +14,140 @@ import type {
TableRows_immutable,
TableBodyRow,
TableOnAddFilter,
} from './types.js';
import type {MenuTemplate} from '../ContextMenu.tsx';
} from './types';
import {MenuTemplate} from '../ContextMenu';
import React from 'react';
import styled from '../../styled/index.js';
import styled from 'react-emotion';
import AutoSizer from 'react-virtualized-auto-sizer';
import {VariableSizeList as List} from 'react-window';
import {clipboard} from 'electron';
import TableHead from './TableHead.js';
import TableRow from './TableRow.js';
import ContextMenu from '../ContextMenu.tsx';
import FlexColumn from '../FlexColumn.tsx';
import createPaste from '../../../fb-stubs/createPaste.tsx';
import {clipboard, MenuItemConstructorOptions} from 'electron';
import TableHead from './TableHead';
import TableRow from './TableRow';
import ContextMenu from '../ContextMenu';
import FlexColumn from '../FlexColumn';
import createPaste from '../../../fb-stubs/createPaste';
import debounceRender from 'react-debounce-render';
import debounce from 'lodash.debounce';
import {DEFAULT_ROW_HEIGHT} from './types';
import textContent from '../../../utils/textContent.tsx';
import textContent from '../../../utils/textContent';
export type ManagedTableProps_immutable = {|
export type ManagedTableProps_immutable = {
/**
* Column definitions.
*/
columns: TableColumns,
columns: TableColumns;
/**
* Row definitions.
*/
rows: TableRows_immutable,
rows: TableRows_immutable;
/*
* Globally unique key for persisting data between uses of a table such as column sizes.
*/
tableKey?: string,
tableKey?: string;
/**
* Whether the table has a border.
*/
floating?: boolean,
floating?: boolean;
/**
* Whether a row can span over multiple lines. Otherwise lines cannot wrap and
* are truncated.
*/
multiline?: boolean,
multiline?: boolean;
/**
* Whether the body is scrollable. When this is set to `true` then the table
* is not scrollable.
*/
autoHeight?: boolean,
autoHeight?: boolean;
/**
* Order of columns.
*/
columnOrder?: TableColumnOrder,
columnOrder?: TableColumnOrder;
/**
* Initial size of the columns.
*/
columnSizes?: TableColumnSizes,
columnSizes?: TableColumnSizes;
/**
* Value to filter rows on. Alternative to the `filter` prop.
*/
filterValue?: string,
filterValue?: string;
/**
* Callback to filter rows.
*/
filter?: (row: TableBodyRow) => boolean,
filter?: (row: TableBodyRow) => boolean;
/**
* Callback when the highlighted rows change.
*/
onRowHighlighted?: (keys: TableHighlightedRows) => void,
onRowHighlighted?: (keys: TableHighlightedRows) => void;
/**
* Whether rows can be highlighted or not.
*/
highlightableRows?: boolean,
highlightableRows?: boolean;
/**
* Whether multiple rows can be highlighted or not.
*/
multiHighlight?: boolean,
multiHighlight?: boolean;
/**
* Height of each row.
*/
rowLineHeight?: number,
rowLineHeight?: number;
/**
* This makes it so the scroll position sticks to the bottom of the window.
* Useful for streaming data like requests, logs etc.
*/
stickyBottom?: boolean,
stickyBottom?: boolean;
/**
* Used by SearchableTable to add filters for rows.
*/
onAddFilter?: TableOnAddFilter,
onAddFilter?: TableOnAddFilter;
/**
* Enable or disable zebra striping.
*/
zebra?: boolean,
zebra?: boolean;
/**
* Whether to hide the column names at the top of the table.
*/
hideHeader?: boolean,
hideHeader?: boolean;
/**
* Rows that are highlighted initially.
*/
highlightedRows?: Set<string>,
highlightedRows?: Set<string>;
/**
* Allows to create context menu items for rows.
*/
buildContextMenuItems?: () => MenuTemplate,
initialSortOrder?: ?TableRowSortOrder,
buildContextMenuItems?: () => MenuTemplate;
/**
* Callback when sorting changes.
*/
onSort?: (order: TableRowSortOrder) => void,
onSort?: (order: TableRowSortOrder) => void;
/**
* Initial sort order of the table.
*/
initialSortOrder?: ?TableRowSortOrder,
initialSortOrder?: TableRowSortOrder;
/**
* Table scroll horizontally, if needed
*/
horizontallyScrollable?: boolean,
|};
horizontallyScrollable?: boolean;
};
type ManagedTableState = {|
highlightedRows: Set<string>,
sortOrder: ?TableRowSortOrder,
columnOrder: TableColumnOrder,
columnSizes: TableColumnSizes,
shouldScrollToBottom: boolean,
|};
type ManagedTableState = {
highlightedRows: Set<string>;
sortOrder?: TableRowSortOrder;
columnOrder: TableColumnOrder;
columnSizes: TableColumnSizes;
shouldScrollToBottom: boolean;
};
const Container = styled(FlexColumn)(props => ({
const Container = styled(FlexColumn)((props: {canOverflow?: boolean}) => ({
overflow: props.canOverflow ? 'scroll' : 'visible',
flexGrow: 1,
}));
const globalTableState: {[string]: TableColumnSizes} = {};
const globalTableState: {[key: string]: TableColumnSizes} = {};
class ManagedTable extends React.Component<
ManagedTableProps_immutable,
ManagedTableState,
ManagedTableState
> {
static defaultProps = {
highlightableRows: true,
@@ -183,10 +181,10 @@ class ManagedTable extends React.Component<
tableRef = React.createRef<List>();
scrollRef: {
current: null | HTMLDivElement,
current: null | HTMLDivElement;
} = React.createRef();
dragStartIndex: ?number = null;
dragStartIndex: number | null = null;
// We want to call scrollToHighlightedRows on componentDidMount. However, at
// this time, tableRef is still null, because AutoSizer needs one render to
@@ -220,7 +218,7 @@ class ManagedTable extends React.Component<
// if columnOrder has changed
if (nextProps.columnOrder !== this.props.columnOrder) {
if (this.tableRef && this.tableRef.current) {
this.tableRef.current.resetAfterIndex(0);
this.tableRef.current.resetAfterIndex(0, true);
}
this.setState({
columnOrder: nextProps.columnOrder,
@@ -233,7 +231,7 @@ class ManagedTable extends React.Component<
this.tableRef.current
) {
// rows were filtered, we need to recalculate heights
this.tableRef.current.resetAfterIndex(0);
this.tableRef.current.resetAfterIndex(0, true);
}
}
@@ -331,7 +329,7 @@ class ManagedTable extends React.Component<
}
};
onRowHighlighted = (highlightedRows: Set<string>, cb?: Function) => {
onRowHighlighted = (highlightedRows: Set<string>, cb?: () => void) => {
if (!this.props.highlightableRows) {
return;
}
@@ -380,11 +378,7 @@ class ManagedTable extends React.Component<
}
}
onHighlight = (
e: SyntheticMouseEvent<>,
row: TableBodyRow,
index: number,
) => {
onHighlight = (e: React.MouseEvent, row: TableBodyRow, index: number) => {
if (e.shiftKey) {
// prevents text selection
e.preventDefault();
@@ -466,11 +460,7 @@ class ManagedTable extends React.Component<
return selected;
};
onMouseEnterRow = (
e: SyntheticMouseEvent<>,
row: TableBodyRow,
index: number,
) => {
onMouseEnterRow = (e: React.MouseEvent, row: TableBodyRow, index: number) => {
const {dragStartIndex} = this;
const {current} = this.tableRef;
if (
@@ -493,7 +483,7 @@ class ManagedTable extends React.Component<
clipboard.writeText(cellText);
};
buildContextMenuItems: () => Array<MenuItemConstructorOptions> = () => {
buildContextMenuItems: () => MenuItemConstructorOptions[] = () => {
const {highlightedRows} = this.state;
if (highlightedRows.size === 0) {
return [];
@@ -584,9 +574,9 @@ class ManagedTable extends React.Component<
scrollDirection,
scrollOffset,
}: {
scrollDirection: 'forward' | 'backward',
scrollOffset: number,
scrollUpdateWasRequested: boolean,
scrollDirection: 'forward' | 'backward';
scrollOffset: number;
scrollUpdateWasRequested: boolean;
}) => {
const {current} = this.scrollRef;
const parent = current ? current.parentElement : null;
@@ -611,13 +601,7 @@ class ManagedTable extends React.Component<
);
getRow = ({index, style}) => {
const {
onAddFilter,
multiline,
zebra,
rows,
horizontallyScrollable,
} = this.props;
const {onAddFilter, multiline, zebra, rows} = this.props;
const {columnOrder, columnSizes, highlightedRows} = this.state;
const columnKeys = columnOrder
.map(k => (k.visible ? k.key : null))
@@ -643,7 +627,6 @@ class ManagedTable extends React.Component<
style={style}
onAddFilter={onAddFilter}
zebra={zebra}
horizontallyScrollable={horizontallyScrollable}
/>
);
};
@@ -668,12 +651,12 @@ class ManagedTable extends React.Component<
}
const width = columnSizes[col.key];
if (isNaN(width)) {
if (typeof width === 'number' && isNaN(width)) {
// non-numeric columns with, can't caluclate
computedWidth = 0;
break;
} else {
computedWidth += parseInt(width, 10);
computedWidth += parseInt(String(width), 10);
}
}
}

View File

@@ -5,27 +5,24 @@
* @format
*/
import type {
import {
TableColumnOrder,
TableColumnSizes,
TableColumns,
TableOnColumnResize,
TableOnSort,
TableRowSortOrder,
} from './types.js';
import {normaliseColumnWidth, isPercentage} from './utils.js';
} from './types';
import {normaliseColumnWidth, isPercentage} from './utils';
import {PureComponent} from 'react';
import ContextMenu from '../ContextMenu.tsx';
import Interactive from '../Interactive.tsx';
import styled from '../../styled/index.js';
import {colors} from '../colors.tsx';
import FlexRow from '../FlexRow.tsx';
import ContextMenu from '../ContextMenu';
import Interactive from '../Interactive';
import styled from 'react-emotion';
import {colors} from '../colors';
import FlexRow from '../FlexRow';
import invariant from 'invariant';
type MenuTemplate = Array<MenuItemConstructorOptions>;
import {MenuItemConstructorOptions} from 'electron';
import React from 'react';
const TableHeaderArrow = styled('span')({
float: 'right',
@@ -43,41 +40,45 @@ const TableHeaderColumnContainer = styled('div')({
padding: '0 8px',
});
const TableHeadContainer = styled(FlexRow)(props => ({
borderBottom: `1px solid ${colors.sectionHeaderBorder}`,
color: colors.light50,
flexShrink: 0,
left: 0,
overflow: 'hidden',
right: 0,
textAlign: 'left',
top: 0,
zIndex: 2,
minWidth: props.horizontallyScrollable ? 'min-content' : 0,
}));
const TableHeadColumnContainer = styled('div')(props => ({
position: 'relative',
backgroundColor: colors.white,
flexShrink: props.width === 'flex' ? 1 : 0,
height: 23,
lineHeight: '23px',
fontSize: '0.85em',
fontWeight: 500,
width: props.width === 'flex' ? '100%' : props.width,
'&::after': {
position: 'absolute',
content: '""',
const TableHeadContainer = styled(FlexRow)(
(props: {horizontallyScrollable?: boolean}) => ({
borderBottom: `1px solid ${colors.sectionHeaderBorder}`,
color: colors.light50,
flexShrink: 0,
left: 0,
overflow: 'hidden',
right: 0,
top: 5,
height: 13,
width: 1,
background: colors.light15,
},
'&:last-child::after': {
display: 'none',
},
}));
textAlign: 'left',
top: 0,
zIndex: 2,
minWidth: props.horizontallyScrollable ? 'min-content' : 0,
}),
);
const TableHeadColumnContainer = styled('div')(
(props: {width: string | number}) => ({
position: 'relative',
backgroundColor: colors.white,
flexShrink: props.width === 'flex' ? 1 : 0,
height: 23,
lineHeight: '23px',
fontSize: '0.85em',
fontWeight: 500,
width: props.width === 'flex' ? '100%' : props.width,
'&::after': {
position: 'absolute',
content: '""',
right: 0,
top: 5,
height: 13,
width: 1,
background: colors.light15,
},
'&:last-child::after': {
display: 'none',
},
}),
);
const RIGHT_RESIZABLE = {right: true};
@@ -86,19 +87,19 @@ function calculatePercentage(parentWidth: number, selfWidth: number): string {
}
class TableHeadColumn extends PureComponent<{
id: string,
width: string | number,
sortable: ?boolean,
isResizable: boolean,
leftHasResizer: boolean,
hasFlex: boolean,
sortOrder: ?TableRowSortOrder,
onSort: ?TableOnSort,
columnSizes: TableColumnSizes,
onColumnResize: ?TableOnColumnResize,
children?: React$Node,
title?: string,
horizontallyScrollable?: boolean,
id: string;
width: string | number;
sortable?: boolean;
isResizable: boolean;
leftHasResizer: boolean;
hasFlex: boolean;
sortOrder?: TableRowSortOrder;
onSort?: TableOnSort;
columnSizes: TableColumnSizes;
onColumnResize?: TableOnColumnResize;
children?: React.ReactNode;
title?: string;
horizontallyScrollable?: boolean;
}> {
ref: HTMLElement;
@@ -131,7 +132,7 @@ class TableHeadColumn extends PureComponent<{
return;
}
let normalizedWidth = newWidth;
let normalizedWidth: number | string = newWidth;
// normalise number to a percentage if we were originally passed a percentage
if (isPercentage(width)) {
@@ -191,16 +192,16 @@ class TableHeadColumn extends PureComponent<{
}
export default class TableHead extends PureComponent<{
columnOrder: TableColumnOrder,
onColumnOrder: ?(order: TableColumnOrder) => void,
columns: TableColumns,
sortOrder: ?TableRowSortOrder,
onSort: ?TableOnSort,
columnSizes: TableColumnSizes,
onColumnResize: ?TableOnColumnResize,
horizontallyScrollable?: boolean,
columnOrder: TableColumnOrder;
onColumnOrder?: (order: TableColumnOrder) => void;
columns: TableColumns;
sortOrder?: TableRowSortOrder;
onSort?: TableOnSort;
columnSizes: TableColumnSizes;
onColumnResize?: TableOnColumnResize;
horizontallyScrollable?: boolean;
}> {
buildContextMenu = (): MenuTemplate => {
buildContextMenu = (): MenuItemConstructorOptions[] => {
const visibles = this.props.columnOrder
.map(c => (c.visible ? c.key : null))
.filter(Boolean)
@@ -231,7 +232,7 @@ export default class TableHead extends PureComponent<{
}
}
},
type: 'checkbox',
type: 'checkbox' as 'checkbox',
checked: visible,
};
});

View File

@@ -1,157 +0,0 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
import type {
TableColumnKeys,
TableColumnSizes,
TableOnAddFilter,
TableBodyRow,
} from './types.js';
import React from 'react';
import FilterRow from '../filter/FilterRow.tsx';
import styled from 'react-emotion';
import FlexRow from '../FlexRow.tsx';
import {colors} from '../colors.tsx';
import {normaliseColumnWidth} from './utils.js';
import {DEFAULT_ROW_HEIGHT} from './types';
const backgroundColor = props => {
if (props.highlighted) {
if (props.highlightedBackgroundColor) {
return props.highlightedBackgroundColor;
} else {
return colors.macOSTitleBarIconSelected;
}
} else {
if (props.backgroundColor) {
return props.backgroundColor;
} else if (props.even && props.zebra) {
return colors.light02;
} else {
return 'transparent';
}
}
};
const TableBodyRowContainer = styled(FlexRow)(props => ({
backgroundColor: backgroundColor(props),
boxShadow: props.zebra ? 'none' : 'inset 0 -1px #E9EBEE',
color: props.highlighted ? colors.white : props.color || 'inherit',
'& *': {
color: props.highlighted ? `${colors.white} !important` : null,
},
'& img': {
backgroundColor: props.highlighted ? `${colors.white} !important` : 'none',
},
height: props.multiline ? 'auto' : props.rowLineHeight,
lineHeight: `${String(props.rowLineHeight || DEFAULT_ROW_HEIGHT)}px`,
fontWeight: props.fontWeight || 'inherit',
overflow: 'hidden',
width: '100%',
userSelect: 'none',
flexShrink: 0,
'&:hover': {
backgroundColor:
!props.highlighted && props.highlightOnHover ? colors.light02 : 'none',
},
}));
const TableBodyColumnContainer = styled('div')(props => ({
display: 'flex',
flexShrink: props.width === 'flex' ? 1 : 0,
overflow: 'hidden',
padding: '0 8px',
userSelect: 'none',
textOverflow: 'ellipsis',
verticalAlign: 'top',
whiteSpace: props.multiline ? 'normal' : 'nowrap',
wordWrap: props.multiline ? 'break-word' : 'normal',
width: props.width === 'flex' ? '100%' : props.width,
maxWidth: '100%',
justifyContent: props.justifyContent,
}));
type Props = {
columnSizes: TableColumnSizes,
columnKeys: TableColumnKeys,
onMouseDown: (e: SyntheticMouseEvent<>) => mixed,
onMouseEnter?: (e: SyntheticMouseEvent<>) => void,
multiline: ?boolean,
rowLineHeight: number,
highlighted: boolean,
row: TableBodyRow,
index: number,
style: ?Object,
onAddFilter?: TableOnAddFilter,
zebra: ?boolean,
};
export default class TableRow extends React.PureComponent<Props> {
static defaultProps = {
zebra: true,
};
render() {
const {
index,
highlighted,
rowLineHeight,
row,
style,
multiline,
columnKeys,
columnSizes,
onMouseEnter,
onMouseDown,
zebra,
onAddFilter,
} = this.props;
return (
<TableBodyRowContainer
rowLineHeight={rowLineHeight}
highlightedBackgroundColor={row.highlightedBackgroundColor}
backgroundColor={row.backgroundColor}
highlighted={highlighted}
multiline={multiline}
even={index % 2 === 0}
zebra={zebra}
onMouseDown={onMouseDown}
onMouseEnter={onMouseEnter}
style={style}
highlightOnHover={row.highlightOnHover}
data-key={row.key}
{...row.style}>
{columnKeys.map(key => {
const col = row.columns[key];
const isFilterable = col?.isFilterable || false;
const value = col?.value;
const title = col?.title;
return (
<TableBodyColumnContainer
key={key}
title={title}
multiline={multiline}
justifyContent={col?.align || 'flex-start'}
width={normaliseColumnWidth(columnSizes[key])}>
{isFilterable && onAddFilter != null ? (
<FilterRow addFilter={onAddFilter} filterKey={key}>
{value}
</FilterRow>
) : (
value
)}
</TableBodyColumnContainer>
);
})}
</TableBodyRowContainer>
);
}
}

View File

@@ -0,0 +1,185 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
import {
TableColumnKeys,
TableColumnSizes,
TableOnAddFilter,
TableBodyRow,
} from './types';
import React from 'react';
import FilterRow from '../filter/FilterRow';
import styled from 'react-emotion';
import FlexRow from '../FlexRow';
import {colors} from '../colors';
import {normaliseColumnWidth} from './utils';
import {DEFAULT_ROW_HEIGHT} from './types';
import {
FontWeightProperty,
ColorProperty,
JustifyContentProperty,
BackgroundColorProperty,
} from 'csstype';
type TableBodyRowContainerProps = {
even?: boolean;
zebra?: boolean;
highlighted?: boolean;
rowLineHeight?: number;
multiline?: boolean;
fontWeight?: FontWeightProperty;
color?: ColorProperty;
highlightOnHover?: boolean;
backgroundColor?: BackgroundColorProperty;
highlightedBackgroundColor?: BackgroundColorProperty;
};
const backgroundColor = (props: TableBodyRowContainerProps) => {
if (props.highlighted) {
if (props.highlightedBackgroundColor) {
return props.highlightedBackgroundColor;
} else {
return colors.macOSTitleBarIconSelected;
}
} else {
if (props.backgroundColor) {
return props.backgroundColor;
} else if (props.even && props.zebra) {
return colors.light02;
} else {
return 'transparent';
}
}
};
const TableBodyRowContainer = styled(FlexRow)(
(props: TableBodyRowContainerProps) => ({
backgroundColor: backgroundColor(props),
boxShadow: props.zebra ? 'none' : 'inset 0 -1px #E9EBEE',
color: props.highlighted ? colors.white : props.color || 'inherit',
'& *': {
color: props.highlighted ? `${colors.white} !important` : null,
},
'& img': {
backgroundColor: props.highlighted
? `${colors.white} !important`
: 'none',
},
height: props.multiline ? 'auto' : props.rowLineHeight,
lineHeight: `${String(props.rowLineHeight || DEFAULT_ROW_HEIGHT)}px`,
fontWeight: props.fontWeight || 'inherit',
overflow: 'hidden',
width: '100%',
userSelect: 'none',
flexShrink: 0,
'&:hover': {
backgroundColor:
!props.highlighted && props.highlightOnHover ? colors.light02 : 'none',
},
}),
);
const TableBodyColumnContainer = styled('div')(
(props: {
width?: any;
multiline?: boolean;
justifyContent: JustifyContentProperty;
}) => ({
display: 'flex',
flexShrink: props.width === 'flex' ? 1 : 0,
overflow: 'hidden',
padding: '0 8px',
userSelect: 'none',
textOverflow: 'ellipsis',
verticalAlign: 'top',
whiteSpace: props.multiline ? 'normal' : 'nowrap',
wordWrap: props.multiline ? 'break-word' : 'normal',
width: props.width === 'flex' ? '100%' : props.width,
maxWidth: '100%',
justifyContent: props.justifyContent,
}),
);
type Props = {
columnSizes: TableColumnSizes;
columnKeys: TableColumnKeys;
onMouseDown: (e: React.MouseEvent) => any;
onMouseEnter?: (e: React.MouseEvent) => void;
multiline?: boolean;
rowLineHeight: number;
highlighted: boolean;
row: TableBodyRow;
index: number;
style?: React.CSSProperties | null;
onAddFilter?: TableOnAddFilter;
zebra?: boolean;
};
export default class TableRow extends React.PureComponent<Props> {
static defaultProps = {
zebra: true,
};
render() {
const {
index,
highlighted,
rowLineHeight,
row,
style,
multiline,
columnKeys,
columnSizes,
onMouseEnter,
onMouseDown,
zebra,
onAddFilter,
} = this.props;
return (
<TableBodyRowContainer
rowLineHeight={rowLineHeight}
highlightedBackgroundColor={row.highlightedBackgroundColor}
backgroundColor={row.backgroundColor}
highlighted={highlighted}
multiline={multiline}
even={index % 2 === 0}
zebra={zebra}
onMouseDown={onMouseDown}
onMouseEnter={onMouseEnter}
style={style}
highlightOnHover={row.highlightOnHover}
data-key={row.key}
{...row.style}>
{columnKeys.map(key => {
const col = row.columns[key];
const isFilterable = Boolean(col && col.isFilterable);
const value = col && col.value ? col.value : null;
const title = col && col.title ? col.title : null;
return (
<TableBodyColumnContainer
key={key}
title={title}
multiline={multiline}
justifyContent={col && col.align ? col.align : 'flex-start'}
width={normaliseColumnWidth(columnSizes[key])}>
{isFilterable && onAddFilter != null ? (
<FilterRow addFilter={onAddFilter} filterKey={key}>
{value}
</FilterRow>
) : (
value
)}
</TableBodyColumnContainer>
);
})}
</TableBodyRowContainer>
);
}
}

View File

@@ -5,24 +5,25 @@
* @format
*/
import {default as styled} from 'react-emotion';
import {colors} from '../colors.tsx';
import {default as Text} from '../Text.tsx';
import {colors} from '../colors';
import {default as Text} from '../Text';
import React from 'react';
export type Value =
| {
type: 'string',
value: string,
type: 'string';
value: string;
}
| {
type: 'boolean',
value: boolean,
type: 'boolean';
value: boolean;
}
| {
type: 'integer' | 'float' | 'double' | 'number',
value: number,
type: 'integer' | 'float' | 'double' | 'number';
value: number;
}
| {
type: 'null',
type: 'null';
};
const NonWrappingText = styled(Text)({
@@ -32,7 +33,7 @@ const NonWrappingText = styled(Text)({
userSelect: 'none',
});
const BooleanValue = styled(NonWrappingText)(props => ({
const BooleanValue = styled(NonWrappingText)((props: {active?: boolean}) => ({
'&::before': {
content: '""',
display: 'inline-block',
@@ -63,6 +64,6 @@ export function renderValue(val: Value) {
case 'null':
return <NonWrappingText>NULL</NonWrappingText>;
default:
return <NonWrappingText>{val.value}</NonWrappingText>;
return <NonWrappingText />;
}
}

View File

@@ -5,23 +5,23 @@
* @format
*/
import type {Filter} from '../filter/types.tsx';
import {Filter} from '../filter/types';
import {List} from 'immutable';
import {BackgroundColorProperty} from 'csstype';
export const MINIMUM_COLUMN_WIDTH = 100;
export const DEFAULT_COLUMN_WIDTH = 200;
export const DEFAULT_ROW_HEIGHT = 23;
export type TableColumnOrderVal = {
key: string,
visible: boolean,
key: string;
visible: boolean;
};
export type TableColumnOrder = Array<TableColumnOrderVal>;
export type TableColumnSizes = {
[key: string]: string | number,
[key: string]: string | number;
};
export type TableHighlightedRows = Array<string>;
@@ -33,55 +33,55 @@ export type TableOnColumnOrder = (order: TableColumnOrder) => void;
export type TableOnSort = (order: TableRowSortOrder) => void;
export type TableOnHighlight = (
highlightedRows: TableHighlightedRows,
e: SyntheticUIEvent<>,
e: React.UIEvent,
) => void;
export type TableHeaderColumn = {|
value: string,
sortable?: boolean,
resizable?: boolean,
|};
export type TableHeaderColumn = {
value: string;
sortable?: boolean;
resizable?: boolean;
};
export type TableBodyRow = {|
key: string,
height?: ?number,
filterValue?: ?string,
backgroundColor?: ?string,
sortKey?: string | number,
style?: Object,
type?: ?string,
highlightedBackgroundColor?: ?string,
onDoubleClick?: (e: SyntheticMouseEvent<>) => void,
copyText?: string,
highlightOnHover?: boolean,
export type TableBodyRow = {
key: string;
height?: number | null | undefined;
filterValue?: string | null | undefined;
backgroundColor?: string | null | undefined;
sortKey?: string | number;
style?: Object;
type?: string | null | undefined;
highlightedBackgroundColor?: BackgroundColorProperty | null | undefined;
onDoubleClick?: (e: React.MouseEvent) => void;
copyText?: string;
highlightOnHover?: boolean;
columns: {
[key: string]: TableBodyColumn,
},
|};
[key: string]: TableBodyColumn;
};
};
export type TableBodyColumn = {|
sortValue?: string | number,
isFilterable?: boolean,
value: any,
align?: 'left' | 'center' | 'right' | 'flex-start' | 'flex-end',
title?: string,
|};
export type TableBodyColumn = {
sortValue?: string | number;
isFilterable?: boolean;
value: any;
align?: 'left' | 'center' | 'right' | 'flex-start' | 'flex-end';
title?: string;
};
export type TableColumns = {
[key: string]: TableHeaderColumn,
[key: string]: TableHeaderColumn;
};
export type TableRows = Array<TableBodyRow>;
export type TableRows_immutable = List<TableBodyRow>;
export type TableRowSortOrder = {|
key: string,
direction: 'up' | 'down',
|};
export type TableRowSortOrder = {
key: string;
direction: 'up' | 'down';
};
export type TableOnDragSelect = (
e: SyntheticMouseEvent<>,
e: React.MouseEvent,
key: string,
index: number,
) => void;

View File

@@ -6,7 +6,7 @@
*/
export function normaliseColumnWidth(
width: void | string | number,
width: string | number | null | undefined,
): number | string {
if (width == null || width === 'flex') {
// default
@@ -26,6 +26,6 @@ export function normaliseColumnWidth(
throw new TypeError(`Unknown value ${width} for table column width`);
}
export function isPercentage(width: mixed): boolean {
export function isPercentage(width: any): boolean {
return typeof width === 'string' && width[width.length - 1] === '%';
}

View File

@@ -38,18 +38,18 @@ export type {
TableColumnOrder,
TableColumnOrderVal,
TableColumnSizes,
} from './components/table/types.js';
export {default as ManagedTable} from './components/table/ManagedTable.js';
export type {ManagedTableProps} from './components/table/ManagedTable.js';
} from './components/table/types.tsx';
export {default as ManagedTable} from './components/table/ManagedTable.tsx';
export type {ManagedTableProps} from './components/table/ManagedTable.tsx';
export {
default as ManagedTable_immutable,
} from './components/table/ManagedTable_immutable.js';
} from './components/table/ManagedTable_immutable.tsx';
export type {
ManagedTableProps_immutable,
} from './components/table/ManagedTable_immutable.js';
} from './components/table/ManagedTable_immutable.tsx';
export type {Value} from './components/table/TypeBasedValueRenderer.js';
export {renderValue} from './components/table/TypeBasedValueRenderer.js';
export type {Value} from './components/table/TypeBasedValueRenderer.tsx';
export {renderValue} from './components/table/TypeBasedValueRenderer.tsx';
//
export type {

View File

@@ -16,6 +16,6 @@
"flipper": ["./src/index.js"]
}
},
"include": ["src/**/*", "types/globals.tsx", "types/nodejs.tsx"],
"include": ["src/**/*", "types/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}

View File

@@ -0,0 +1,18 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
declare module 'react-debounce-render' {
export default function<P>(
component: React.ComponentType<P>,
maxWait: number,
options: {
maxWait?: number;
leading?: boolean;
trailing?: boolean;
},
): React.ComponentType<P & {ref?: (ref: React.RefObject<any>) => void}>;
}

View File

@@ -1185,6 +1185,20 @@
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react-virtualized-auto-sizer@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.0.tgz#fc32f30a8dab527b5816f3a757e1e1d040c8f272"
integrity sha512-NMErdIdSnm2j/7IqMteRiRvRulpjoELnXWUwdbucYCz84xG9PHcoOrr7QfXwB/ku7wd6egiKFrzt/+QK4Imeeg==
dependencies:
"@types/react" "*"
"@types/react-window@^1.8.1":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.1.tgz#6e1ceab2e6f2f78dbf1f774ee0e00f1bb0364bb3"
integrity sha512-V3k1O5cbfZIRa0VVbQ81Ekq/7w42CK1SuiB9U1oPMTxv270D9qUn7rHb3sZoqMkIJFfB1NZxaH7NRDlk+ToDsg==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.8.24":
version "16.8.24"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.24.tgz#8d1ea1fcbfa214220da3d3c04e506f1077b0deac"