import { KeyboardEvent as ReactKeyboardEvent, ReactNode, SetStateAction } from 'react';
import { BooleanFormatterOptions, CurrencyFormatterOptions, DateFormatterOptions, DateTimeFormatterOptions, NumberFormatterOptions, PercentFormatterOptions, TimeFormatterOptions } from './formatters';
import { SelectMenuOption, SelectMenuGroupByValue } from '../../../components/SelectMenu';
import { SelectMenuSyncProps } from '../../../components/SelectMenu/SelectMenuSync';
import { SelectMenuProps } from '../../../components/SelectMenu/types';
import { MultiSelectMenuOption } from '../../../components/MultiSelectMenu';
import { MultiSelectMenuSyncProps } from '../../../components/MultiSelectMenu/MultiSelectMenuSync';
import { MultiSelectMenuProps } from '../../../components/MultiSelectMenu/types';
/**
 * Column type literals for display configuration.
 * Each type maps to a default formatter and alignment.
 */
export type ColumnType = "text" | "number" | "currency" | "percent" | "date" | "dateTime" | "time" | "boolean" | "markdown" | "html";
/**
 * Maps column types to their formatter options.
 * Used for type-safe formatter configuration.
 */
export type ColumnTypeOptionsMap = {
    text: undefined;
    number: NumberFormatterOptions;
    currency: CurrencyFormatterOptions;
    percent: PercentFormatterOptions;
    date: DateFormatterOptions;
    dateTime: DateTimeFormatterOptions;
    time: TimeFormatterOptions;
    boolean: BooleanFormatterOptions;
    markdown: undefined;
    html: undefined;
};
/**
 * Column type configuration.
 * Can be a simple type string (uses defaults) or an object with custom options.
 *
 * @example
 * ```ts
 * // Simple - uses default formatter options
 * type: "currency"
 *
 * // With options - customizes formatter behavior
 * type: { type: "currency", options: { currency: "EUR", locale: "de-DE" } }
 * ```
 */
export type ColumnTypeConfig<T extends ColumnType = ColumnType> = T | {
    type: T;
    options: ColumnTypeOptionsMap[T];
};
/**
 * Edit mode literals for editable cells.
 */
export type EditMode = "text" | "number" | "select" | "select-async" | "multiselect" | "multiselect-async" | "boolean" | "custom";
/**
 * Base edit configuration shared by all edit modes.
 * @template T - The row data type
 * @template K - The column key
 */
