import type { MenuProps } from '@planview/pv-uikit'; import type { ColumnPreference } from './state'; export type SortDirection = 'asc' | 'desc'; export type ColumnField = Extract | string; export type GridColumnBorder = 'left' | 'right' | 'both'; export type GridTreeIndentSize = 'large' | 'small'; export type HeaderCellParams = { columnId: ColumnField; tabIndex: number; }; type FooterCellParams = { label: string | number; columnId: ColumnField; }; export type ColumnHeaderConfig = { /** * Should the header use left or right alignment. */ align?: 'left' | 'right'; /** * When this column is marked as a tree column, it will automatically gain an * expand/collapse control. In lazy-loaded situations, it may not be possible * to expand all given the server cost. This flag changes the behavior to only * allow collapsing of rows, not expanding */ treeCollapseOnly?: boolean; /** * Renderer to be used for the header cell. This component is * responsible for rendering sort information. * * Read more about overriding the default renderer in the [useColumnHeader](https://planview-ds.github.io/react-pvds/?path=/docs/pv-grid-hooks-usecolumnheader--docs) documentation. */ Renderer?: (props: HeaderCellParams) => React.JSX.Element; }; export type ColumnFooterConfig> = { /** * Aggregation method to be used for collected data. */ aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'size' | ((values: Array) => number | Date); /** * The value is used for collecting value from each row and will be passed to aggregation function. * It is recommended to define a value getter on the `cell` -configuration and this attribute should only be used when there is need to override it. */ value?: (props: CellValueParams) => number | Date | null; /** * Function to format the label of the cell. Defaults to value */ label?: (value: number | Date | null) => string; /** * Renderer to be used for the footer cell. This component is * responsible for rendering aggregation information. */ Renderer?: (props: FooterCellParams) => React.JSX.Element; }; export type CellValueParams> = { columnId: ColumnField; row: TDataModel; rowMeta: TMetaModel; }; export type CellColSpanParams> = { columnId: ColumnField; row: TDataModel; rowMeta: TMetaModel; sortedColumnIds: ColumnField[]; }; export type CellLabelParams = { columnId: ColumnField; row: T; rowMeta: TM; value: any; }; export type CellParams = { value: any; label: string; rowId: TDataModel['id']; columnId: ColumnField; tabIndex: number; }; export type EditorConfirmPayload = { continueEditing?: false | 'current' | 'next' | 'previous'; }; /** * This generic can be used to provide type information to the * onCellChange callback. You can [read more and see examples](https://planview-ds.github.io/react-pvds/?path=/docs/pv-grid-components-grid-cell-change-callback--docs) * in our documentation. * * @template TDataModel Model used to ensure rowId is of the correct type. * @template TKey String literal or a union of string literals that * reference existing properties on the model or * that match the ids of editable columns. * @template TNextVal nextValue type being passed from the editor * (assumed to also be the previousValue type if one is not provided). * @template TPrevVal - Value type of the previousValue if different * from the nextValue type. */ export type GridConfirmPayload = { [P in TKey]: { nextValue: TNextVal extends void ? P extends keyof TDataModel ? TDataModel[P] : any : TNextVal; previousValue: TPrevVal extends void ? P extends keyof TDataModel ? TDataModel[P] : any : TPrevVal; columnId: P; rowId: TDataModel['id']; }; }[TKey]; export type CellEditorParams = CellParams & { /** * Which mode is this? This is useful only with Hybrid Editors. It will always be "edit" for traditional editors. */ mode: 'navigation' | 'editing'; /** * confirm callback */ onConfirm: (value: any, payload?: EditorConfirmPayload) => void; /** * cancel callback */ onCancel: () => void; }; export type ColumnCellConfig> = { /** * The value is used for sorting, and will be used * for display if label or Renderer are not provided */ value?: (props: CellValueParams) => any; /** * The display value of the cell. Defaults to value function * or property from data object. */ label?: (props: CellLabelParams) => string; /** * Renderer to be used for the cell. This is a normal functional * component, so it can leverage hooks to get its data. */ Renderer?: (props: CellParams) => React.JSX.Element; /** * @deprecated: this prop is not used anymore and will be ignored. Focus is always handled inline. * * If focus should be passed into and handled in the component level. * This is always `inline` while rendering Editor */ focusStrategy?: 'auto' | 'inline'; /** * Can this cell value be edited. Can either be a boolean, or a function that returns a boolean */ editable?: boolean | ((props: CellValueParams) => boolean); /** * Should the editor be used as both renderer and editor. Very few components fit into this category, * and they should not take user text input. An example of an always editing cell is a binary switch. * * Use 'always' to render the editor even when editable is false. * */ hybridEditor?: boolean | 'always'; /** * Editor to be used for the cell. This is a normal functional * component, so it can leverage hooks to get its data. */ Editor?: (props: CellEditorParams) => React.JSX.Element; /** * Should this cell span multiple columns. An empty array or an array with only this columnId will turn off column spanning. * When multiple ids are set or returned, then this renderer will be used regardless of which column is first. If cells * are not contiguous, and cells between the specified columns will become part of the colSpan. * * If this column is sticky, all columns in the colSpan must also be sticky on the same side (left or right). * * See [Column Spans](https://planview-ds.github.io/react-pvds/docs/pv-grid-components-grid-column-spans--docs) documentation for more information. */ colSpan?: ColumnField[] | ((props: CellColSpanParams) => ColumnField[]); }; export type Column = GridRowMeta> = { /** * Unique column id. If no additional configuration for value or formatting are * applied, the field matching this id from the row will be displayed in the cells */ id: ColumnField; /** * Translated visual column heading label */ label: string; /** * Optional label of the column. This will be used for accessibility, labelling the column in case there is no visual label defined. * This will also be used in the context menu for column visibility. */ accessibleLabel?: string; /** * Does this column allow the user to change the sort by clicking on it */ sortable?: boolean; /** * Which type of sort should be used on this column * * fast: will work for some use cases, but is not locale aware nor * will it sort numbers contained in strings in numerical order. * * natural: this is a locale aware sort that is additionally configured * to sort numbers contained within strings in numerical order. The locale * used for natural sorting is inherited from react-intl IntlProvider context. */ sortStrategy?: 'fast' | 'natural'; /** * When dealing with values that are `null`, `undefined` or `""` (empty string), this setting * allows you to control where they end up after sorting. * * - `low` (default) - Treats them as low values, causing them to show first in ascending sort and last in descending sort * - `high` - Treats them as high values, causing them to show last in ascending sort and first in descending sort * - `always-first` - Always show before sorted content * - `always-last` - Always show after sorted content */ sortEmptyAs?: GridColumnSortEmptyAs; /** * Can this column be moved around by the user. * Defaults to true. */ movable?: boolean; /** * Should the column stay on screen instead of scrolling off screen * * When turned on, this will automatically set `lockedLocation` to match and set `movable` to false */ sticky?: 'none' | 'left' | 'right'; /** * Can this column be resized */ resizable?: boolean; /** * Minimum width in pixels * Defaults to size.medium */ minWidth?: number; /** * Default width in pixels */ width?: number; /** * Maximum width in pixels * Defaults to Infinity */ maxWidth?: number; /** * Should this be locked on the left or right of the table. This does not * make the column sticky, but does prevent other columns from being * reordered before (left) or after (right) this column. * * When turned on, this will automatically set `movable` to false */ lockedLocation?: 'none' | 'left' | 'right'; /** * Configuration for the header, including custom rendering */ header?: ColumnHeaderConfig; /** * Configuration of footer in a flat Grid, including aggregation */ footer?: ColumnFooterConfig; /** * Configuration for the cells, including formatting and custom rendering */ cell?: ColumnCellConfig; /** Is this the cell that should render expand/collapse controls? Only one column should be configured with this per grid */ tree?: boolean; /** Should the tree indentation be large or small (Defaults to `large`) */ treeIndentSize?: GridTreeIndentSize; /** * Should the column present a border. This will automatically set header, cell, and * footer border properties if they are set to auto or not configured. * * Use sparingly when needed to separate a few columns. Do not apply enough borders to make * the grid appear like a SpreadsheetGrid which adds vertical grid lines to indicate * a different set of expectations for the user like range cell selection and copy/paste. */ border?: GridColumnBorder; /** * Is column is hideable. Defaults to true. * * * This flag will be overridden if `tree` is set to true. */ hideable?: boolean; /** * Is column is hidden. * * This flag will be overridden if `tree` is set to true. */ hidden?: boolean; }; export type ColumnGroup = Pick, 'resizable' | 'lockedLocation' | 'movable' | 'label' | 'sticky'> & { /** * List of ids of columns grouped together under this group. */ children: Column['id'][]; /** * Unique column-group id. */ id: string; /** Should the column group present a border. This will automatically override appropriate column borders to enforce this setting. Borders shown will apply to header, body, and footer cells. */ border?: GridColumnBorder; }; export type Sort = { columnId: string; direction: SortDirection; }; export type FilterMode = 'default' | 'highlight'; export type GridRowIndexes = [start: number, end: number]; export type GridRowId = string | number; export type GridRowData = { id: GridRowId; }; /** @deprecated use GridRowData */ export type GridDataRow = GridRowData; export type GridRowMeta = { /** * Tree and group both can act as expandable parents, * but differ when it comes to selection * */ type?: 'tree' | 'group' | 'leaf'; /** * The tree is rebuilt as needed starting with the root ids. * Children point to other row ids */ children?: TDataModel['id'][]; /** * When using drag and drop, if a row should not be draggable you can set * this to true. This is true by default for type = group */ preventDrag?: boolean; }; export type GridServerData> = { /** * Orderer array of row ids. Rows not yet loaded should use stable ids, but not map * to a record in the data collection. */ ids: TDataModel['id'][]; /** * Map or object keyed by id with stable references to the actual row */ data: Map | Record; /** * Map or object keyed by id with stable references to row metadata */ meta?: Map | Record; /** * Optional callback that will be called frequently during scroll operations and during mount * You will want to throttle or debounce this method and only request missing data. */ fetch?: (indexes: GridRowIndexes) => void; }; export type GridDataProp> = TDataModel[] | GridServerData; export type GridColumnSort = { columnId: string; direction: SortDirection; }; export type GridColumnSortEmptyAs = 'low' | 'high' | 'always-first' | 'always-last'; export type GridPreferences = { columns: ColumnPreference[]; }; export type GridPreferencesAdapter = { load: () => Promise | GridPreferences | undefined; save: (prefs: GridPreferences) => void; }; export type GridActionsMenu = any> = GridActionsMenuComponent | { Menu?: never; MenuItems?: never; /** @deprecated use MenuItems as a direct replacement, or Menu for more granular control */ Component?: GridActionsMenuComponent; visible?: (props: GridActionsMenuProps) => boolean; } | { Menu?: never; MenuItems: GridActionsMenuComponent; /** @deprecated use MenuItems as a direct replacement, or Menu for more granular control */ Component?: never; visible?: (props: GridActionsMenuProps) => boolean; } | { Menu: GridActionsMenuFullComponent; MenuItems?: never; /** @deprecated use MenuItems as a direct replacement, or Menu for more granular control */ Component?: never; visible?: (props: GridActionsMenuProps) => boolean; }; export type GridActionsMenuComponent = GridRowMeta> = (props: GridActionsMenuProps) => React.JSX.Element; export type GridActionsMenuFullComponent = GridRowMeta> = (props: GridActionsMenuFullProps) => React.JSX.Element; export type GridRowDropInfo = any> = { draggedRowIds: TDataModel['id'][]; draggedRows: { row: TDataModel; rowMeta: TMetaModel; }[]; targetParentId: null | TDataModel['id']; targetParent: null | { row: TDataModel; rowMeta: TMetaModel; }; targetIndex: null | number; resultIds: null | TDataModel['id'][]; droppedAfterId: null | TDataModel['id']; }; export type GridDragResponse = { allowed: false; message: string; } | { allowed: true; message?: never; }; export type GridRangeSelection = { from: { columnId: string; rowId: TDataModel['id']; }; to: { columnId: string; rowId: TDataModel['id']; }; }; export type GridRowDragMode = 'default' | 'parent'; export type GridRowDragConfig> = { /** * What type of drag and drop operations are enabled? * * default: drop items in specific locations (flat or tree) or under a new parent (tree grids only) * parent: drop items under a new parent, but not in a specific order */ mode?: GridRowDragMode; /** * When dragging a row, one column is used as the content for the drag preview. By default, it will be the first * non-selection column that is not hidden. If you want to use a specific column, you can set this property * to the id of the column you want to use. */ previewColumnId?: ColumnField; /** * Can one item be dragged over a leaf node to create a new parent node? * Only applicable in a tree grid */ enableLeafConversion?: boolean; /** * Can more than one row be dragged at a time? Defaults to false */ multiple?: boolean; /** * Callback that will be called as the drop target (parent or index) changes. If a drop is not allowed * you must return a localized message explaining why. */ canDrop?: (info: GridRowDropInfo) => GridDragResponse; /** Callback that will be called when a drop is allowed and completed */ onDrop: (info: GridRowDropInfo) => void; }; export type GridProps = any> = { /** * Accessible label for this grid. Will be used to provide an aria-label. */ label?: string; /** * Columns that are part of the configuration. You can provide * the data type for your rows to help with typescript hinting * on some of the configuration options. */ columns: Column[]; /** * Column-grouping configuration. */ columnGroups?: ColumnGroup[]; /** * When enabled the user can trigger a context menu by right-clicking on any column header. Within this menu, options are provided to show or hide specific columns. */ enableColumnVisibilityMenu?: boolean; /** * Data used to generate rows. It can either be an array of objects * (must have an `id` field with a unique id for the row) or an object * with `ids`, `data` and `fetch` method. This second use will be documented * further in future releases. For early uses, please provide an array of objects. */ rows: GridDataProp; /** * Default sort is used to initialize sorting but not * take full control of sorting state */ defaultSort?: GridColumnSort[]; /** * Use this properly to fully control sorting. You should also add an * onSortChange callback to be notified when sorting should change */ sort?: GridColumnSort[]; /** * Callback when sorting changes */ onSortChange?: (sort: GridColumnSort[]) => void; /** * Should the grid handle sorting, or should it only display the indicators for sorting */ sortMode?: 'internal' | 'external'; /** * Multi-column sorting. By default, the grid supports sorting on multiple columns at once. * If you are using `sortMode="internal"`, you shouldn't need to turn this off. But if you * are using server sorting or something else custom, you may need to turn this off. */ multiColumnSort?: boolean; /** * When provided, will limit the data to these ids * * An empty array means there were no matches and the grid * should be empty. * * A null value instead means there are no filters applied * and the grid should show all rows. */ filteredIds?: TDataModel['id'][] | null; /** * When provided, will be used to filter each row */ filter?: (row: TDataModel) => boolean; /** * When provided, will render placeholder rows for the data * true will render 10 placeholder rows, otherwise will render the * number of rows specified */ loading?: boolean | number; /** * Should rows that do not match the filter be hidden, * or should rows that do not match be dimmed * * Defaults to 'show' */ filterMode?: FilterMode; /** * A set of selected ids. If your selection is tied to the URL (enabling a user to use * browser history Back/Forward), you may want to instead pass an object: * * ```tsx * { ids: selection, autoScroll: true } * ``` * * This will ensure the final id in the selection is scrolled into view if needed * when the selection changes programmatically. User initiated selection changes * will not cause it to scroll. */ selection?: Set | { ids: Set; autoScroll?: boolean; }; /** * When mode is set to single, clicking anywhere * on a row will cause it to be selected and any other row will * be deselected. Checkboxes will not be rendered on the left. * * When set to 'multi', clicking anywhere on a row will cause it to be * selected and any other row will be deselected. Clicking on a checkbox * will instead add/remove the row from the selection. Clicking the checkbox in the * header will select all rows. * * `multi-hidden` behaves the same as `multi` except that the selection column * is not added to the grid. This should only be used when presenting two grids * side by side and this grid is in a secondary position. */ selectionMode?: 'none' | 'single' | 'multi' | 'multi-hidden'; /** * When rows are selected or deselected, this is run * with an updated set of ids. * * Question: does the user need a way to prevent a row from being updated? */ onSelectionChange?: (selection: Set) => void; /** * A set of tree or group rows that should be expanded to render their child rows */ expandedRows?: Set; /** * When tree or group rows are expanded or collapsed, this is run * with an updated set of ids. */ onExpandedRowsChange?: (expandedRows: Set, context: { expanded: Set; collapsed: Set; }) => void; /** * Should the rows be size medium with a separator line, or size * small with no separator */ rowHeight?: 'small' | 'medium'; /** * Callback called whenever a row is clicked. Will not be called in cases where the click would take * an action other than selecting the row. */ onRowClick?: (rowId: TDataModel['id']) => void; /** * A preferences adapter can be used to save and load column settings like width, visibility and order. * These values can be persisted to local storage, a database, etc. * * The adapter must provide two methods: `load` and `save` * * - `save` will be called when a user finishes resizing or reordering a column * - `load` will be called when grid is initialized and whenever the adapter object changes. * * Be sure to have a consistent instance handed to the prop to avoid unnecessary loads. */ preferencesAdapter?: GridPreferencesAdapter; /** * Called whenever an edit action is completed on a cell. Since the representation * of data between value and editor may differ, this may be called even when nothing has changed * as a result of the edit. * * See [Cell Change Callback](https://planview-ds.github.io/react-pvds/?path=/docs/pv-grid-components-grid-cell-change-callback--docs) for * details on how to handle types. */ onCellChange?: (payload: GridConfirmPayload) => void; /** * In situations where the grid renders no data, use this property to present more context to the user * by passing in `EmptyState`, `EmptyStateError` or `EmptyStateFilter` components from `@planview/pv-uikit`. * * Will only be shown when there are no rows to render (no data or all data excluded by filters) */ emptyContent?: React.ReactNode; /** * When provided, a menu will be available on right-click of a row and shown * as a triple dot menu for the row. The contents of the menu can be customized per row, * but it is recommended the same options be shown for each row, with actions * that don't apply to a particular row marked as disabled. * * This property (or the Component sub-property) should point to a component that * returns a fragment with children suitable for use in our Menu component such as ListItem, * ListGroup, and SubMenu * * See [Actions Menu](https://planview-ds.github.io/react-pvds/?path=/docs/pv-grid-components-grid-actions-menu--docs) page for * more information and examples. */ actionsMenu?: GridActionsMenu; /** * Configuration for enabling drag and drop and keyboard reordering of rows * * See the [Row drag](https://planview-ds.github.io/react-pvds/?path=/docs/pv-grid-components-grid-row-drag--docs) documentation page for more details. */ rowDrag?: GridRowDragConfig; }; export type GridActionsMenuProps = GridRowMeta> = { row: TDataModel; rowMeta: TMetaModel; }; /** @deprecated use GridActionsMenuProps */ export type GridActionsMenuParams> = GridActionsMenuProps; export type GridActionsMenuFullProps = GridRowMeta> = { row: TDataModel; rowMeta: TMetaModel; menuProps: Omit; }; export type GridStateProps = { actionsMenuPresent: boolean; footerEnabled: boolean; selection?: Set; selectionMode?: Exclude['selectionMode'], 'multi-hidden'>; rowDrag: Pick, 'mode' | 'enableLeafConversion' | 'multiple' | 'canDrop' | 'previewColumnId'> & { enabled: boolean; }; hideHeaders?: boolean; initialFocusMode?: 'cell' | 'row'; loopHorizontally?: boolean; spreadsheet?: boolean; rangeSelection?: GridRangeSelection | null; } & Omit, 'label' | 'filterIds' | 'selectionMode' | 'selection' | 'onSelectionChange' | 'onExpandedRowsChange' | 'onSortChange' | 'rowHeight' | 'onCellChange' | 'emptyContent' | 'actionsMenu' | 'rowDrag'>; export {}; //# sourceMappingURL=types.d.ts.map