From af59f37b7ebfefcdf738928e66c99aba6514899d Mon Sep 17 00:00:00 2001 From: sgrabar Date: Fri, 31 Aug 2018 11:05:39 +0200 Subject: [PATCH] react-data-grid Add generic ReactDataGrid and proptypes for some Editors * Add generic ReactDataGrid to return actual row type on methods that return rows * Add props for AutoComplete, AutoCompleteTokensEditor and DropDownEditor editors * Add EditorBase class --- types/react-data-grid/index.d.ts | 136 +++- .../react-data-grid/react-data-grid-tests.tsx | 10 +- types/react-data-grid/v1/tsconfig.json | 7 +- types/react-data-grid/v2/index.d.ts | 636 ++++++++++++++++++ .../v2/react-data-grid-tests.tsx | 362 ++++++++++ types/react-data-grid/v2/tsconfig.json | 33 + types/react-data-grid/v2/tslint.json | 80 +++ 7 files changed, 1223 insertions(+), 41 deletions(-) create mode 100644 types/react-data-grid/v2/index.d.ts create mode 100644 types/react-data-grid/v2/react-data-grid-tests.tsx create mode 100644 types/react-data-grid/v2/tsconfig.json create mode 100644 types/react-data-grid/v2/tslint.json diff --git a/types/react-data-grid/index.d.ts b/types/react-data-grid/index.d.ts index bfa4ea979f..02e25e1612 100644 --- a/types/react-data-grid/index.d.ts +++ b/types/react-data-grid/index.d.ts @@ -1,24 +1,43 @@ -// Type definitions for react-data-grid 2.0 +// Type definitions for react-data-grid 3.0 // Project: https://github.com/adazzle/react-data-grid.git -// Definitions by: Simon Gellis , Kieran Peat , Martin Novak +// Definitions by: Simon Gellis , Kieran Peat , Martin Novak , Sebastijan Grabar // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 /// declare namespace AdazzleReactDataGrid { - - interface SelectionParams { - rowIdx: number, - row: any + interface ExcelColumn { + editable: boolean; + name: any; + key: string; + width: number; + resizeable: boolean; + filterable: boolean; } - interface GridProps { + interface EditorBaseProps { + value: any; + column: ExcelColumn; + height: number; + onBlur: () => void; + onCommit: () => void; + onCommitCancel: () => void; + rowData: any; + rowMetaData: any; + } + + interface SelectionParams { + rowIdx: number; + row: T; + } + + interface GridProps { /** * Gets the data to render in each row. Required. * Can be an array or a function that takes an index and returns an object. */ - rowGetter: Array | ((rowIdx: number) => object) + rowGetter: Array | ((rowIdx: number) => T) /** * The total number of rows to render. Required. */ @@ -26,14 +45,14 @@ declare namespace AdazzleReactDataGrid { /** * The columns to render. */ - columns?: Array + columns?: Array> /** * Invoked when the user changes the value of a single cell. * Should update that cell's value. * @param e Information about the event */ - onRowUpdated?: (e: RowUpdateEvent) => void + onRowUpdated?: (e: RowUpdateEvent) => void /** * Invoked when the user pulls down the drag handle of an editable cell. * Should update the values of the selected cells. @@ -45,7 +64,7 @@ declare namespace AdazzleReactDataGrid { * Should update the values of the cells beneath the selected cell. * @param e Information about the event */ - onDragHandleDoubleClick?: (e: DragHandleDoubleClickEvent) => void + onDragHandleDoubleClick?: (e: DragHandleDoubleClickEvent) => void /** * Invoked when the user copies a value from one cell and pastes it into another (in the same column). * Should update the value of the cell in row e.toRow. @@ -56,7 +75,7 @@ declare namespace AdazzleReactDataGrid { * Invoked after the user updates the grid rows in any way. * @param e Information about the event */ - onGridRowsUpdated?: (e: GridRowsUpdatedEvent) => void + onGridRowsUpdated?: (e: GridRowsUpdatedEvent) => void /** * A toolbar to display above the grid. @@ -164,7 +183,7 @@ declare namespace AdazzleReactDataGrid { * Called when a row is selected. * @param rows The (complete) current selection of rows. */ - onRowSelect?: (rows: Array) => void + onRowSelect?: (rows: Array) => void /** * A property that's unique to every row. * This property is required to enable row selection. @@ -206,8 +225,8 @@ declare namespace AdazzleReactDataGrid { rowSelection?: { showCheckbox?: boolean enableShiftSelect?: boolean - onRowsSelected?: (rows: Array) => void, - onRowsDeselected?: (rows: Array) => void, + onRowsSelected?: (rows: Array>) => void, + onRowsDeselected?: (rows: Array>) => void, selectBy?: { indexes?: Array; keys?: { rowKey: string, values: Array }; @@ -230,7 +249,7 @@ declare namespace AdazzleReactDataGrid { * @param rowIdx zero index number of row clicked * @param row object behind the row */ - onRowClick?: (rowIdx : number, row : object) => void + onRowClick?: (rowIdx: number, row: T) => void /** * An event function called when a row is expanded with the toggle @@ -246,12 +265,12 @@ declare namespace AdazzleReactDataGrid { */ getValidFilterValues?: (columnKey: string) => Array - getCellActions?: (column: Column, row: object) => (ActionButton | ActionMenu)[] + getCellActions?: (column: Column, row: T) => (ActionButton | ActionMenu)[] } type ActionButton = { icon: string; - callback: () => void; + callback: () => void; } type ActionMenu = { @@ -266,7 +285,7 @@ declare namespace AdazzleReactDataGrid { /** * Information about a specific column to be rendered. */ - interface Column { + interface Column { /** * A unique key for this column. Required. * Each row should have a property with this name, which contains this column's value. @@ -314,7 +333,10 @@ declare namespace AdazzleReactDataGrid { * The editor for this column. Several editors are available in "react-data-grid/addons". * @default A simple text editor */ - editor?: React.ReactElement | React.ComponentClass | React.StatelessComponent + editor?: + | React.ReactElement + | React.ComponentClass + | React.StatelessComponent; /** * A custom read-only formatter for this column. An image formatter is available in "react-data-grid/addons". */ @@ -331,11 +353,11 @@ declare namespace AdazzleReactDataGrid { */ events?: { [name: string]: ColumnEventCallback - } + }; /** * Retrieve meta data about the row, optionally provide column as a second argument */ - getRowMetaData?: (rowdata: any, column?: Column) => any; + getRowMetaData?: (rowdata: T, column?: Column) => any; /** * A class name to be applied to the cells in the column */ @@ -359,7 +381,7 @@ declare namespace AdazzleReactDataGrid { /** * Information about a row update */ - interface RowUpdateEvent { + interface RowUpdateEvent { /** * The index of the updated row. */ @@ -367,7 +389,7 @@ declare namespace AdazzleReactDataGrid { /** * The columns that were updated and their values. */ - updated: object + updated: T /** * The name of the column that was updated. */ @@ -403,7 +425,7 @@ declare namespace AdazzleReactDataGrid { /** * Information about a drag handle double click */ - interface DragHandleDoubleClickEvent { + interface DragHandleDoubleClickEvent { /** * The row where the double click occurred. */ @@ -415,7 +437,7 @@ declare namespace AdazzleReactDataGrid { /** * The values of the row. */ - rowData: object + rowData: T /** * The double click event. */ @@ -451,7 +473,7 @@ declare namespace AdazzleReactDataGrid { /** * Information about some update to the grid's contents */ - interface GridRowsUpdatedEvent { + interface GridRowsUpdatedEvent { /** * The key of the column where the event occurred. */ @@ -467,7 +489,7 @@ declare namespace AdazzleReactDataGrid { /** * The columns that were updated and their values. */ - updated: object + updated: T /** * The action that occurred to trigger this event. * One of 'cellUpdate', 'cellDrag', 'columnFill', or 'copyPaste'. @@ -511,7 +533,7 @@ declare namespace AdazzleReactDataGrid { * Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like * http://adazzle.github.io/react-data-grid/ */ - export class ReactDataGrid extends React.Component { + export class ReactDataGrid extends React.Component> { /** * Opens the editor for the cell (idx) in the given row (rowIdx). If the column is not editable then nothing will happen. */ @@ -531,6 +553,18 @@ declare namespace AdazzleReactDataGrid { export import GridRowsUpdatedEvent = AdazzleReactDataGrid.GridRowsUpdatedEvent; export import OnRowExpandToggle = AdazzleReactDataGrid.OnRowExpandToggle; + export namespace editors { + class EditorBase extends React.Component { + getStyle(): { width: string }; + + getValue(): any; + + getInputNode(): Element | null | Text; + + inheritContainerStyles(): boolean; + } + } + // Actual classes exposed on module.exports /** * A react component that renders a row of the grid @@ -544,12 +578,46 @@ declare namespace AdazzleReactDataGrid { } declare namespace AdazzleReactDataGridPlugins { - // TODO: refine types for these addons + interface AutoCompleteEditorProps { + onCommit?: () => void; + options?: Array<{ id: number; title: string }>; + label?: any; + value?: any; + height?: number; + valueParams?: string[]; + column?: AdazzleReactDataGrid.ExcelColumn; + resultIdentifier?: string; + search?: string; + onKeyDown?: () => void; + onFocus?: () => void; + editorDisplayValue?: (column: AdazzleReactDataGrid.ExcelColumn, value: any) => string; + } + + interface AutoCompleteTokensEditorProps { + options: Array | Array<{ id: number; caption: string }>; + column?: AdazzleReactDataGrid.ExcelColumn; + value?: any[]; + } + + interface DropDownEditorProps { + options: + | Array + | Array<{ + id: string; + title: string; + value: string; + text: string; + }>; + } + export namespace Editors { - export class AutoComplete extends React.Component { } - export class DropDownEditor extends React.Component { } - export class SimpleTextEditor extends React.Component { } - export class CheckboxEditor extends React.Component { } + export class AutoComplete extends React.Component {} + export class AutoCompleteTokensEditor extends React.Component {} + export class DropDownEditor extends React.Component {} + + // TODO: refine types for these addons + export class SimpleTextEditor extends React.Component {} + export class CheckboxEditor extends React.Component {} } export namespace Filters { export class NumericFilter extends React.Component { } diff --git a/types/react-data-grid/react-data-grid-tests.tsx b/types/react-data-grid/react-data-grid-tests.tsx index aa09041846..201e53a3ca 100644 --- a/types/react-data-grid/react-data-grid-tests.tsx +++ b/types/react-data-grid/react-data-grid-tests.tsx @@ -131,7 +131,7 @@ var counties = [ var titles = ['Dr.', 'Mr.', 'Mrs.', 'Miss', 'Ms.']; -var columns:ReactDataGrid.Column[] = [ +var columns:ReactDataGrid.Column[] = [ { key: 'id', name: 'ID', @@ -152,7 +152,7 @@ var columns:ReactDataGrid.Column[] = [ editor: , width: 200, resizable: true, - getRowMetaData: (rowdata: any, column: ReactDataGrid.Column) => { + getRowMetaData: (rowdata: any, column: ReactDataGrid.Column) => { return {}; } }, @@ -262,7 +262,7 @@ class Example extends React.Component { return clonedColumns; } - handleGridRowsUpdated(updatedRowData:ReactDataGrid.GridRowsUpdatedEvent) { + handleGridRowsUpdated(updatedRowData:ReactDataGrid.GridRowsUpdatedEvent) { var rows = this.state.rows; for (var i = updatedRowData.fromRow; i <= updatedRowData.toRow; i++) { @@ -315,12 +315,12 @@ class Example extends React.Component { return this.state.rows.length; } - onRowsSelected(rows: Array) { + onRowsSelected(rows: Array>) { var selectedIndexes = this.state.selectedIndexes as Array; this.setState({selectedIndexes: selectedIndexes.concat(rows.map(r => r.rowIdx))}); } - onRowsDeselected(rows: Array) { + onRowsDeselected(rows: Array>) { var rowIndexes = rows.map(r => r.rowIdx); var selectedIndexes = this.state.selectedIndexes as Array; this.setState({selectedIndexes: selectedIndexes.filter(i => rowIndexes.indexOf(i) === -1 )}); diff --git a/types/react-data-grid/v1/tsconfig.json b/types/react-data-grid/v1/tsconfig.json index c2602fd049..6919c8eb55 100644 --- a/types/react-data-grid/v1/tsconfig.json +++ b/types/react-data-grid/v1/tsconfig.json @@ -20,11 +20,14 @@ "paths": { "react-data-grid": [ "react-data-grid/v1" - ] + ], + "react-data-grid/*": [ + "react-data-grid/v1/*" + ] } }, "files": [ "index.d.ts", "react-data-grid-tests.tsx" ] -} \ No newline at end of file +} diff --git a/types/react-data-grid/v2/index.d.ts b/types/react-data-grid/v2/index.d.ts new file mode 100644 index 0000000000..bfa4ea979f --- /dev/null +++ b/types/react-data-grid/v2/index.d.ts @@ -0,0 +1,636 @@ +// Type definitions for react-data-grid 2.0 +// Project: https://github.com/adazzle/react-data-grid.git +// Definitions by: Simon Gellis , Kieran Peat , Martin Novak +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +/// + +declare namespace AdazzleReactDataGrid { + + interface SelectionParams { + rowIdx: number, + row: any + } + + interface GridProps { + /** + * Gets the data to render in each row. Required. + * Can be an array or a function that takes an index and returns an object. + */ + rowGetter: Array | ((rowIdx: number) => object) + /** + * The total number of rows to render. Required. + */ + rowsCount: number + /** + * The columns to render. + */ + columns?: Array + + /** + * Invoked when the user changes the value of a single cell. + * Should update that cell's value. + * @param e Information about the event + */ + onRowUpdated?: (e: RowUpdateEvent) => void + /** + * Invoked when the user pulls down the drag handle of an editable cell. + * Should update the values of the selected cells. + * @param e Information about the event + */ + onCellsDragged?: (e: CellDragEvent) => void + /** + * Invoked when the user double clicks on the drag handle of an editable cell. + * Should update the values of the cells beneath the selected cell. + * @param e Information about the event + */ + onDragHandleDoubleClick?: (e: DragHandleDoubleClickEvent) => void + /** + * Invoked when the user copies a value from one cell and pastes it into another (in the same column). + * Should update the value of the cell in row e.toRow. + * @param e Information about the event + */ + onCellCopyPaste?: (e: CellCopyPasteEvent) => void + /** + * Invoked after the user updates the grid rows in any way. + * @param e Information about the event + */ + onGridRowsUpdated?: (e: GridRowsUpdatedEvent) => void + + /** + * A toolbar to display above the grid. + * Consider using the toolbar included in "react-data-grid/addons". + */ + toolbar?: React.ReactElement + /** + * A context menu to disiplay when the user right-clicks a cell. + * Consider using "react-contextmenu", included in "react-data-grid/addons". + */ + contextMenu?: React.ReactElement + /** + * A react component to customize how rows are rendered. + * If you want to define your own, consider extending ReactDataGrid.Row. + */ + rowRenderer?: React.ReactElement | React.ComponentClass | React.StatelessComponent + /** + * A component to display when there are no rows to render. + */ + emptyRowsView?: React.ComponentClass | React.StatelessComponent + + /** + * The minimum width of the entire grid in pixels. + */ + minWidth?: number + /** + * The minimum height of the entire grid in pixels. + * @default 350 + */ + minHeight?: number + /** + * The height of each individual row in pixels. + * @default 35 + */ + rowHeight?: number + /** + * The height of the header row in pixels. + * @default rowHeight + */ + headerRowHeight?: number + /** + * The height of the header filter row in pixels. + * @default 45 + */ + headerFiltersHeight?: number + /** + * The minimum width of each column in pixels. + * @default 80 + */ + minColumnWidth?: number + /** + * Invoked when a column has been resized. + * @param index The index of the column + * @param width The new width of the column + */ + onColumnResize?: (index: number, width: number) => void + + /** + * Controls what happens when the user navigates beyond the first or last cells. + * 'loopOverRow' will navigate to the beginning/end of the current row. + * 'changeRow' will navigate to the beginning of the next row or the end of the last. + * 'none' will do nothing. + * @default none + */ + cellNavigationMode?: 'none' | 'loopOverRow' | 'changeRow' + + /** + * Called when the user sorts the grid by some column. + * Should update the order of the rows returned by rowGetter. + * @param sortColumn The name of the column being sorted by + * @param sortDirection The direction to sort ('ASC'/'DESC'/'NONE') + */ + onGridSort?: (sortColumn: string, sortDirection: 'ASC' | 'DESC' | 'NONE') => void + + /** + * Initial sorting direction + */ + sortDirection?: 'ASC' | 'DESC' | 'NONE' + + /** + * key of the initial sorted column + */ + sortColumn?: string + + /** + * Called when the user filters a column by some value. + * Should restrict the rows in rowGetter to only things that match the filter. + * @param filter The filter being added + */ + onAddFilter?: (filter: Filter) => void + /** + * Called when the user clears all filters. + * Should restore the rows in rowGetter to their original state. + */ + onClearFilters?: () => void + + /** + * When set to true or 'multi', enables multiple row select. + * When set to 'single', enables single row select. + * When set to false or not set, disables row select. + * @default false + */ + enableRowSelect?: boolean | 'single' | 'multi' + /** + * Called when a row is selected. + * @param rows The (complete) current selection of rows. + */ + onRowSelect?: (rows: Array) => void + /** + * A property that's unique to every row. + * This property is required to enable row selection. + * @default 'id' + */ + rowKey?: string + + /** + * Enables cells to be selected when clicked. + * @default false + */ + enableCellSelect?: boolean + + /** + * Enables cells to be dragged and dropped + * @default false + */ + enableDragAndDrop?: boolean + + /** + * Called when a cell is selected. + * @param coordinates The row and column indices of the selected cell. + */ + onCellSelected?: (coordinates: {rowIdx: number, idx: number}) => void + /** + * Called when a cell is deselected. + * @param coordinates The row and column indices of the deselected cell. + */ + onCellDeSelected?: (coordinates: {rowIdx: number, idx: number}) => void + + /** + * How long to wait before rendering a new row while scrolling in milliseconds. + * @default 0 + */ + rowScrollTimeout?: number + /** + * Options object for selecting rows + */ + rowSelection?: { + showCheckbox?: boolean + enableShiftSelect?: boolean + onRowsSelected?: (rows: Array) => void, + onRowsDeselected?: (rows: Array) => void, + selectBy?: { + indexes?: Array; + keys?: { rowKey: string, values: Array }; + isSelectedKey?: string; + } + } + /** + * A custom formatter for the select all checkbox cell + * @default react-data-grid/src/formatters/SelectAll.js + */ + selectAllRenderer?: React.ComponentClass | React.StatelessComponent; + /** + * A custom formatter for select row column + * @default AdazzleReactDataGridPlugins.Editors.CheckboxEditor + */ + rowActionsCell?: React.ComponentClass | React.StatelessComponent; + /** + * An event function called when a row is clicked. + * Clicking the header row will trigger a call with -1 for the rowIdx. + * @param rowIdx zero index number of row clicked + * @param row object behind the row + */ + onRowClick?: (rowIdx : number, row : object) => void + + /** + * An event function called when a row is expanded with the toggle + * @param props OnRowExpandToggle object + */ + onRowExpandToggle?: (props: OnRowExpandToggle ) => void + + /** + * Responsible for returning an Array of values that can be used for filtering + * a column that is column.filterable and using a column.filterRenderer that + * displays a list of options. + * @param columnKey the column key that we are looking to pull values from + */ + getValidFilterValues?: (columnKey: string) => Array + + getCellActions?: (column: Column, row: object) => (ActionButton | ActionMenu)[] + } + + type ActionButton = { + icon: string; + callback: () => void; + } + + type ActionMenu = { + icon: string; + actions: { + icon: string; + text: string; + callback: () => void; + }[]; + } + + /** + * Information about a specific column to be rendered. + */ + interface Column { + /** + * A unique key for this column. Required. + * Each row should have a property with this name, which contains this column's value. + */ + key: string + /** + * This column's display name. Required. + */ + name: string + /** + * A custom width for this specific column. + * @default minColumnWidth from the ReactDataGrid + */ + width?: number + /** + * Whether this column can be resized by the user. + * @default false + */ + resizable?: boolean + /** + * Whether this column should stay fixed on the left as the user scrolls horizontally. + * @default false + */ + locked?: boolean + /** + * Whether this column can be edited. + * @default false + */ + editable?: boolean + /** + * Whether the rows in the grid can be sorted by this column. + * @default false + */ + sortable?: boolean + /** + * Whether the rows in the grid can be filtered by this column. + * @default false + */ + filterable?: boolean; + /** + * A custom formatter for this column's filter. + */ + filterRenderer?: React.ReactElement | React.ComponentClass | React.StatelessComponent; + /** + * The editor for this column. Several editors are available in "react-data-grid/addons". + * @default A simple text editor + */ + editor?: React.ReactElement | React.ComponentClass | React.StatelessComponent + /** + * A custom read-only formatter for this column. An image formatter is available in "react-data-grid/addons". + */ + formatter?: React.ReactElement | React.ComponentClass | React.StatelessComponent + /** + * A custom formatter for this column's header. + */ + headerRenderer?: React.ReactElement | React.ComponentClass | React.StatelessComponent + /** + * Events to be bound to the cells in this specific column. + * Each event must respect this standard in order to work correctly: + * @example + * function onXxx(ev :SyntheticEvent, (rowIdx, idx, name): args) + */ + events?: { + [name: string]: ColumnEventCallback + } + /** + * Retrieve meta data about the row, optionally provide column as a second argument + */ + getRowMetaData?: (rowdata: any, column?: Column) => any; + /** + * A class name to be applied to the cells in the column + */ + cellClass?: string; + /** + * Whether this column can be dragged (re-arranged). + * @default false + */ + draggable?: boolean; + } + + interface ColumnEventCallback { + /** + * A callback for a native react event on a specific cell. + * @param ev The react event + * @param args The row and column coordinates of the cell, and the name of the event. + */ + (ev: React.SyntheticEvent, args: {rowIdx: number, idx: number, name: string}): void + } + + /** + * Information about a row update + */ + interface RowUpdateEvent { + /** + * The index of the updated row. + */ + rowIdx: number + /** + * The columns that were updated and their values. + */ + updated: object + /** + * The name of the column that was updated. + */ + cellKey: string + /** + * The name of the key pressed to trigger the event ('Tab', 'Enter', etc.). + */ + key: string + } + + /** + * Information about a cell drag + */ + interface CellDragEvent { + /** + * The name of the column that was dragged. + */ + cellKey: string + /** + * The row where the drag began. + */ + fromRow: number + /** + * The row where the drag ended. + */ + toRow: number + /** + * The value of the cell that was dragged. + */ + value: any + } + + /** + * Information about a drag handle double click + */ + interface DragHandleDoubleClickEvent { + /** + * The row where the double click occurred. + */ + rowIdx: number + /** + * The column where the double click occurred. + */ + idx: number + /** + * The values of the row. + */ + rowData: object + /** + * The double click event. + */ + e: React.SyntheticEvent + } + + /** + * Information about a copy paste + */ + interface CellCopyPasteEvent { + /** + * The row that was pasted to. + */ + rowIdx: number + /** + * The value that was pasted. + */ + value: any + /** + * The row that was copied from. + */ + fromRow: number + /** + * The row that was pasted to. + */ + toRow: number + /** + * The key of the column where the copy paste occurred. + */ + cellKey: string + } + + /** + * Information about some update to the grid's contents + */ + interface GridRowsUpdatedEvent { + /** + * The key of the column where the event occurred. + */ + cellKey: string + /** + * The top row affected by the event. + */ + fromRow: number + /** + * The bottom row affected by the event. + */ + toRow: number + /** + * The columns that were updated and their values. + */ + updated: object + /** + * The action that occurred to trigger this event. + * One of 'cellUpdate', 'cellDrag', 'columnFill', or 'copyPaste'. + */ + action: 'cellUpdate' | 'cellDrag' | 'columnFill' | 'copyPaste' + } + + /** + * Information about the row toggler + */ + interface OnRowExpandToggle { + /** + * The name of the column group the row is in + */ + columnGroupName: string + /** + * The name of the expanded row + */ + name: string + /** + * If it should expand or not + */ + shouldExpand: boolean + } + + /** + * Some filter to be applied to the grid's contents + */ + interface Filter { + /** + * The key of the column being filtered. + */ + columnKey: string + /** + * The term to filter by. + */ + filterTerm: string + } + + /** + * Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like + * http://adazzle.github.io/react-data-grid/ + */ + export class ReactDataGrid extends React.Component { + /** + * Opens the editor for the cell (idx) in the given row (rowIdx). If the column is not editable then nothing will happen. + */ + openCellEditor(rowIdx: number, idx: number): void; + } + export namespace ReactDataGrid { + // Useful types + export import Column = AdazzleReactDataGrid.Column; + export import Filter = AdazzleReactDataGrid.Filter; + + // Various events + export import RowUpdateEvent = AdazzleReactDataGrid.RowUpdateEvent; + export import SelectionParams = AdazzleReactDataGrid.SelectionParams; + export import CellDragEvent = AdazzleReactDataGrid.CellDragEvent; + export import DragHandleDoubleClickEvent = AdazzleReactDataGrid.DragHandleDoubleClickEvent; + export import CellCopyPasteEvent = AdazzleReactDataGrid.CellCopyPasteEvent; + export import GridRowsUpdatedEvent = AdazzleReactDataGrid.GridRowsUpdatedEvent; + export import OnRowExpandToggle = AdazzleReactDataGrid.OnRowExpandToggle; + + // Actual classes exposed on module.exports + /** + * A react component that renders a row of the grid + */ + export class Row extends React.Component { } + /** + * A react coponent that renders a cell of the grid + */ + export class Cell extends React.Component { } + } +} + +declare namespace AdazzleReactDataGridPlugins { + // TODO: refine types for these addons + export namespace Editors { + export class AutoComplete extends React.Component { } + export class DropDownEditor extends React.Component { } + export class SimpleTextEditor extends React.Component { } + export class CheckboxEditor extends React.Component { } + } + export namespace Filters { + export class NumericFilter extends React.Component { } + export class AutoCompleteFilter extends React.Component { } + export class MultiSelectFilter extends React.Component { } + export class SingleSelectFilter extends React.Component { } + } + export namespace Formatters { + export class ImageFormatter extends React.Component { } + export class DropDownFormatter extends React.Component { } + } + export class Toolbar extends React.Component {} + export namespace DraggableHeader { + export class DraggableContainer extends React.Component{ } + } + export namespace Data { + export const Selectors: { + getRows: (state: object) => object[]; + getSelectedRowsByKey: (state: object) => object[]; + } + } + // TODO: re-export the react-contextmenu typings once those exist + // https://github.com/vkbansal/react-contextmenu/issues/10 + export namespace Menu { + export class ContextMenu extends React.Component { } + export class MenuHeader extends React.Component { } + export class MenuItem extends React.Component { } + export class SubMenu extends React.Component { } + export const monitor: { + getItem(): any + getPosition(): any + hideMenu(): void + }; + export function connect(Menu: any): any; + export function ContextMenuLayer( + identifier: any, + configure?: (props: any) => any + ): (Component: any) => any + } +} + +declare module "react-data-grid" { + import ReactDataGrid = AdazzleReactDataGrid.ReactDataGrid; + + // commonjs export + export = ReactDataGrid; +} + +declare module "react-data-grid-addons" { + import Plugins = AdazzleReactDataGridPlugins; + import Editors = Plugins.Editors; + import Filters = Plugins.Filters; + import Formatters = Plugins.Formatters; + import Toolbar = Plugins.Toolbar; + import Menu = Plugins.Menu; + import Data = Plugins.Data; + import DraggableHeader = Plugins.DraggableHeader; + + // ES6 named exports + export { + Editors, + Filters, + Formatters, + Toolbar, + Menu, + Data, + DraggableHeader + } + + // attach to window + global { + interface Window { + ReactDataGridPlugins: { + Editors: typeof Editors, + Filters: typeof Filters, + Formatters: typeof Formatters, + Toolbar: typeof Toolbar, + Menu: typeof Menu, + Data: typeof Data, + DraggableHeader: typeof DraggableHeader + } + } + } +} diff --git a/types/react-data-grid/v2/react-data-grid-tests.tsx b/types/react-data-grid/v2/react-data-grid-tests.tsx new file mode 100644 index 0000000000..aa09041846 --- /dev/null +++ b/types/react-data-grid/v2/react-data-grid-tests.tsx @@ -0,0 +1,362 @@ +import * as React from 'react'; +import ReactDataGrid = require('react-data-grid'); +import * as ReactDataGridPlugins from 'react-data-grid-addons'; +import faker = require('faker'); + +var Editors = ReactDataGridPlugins.Editors; +var Toolbar = ReactDataGridPlugins.Toolbar; +var AutoCompleteEditor = Editors.AutoComplete; +var DropDownEditor = Editors.DropDownEditor; +var { Selectors } = ReactDataGridPlugins.Data; + +class CustomFilterHeaderCell extends React.Component { + state = { + filterTerm: "" + }; + handleChange(e: any) { + let val = e.target.value; + this.setState({filterTerm: val}); + this.props.onChange({filterTerm: val, column: this.props.column}); + } + render() { + return ( +
+ this.handleChange(e)} /> +
+ ); + } +} + +class CustomRowSelectorCell extends ReactDataGridPlugins.Editors.CheckboxEditor { + render(){ + return super.render(); + } +} + +export interface ICustomSelectAllProps { + onChange: any; + inputRef: any; +} + +class CustomSelectAll extends React.Component { + render() { + return ( +
+ + +
+ ); + } +} + +faker.locale = 'en_GB'; + +function createFakeRowObjectData(index:number):Object { + return { + id: 'id_' + index, + avartar: faker.image.avatar(), + county: faker.address.county(), + email: faker.internet.email(), + title: faker.name.prefix(), + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + street: faker.address.streetName(), + zipCode: faker.address.zipCode(), + date: faker.date.past().toLocaleDateString(), + bs: faker.company.bs(), + catchPhrase: faker.company.catchPhrase(), + companyName: faker.company.companyName(), + words: faker.lorem.words(), + sentence: faker.lorem.sentence() + }; +} + +function createRows(numberOfRows:number) { + var rows:Object[] = []; + for (var i = 0; i < numberOfRows; i++) { + rows[i] = createFakeRowObjectData(i); + } + return rows; +} + +var counties = [ + {id: 0, title: 'Bedfordshire'}, + {id: 1, title: 'Berkshire'}, + {id: 2, title: 'Buckinghamshire'}, + {id: 3, title: 'Cambridgeshire'}, + {id: 4, title: 'Cheshire'}, + {id: 5, title: 'Cornwall'}, + {id: 6, title: 'Cumbria, (Cumberland)'}, + {id: 7, title: 'Derbyshire'}, + {id: 8, title: 'Devon'}, + {id: 9, title: 'Dorset'}, + {id: 10, title: 'Durham'}, + {id: 11, title: 'Essex'}, + {id: 12, title: 'Gloucestershire'}, + {id: 13, title: 'Hampshire'}, + {id: 14, title: 'Hertfordshire'}, + {id: 15, title: 'Huntingdonshire'}, + {id: 16, title: 'Kent'}, + {id: 17, title: 'Lancashire'}, + {id: 18, title: 'Leicestershire'}, + {id: 19, title: 'Lincolnshire'}, + {id: 20, title: 'Middlesex'}, + {id: 21, title: 'Norfolk'}, + {id: 22, title: 'Northamptonshire'}, + {id: 23, title: 'Northumberland'}, + {id: 24, title: 'Nottinghamshire'}, + {id: 25, title: 'Northamptonshire'}, + {id: 26, title: 'Oxfordshire'}, + {id: 27, title: 'Northamptonshire'}, + {id: 28, title: 'Rutland'}, + {id: 29, title: 'Shropshire'}, + {id: 30, title: 'Somerset'}, + {id: 31, title: 'Staffordshire'}, + {id: 32, title: 'Suffolk'}, + {id: 33, title: 'Surrey'}, + {id: 34, title: 'Sussex'}, + {id: 35, title: 'Warwickshire'}, + {id: 36, title: 'Westmoreland'}, + {id: 37, title: 'Wiltshire'}, + {id: 38, title: 'Worcestershire'}, + {id: 39, title: 'Yorkshire'} +]; + +var titles = ['Dr.', 'Mr.', 'Mrs.', 'Miss', 'Ms.']; + +var columns:ReactDataGrid.Column[] = [ + { + key: 'id', + name: 'ID', + width: 80, + resizable: true + }, + { + key: 'avartar', + name: 'Avartar', + width: 60, + formatter: ReactDataGridPlugins.Formatters.ImageFormatter, + resizable: true, + headerRenderer: + }, + { + key: 'county', + name: 'County', + editor: , + width: 200, + resizable: true, + getRowMetaData: (rowdata: any, column: ReactDataGrid.Column) => { + return {}; + } + }, + { + key: 'title', + name: 'Title', + editor: , + width: 200, + resizable: true, + events: { + onDoubleClick: function () { + console.log("The user double clicked on title column"); + } + } + }, + { + key: 'firstName', + name: 'First Name', + editable: true, + width: 200, + resizable: true + }, + { + key: 'lastName', + name: 'Last Name', + editable: true, + width: 200, + resizable: true + }, + { + key: 'email', + name: 'Email', + editable: true, + width: 200, + resizable: true + }, + { + key: 'street', + name: 'Street', + editable: true, + width: 200, + resizable: true + }, + { + key: 'zipCode', + name: 'ZipCode', + editable: true, + width: 200, + resizable: true + }, + { + key: 'date', + name: 'Date', + editable: true, + width: 200, + resizable: true + }, + { + key: 'bs', + name: 'bs', + editable: true, + width: 200, + resizable: true + }, + { + key: 'catchPhrase', + name: 'Catch Phrase', + editable: true, + width: 200, + resizable: true + }, + { + key: 'companyName', + name: 'Company Name', + editable: true, + width: 200, + resizable: true, + filterable: true, + filterRenderer: CustomFilterHeaderCell + }, + { + key: 'sentence', + name: 'Sentence', + editable: true, + width: 200, + resizable: true, + cellClass: 'sentence-class' + } +]; + +class Example extends React.Component { + getInitialState() { + var fakeRows = createRows(2000); + return {rows: fakeRows}; + } + + getColumns() { + var clonedColumns = columns.slice(); + clonedColumns[2].events = { + onClick: function (ev:React.SyntheticEvent, args:{idx:number, rowIdx:number}) { + var idx = args.idx; + var rowIdx = args.rowIdx; + this.refs.grid.openCellEditor(rowIdx, idx); + }.bind(this) + }; + + return clonedColumns; + } + + handleGridRowsUpdated(updatedRowData:ReactDataGrid.GridRowsUpdatedEvent) { + var rows = this.state.rows; + + for (var i = updatedRowData.fromRow; i <= updatedRowData.toRow; i++) { + var rowToUpdate = rows[i]; + var updatedRow = Object.assign({}, rowToUpdate, updatedRowData.updated); + rows[i] = updatedRow; + } + + this.setState({rows: rows}); + } + + onRowExpandToggle = ({ columnGroupName, name, shouldExpand }:ReactDataGrid.OnRowExpandToggle ) => { + let expandedRows = Object.assign({}, this.state.expandedRows); + expandedRows[columnGroupName] = Object.assign({}, expandedRows[columnGroupName]); + expandedRows[columnGroupName][name] = {isExpanded: shouldExpand}; + this.setState({expandedRows: expandedRows}); + } + + onRowClick(rowIdx:number, row: Object) { + // Do nothing, just test that it accepts an event + } + + getRows() { + const rows = Selectors.getRows(this.state); + console.log(rows); + return rows; + } + + handleAddRow(e:any) { + var newRow = { + value: e.newRowIndex, + userStory: '', + developer: '', + epic: '' + }; + var rows = this.state.rows; + rows.push(newRow); + this.setState({rows: rows}); + } + + getRowAt(index:number) { + this.getRows(); + if (index < 0 || index > this.getSize()) { + return undefined; + } + return this.state.rows[index]; + } + + getSize() { + return this.state.rows.length; + } + + onRowsSelected(rows: Array) { + var selectedIndexes = this.state.selectedIndexes as Array; + + this.setState({selectedIndexes: selectedIndexes.concat(rows.map(r => r.rowIdx))}); + } + onRowsDeselected(rows: Array) { + var rowIndexes = rows.map(r => r.rowIdx); + var selectedIndexes = this.state.selectedIndexes as Array; + this.setState({selectedIndexes: selectedIndexes.filter(i => rowIndexes.indexOf(i) === -1 )}); + } + + render() { + let selectedRows = ['id1', 'id2']; + return ( + } + enableRowSelect={true} + rowHeight={50} + minHeight={600} + rowScrollTimeout={200} + rowSelection={{ + showCheckbox: true, + enableShiftSelect: true, + onRowsSelected: this.onRowsSelected, + onRowsDeselected: this.onRowsDeselected, + selectBy: { + keys: {rowKey: 'id', values: selectedRows} + } + }} + rowActionsCell={CustomRowSelectorCell} + selectAllRenderer={CustomSelectAll} + onRowClick={this.onRowClick} + /> + + ); + } +} diff --git a/types/react-data-grid/v2/tsconfig.json b/types/react-data-grid/v2/tsconfig.json new file mode 100644 index 0000000000..1f5bd63312 --- /dev/null +++ b/types/react-data-grid/v2/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": false, + "strictNullChecks": false, + "strictFunctionTypes": true, + "baseUrl": "../../", + "jsx": "react", + "typeRoots": [ + "../../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "paths": { + "react-data-grid": [ + "react-data-grid/v2" + ], + "react-data-grid/*": [ + "react-data-grid/v2/*" + ] + } + }, + "files": [ + "index.d.ts", + "react-data-grid-tests.tsx" + ] +} diff --git a/types/react-data-grid/v2/tslint.json b/types/react-data-grid/v2/tslint.json new file mode 100644 index 0000000000..637071b426 --- /dev/null +++ b/types/react-data-grid/v2/tslint.json @@ -0,0 +1,80 @@ +{ + "extends": "dtslint/dt.json", + "rules": { + "adjacent-overload-signatures": false, + "array-type": false, + "arrow-return-shorthand": false, + "ban-types": false, + "callable-types": false, + "comment-format": false, + "dt-header": false, + "eofline": false, + "export-just-namespace": false, + "import-spacing": false, + "interface-name": false, + "interface-over-type-literal": false, + "jsdoc-format": false, + "max-line-length": false, + "member-access": false, + "new-parens": false, + "no-any-union": false, + "no-boolean-literal-compare": false, + "no-conditional-assignment": false, + "no-consecutive-blank-lines": false, + "no-construct": false, + "no-declare-current-package": false, + "no-duplicate-imports": false, + "no-duplicate-variable": false, + "no-empty-interface": false, + "no-for-in-array": false, + "no-inferrable-types": false, + "no-internal-module": false, + "no-irregular-whitespace": false, + "no-mergeable-namespace": false, + "no-misused-new": false, + "no-namespace": false, + "no-object-literal-type-assertion": false, + "no-padding": false, + "no-redundant-jsdoc": false, + "no-redundant-jsdoc-2": false, + "no-redundant-undefined": false, + "no-reference-import": false, + "no-relative-import-in-test": false, + "no-self-import": false, + "no-single-declare-module": false, + "no-string-throw": false, + "no-unnecessary-callback-wrapper": false, + "no-unnecessary-class": false, + "no-unnecessary-generics": false, + "no-unnecessary-qualifier": false, + "no-unnecessary-type-assertion": false, + "no-useless-files": false, + "no-var-keyword": false, + "no-var-requires": false, + "no-void-expression": false, + "no-trailing-whitespace": false, + "object-literal-key-quotes": false, + "object-literal-shorthand": false, + "one-line": false, + "one-variable-per-declaration": false, + "only-arrow-functions": false, + "prefer-conditional-expression": false, + "prefer-const": false, + "prefer-declare-function": false, + "prefer-for-of": false, + "prefer-method-signature": false, + "prefer-object-spread": false, + "prefer-template": false, + "radix": false, + "semicolon": false, + "space-before-function-paren": false, + "space-within-parens": false, + "strict-export-declare-modifiers": false, + "trim-file": false, + "triple-equals": false, + "typedef-whitespace": false, + "unified-signatures": false, + "void-return": false, + "whitespace": false + } +}