type BaseEditConfig<T, K extends keyof T> = {
    /**
     * Callback fired when the cell value is saved.
     * @param value - The new value
     * @param rowId - The id of the row being edited
     */
    onChange: (value: T[K], rowId: string) => void;
};
type CustomEditInvalidPresentValue<TValue> = Extract<NonNullable<TValue>, readonly unknown[]> | Extract<NonNullable<TValue>, (...args: never[]) => unknown> | Exclude<NonNullable<TValue>, object>;
type CustomEditPresentObjectValueForValue<TValue> = [
    CustomEditInvalidPresentValue<TValue>
] extends [never] ? NonNullable<TValue> extends object ? NonNullable<TValue> : never : never;
type CustomEditPartialPresentValue<TValue extends object> = TValue extends object ? Partial<TValue> : never;
export type CustomEditAllowedNullishValue<TValue> = Extract<TValue, null | undefined>;
export type CustomEditPresentObjectValue<T, K extends keyof T> = CustomEditPresentObjectValueForValue<T[K]>;
export type CustomEditDraftValueForValue<TValue> = [
    CustomEditPresentObjectValueForValue<TValue>
] extends [never] ? never : CustomEditPartialPresentValue<CustomEditPresentObjectValueForValue<TValue>> | CustomEditAllowedNullishValue<TValue>;
export type CustomEditDraftValue<T, K extends keyof T> = CustomEditDraftValueForValue<T[K]>;
export type CustomEditInitialValue<T, K extends keyof T> = T[K];
export type CustomEditFieldValueUpdater<TValue extends object, TField extends keyof TValue> = TValue[TField] | ((previousValue: TValue[TField] | undefined, draftValue: Partial<TValue>) => TValue[TField]);
export type CustomEditCloseReason = "submit" | "escape" | "outside-click" | "close-button" | "programmatic";
export type CustomEditValidation<TValue extends object> = {
    /**
     * Form-level validation summary for the entire editor.
     */
    formError?: ReactNode;
    /**
     * Field-level validation messages keyed by draft field.
     */
    fieldErrors?: Partial<Record<keyof TValue, ReactNode>>;
};
export type CustomEditSurfaceConfig = {
    /**
     * Optional title rendered in the editor surface header.
     */
    title?: ReactNode;
    /**
     * Optional surface width.
     */
    width?: number | string;
    /**
     * Optional surface max height.
     */
    maxHeight?: number | string;
    /**
     * Accessible label for the close button.
     */
    closeButtonLabel?: string;
    /**
     * Optional keydown handler forwarded to the surface.
     */
    onKeyDown?: (event: ReactKeyboardEvent<HTMLDivElement>) => void;
};
export type CustomEditCloseRequest<TValue extends object, TDraftValue = Partial<TValue>, TInitialValue = TValue> = {
    /**
     * Why the close was requested.
     */
    reason: CustomEditCloseReason;
    /**
     * Draft value at the time the request is evaluated.
     */
    draftValue: TDraftValue;
    /**
     * Original committed value when editing began.
     */
    initialValue: TInitialValue;
    /**
     * Whether the draft differs from the initial value.
     */
    isDirty: boolean;
    /**
     * Current validation metadata.
     */
    validation: CustomEditValidation<TValue>;
};
export type CustomEditController<TValue extends object, TDraftValue = Partial<TValue>, TInitialValue = TValue> = {
    /**
     * Current local draft. Custom editors may hold a partial object, or a
     * row-type-supported nullish value.
     */
    draftValue: TDraftValue;
    /**
     * Original value before editing began.
     */
    initialValue: TInitialValue;
    /**
     * Whether the draft differs from the initial value.
     */
    isDirty: boolean;
    /**
     * Ordered list of changed object fields. Whole-value nullish changes are
     * represented by `isDirty`, not by synthetic field names.
     */
    changedFields: ReadonlyArray<keyof TValue>;
    /**
     * Current validation metadata for the draft.
     */
    validation: CustomEditValidation<TValue>;
    /**
     * Replace the entire draft value. Null and undefined are accepted only when
     * the column's row value type includes that nullish value.
     */
    setDraftValue: (nextValue: SetStateAction<TDraftValue>) => TDraftValue;
    /**
     * Update a single field in the current draft value. If the current draft is
     * nullish, a partial object containing this field is synthesized.
     */
    setDraftField: <TField extends keyof TValue>(field: TField, nextValue: CustomEditFieldValueUpdater<TValue, TField>) => TDraftValue;
    /**
     * Submit the current draft and close the editor.
     */
    submit: () => void;
    /**
     * Restore the initial value and close the editor.
     */
    discard: () => void;
    /**
     * Request closure using the configured policy for the supplied reason.
     */
    requestClose: (reason: CustomEditCloseReason) => void;
    /**
     * Register the one preferred initial-focus action for the editor.
     */
    setInitialFocus: (focus: (() => void) | null) => void;
    /**
     * Canonical submit handler for form-based editors.
     */
    handleSubmit: (event?: {
        preventDefault?: () => void;
    }) => void;
};
export type ColumnReadRenderContext<T> = {
    row: T;
    depth: number;
};
export type ColumnReadRenderResult = {
    /**
     * Advanced read-path rendered content.
     * Most consumers should prefer `renderCell` + `getCellText` and only use
     * this shape when one hook should return both rendered content and sortable text.
     */
    content: ReactNode;
    /**
     * Optional sortable plain-text representation of the rendered content.
     */
    rawString?: string;
};
export type CustomEditRenderContext<T, K extends keyof T> = {
    /**
     * Full row data for the cell being edited.
     */
    row: T;
    /**
     * String row id for the cell being edited.
     */
    rowId: string;
    /**
     * Committed value for the cell, exactly as declared by the row type.
     */
    value: T[K];
    /**
     * Typed controller for draft mutation, validation, focus, and lifecycle control.
     */
    controller: CustomEditController<CustomEditPresentObjectValue<T, K>, CustomEditDraftValue<T, K>, CustomEditInitialValue<T, K>>;
};
/**
 * Edit configuration for custom mode cells.
 * Custom mode is for structured object-valued columns. The committed read
 * value remains `T[K]`; editable drafts may be partial objects, plus `null`
 * or `undefined` when those values are part of `T[K]`.
 *
 * @template T - The row data type
 * @template K - The column key
 */
