import type { HoistModel, HSide, PersistOptions, Some } from '@xh/hoist/core'; import type { PanelConfig } from '@xh/hoist/desktop/cmp/panel'; import type { FilterBindTarget, FilterMatchMode, FilterValueSource, Store, StoreRecord } from '@xh/hoist/data'; import type { CellClassParams, CustomCellEditorProps, HeaderClassParams, HeaderValueGetterParams, ICellRendererParams, IRowNode, ITooltipParams, RowClassParams, ValueSetterParams } from '@xh/hoist/kit/ag-grid'; import type { ReactElement, ReactNode } from 'react'; import type { Column, ColumnSpec } from './columns/Column'; import type { ColumnGroup, ColumnGroupSpec } from './columns/ColumnGroup'; import type { GridFilterFieldSpecConfig } from './filter/GridFilterFieldSpec'; import type { GridModel } from './GridModel'; export interface ColumnState { colId: string; width: number; hidden: boolean; /** has this column been resized manually? */ manuallySized?: boolean; /** Side if pinned, null if not. */ pinned?: HSide; } /** Options for {@link GridModel.setColumnState}. */ export interface ColumnStateOptions { /** * True to hide any columns missing from the provided state, regardless of their in-code * `hidden` config. Default false, respecting that config. * * Columns configured with `hideable: false` or `excludeFromChooser: true` are never hidden by * this option, as the app has indicated that they must be displayed and/or cannot be restored * by the user. */ hideNewColumns?: boolean; } /** * Comparator for custom grid group sorting, provided to GridModel. * @param groupAVal - first group value to be compared. * @param groupBVal - second group value to be compared. * @param groupField - field name being grouped at this level. * @param metadata - additional metadata with raw ag-Grid group nodes. * @returns 0 if group values are equal, a negative number if `a` sorts first, * and a positive number if `b` sorts first. */ export type GridGroupSortFn = (groupAVal: string, groupBVal: string, groupField: string, metadata: { gridModel: GridModel; nodeA: IRowNode; nodeB: IRowNode; }) => number; /** Position of a row in the viewport when scrolled into view - default null scrolls minimally. */ export type GridScrollPosition = 'top' | 'middle' | 'bottom'; /** * Closure to generate CSS class names for a row. * @param record - the StoreRecord associated with the rendered row. * @returns CSS class(es) to apply to the row level. */ export type RowClassFn = (record: StoreRecord) => Some; /** * Function to determine if a particular CSS class should be added/removed from a row, * via rowClassRules config. * @param agParams - as provided by AG-Grid. Note that when a RowClassRuleFn is called by the * GridAutosizeService, it is only provided with an object with the 'data' key, * not the entire RowClassParams params. * @returns true if the class to which this function is keyed should be added, false if * it should be removed. */ export type RowClassRuleFn = (agParams: RowClassParams) => boolean; export interface GridModelPersistOptions extends PersistOptions { /** True (default) to include column state or provide column-specific PersistOptions. */ persistColumns?: boolean | PersistOptions; /** True (default) to include grouping state or provide grouping-specific PersistOptions. */ persistGrouping?: boolean | PersistOptions; /** True (default) to include sort state or provide sort-specific PersistOptions. */ persistSort?: boolean | PersistOptions; /** True (default) to include expanded level state or provide expanded level-specific PersistOptions. */ persistExpandToLevel?: boolean | PersistOptions; /** * True to force columns newly added to the code - and therefore missing from any previously * persisted state - to be initially hidden, regardless of their in-code `hidden` config. False * to respect that config, allowing new columns to appear automatically. * * Defaults to true when persisting to a user-curated, named view - i.e. a `ViewManagerModel` * or `DashViewModel`, per the resolved `persistColumns` options - as a release should not add * columns to views users have deliberately composed. Defaults to false for all other * providers, where state records a user's last-used layout and new columns aid discovery of * newly released data. The in-code default view of a `ViewManagerModel` always follows the * code - set this config to true to force-hide new columns there as well. * * Affects initial visibility only - new columns are always added to state and remain available * via the column chooser. Columns with `hideable: false` or `excludeFromChooser: true` are * never force-hidden, as the app requires them shown and/or users could not restore them. */ hideNewColumns?: boolean; } /** * Configuration for a {@link GridFilterModel} - the model powering column-header filter menus. * Passed via the `filterModel` config on {@link GridConfig}. * * @see GridFilterModel * @see GridFilterFieldSpec */ export interface GridFilterModelConfig { /** * Target (typically a {@link Store} or Cube {@link View}) to be filtered as column filters * are applied and used as a source for unique values displayed in the filtering UI when * applicable. Defaulted to the gridModel's store. */ bind?: GridFilterBindTarget; /** * True to update filters immediately after each change made in the column-based filter UI. * Defaults to False. */ commitOnChange?: boolean; /** * Specifies the fields this model supports for filtering. Should be configs for * {@link GridFilterFieldSpec}, string names to match with Fields in bound Store/View, or * omitted entirely to indicate that all fields should be filter-enabled. */ fieldSpecs?: Array; /** Default properties to be assigned to all fieldSpecs created by this model. */ fieldSpecDefaults?: Omit; /** * Icon element rendered in the column header when a filter is active on that column. * Use to customize the icon's appearance with e.g. a specific intent or prefix. * Defaults to `Icon.filter()` (the standard funnel icon in regular/outline style). */ activeFilterIcon?: ReactElement; } /** * {@link GridFilterModel} currently accepts a single `bind` target that also provides available * values. Note that both `Store` and `View` satisfy this intersection. */ export interface GridFilterBindTarget extends FilterBindTarget, FilterValueSource { } /** * Renderer for a group row * @param context - The group renderer params from ag-Grid * @returns the formatted value for display. */ export type GroupRowRenderer = (context: ICellRendererParams) => ReactNode; /** Cross-platform interface for desktop and mobile ColChooserModels. */ export interface IColChooserModel extends HoistModel { readonly gridModel: GridModel; readonly mode: ColChooserMode; readonly isOpen: boolean; open(): void; close(): void; toggle(): void; } /** * Presentation for a grid's column chooser, as specified by {@link ColChooserConfig.mode}. * `modal` - an overlay (dialog or popover) shown above the grid. * `docked` - a resizable, non-modal side-panel rendered alongside the grid. Desktop only. */ export type ColChooserMode = 'modal' | 'docked'; /** * Configuration for a grid's column chooser - the model backing the column chooser UI. Passed via * the `colChooserModel` config on {@link GridConfig}, or set app-wide via * `GridModel.defaults.colChooserModel`. * * A grid has at most one chooser; `mode` selects how it is presented. */ export interface ColChooserConfig { /** GridModel to bind to. Not required if creating via `GridModel.colChooserModel` */ gridModel?: GridModel; /** * How the chooser is presented (default 'modal'). Pass a bare {@link ColChooserMode} in place of * this config as a shortcut - e.g. `colChooserModel: 'docked'`. Docked is desktop only and will * throw in a mobile app. */ mode?: ColChooserMode; /** * Immediately render changed columns on grid (default true). Set to false to enable Save button * for committing changes on save. Desktop only, and modal only - the docked chooser stays in * sync with external column state, so it always commits immediately. */ commitOnChange?: boolean; /** * Show Restore Defaults button (default true). Set to false to hide Restore Grid * Defaults button, which immediately commits grid defaults (all column, grouping, * and sorting states). */ showRestoreDefaults?: boolean; /** * Autosize grid columns after committing changes (default false for desktop, true for mobile). */ autosizeOnCommit?: boolean; /** * Width of the chooser's bucket column - the always-present part, excluding the optional Column * Library (see {@link ColLibraryConfig.libraryWidth}). In the modal overlay this sizes to fit * this plus the library when shown; in the docked panel it is the initial dock width (grown by * the library width while shown). Desktop only. */ width?: string | number; /** Chooser height. Desktop only, and modal only - the dock sizes itself vertically. */ height?: string | number; /** Mode to use when filtering (default 'startWord'). Desktop only. */ filterMatchMode?: FilterMatchMode; /** * Enable the Column Library - a docked panel listing hidden columns (grouped by `chooserGroup`) * that users drag onto the chooser's bucket grids to show, and onto which they drag columns to * hide. When enabled, hidden columns are removed from the buckets by default. Default false. * Pass `true` for defaults, or a {@link ColLibraryConfig} to customize. Desktop only. */ columnLibrary?: boolean | ColLibraryConfig; /** * Config for the docked PanelModel (e.g. `side`, `defaultSize`, `minSize`). The chooser docks * horizontally, so `side` is limited to 'left'/'right' (default 'right'). The dock is resize-only * (open/close is driven externally - e.g. a `ColChooserButton` or `GridModel.showColChooser()`), * so `collapsible` is omitted. Requires `mode: 'docked'`. */ panelConfig?: Omit & { side?: HSide; }; } /** * Configuration for the ColumnChooser's optional Column Library, passed via * {@link ColChooserConfig.columnLibrary}. Desktop only. */ export interface ColLibraryConfig { /** * Render the library's `chooserGroup` groups collapsed by default (default false). Recommended * for large column sets. */ collapseGroups?: boolean; /** * Max number of matching columns for a library group to be expanded while the chooser's filter * is active (default 5). Set to 0 to disable. */ autoExpandOnFilter?: number; /** * Fixed width of the Column Library panel (default 250). */ libraryWidth?: number; } export type ColumnOrGroup = Column | ColumnGroup; export type ColumnOrGroupSpec = ColumnSpec | ColumnGroupSpec; export declare function isColumnSpec(spec: ColumnOrGroupSpec): spec is ColumnSpec; /** * Sort comparator function for a grid column. Note that this comparator will also be called if * agGrid-provided column filtering is enabled: it is used to sort values shown for set filter * options. In that case, some extra params will be null. * @param valueA - cell data valueA to be compared * @param valueB - cell data valueB to be compared * @param sortDir - either 'asc' or 'desc' * @param abs - true to sort by absolute value * @param params - additional context about records and column for usage by comparator. */ export type ColumnComparator = (valueA: T, valueB: T, sortDir: 'asc' | 'desc', abs: boolean, params: { recordA: StoreRecord; recordB: StoreRecord; agNodeA: IRowNode; agNodeB: IRowNode; column: Column; gridModel: GridModel; defaultComparator: (a: T, b: T) => number; }) => number; export interface CellContext { record: StoreRecord; column: Column; gridModel: GridModel; } /** * Renderer function for a grid cell. * @param value - cell data value (column + row). * @param context - additional data about the column, row and GridModel. * Note that columns with renderers that access/rely on record fields other than the primary * value should also have their `rendererIsComplex` flag set to true to ensure they are * re-run whenever the record (and not just the primary value) changes. * @returns the formatted value for display. */ export type ColumnRenderer = (value: T, context: CellContext) => ReactNode; /** * Function to return a value to export for a grid cell. * @param value - cell data value (column + row). * @param context - additional data about the column, row and GridModel. * @returns value for export. */ export type ColumnExportValueFn = (value: T, context: CellContext) => any; /** * Function to return an excel format for a grid cell. * @param value - cell data value (column + row). * @param context - additional data about the column, row and GridModel. * @returns excel format */ export type ColumnExcelFormatFn = (value: T, context: CellContext) => string; /** * Function to return a value for sorting. * @param value - cell data value (column + row). * @param context - additional data about the column, row and GridModel. * @returns value for sort. */ export type ColumnSortValueFn = (value: T, context: CellContext) => any; /** * Function to generate grid cell CSS classes. * @param value - cell data value (column + row). * @param context - additional data about the column, row and GridModel. * @returns CSS class(es) to use. */ export type ColumnCellClassFn = (value: T, context: CellContext & { agParams: CellClassParams; }) => Some; /** * Function to determine if a particular CSS class should be added/removed from a cell, via * cellClassRules config. * @param agParams - as provided by Ag-Grid. Includes keys: * value - the current cell value. * data - the backing Hoist record for the row, if any. * @returns true if the class to which this function is keyed should be added, false if * it should be removed. */ export type ColumnCellClassRuleFn = (agParams: CellClassParams) => boolean; /** * Function to produce a grid column tooltip. * @param value - cell data value (column + row). * @param metadata - additional data about the column and row. * @returns the formatted value for display. */ export type ColumnTooltipFn = (value: T, cellContext: CellContext & { agParams: ITooltipParams; }) => ReactNode; /** * Function to generate header CSS classes. * @param context - contains data about the column and GridModel. * @returns CSS class(es) to use. */ export type ColumnHeaderClassFn = (context: { column: ColumnOrGroup; gridModel: GridModel; agParams: HeaderClassParams; }) => Some; /** * Function to generate a Column header name. * Note that using function for the header name will ignore any ag-Grid functionality for * decorating the header name, the return value of the function will be used as-is. * The function should be treated like an autorun - any subsequent changes to observable properties * referenced during the previous execution of the function will trigger a re-render * of the column header. * * @returns the header name to render in the Column header */ export type ColumnHeaderNameFn = (params: { column?: Column; columnGroup?: ColumnGroup; gridModel: GridModel; agParams: HeaderValueGetterParams; }) => ReactNode; /** * Function to determine if a Column should be editable or not. This function will be * called whenever the user takes some action which would initiate inline editing of a cell * before the actual inline editing session is started. * @returns true if cell is editable */ export type ColumnEditableFn = (params: { record: StoreRecord; store: Store; column: Column; gridModel: GridModel; }) => boolean; /** * Function to return one Grid cell editor. This function will be used to create a new * Component, whenever editing is initiated on a cell. * The never parameter is never provided - it is included to satisfy typescript. See * discussion in https://github.com/xh/hoist-react/pull/3351. * @returns the react element to use as the cell editor. */ export type ColumnEditorFn = (props: ColumnEditorProps, never?: any) => ReactElement; /** * The object passed into the first argument of {@link ColumnSpec.editor}. * Satisfies the {@link EditorProps} of an editor component. */ export type ColumnEditorProps = { record: StoreRecord; column: Column; gridModel: GridModel; agParams: CustomCellEditorProps; }; /** * Function to update the value of a StoreRecord field after inline editing */ export type ColumnSetValueFn = (params: { value: T; record: StoreRecord; field: string; store: Store; column: Column; gridModel: GridModel; agParams: ValueSetterParams; }) => void; /** * Function to get the value of a StoreRecord field */ export type ColumnGetValueFn = (params: { record: StoreRecord; field: string; store: Store; column: Column; gridModel: GridModel; }) => T; /** * Entry within a {@link ColumnSpec.sortingOrder} array, defining one step in the sort cycle * applied by successive clicks on a column header. */ export interface ColumnSortSpec { /** Direction to sort, either 'asc' or 'desc', or null to remove sort. */ sort: 'asc' | 'desc' | null; /** True to sort by absolute value. */ abs?: boolean; }