import { Component, HTMLAttributes, MaybeRef, MaybeRefOrGetter, Ref, TdHTMLAttributes, ThHTMLAttributes, VNode, VNodeProps, WatchSource } from 'vue';
import { OnyxI18n } from '../../../i18n/index.js';
import { Nullable } from '../../../types/index.js';
import { Orderable, OrderableMapping } from '../../../utils/feature.js';
import { OnyxMenuItem } from '../../OnyxNavBar/modules/index.js';
import { OnyxTableSlots, TableColumnGroup } from '../../OnyxTable/types.js';
import { DataGridRendererCell, DataGridRendererColumn, DataGridRendererRow } from '../OnyxDataGridRenderer/types.js';
import { ColumnTypesFromFeatures, DataGridEntry, DataGridMetadata } from '../types.js';
import { BASE_FEATURE } from './base/base.js';
import { DataGridAction } from './dataGridActions/types.js';
/**
* Function type for modifying the normalized column configuration.
*/
export type ModifyColumns = OrderableMapping[]>;
export type HeaderCellProps = {
label: string;
typeOptions?: TOptions;
};
export type TypeRendererHeaderDef = Omit>, "key" | "props">;
export type CellMetadata = {
typeOptions?: TOptions;
editable?: Nullable;
};
export type TypeRendererCell = Omit>, "props">;
/**
* Defines how a specific column type should be rendered.
*/
export type TypeRenderer = {
header?: TypeRendererHeaderDef;
cell: TypeRendererCell;
};
/**
* Maps a "type" key to a column renderer.
* `symbol` keys are intended for internal/helper columns.
*/
export type TypeRenderMap = Partial>>>;
/**
* ColumnConfig as it can be defined by the user.
*/
export type ColumnConfig, TTypes extends ColumnConfigTypeOption = never> = keyof TEntry | PublicNormalizedColumnConfig>>;
export type DefaultSupportedTypes = keyof ReturnType>["typeRenderer"];
/**
* Configuration for the column groupings.
*/
export type ColumnGroupConfig = Record;
/**
* Column config used internally and by the `modifyColumns` functions.
*/
export type InternalColumnConfig = Omit, "label" | "type"> & {
type: ColumnTypeNormalized;
/**
* Attributes that should be set on all `td` elements
*/
tdAttributes?: TdHTMLAttributes;
/**
* Attributes that should be set on all `th` elements
*/
thAttributes?: ThHTMLAttributes;
/**
* After normalization the label is always defined.
*/
label: string;
};
export type ColumnTypeNormalized = {
name: TKey;
options?: TOptions;
};
export type ColumnConfigTypeOption = TKey | ColumnTypeNormalized;
/**
* Normalized column config for public/external usage.
*/
export type PublicNormalizedColumnConfig> = Pick, "width" | "key"> & {
/**
* The `label` is displayed in the data grid as column header.
* If not defined, the key is used instead.
*/
label?: string;
/**
* The `type` of the column. It defines how the header and cells of a column is rendered.
* If not defined the values are displayed as plain strings.
*/
type?: TTypes;
/**
* Key of the ColumnGroup that this column should be visually grouped in.
* The columns have to be defined in the correct order.
* So columns that should be grouped together have to actually be defined after each other.
*
* The label for the column group can be configured via the `columnGroups` prop.
*/
columnGroupKey?: keyof TColumnGroup;
};
/**
* Context that is passed to a feature when it is set up by the `useDataGridFeatures` composable.
*/
export type DataGridFeatureContext = {
/**
* Ref for the `async` state of the `OnyxDataGrid`. If `true` data mutations should be skipped, if they are expected to be handled by a backend.
*/
async: Readonly[>;
/**
* The `i18n` object, which can be used to access messages, formatters and the current locale.
*/
i18n: OnyxI18n;
/**
* Whether the data grid should be shows as skeleton.
*/
skeleton: Readonly][>;
};
/**
* Complete Type for a single data grid feature.
*/
export type DataGridFeature = TypeRenderMap, TFeatureName extends symbol = symbol> = (ctx: DataGridFeatureContext) => DataGridFeatureDescription;
export type DataGridFeatureMutation = {
func: (state: Readonly[]) => Readonly[] | void;
} & Orderable;
/**
* Object that describes the hooks and properties of a datagrid feature.
*/
export type DataGridFeatureDescription = TypeRenderMap, TFeatureName extends symbol = symbol> = {
/**
* Unique name and identifier of the datagrid feature
*/
name: TFeatureName;
/**
* An array of reactive states that should trigger a datagrid re-generation
*/
watch?: WatchSource[];
/**
* Use mutations to modify the dataset before it is mapped to the rendered rows and cells.
*/
mutation?: DataGridFeatureMutation;
/**
* With `enhanceCell` the render details for a cell can be modified.
* The provided function is called for every cell, after the matching typeRenderer was applied.
*
*/
enhanceCells?: {
func: (cell: Readonly>, entry: Readonly, index: number) => {
component?: DataGridRendererCell["component"];
props?: Partial["props"]>;
tdAttributes?: Partial["tdAttributes"]>;
};
} & Orderable;
/**
* Use `enhanceRow` the render details for a complete row can be modified.
* The provided function is called for every row that is supposed to be rendered.
*/
enhanceRow?: {
func: (row: Readonly>, entry: Readonly, index: number) => Partial>;
} & Orderable;
/**
* Allows defining actions that are displayed in the "action" slot above the data grid.
* Will be automatically wrapped into a "more" flyout if not all actions fit
* into the available width.
*/
actions?: () => DataGridAction[];
/**
* Defines a renderer for a column type.
*/
typeRenderer?: TTypeRenderer;
/**
* Allows modification of the normalized column configuration.
* While the entries are passed as readonly, but the array itself can be modified.
* To change entries, you need to clone them first:
*
* @example
* ```ts
* {
* modifyColumns: [ { func: (config) => configs.map(column => ({ ...column, type: "newType" })) } ];
* }
* ```
*/
modifyColumns?: ModifyColumns;
/**
* Allows modification of the column groups.
*
* @example
* ```ts
* {
* modifyColumnGroups: {
* func: (groups, columns) => {
* return groups.flatMap(group => {
* return [ { ...group, class: 'my-custom-group-class' } ];
* });
* }
* }
* }
* ```
*/
modifyColumnGroups?: ModifyColumnGroups;
/**
* Allows the modification of the headers.
*/
header?: {
/**
* Adds header icon button(s).
* `iconComponent` of an action is shown after the header label.
* The components must be ARIA-conform buttons.
*/
actions?: (column: InternalColumnConfig, index: number, all: InternalColumnConfig[]) => {
iconComponent?: Component | {
iconComponent: Component;
/**
* Will force the icon component to be always shown in the header and not be put into the menu
*/
alwaysShowInHeader?: boolean;
};
menuItems?: Component[];
showFlyoutMenu?: boolean;
}[];
wrapper?: (column: InternalColumnConfig, index: number, all: InternalColumnConfig[]) => Component;
};
scrollContainerAttributes?: () => DataGridScrollContainerAttributes;
tableAttributes?: () => DataGridTableAttributes;
/**
* Optional table slots.
*/
slots?: DataGridFeatureSlots;
};
export type DataGridScrollContainerAttributes = HTMLAttributes & Pick;
export type DataGridTableAttributes = HTMLAttributes & Pick;
export type DataGridFeatureSlots = Partial<{
[TSlotName in keyof Pick]: (slotContent: () => VNode[]) => Nullable[];
}>;
export type InternalDataGridSlots = Partial VNode[]>>;
export type DataGridFeatureOptions>, TWithAsync extends boolean = false> = {
/**
* Whether the feature is enabled by default. Can be overridden per column.
*
* @default true
*/
enabled?: MaybeRef;
/**
* Options for each column. Will override default/global options of the feature.
*/
columns?: MaybeRef<{
[TKey in keyof TEntry]?: TColumnOptions[TKey] & {
/**
* Whether the feature is enabled for this column. If unset, the default/global `enabled` option of this feature will be used.
*/
enabled?: boolean;
};
} | undefined>;
} & (TWithAsync extends true ? {
/**
* When async is `true`, then the internal data transformations of this feature are disabled and have to be performed manually.
*/
async?: boolean;
} : unknown);
/**
* Helper function that checks the generics of the DataGridFeature type, without breaking type inference.
* @example
* ```ts
*
* const MY_FEATURE = Symbol("TABLE_HEADER_BUTTON");
* export const useDataGridHeaderButton = createFeature(() => {
* return {
* name: MY_FEATURE,
* header: {
* actions: (column) => [
* {
* iconComponent: h('button', { onClick: (column) => console.log(`Clicked on ${column}`) },),
* },
* ],
* },
* };
* });
* ```
*/
export declare function createFeature, T extends CheckDataGridFeature>(featureDefinition: T): T;
type CheckDataGridFeature = T extends DataGridFeature, infer C> ? DataGridFeature, C> : never;
export type UseDataGridFeaturesOptions> = {
columnConfig: MaybeRefOrGetter[]>;
i18n: OnyxI18n;
columnGroups: MaybeRefOrGetter;
async: Readonly][>;
skeleton: DataGridFeatureContext["skeleton"];
};
export declare const createTableColumnGroups: (columns?: InternalColumnConfig[], columnGroups?: ColumnGroupConfig) => TableColumnGroup[] | undefined;
export type ModifyColumnGroups = {
func: (groups: TableColumnGroup[], columns: InternalColumnConfig[]) => TableColumnGroup[];
};
/**
* Uses the defined datagrid features to provide factory functions.
* These factories are to be used to map data and configuration to `OnyxDataGridRenderer` properties.
* The properties are then used to render the data grid.
*
* Make use of the `watchSources` to trigger re-rendering when state changes occur.
* @example
* ```vue
*
*
*
*
* ```
*/
export declare const useDataGridFeatures: , TColumnGroup extends ColumnGroupConfig, TTypes extends ColumnConfigTypeOption, T extends DataGridFeature[] | []>(featureDefinitions: T, { i18n, columnConfig, columnGroups, async, skeleton, }: UseDataGridFeaturesOptions) => {
/**
* Returns the merged attributes that should be applied to the tables scroll-container.
*/
createScrollContainerAttributes: () => never;
/**
* Returns the merged attributes that should be applied to the native ] element.
*/
createTableAttributes: () => never;
/** Uses the column definition and available column group config to generate the column groups for the underlying OnyxTable */
createRendererColumnGroups: () => TableColumnGroup[];
/** Takes the column definition and maps all, calls mutation func and maps at the end to RendererCell */
createRendererRows: (entries: TEntry[]) => DataGridRendererRow[];
/** Takes the column definition and creates a RenderHeader for each, adds actions from features */
createRendererColumns: () => DataGridRendererColumn[];
/** Uses all features and generates the content of the additional table slots (headline, pagination etc.) for the underlying OnyxTable */
createSlots: () => Partial VNode[]>>;
watchSources: WatchSource[];
};
export declare const useFeatureContext: (ctx: DataGridFeatureContext, options?: DataGridFeatureOptions) => {
/**
* Checks whether a data grid feature is enabled for a given column.
* Considers the feature defaults as well as column-specific overrides.
*
* @default true
*/
isEnabled: import('vue').ComputedRef<(column?: PropertyKey) => boolean>;
/**
* Whether the feature only or all features have data transformations enabled.
*/
isAsync: import('vue').ComputedRef;
};
export {};