export type CustomEditConfig<T, K extends keyof T> = [
    CustomEditPresentObjectValue<T, K>
] extends [never] ? never : Omit<BaseEditConfig<T, K>, "onChange"> & {
    /**
     * Custom edit mode - renders a multi-field editor surface.
     */
    mode: "custom";
    /**
     * Callback fired when the current draft is committed. The value is the
     * exact draft state: partial object, full object, or allowed nullish value.
     */
    onCommit: (value: CustomEditDraftValue<T, K>, rowId: string) => void;
    /**
     * Callback fired on every local draft mutation with the exact draft state.
     */
    onDraftUpdate?: (value: CustomEditDraftValue<T, K>, rowId: string) => void;
    /**
     * Optional validation metadata derived from the current draft.
     */
    validateDraft?: (draftValue: CustomEditDraftValue<T, K>, rowId: string) => CustomEditValidation<CustomEditPresentObjectValue<T, K>> | undefined;
    /**
     * When true, submit-style close requests are blocked while validation contains
     * a form error or any field error. Defaults to `false`.
     */
    blockOnValidationError?: boolean;
    /**
     * Optional close interception hook.
     * Return `false` to keep the editor open.
     */
    onRequestClose?: (request: CustomEditCloseRequest<CustomEditPresentObjectValue<T, K>, CustomEditDraftValue<T, K>, CustomEditInitialValue<T, K>>) => boolean | void;
    /**
     * Optional surface presentation overrides.
     */
    surface?: CustomEditSurfaceConfig;
    /**
     * Consumer-owned renderer for the custom editor contents. Editors should
     * handle partial and row-type-supported nullish draft values defensively.
     */
    renderEditor: (context: CustomEditRenderContext<T, K>) => ReactNode;
};
/**
 * Edit configuration for text mode cells.
 * @template T - The row data type
 * @template K - The column key
 */
export type TextEditConfig<T, K extends keyof T> = BaseEditConfig<T, K> & {
    /**
     * Text edit mode - renders an inline text input.
     */
    mode: "text";
};
/**
 * Edit configuration for number mode cells.
 * Renders an inline number input with increment/decrement support.
 *
 * @template T - The row data type
 * @template K - The column key
 */
export type NumberEditConfig<T, K extends keyof T> = BaseEditConfig<T, K> & {
    /**
     * Number edit mode - renders an inline number input with formatting and validation.
     */
    mode: "number";
    /**
     * The minimum value for the number field.
     * @default 0
     */
    minValue?: number;
    /**
     * The maximum value for the number field.
     * @default 100000000000000
     */
    maxValue?: number;
    /**
     * The step value for the number field.
     * @default 1
     */
    step?: number;
    /**
     * The maximum number of decimal places for the number field.
     * @default 0
     */
    maximumFractionDigits?: number;
    /**
     * The minimum number of decimal places for the number field.
     * @default 0
     */
    minimumFractionDigits?: number;
};
type SelectMenuCellPassthroughProps = Omit<SelectMenuSyncProps, "trigger" | "label" | "value" | "onSelectedOptionChange" | "options" | "onMenuKeyDown" | "onImplicitClose" | "onExplicitClose">;
type MultiSelectMenuCellPassthroughProps = Omit<MultiSelectMenuSyncProps, "trigger" | "label" | "value" | "onSelectedOptionsChange" | "options" | "onMenuKeyDown" | "onImplicitClose" | "onExplicitClose">;
/**
 * Edit configuration for select mode cells.
 * @template T - The row data type
 * @template K - The column key
 */
