import { FormFieldValueComponentProps } from '@procore/core-react';
import { ComponentWithFieldProp } from '@procore/core-react/dist/Form/Form.types';
import { ColDef, Column, ColumnEverythingChangedEvent, ExcelDataType, ICellEditor, ICellRendererParams, RefreshCellsParams, RowDataTransaction, RowHeightParams, RowNode as AGRowNode, RowNodeTransaction, RowSelectedEvent } from 'ag-grid-community';
import { AgGridColumnProps } from 'ag-grid-react';
import { ChangeDetectionStrategyType } from 'ag-grid-react/lib/shared/changeDetectionService';
import React from 'react';
import { ColumnSort, PinColumnSide, RowSize } from './constants';
import { IDateFilterProps, IFilterProps, ILocationFilterProps, INumberFilterProps, IServerFilter } from './FilterRenderers';
import { NumberFilterModel, NumberFilterValue } from './FilterRenderers/NumberFilterRenderer';
import { MenuDropdownOption } from './GenericHeader/GenericHeader';
import { ListFilter } from './state/useFilterState';
import { ExportPageFormat } from './utils/generateHTMLString';
import { AffectedRows } from './utils/rowSelectionHelpers';
export declare type GranularRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
export declare type GranularPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
/** Column Definitions */
export interface ColumnDefinition<TValue = any, TRenderer = string, TRendererParams = any, TEditor = string, TEditorParams = any, TFilterOption = TValue, TFilterValue = number | string | LocationFilterOpt | {
    date: Date;
} | NumberFilterValue, TBulkEditor = string, TBulkEditorParams = any> {
    aggFunc?: string | AggregationFunction<TValue>;
    bulkEditable?: ((params: IsEditableParams) => boolean) | boolean;
    bulkEditEditor?: TBulkEditor;
    bulkEditEditorParams?: TBulkEditorParams;
    cellEditor?: TEditor;
    cellEditorParams?: TEditorParams;
    cellCSVFormatter?: (value: TValue) => string;
    cellExcelFormatter?: (value: TValue) => string;
    cellExcelDataType?: string;
    cellRenderer?: TRenderer;
    cellRendererParams?: TRendererParams;
    cellRendererSelector?: (params?: ICellRendererParams) => {
        component: TRenderer;
        params: TRendererParams;
    };
    comparator?: (a: any, b: any) => number;
    editable?: ((params: IsEditableParams) => boolean) | boolean;
    enableRowGroup?: boolean;
    field: string;
    filterRenderer?: string;
    filterProps?: IFilterProps<TFilterOption, TFilterValue> | IDateFilterProps<TFilterOption, TFilterValue> | ILocationFilterProps<TFilterOption, TFilterValue> | INumberFilterProps<{
        id: NumberFilterModel['type'];
        label: string;
    }, TFilterValue>;
    /** @deprecated use filterProps instead */
    filterParams?: IFilterProps<TFilterOption, TFilterValue>;
    flex?: number;
    getStringFormattedValue?: (value: TValue) => string;
    getFilterKeyCreator?: AgGridColumnProps['keyCreator'];
    headerName?: string;
    columnHeaderParams?: {
        menuOptions?: MenuDropdownOption[];
        headerNode?: (props: {
            columnDefinition: ColumnDefinition;
        }) => React.ReactNode;
    };
    hidden?: boolean;
    initialIsPinned?: PinColumnSide;
    initialSort?: ColumnSort;
    lockPinned?: boolean;
    lockVisible?: boolean;
    marryChildren?: boolean;
    maxWidth?: number;
    minWidth?: number;
    onCellValueChanged?: (params: CellValueChangeParams<TValue>) => void;
    resizable?: boolean;
    rightAlign?: boolean;
    rowGroup?: boolean;
    sortable?: boolean;
    suppressMenu?: boolean;
    suppressMovable?: boolean;
    suppressSizeToFit?: boolean;
    valueGetter?: (params: ValueGetterParams) => TValue;
    valueParser?: (params: ValueParserParams) => TValue;
    valueSetter?: (params: ValueSetterParams) => boolean;
    valueValidator?: ValueValidator<TValue>;
    width?: number;
}
export interface ExtendedColDef extends ColDef {
    bulkEditable?: ((params: IsEditableParams) => boolean) | boolean;
    valueValidator?: ValueValidator;
    bulkEditEditor?: 'number' | 'text';
    cellCSVFormatter?: (v: any) => any;
    cellExcelFormatter?: (v: any) => any;
}
export interface NestedColumnDefinition {
    children: ColumnDefinition[];
    groupId: string;
    headerName: string;
    columnGroupShow?: 'open' | 'closed';
    marryChildren?: boolean;
}
/** Controls the type of filtering: single, range,
 * or up to user choice (either) */
