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": "^16.8.24",
"@types/react-dom": "^16.8.5", "@types/react-dom": "^16.8.5",
"@types/react-redux": "^7.1.1", "@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/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.2", "@types/rsocket-core": "^0.0.2",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,7 +21,7 @@ type Props = {
children: React.ReactNode; children: React.ReactNode;
/** The component that is used to wrap the children. Defaults to `FlexColumn`. */ /** The component that is used to wrap the children. Defaults to `FlexColumn`. */
component: React.ComponentType<any> | string; 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; minLeft?: number;
width?: number | string; width?: number | string;
height?: number | string; height?: number | string;
minWidth: number; minWidth?: number;
minHeight: number; minHeight?: number;
maxWidth?: number; maxWidth?: number;
maxHeight?: number; maxHeight?: number;
onCanResize?: (sides: ResizingSides) => void; onCanResize?: (sides: ResizingSides) => void;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,6 +16,6 @@
"flipper": ["./src/index.js"] "flipper": ["./src/index.js"]
} }
}, },
"include": ["src/**/*", "types/globals.tsx", "types/nodejs.tsx"], "include": ["src/**/*", "types/*"],
"exclude": ["node_modules", "**/*.spec.ts"] "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" hoist-non-react-statics "^3.3.0"
redux "^4.0.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": "@types/react@*", "@types/react@^16.8.24":
version "16.8.24" version "16.8.24"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.24.tgz#8d1ea1fcbfa214220da3d3c04e506f1077b0deac" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.24.tgz#8d1ea1fcbfa214220da3d3c04e506f1077b0deac"