export type SelectEditConfig<T, K extends keyof T> = Omit<BaseEditConfig<T, K>, "onChange"> & {
    /**
     * Select edit mode - renders a SelectMenu popover.
     */
    mode: "select";
    /**
     * The options available for selection.
     */
    options: SelectMenuOption[];
    /**
     * Callback fired when the selected option changes.
     * @param option - The newly selected option, or null if cleared
     * @param rowId - The id of the row being edited
     */
    onChange: (option: SelectMenuOption | null, rowId: string) => void;
} & SelectMenuCellPassthroughProps;
/**
 * Edit configuration for multiselect mode cells.
 * @template T - The row data type
 * @template K - The column key
 */
export type MultiselectEditConfig<T, K extends keyof T> = Omit<BaseEditConfig<T, K>, "onChange"> & {
    /**
     * Multiselect edit mode - renders a searchable MultiSelectMenu popover.
     */
    mode: "multiselect";
    /**
     * The options available for selection.
     */
    options: MultiSelectMenuOption[];
    /**
     * Callback fired when the selected options change.
     * @param options - The newly selected options
     * @param rowId - The id of the row being edited
     */
    onChange: (options: MultiSelectMenuOption[], rowId: string) => void;
} & MultiSelectMenuCellPassthroughProps;
type SelectMenuAsyncCellPassthroughProps = Omit<SelectMenuProps, "trigger" | "label" | "value" | "onSelectedOptionChange" | "loadOptions" | "lazy" | "lazyOptions" | "onMenuKeyDown" | "onImplicitClose" | "onExplicitClose">;
type MultiSelectMenuAsyncCellPassthroughProps = Omit<MultiSelectMenuProps, "trigger" | "label" | "value" | "onSelectedOptionsChange" | "loadOptions" | "lazy" | "lazyOptions" | "onMenuKeyDown" | "onImplicitClose" | "onExplicitClose">;
/**
 * Context passed to `loadOptions` for async edit configs.
 * Provides row data for per-row option loading.
 * @template T - The row data type
 * @property row - The full row data object
 * @property rowId - The string id of the row
 */
export type AsyncCellContext<T> = {
    row: T;
    rowId: string;
};
/**
 * Eager loader for `mode: "select-async"` — returns all matching options at once.
 * @template T - The row data type
 */
export type SelectAsyncCellEagerLoader<T> = (searchValue: string, context: AsyncCellContext<T>) => SelectMenuOption[] | Promise<SelectMenuOption[]>;
/**
 * Page-based lazy loader for `mode: "select-async"`.
 * @template T - The row data type
 */
export type SelectAsyncCellPageLoader<T> = (searchValue: string, pageNumber: number, pageSize: number, context: AsyncCellContext<T>) => {
    options: SelectMenuOption[];
    hasMore?: boolean;
} | Promise<{
    options: SelectMenuOption[];
    hasMore?: boolean;
}>;
/**
 * Offset-based lazy loader for `mode: "select-async"`.
 * @template T - The row data type
 */
export type SelectAsyncCellOffsetLoader<T> = (searchValue: string, offset: number, limit: number, context: AsyncCellContext<T>) => {
    options: SelectMenuOption[];
    hasMore?: boolean;
} | Promise<{
    options: SelectMenuOption[];
    hasMore?: boolean;
}>;
/**
 * Group-based lazy loader for `mode: "select-async"`.
 * @template T - The row data type
 */
export type SelectAsyncCellGroupLoader<T> = (searchValue: string, previousGroupKey: SelectMenuGroupByValue | null, context: AsyncCellContext<T>) => {
    options: SelectMenuOption[];
    hasMore?: boolean;
} | Promise<{
    options: SelectMenuOption[];
    hasMore?: boolean;
}>;
/**
 * Eager loader for `mode: "multiselect-async"` — returns all matching options at once.
 * @template T - The row data type
 */
export type MultiselectAsyncCellEagerLoader<T> = (searchValue: string, context: AsyncCellContext<T>) => MultiSelectMenuOption[] | Promise<MultiSelectMenuOption[]>;
/**
 * Page-based lazy loader for `mode: "multiselect-async"`.
 * @template T - The row data type
 */