export declare type DateFilterSelectionType = 'single' | 'range' | 'either';
export interface DateTimeCellColumnDefinition<TValue = any, TRenderer = string, TRendererParams = any, TEditor = string, TEditorParams = any> extends ColumnDefinition<TValue, TRenderer, TRendererParams, TEditor, TEditorParams, {
    date: Date;
}, string> {
    filterProps?: IDateFilterProps<{
        date: Date;
    }, string>;
    /** See this this list of timezones: https://github.com/eggert/tz/blob/main/zone1970.tab */
    timeZone?: string;
}
export interface LocationFilterOpt {
    id: number | string;
    label: string;
}
export interface LocationColumnDefinition extends Omit<ColumnDefinition, 'filterProps'> {
    filterProps?: ILocationFilterProps<LocationFilterOpt, string>;
}
export { BooleanCellColumnDefinition } from './CellRenderers/BooleanCell';
export { ButtonsCellColumnDefinition } from './CellRenderers/ButtonsCell';
export { CompanyCellColumnDefinition } from './CellRenderers/CompanyCell';
export { CurrencyCellColumnDefinition } from './CellRenderers/CurrencyCell';
export { DataTableCellEditorProps, DataTableCellRendererProps, } from './CellRenderers/DataTableCell';
export { DateCellColumnDefinition } from './CellRenderers/DateCell';
export { GroupCellColumnDefinition } from './CellRenderers/GroupCell';
export { LinkCellColumnDefinition } from './CellRenderers/LinkCell';
export { MultiSelectCellColumnDefinition } from './CellRenderers/MultiSelectCell';
export { NumberCellColumnDefinition } from './CellRenderers/NumberCell';
export { PeopleCellColumnDefinition } from './CellRenderers/PeopleCell';
export { PercentCellColumnDefinition } from './CellRenderers/PercentCell';
export { PillCellColumnDefinition } from './CellRenderers/PillCell';
export { SelectCellColumnDefinition } from './CellRenderers/SelectCell';
export { TextCellColumnDefinition } from './CellRenderers/TextCell';
/** End Column Definitions */
export interface TableApi {
    applyListFilter: (field: string, values: any[]) => Promise<void>;
    applyNumberFilter: (field: string, values: Omit<NumberFilterModel, 'filterType'>) => Promise<void>;
    applyTransaction: (rowDataTransaction: RowDataTransaction) => RowNodeTransaction | null | undefined;
    collapseAll: () => void;
    exportToCSV: (config: CSVExportConfig) => void;
    expandAll: () => void;
    exportToExcel: (config: ExcelExportConfig) => void;
    exportToHTMLString: (config?: HTMLStringExportConfig) => Promise<string>;
    /**
     * Returns an array of column definitions (of type ColumnDefinition from DataTable) transformed
     * from ag-grid's current array of col defs (of type ColDef from ag-grid)
     */
    getColumnDefinitions: () => ColumnDefinition[];
    getDetailGridTableApi: (rowId: string) => PartialTableApi | undefined;
    getRootAggregateData: () => any;
    /**
     * For now, used for testing to detect open editors. If programmatic editing
     * is something we want to enable, we can consider making this public
     * @private
     */
    getCellEditorInstances: () => ICellEditor[];
    /**
     * Get the sorted leaf and group nodes remaining after filtering. Note: This only works for tables using the client side row model.
     */
    getFilteredAndSortedRowNodes: () => RowNode[];
    getListFilter: (field: string) => Promise<any | undefined>;
    getListFilters: (fields?: string[]) => Promise<ListFilter[]>;
    getTableConfiguration: () => DataTableConfig;
    getBulkEditColumns: () => ColumnDefinition[];
    hideContextPanel: ContextPanelApi['hide'];
    isAnyFilterPresent: () => boolean;
    isSearchPresent: () => boolean;
    refreshCells: (params?: RefreshCellsParams) => void;
    refreshServerSideStore: (params: RefreshServerSideDataParams) => void;
    removeAllFilters: () => void;
    removeFilter: (field: string) => Promise<void>;
    setColumnsVisibility: (field: string[], visibility: boolean) => void;
    setColumnVisibility: (field: string, visibility: boolean) => void;
    setLoading: (loading: boolean, message?: string) => void;
    setPinnedBottomRowData: (rows: any[]) => void;
    setRowNodeExpanded: (rowNode: AGRowNode, expanded: boolean) => void;
    setRowGrouping: (group: string[]) => void;
    setRowHeight: (size: RowSize) => void;
    setSearchValue: (value: string) => void;
    setTableConfiguration: (config: DataTableConfig) => void;
    showContextPanel: ContextPanelApi['show'];
    sizeColumnsToFit: (tableWidth?: number) => void;
    /**
     * Get row data for all leaf row nodes. Note: This only works for tables using the client side row model.
     */
    getRowData: () => any[];
    setRowData: (items: any[]) => void;
    getSelectedRows: () => any[];
    filterComponents?: FilterComponents;
    /**
     * Select all rows, regardless of filtering and rows that are not visible due to grouping being enabled and their groups not expanded.
     * Note: This currently doesn't work for SSRM tables.
     */
    selectAll: () => void;
    /** Clear all row selections, regardless of filtering. */
    deselectAll: () => void;
    /** Auto-sizes a column based on its contents. */
    autoSizeColumn?: (key: string | Column, skipHeader?: boolean) => void;
    /** Same as `autoSizeColumn`, but provide a list of column keys. */
    autoSizeColumns?: (keys: (string | Column)[], skipHeader?: boolean) => void;
    /** Calls `autoSizeColumns` on all displayed columns. */
    autoSizeAllColumns?: (skipHeader?: boolean) => void;
    /**
     * Scroll a row into view and optionally focus on one of its cells. If no argument is passed to `focusField` it will default to not applying focus.
     * Once in view the row will be positioned at the top, middle or bottom of the visible table rows depending on the optional `position` parameter.
     * If no argument is passsed to `position` it will default to doing the minimum amount of scrolling required to show the row.
     * */
    scrollToRow(rowIndex: number, focusField?: string, position?: 'top' | 'bottom' | 'middle'): void;
    /**
     * Selects row nodes by their respective row node IDs.
     * The row node ID is the one you provide from the callback `getRowNodeId(data)`,
     * otherwise the ID is a number auto-generated by the grid when the row data is set.
     */
    selectRows: (rowIds: (string | number)[]) => void;
    /**
     * Deselects row nodes by their respective row node IDs.
     * The row node ID is the one you provide from the callback `getRowNodeId(data)`,
     * otherwise the ID is a number auto-generated by the grid when the row data is set.
     */
    deselectRows: (rowIds: (string | number)[]) => void;
    /**
     * Set a function determining if selection is enabled for each row as it's loaded into the table.
     * Note: Changing this will not affect existing rows that have already been loaded. Additionally,
     * selected rows which are later disabled remain selected.
     */
    setIsRowSelectable?(isRowSelectableFunc: IsRowSelectable): void;
}
export declare type PartialTableApi = Pick<TableApi, 'applyTransaction' | 'collapseAll' | 'deselectAll' | 'expandAll' | 'getColumnDefinitions' | 'getDetailGridTableApi' | 'getFilteredAndSortedRowNodes' | 'getRootAggregateData' | 'getRowData' | 'getSelectedRows' | 'getTableConfiguration' | 'refreshCells' | 'scrollToRow' | 'selectAll' | 'setPinnedBottomRowData' | 'setRowData' | 'setRowNodeExpanded' | 'sizeColumnsToFit'>;
export interface IsRowSelectable {
    (node: RowNode): boolean;
}
export interface RowSelectionRef {
    affectedRows: AffectedRows;
    enabled?: boolean | ((params: RowSelectablePredicateParams<any>) => boolean);
    getRowNodeId: TableProps['getRowNodeId'];
    siblingGroupsRowDisabled?: boolean;
}
export interface CellValueChangeParams<TValue> {
    field: string;
    rowData: Record<string, any>;
    newValue: TValue;
    oldValue: TValue;
    rowIndex?: number | null;
}
export interface ColumnConfig {
    field: string | undefined;
    flex?: number | null | undefined;
    hidden: boolean | null | undefined;
    pinned: string | boolean | 'left' | 'right' | null | undefined;
    rowGroup: boolean | null | undefined;
    rowGroupIndex: number | null | undefined;
    sort: string | null | undefined;
    sortIndex: number | null | undefined;
    width: number | undefined;
}
export declare type ColumnGroupStateConfig = {
    groupId: string;
    open: boolean;
};
export declare type ContextPanelContent = 'configuration' | 'custom' | 'filters' | 'bulkEdit';
export interface ContextPanelApi {
    content?: ContextPanelContent;
    hide: () => void;
    isVisible: boolean;
    show: (content: ContextPanelContent) => void;
}
export interface CustomFooterConfig {
    height?: RowSize;
    id: string;
}
export interface AgGetDetailRowDataParams<TRow = any> {
    /** Row node for the details request */
    node: RowNode;
    /** Data for the current row */
    data: TRow;
    /** Callback to pass the rows back for the grid request */
    successCallback(rowData: any[]): void;
}
export interface GetDetailRowDataParams<TRow = any> extends Omit<AgGetDetailRowDataParams<TRow>, 'node'> {
}
export declare type GetRowHeightWithFooters = (customFooters: CustomFooterConfig[] | undefined) => (params: Partial<RowHeightParams>) => number;
export interface DetailRowConfig<TRow = any> {
    columnDefinitions: ColumnDefinition[];
    getDetailRowData: (params: GetDetailRowDataParams<TRow>) => void;
    height?: 'auto' | number;
    isExpandable?: (rowData: TRow) => boolean;
    customFooters?: CustomFooterConfig[];
    /** See ag-grid docs for more info: https://www.ag-grid.com/javascript-data-grid/master-detail-refresh/ */
    refreshStrategy?: 'everything' | 'rows' | 'nothing';
}
export declare type CustomRendererCell = {
    component: React.ComponentType<any>;
    editorType?: 'input' | 'select';
    name: string;
    type: 'renderer';
};
export declare type CustomEditorCell = {
    component: React.ForwardRefExoticComponent<any>;
    editorType: 'input' | 'select';
    name: string;
    type: 'editor';
};
export declare type CustomFilter = {
    component: React.FunctionComponent<any>;
    name: string;
};
export declare type CustomBulkEditorFields = {
    [key: string]: {
        component: ComponentWithFieldProp<any, FormFieldValueComponentProps<any>>;
        isEmpty: (value: any, defaultIsEmpty: (value: any) => boolean) => boolean;
    };
};
export interface CSVExportConfig {
    fileName: string;
    columnKeys?: string[];
    skipFooters?: boolean;
    skipGroups?: boolean;
    skipPinnedBottom?: boolean;
    skipPinnedTop?: boolean;
}
export interface ExcelExportConfig {
    fileName: string;
    columnKeys?: string[];
    sheetName?: string;
}
export interface DataTableConfig {
    columnState: ColumnConfig[];
    columnGroupState?: ColumnGroupStateConfig[];
    filters?: {
        [key: string]: any;
    } | undefined;
    rowHeight?: RowSize;
    serverFilters?: IServerFilter[];
}
export interface HTMLStringExportConfig {
    header?: React.FunctionComponent;
    preserveColumnWidths?: boolean;
    pageFormat?: ExportPageFormat;
    showTableHeaderOnEveryPage?: boolean;
}
export interface IsEditableParams {
    columnDefinition: ColumnDefinition;
    data: Record<string, any>;
    node: {
        isRowPinned: () => boolean;
    };
}
export interface SortModel {
    /** The column that is being sorted */
    field: string;
    /** The sort direction, ascending or descending */
    sort: 'asc' | 'desc';
}
export interface ServerSideGetRowsRequest {
    /** The row index of the last row of request data
     * or undefined from all rows */
    endRow: number | undefined;
    /** Array of fields of grouped columns that are currently expanded  */
    groupKeys: string[];
    /** Array of fields of all columns that are grouped */
    rowGroupCols: ColumnDefinition[];
    /** The value entered in the search */
    searchValue: string;
    /** Contains the selected filters; the filter type,
     * and the value being filtered on */
    serverFilters: IServerFilter[];
    /** Array of objects consisting of the field of the column being sorted,
     * along with the sort direction ('asc' or 'desc')
     */
    sortModel: SortModel[];
    /** The row index of the first row of requested data
     * or undefined from all rows */
    startRow: number | undefined;
    /** The list of columns which are being aggregated */
    valueCols: ColumnDefinition[];
}
export declare type SuccessParams = {
    /** The collection of data for a given request */
    rowData: any[];
    /** The total amount of rows */
    rowCount?: number;
    /** @private */
    storeInfo?: any;
};
export declare type UpdateServerSideDataSourceParams = {
    search?: ISearchState;
    filter?: {
        field: string;
        value: any;
    };
};
export declare type ServerSideGetRowsParams = {
    /** Callback function to indicate that data fetching failed */
    onError(): void;
    /** Callback function to load row data into DataTable */
    onSuccess(params: SuccessParams): void;
    /** The data request object */
    request: ServerSideGetRowsRequest;
};
export declare type RefreshServerSideDataParams = {
    route?: string[];
    purge?: boolean;
};
export declare type RowActivePredicateParams<TRow = any> = {
    data: TRow;
    node: RowNode;
    rowIndex: number;
};
export declare type RowSelectablePredicateParams<TRow = any> = {
    data: TRow;
    node: RowNode;
    rowIndex: number | null;
};
export interface DTExcelFormats {
    id: string;
    numberFormat?: {
        format: string;
    };
    dataType?: ExcelDataType;
}
export declare type ISearchState = string;
export interface TableProps<TRow = any, TBottomRow = any> {
    autoGroupColumnDefinition?: ColumnDefinition;
    customCells?: (CustomEditorCell | CustomRendererCell)[];
    customFooters?: CustomFooterConfig[];
    columnHeaderMenuOptions?: MenuDropdownOption[];
    detailRowConfigs?: DetailRowConfig<TRow>[];
    detailRowSelectionEnabled?: boolean;
    siblingGroupsRowSelectionDisabled?: boolean;
    emptyStateRenderer?: React.FunctionComponent;
    excelDataTypeFormats?: DTExcelFormats[];
    fullWidthCellRenderer?: React.FunctionComponent<ICellRendererParams>;
    getGroupRowAgg?: (nodes: RowNode[], currentGroupsValues: string[]) => TRow;
    getRowNodeId?: (data: TRow) => any;
    getSubtotalLabel?: (columnDefinition: ColumnDefinition, rowData: TRow) => string;
    groupDefaultExpanded?: number;
    groupIncludeFooter?: boolean;
    headerHeight?: number;
    hideActionsOnGroupedRow?: boolean;
    immutableData?: boolean;
    isFullWidth?: (data: TRow) => boolean;
    isRowActive?: (params: RowActivePredicateParams<TRow>) => boolean;
    isRowOverdue?: (params: RowActivePredicateParams<TRow>) => boolean;
    loading?: boolean;
    maxHeight?: number;
    maintainColumnOrder?: boolean;
    onCellValueChanged?: (params: CellValueChangeParams<any>) => void;
    onRowDragEnd?: (row: TRow, endIndex: number) => void;
    onRowSelected?: (event: RowSelectedEvent) => void;
    onSelectAll?: (param: 'all' | 'none') => void;
    onTableReady?: (tableApi: TableApi, tableApiRef: React.RefObject<TableApi>) => void;
    onColumnEverythingChanged?: (changeEvent: ColumnEverythingChangedEvent) => void;
    pagination?: boolean;
    paginationPageSize?: number;
    pinnedBottomRowData?: TBottomRow[];
    popupParent?: HTMLElement;
    rowActions?: React.FunctionComponent<any>[];
    /**
     * @private
     * Unsafe to use.
     *
     * Sets row virtualization buffer
     */
    rowBuffer?: number;
    rowDataChangeDetectionStrategy?: ChangeDetectionStrategyType;
    /**
     * Row data for the table. Only necessary when using client side data
     * model.
     * @see onServerSideDataRequest if using server side data model
     */
    rows?: TRow[];
    rowDragManaged?: boolean;
    rowSelectionEnabled?: boolean | ((params: RowSelectablePredicateParams<TRow>) => boolean);
    showExpandableMenuOptions?: boolean;
    showGroupChildCount?: boolean;
    /**
     * Removes border right from column group's last column
     */
    suppressColumnGroupBorders?: boolean;
    suppressColumnVirtualisation?: boolean;
    suppressFieldDotNotation?: boolean;
    suppressResetColumnsOption?: boolean;
    suppressRowClickSelection?: boolean;
}
export declare type AggregationFunction<TValue> = (params: {
    columnDefinition: ColumnDefinition;
    values: TValue[];
    rowNode: {
        allLeafChildren: {
            data: TValue;
        }[];
    };
}) => number;
export declare type RowNode = {
    aggData: any;
    childIndex: number;
    data: any;
    field: string | null;
    footer?: boolean;
    group?: boolean;
    id: string | undefined;
    key: string | null;
    parent: RowNode | null;
    rowGroupIndex: number | null;
    rowIndex: number | null;
    rowPinned: string;
};
export interface ValueGetterParams {
    columnDefinition: ColumnDefinition;
    data: Record<string, any>;
    node?: RowNode;
}
export interface ValueParserParams {
    columnDefinition: ColumnDefinition;
    newValue: any;
    oldValue: any;
}
export interface ValueSetterParams {
    columnDefinition: ColumnDefinition;
    data: Record<string, any>;
    newValue: any;
    oldValue: any;
}
export interface ValueValidator<TValue extends any = any> {
    (params: ValueValidatorParams<TValue>): {
        isValid: boolean;
        errorMessage?: string | string[];
        isRequired?: boolean;
    };
}
export interface ValueValidatorParams<TValue = any> {
    columnDefinition: ColumnDefinition;
    data: Record<string, any>;
    value: TValue;
}
export interface FrameworkComponents {
    [key: string]: React.ComponentType<any>;
}
export interface FilterComponents extends FrameworkComponents {
}
export interface PinnedBottomRow extends Record<string, any> {
    footerId: 'grandTotal' | string;
    isAggData?: boolean;
}
export interface TablePanelProps extends React.HtmlHTMLAttributes<HTMLDivElement> {
    children?: React.ReactNode;
    className?: string;
    style?: React.CSSProperties;
}