export type MultiselectAsyncCellPageLoader<T> = (searchValue: string, pageNumber: number, pageSize: number, context: AsyncCellContext<T>) => {
    options: MultiSelectMenuOption[];
    hasMore?: boolean;
} | Promise<{
    options: MultiSelectMenuOption[];
    hasMore?: boolean;
}>;
/**
 * Offset-based lazy loader for `mode: "multiselect-async"`.
 * @template T - The row data type
 */
export type MultiselectAsyncCellOffsetLoader<T> = (searchValue: string, offset: number, limit: number, context: AsyncCellContext<T>) => {
    options: MultiSelectMenuOption[];
    hasMore?: boolean;
} | Promise<{
    options: MultiSelectMenuOption[];
    hasMore?: boolean;
}>;
/**
 * Group-based lazy loader for `mode: "multiselect-async"`.
 * @template T - The row data type
 */
export type MultiselectAsyncCellGroupLoader<T> = (searchValue: string, previousGroupKey: SelectMenuGroupByValue | null, context: AsyncCellContext<T>) => {
    options: MultiSelectMenuOption[];
    hasMore?: boolean;
} | Promise<{
    options: MultiSelectMenuOption[];
    hasMore?: boolean;
}>;
type SelectAsyncEditConfigBase = {
    /**
     * Callback fired when the selected option changes.
     * @param option - The newly selected option, or null if cleared
     * @param rowId - The id of the row being edited
     */
    onChange: (option: SelectMenuOption | null, rowId: string) => void;
} & SelectMenuAsyncCellPassthroughProps;
/**
 * Edit configuration for async select mode cells.
 * Uses `SelectMenu` directly (not `SelectMenuSync`) to support server-side option loading.
 *
 * The `loadOptions` function receives a `context` argument as its last parameter,
 * containing the current row data and row id. This enables per-row option loading.
 *
 * By default, caching is disabled to prevent cross-row cache pollution when `loadOptions`
 * uses row context. Pass `cache={{ enabled: true }}` to override.
 *
 * Cell value is expected to be a primitive that matches a `SelectMenuOption.id`.
 *
 * @template T - The row data type
 */
export type SelectAsyncEditConfig<T> = (SelectAsyncEditConfigBase & {
    mode: "select-async";
    lazy?: false;
    loadOptions: SelectAsyncCellEagerLoader<T>;
    lazyOptions?: never;
}) | (SelectAsyncEditConfigBase & {
    mode: "select-async";
    lazy: "page";
    loadOptions: SelectAsyncCellPageLoader<T>;
    lazyOptions?: {
        pageSize?: number;
    };
}) | (SelectAsyncEditConfigBase & {
    mode: "select-async";
    lazy: "offset";
    loadOptions: SelectAsyncCellOffsetLoader<T>;
    lazyOptions?: {
        limit?: number;
    };
}) | (SelectAsyncEditConfigBase & {
    mode: "select-async";
    lazy: "group";
    loadOptions: SelectAsyncCellGroupLoader<T>;
    lazyOptions?: object;
});
type MultiselectAsyncEditConfigBase = {
    /**
     * Callback fired when the selected options change.
     * @param options - The newly selected options (full option objects)
     * @param rowId - The id of the row being edited
     */
    onChange: (options: MultiSelectMenuOption[], rowId: string) => void;
} & MultiSelectMenuAsyncCellPassthroughProps;
/**
 * Edit configuration for async multiselect mode cells.
 * Uses `MultiSelectMenu` directly (not `MultiSelectMenuSync`) to support server-side option loading.
 *
 * The `loadOptions` function receives a `context` argument as its last parameter,
 * containing the current row data and row id. This enables per-row option loading.
 *
 * By default, caching is disabled to prevent cross-row cache pollution when `loadOptions`
 * uses row context. Pass `cache={{ enabled: true }}` to override.
 *
 * **Value contract**: Unlike `mode: "multiselect"` (which stores ID arrays), the cell value
 * for `mode: "multiselect-async"` must be `MultiSelectMenuOption[]` — full option objects.
 * The `onChange` callback receives these objects directly and the consumer stores them wholesale.
 *
 * @template T - The row data type
 */
export type MultiselectAsyncEditConfig<T> = (MultiselectAsyncEditConfigBase & {
    mode: "multiselect-async";
    lazy?: false;
    loadOptions: MultiselectAsyncCellEagerLoader<T>;
    lazyOptions?: never;
}) | (MultiselectAsyncEditConfigBase & {
    mode: "multiselect-async";
    lazy: "page";
    loadOptions: MultiselectAsyncCellPageLoader<T>;
    lazyOptions?: {
        pageSize?: number;
    };
}) | (MultiselectAsyncEditConfigBase & {
    mode: "multiselect-async";
    lazy: "offset";
    loadOptions: MultiselectAsyncCellOffsetLoader<T>;
    lazyOptions?: {
        limit?: number;
    };
}) | (MultiselectAsyncEditConfigBase & {
    mode: "multiselect-async";
    lazy: "group";
    loadOptions: MultiselectAsyncCellGroupLoader<T>;
    lazyOptions?: object;
});
/**
 * Edit configuration for boolean mode cells.
 * Renders a dropdown menu with predefined true/false options and an optional null option.
 *
 * @template T - The row data type
 * @template K - The column key
 */
export type BooleanEditConfig<T, K extends keyof T> = BaseEditConfig<T, K> & {
    /**
     * Boolean edit mode - renders a dropdown with true/false/null options.
     */
    mode: "boolean";
    /**
     * The label displayed for the `true` option.
     * @default "True"
     */
    trueLabel?: string;
    /**
     * The label displayed for the `false` option.
     * @default "False"
     */
    falseLabel?: string;
    /**
     * Whether to include a null option in the dropdown.
     * @default false
     */
    allowNull?: boolean;
    /**
     * The label displayed for the `null` option. Only used when `allowNull` is true.
     * @default "Unset"
     */
    nullLabel?: string;
};
/**
 * Union of all edit configurations.
 * Use with `editConfig` property on column definitions.
 *
 * @template T - The row data type
 * @template K - The column key
 *
 * @example
 * ```ts
 * // Text editing
 * editConfig: { mode: "text", onChange: (value, rowId) => save(value, rowId) }
 *
 * // Number editing
 * editConfig: {
 *   mode: "number",
 *   minValue: 0,
 *   maxValue: 1000,
 *   step: 1,
 *   onChange: (value, rowId) => save(value, rowId)
 * }
 *
 * // Select editing
 * editConfig: {
 *   mode: "select",
 *   options: [{ id: "active", label: "Active" }],
 *   onChange: (option, rowId) => save(option?.id, rowId)
 * }
 *
 * // Boolean editing
 * editConfig: {
 *   mode: "boolean",
 *   trueLabel: "Yes",
 *   falseLabel: "No",
 *   onChange: (value, rowId) => save(value, rowId)
 * }
 *
 * // Custom editing keeps renderCell as the read path
 * editConfig: {
 *   mode: "custom",
 *   onCommit: (draft, rowId) => saveDraft(draft, rowId),
 *   onDraftUpdate: (draft, rowId) => previewDraft(draft, rowId),
 *   renderEditor: ({ controller }) => renderAddressEditor(controller)
 * }
 * ```
 */
export type EditConfig<T, K extends keyof T> = TextEditConfig<T, K> | NumberEditConfig<T, K> | SelectEditConfig<T, K> | SelectAsyncEditConfig<T> | MultiselectEditConfig<T, K> | MultiselectAsyncEditConfig<T> | BooleanEditConfig<T, K> | CustomEditConfig<T, K>;
/**
 * The type for a table row
 * @extends T
 */
export type TableRow<T> = T & {
    /**
     * The id of the row
     */
    id: string | number;
    /**
     * Row metadata including errors
     */
    meta?: {
        /**
         * Cell-level errors keyed by column id.
         * - `true` marks the cell as having an error
         * - A string marks the cell as having an error with an accessible error message
         */
        errors?: Partial<Record<keyof T, boolean | string>>;
        /**
         * Cell-level warnings keyed by column id.
         * - `true` marks the cell as having a warning
         * - A string marks the cell as having a warning with an accessible warning message
         * - When both an error and warning exist on the same cell, the error takes priority
         */
        warnings?: Partial<Record<keyof T, boolean | string>>;
        /**
         * Row-level error displayed in the first column.
         * - `true` marks the row as having an error
         * - A string marks the row as having an error with an accessible error message
         */
        rowError?: boolean | string;
        /**
         * Row-level warning displayed in the first column.
         * - `true` marks the row as having a warning
         * - A string marks the row as having a warning with an accessible warning message
         * - When both a row error and warning exist, the error takes priority
         */
        rowWarning?: boolean | string;
    };
    /**
     * The sub component displayed when the row is expanded
     */
    subComponent?: ReactNode;
    /**
     * The sub rows of the row when the row is expanded
     */
    subRows?: TableRow<T>[];
};
export type ColumnOverflowConfig = {
    /**
     * Disclosure behavior used when mounted read-only cell content is clipped.
     */
    mode: "surface";
};
export type ColumnBaseDef = ColumnHeaderConfig & {
    /**
     * The alignment of the header and cell content.
     * When using `type`, this is set automatically but can be overridden.
     */
    align?: "start" | "center" | "end";
    /**
     * Custom content to display when a cell value is empty (null, undefined, or empty string).
     * Overrides the default em dash. When set on both the column and the DataTable,
     * the column-level value takes precedence.
     */
    emptyCellContent?: ReactNode;
    /**
     * The content of the footer cell. An array will display multiple footer rows
     */
    footerContent?: ReactNode | ReactNode[];
    /**
     * The maximum width of the column, in pixels. Caps automatic growth when
     * the table has extra horizontal space available.
     */
    maxWidth?: number;
    /**
     * The minimum width of the column, in pixels. Used as the floor for manual
     * resize — users can drag a column down to but not below this value. Also
     * serves as the fallback auto-sizing floor when `defaultWidth` is not set.
     */
    minWidth?: number;
    /**
     * The preferred starting width of the column, in pixels. Used as the basis
     * for automatic growing/shrinking: the column renders at this width by
     * default, grows toward `maxWidth` when the table has spare horizontal
     * space, and never auto-shrinks below it — the table scrolls horizontally
     * instead.
     *
     * Manual resize via the column's resize handle is still bounded by
     * `minWidth`/`maxWidth`, so users can drag a column below `defaultWidth`
     * down to `minWidth`.
     *
     * @remarks Values outside `minWidth`/`maxWidth` are not validated when
     * provided. CSS grid clamps the rendered width at display time.
     *
     * Falls back to `minWidth` when not specified.
     */
    defaultWidth?: number;
    /**
     * The pinning location of the column
     */
    pinned?: "left" | "right";
    /**
     * Whether the column is resizable
     */
    resizable?: boolean;
};
export type ColumnGroupDef<T> = ColumnBaseDef & {
    /**
     * Group column id.
     */
    id: string;
    /**
     * Columns of a group column
     */
    columns: ColumnDef<T>[];
    editConfig?: never;
    overflow?: never;
    renderCell?: never;
    sortable?: never;
    type?: never;
};
type ColumnDataDefBase<T, K extends keyof T> = ColumnBaseDef & {
    /**
     * The id of the column - must be a key of T
     */
    id: K;
    /**
     * Columns of a group column
     */
    columns?: undefined;
    /**
     * The function to customize how the cell content is rendered.
     * When using `type`, a default renderer is provided but can be overridden.
     * Custom edit columns continue to use this read-only render path.
     */
    renderCell?: (value: T[K], context: ColumnReadRenderContext<TableRow<T>>) => ReactNode;
    /**
     * Optional plain-text extractor for the read path.
     * Useful when `renderCell` returns JSX or multiline content but default sorting
     * should still use a simple string.
     */
    getCellText?: (value: T[K], context: ColumnReadRenderContext<TableRow<T>>) => string;
    /**
     * Optional advanced read-display extractor.
     * Prefer `getCellText` for the common case where `renderCell` already handles
     * display and sorting only needs a simple string. Use this when you want one
     * hook to return both rendered read content and the sortable raw string.
     */
    getReadRenderResult?: (value: T[K], context: ColumnReadRenderContext<TableRow<T>>) => ColumnReadRenderResult;
    /**
     * Whether the column is sortable, or a function to customize the sorting logic.
     * When a function, receives values of the column's value type.
     */
    sortable?: boolean | ((valueA: T[K], valueB: T[K]) => number);
    /**
     * The column type for automatic display configuration.
     * Sets default `renderCell` (formatter) and `align` based on the data type.
     */
    type?: ColumnTypeConfig;
};
type ColumnReadOnlyDefForKey<T, K extends keyof T> = ColumnDataDefBase<T, K> & {
    editConfig?: undefined;
    /**
     * Shows full read-only cell content in a Surface when mounted content is clipped.
     */
    overflow?: ColumnOverflowConfig;
};
type ColumnEditableDefForKey<T, K extends keyof T> = ColumnDataDefBase<T, K> & {
    /**
     * Configuration for cell editing. Presence enables editing for the column.
     * Consolidates edit mode, options, and onChange into a single object.
     */
    editConfig: EditConfig<T, K>;
    overflow?: never;
};
export type ColumnDefForKey<T, K extends keyof T> = ColumnReadOnlyDefForKey<T, K> | ColumnEditableDefForKey<T, K>;
type ColumnLeafDef<T> = ColumnDataDefBase<T, keyof T> & ({
    editConfig?: undefined;
    /**
     * Shows full read-only cell content in a Surface when mounted content is clipped.
     */
    overflow?: ColumnOverflowConfig;
} | {
    /**
     * Configuration for cell editing. Presence enables editing for the column.
     * Consolidates edit mode, options, and onChange into a single object.
     */
    editConfig: EditConfig<T, keyof T>;
    overflow?: never;
});
/**
 * Column definition type for DataTable columns.
 *
 * Use `createColumnHelper<T>()` to create type-safe column definitions with
 * proper type inference for `type`, `editConfig`, and value types.
 *
 * @example
 * ```ts
 * type Data = { name: string; amount: number; tags: string[] };
 * const createColumn = createColumnHelper<Data>();
 *
 * const columns = [
 *   // Display-only column with type defaults
 *   createColumn("amount", { header: { label: "Amount" }, type: "currency" }),
 *
 *   // Editable column with editConfig
 *   createColumn("name", {
 *     header: { label: "Name" },
 *     type: "text",
 *     editConfig: { mode: "text", onChange: (value, rowId) => save(value, rowId) }
 *   }),
 *
 *   // Multiselect editing
 *   createColumn("tags", {
 *     header: { label: "Tags" },
 *     editConfig: {
 *       mode: "multiselect",
 *       options: [{ value: "urgent", label: "Urgent" }],
 *       onChange: (value, rowId) => save(value, rowId)
 *     }
 *   }),
 * ];
 * ```
 */
export type ColumnHeader = {
    /**
     * The visible header label text.
     */
    label: string;
    /**
     * Whether the header should show a required indicator.
     */
    required?: boolean;
    /**
     * Additional contextual content rendered from a keyboard-accessible more-info trigger.
     */
    moreInfo?: ReactNode;
};
export type ColumnHeaderConfig = {
    /**
     * The forward-looking header configuration.
     */
    header: ColumnHeader;
    /**
     * Legacy header label support during the transition to `header`.
     * @deprecated Use `header.label` instead.
     */
    headerLabel?: string;
} | {
    /**
     * The forward-looking header configuration.
     */
    header?: ColumnHeader;
    /**
     * Legacy header label support during the transition to `header`.
     * @deprecated Use `header.label` instead.
     */
    headerLabel: string;
};
export type ColumnDef<T> = ColumnGroupDef<T> | ColumnLeafDef<T>;
/**
 * The type for a custom table footer cell props
 */
export type CustomTableFooterCellProps = {
    /**
     * The content of the footer cell
     */
    content: ReactNode;
    /**
     * The number of columns the footer cell should span
     */
    colSpan: number;
};
export {};
