import { ComponentProps, ReactNode } from 'react'; import { AthenaTableAction } from '../actions/table-actions.js'; import { AthenaTableSortDirection, AthenaTableSortingState } from '../hooks/use-table-sorting.js'; import { AuthTableMobileColumn } from '../utils/auth-table-column-utils.js'; import { AthenaTableSortValue, AthenaTableSortNulls, AthenaTableSortStrategy } from '../utils/table-sort-strategies.js'; import { AthenaTableFormatConfig } from '../utils/table-value-formatters.js'; import { AthenaTableChipConfig } from '../utils/table-value-utils.js'; import { WorkspacePaginationProps } from '../../workspace/workspace-pagination.js'; import { Table } from './auth-table.js'; import { AthenaTableEmptyStateInput } from './auth-table-empty-state.js'; export type { AthenaTableSortValue } from '../utils/table-sort-strategies.js'; /** * Smart default compare. Prefer `compareSortValuesWithStrategy` for named strategies. */ export declare function compareSortValues(leftValue: AthenaTableSortValue | undefined, rightValue: AthenaTableSortValue | undefined, strategy?: AthenaTableSortStrategy): number; export type AthenaTableColumnDefaultWidth = ComponentProps["defaultWidth"]; export type AthenaTableColumnMinWidth = ComponentProps["minWidth"]; /** Horizontal alignment for desktop column headers and cells. */ export type AthenaTableColumnAlign = "start" | "center" | "end"; export type AthenaTableSortingMode = "client" | "server"; export type AthenaTableColumn = AuthTableMobileColumn & { /** * Horizontal alignment for desktop header + cell content. * Maps to Tailwind `text-start` / `text-center` / `text-end`. * Sortable headers also justify flex content accordingly. */ align?: AthenaTableColumnAlign; /** Allows this column's desktop header label to wrap. Headers stay on one line by default. */ allowHeaderWrap?: boolean; /** * Allows this column's desktop cell content to wrap onto multiple lines. * When true, single-line ellipsis is disabled for the cell. */ allowCellWrap?: boolean; /** Declarative chip renderer (JSON-serializable). Used when `render` is omitted. */ chip?: AthenaTableChipConfig; /** Value formatter preset or custom function. Used when `render`/`chip` are omitted. */ format?: AthenaTableFormatConfig | ((value: unknown, row: Row, index: number) => React.ReactNode); /** Enables or disables click-to-sort for this column. Action columns default to false. */ isSortable?: boolean; /** Opts this desktop column into HeroUI column resizing. */ isResizable?: boolean; /** Initial desktop width used when the table is rendered inside HeroUI's resizable container. */ defaultWidth?: AthenaTableColumnDefaultWidth; /** Minimum desktop width used by HeroUI column resizing. */ minWidth?: AthenaTableColumnMinWidth; /** Where null/undefined values land when sorting this column. */ sortNulls?: AthenaTableSortNulls; /** Named or configured sort strategy for client-side sorting. */ sortStrategy?: AthenaTableSortStrategy; /** Stable value used for client-side sorting. Falls back to row[valueKey ?? id]. */ sortValue?: (row: Row, index: number) => AthenaTableSortValue | undefined; /** * When true, long scalar cell text ellipsizes at the column edge. * Defaults to true for detail columns and false for action columns. * Overridden by `allowCellWrap`. */ truncate?: boolean; /** * Row field used for sort/format/chip when custom getters are not provided. * Fixes tables where `id` differs from the data key (e.g. builder runtime keys). */ valueKey?: string; }; export declare function isAthenaTableColumnResizable(column: Pick, "defaultWidth" | "isResizable" | "minWidth">): boolean; export declare function resolveAthenaTableHeaderSortIcon(direction: AthenaTableSortDirection | null | undefined): ((props: import('react').SVGProps) => React.JSX.Element) | null; export declare function resolveAthenaTableHeaderLabelClassName(column: Pick, "allowHeaderWrap">): string; /** * Tailwind text-alignment class for a column `align` value. * Returns undefined when align is omitted so existing start/left layout is unchanged. */ export declare function resolveAthenaTableAlignClassName(align?: AthenaTableColumnAlign): string | undefined; /** * Flex + text classes for sortable column header buttons. * Default (no align) preserves `justify-between text-left`. */ export declare function resolveAthenaTableHeaderContentClassName(align?: AthenaTableColumnAlign): string; /** * React Aria / HeroUI tables require at least one column with `isRowHeader`. * When callers omit it (or clear every header), promote the first non-action * column so the desktop table does not throw at render. */ export declare function ensureAthenaTableRowHeaderColumns(columns: readonly AthenaTableColumn[]): AthenaTableColumn[]; /** * Whether desktop cells for this column should ellipsize at the column edge. * Action columns default off so menus/icons stay fully visible. */ export declare function shouldTruncateAthenaTableCell(column: Pick, "allowCellWrap" | "id" | "isRowHeader" | "label" | "mobileRole" | "truncate">): boolean; /** * Shell classes on `Table.Cell` so content cannot paint into the next column. * Truncating columns use `max-w-0` so fixed/auto table layouts can shrink cells. */ export declare function resolveAthenaTableCellClassName(column: Pick, "align" | "allowCellWrap" | "id" | "isRowHeader" | "label" | "mobileRole" | "truncate">): string; /** * Wraps string/number cell values so they ellipsize inside the column width. * Leaves React elements (chips, menus, custom layouts) unchanged. */ export declare function wrapAthenaTableCellContent(content: ReactNode, options: { truncate: boolean; }): ReactNode; export interface AthenaTableSearchConfig { ariaLabel?: string; name?: string; onChange: (value: string) => void; placeholder?: string; value: string; } export interface AthenaTableSortConfig { ariaLabel?: string; name?: string; onChange: (value: string) => void; options: readonly { value: string; label: string; }[]; value: string; } export interface AthenaTableStatusFilterConfig { ariaLabel?: string; name?: string; onChange: (value: string | null) => void; options: readonly { value: string; label: string; }[]; value: string | null; } export interface AthenaTableAsyncLoadingState { isLoading: boolean; } export interface AthenaTableAsyncLoadingConfig { /** Custom sentinel content. Defaults to a compact loading indicator. */ content?: React.ReactNode | ((state: AthenaTableAsyncLoadingState) => React.ReactNode); /** Whether another page can be loaded. */ hasMore: boolean; /** Loading state for the current load-more request. */ isLoading?: boolean; /** Called by HeroUI's sentinel row when it scrolls into view. */ onLoadMore: () => void; /** Distance from viewport before the sentinel triggers. */ scrollOffset?: ComponentProps["scrollOffset"]; } export declare function isAthenaTableAsyncLoadingEnabled(config: AthenaTableAsyncLoadingConfig | null | undefined): boolean; export interface AthenaTableVirtualizationLayoutOptions { /** Height of the table header row used by HeroUI's virtual table layout. */ headingHeight?: number; /** Height of each body row used by HeroUI's virtual table layout. */ rowHeight?: number; } export type AthenaTableVirtualizationConfig = AthenaTableVirtualizationLayoutOptions & { /** Explicitly disable virtualization while keeping the config object in place. */ isEnabled?: boolean; /** Scroll viewport height. Defaults to maxHeight, then 320px. */ height?: number | string; /** Optional minimum desktop table width for horizontally dense tables. */ minWidth?: number | string; /** Matches HeroUI's Virtualizer layoutOptions shape for table virtualization. */ layoutOptions?: AthenaTableVirtualizationLayoutOptions; }; export declare function isAthenaTableVirtualizationEnabled(config: AthenaTableVirtualizationConfig | null | undefined): boolean; export interface AthenaTableProps { /** Custom actions to render in the action bar when items are selected. */ actionBarActions?: React.ReactNode; ariaLabel: string; /** Opt-in HeroUI async loading sentinel for infinite scrolling. */ asyncLoading?: AthenaTableAsyncLoadingConfig; /** Fully configurable bulk actions derived from the current selection. */ bulkActions?: readonly AthenaTableAction[]; className?: string; columns: readonly AthenaTableColumn[]; /** * Built-in top controls toolbar (search, sort, status filter). * AthenaTable renders a consistent, responsive toolbar so you don't have to * create a separate `*TableControls` component with 15+ props every time. * * Example: * controls={{ * search: { value: search, onChange: setSearch, placeholder: "Search..." }, * sort: { value: sort, onChange: setSort, options: sortOptions }, * statusFilter: { value: status, onChange: setStatus, options: statusOptions } * }} */ controls?: { search?: AthenaTableSearchConfig; sort?: AthenaTableSortConfig; statusFilter?: AthenaTableStatusFilterConfig; }; /** * Local/in-memory dataset supplied directly to the component (no Athena query). * Prefer this when the parent owns the full array. Equivalent to `rows` when * both are set (`data` wins). When `data` is set and you omit `pagination`, * AthenaTable can client-paginate automatically via {@link paginateLocally}. */ data?: readonly Row[]; /** Fallback rows-per-page used when pagination.pageSize is not supplied. */ defaultRowsPerPage?: number; /** Breakpoint at which the full (horizontally scrollable) table is shown instead of mobile rows. * * - "md" | "lg" | "xl": Use Tailwind responsive classes (viewport-based). * - "auto": Automatically switch based on the actual available width of the table container * using ResizeObserver. This is the most "set and forget" option and works great inside * sidebars, modals, split views, etc. * * Default behavior (when omitted): picks a sensible breakpoint based on the number of columns * (≤3 → md, ≤6 → lg, else xl). You rarely need to set this manually anymore. */ desktopBreakpoint?: "md" | "lg" | "xl" | "auto"; /** * Empty-state content when `rows` is empty (and not loading via `isLoading`). * * Accepts: * - **function** (legacy): `(state) => ReactNode` * - **static** string / ReactNode * - **config object**: `{ empty, error, loading, isLoading }` so callers * avoid nested ternaries * * Prefer pairing with `error` / `errorMessage` + `isLoading`: * ```tsx * * ``` */ emptyState?: AthenaTableEmptyStateInput; /** * Error content for the table. * - With `showErrorBanner` (default true): renders {@link AthenaTableError} above the table. * - Also feeds the empty-state path when there are no rows. * Alias: `errorMessage`. */ error?: ReactNode | null; /** * Inline error banner above the table body (the CircleInfo / danger strip). * - `true` (default): show when `error` / `errorMessage` is set * - `false`: never show the banner (error still available to empty state) * - ReactNode: replace the default banner entirely */ errorBanner?: boolean | ReactNode; /** @see error */ errorMessage?: string | null; getRowKey: (row: Row, index: number) => string; isLoading?: boolean; maxHeight?: number | string; /** Callback when selection changes. */ onSelectionChange?: (keys: Set) => void; /** Callback for controlled sorting (single or multi-column). */ onSortingChange?: (sorting: AthenaTableSortingState) => void; /** * Client-side pagination for in-memory `data` / `rows`. * * - With `data` and no external `pagination`: defaults to **on** (page size * from `defaultRowsPerPage` or 10). * - With only `rows` (typical server page slice): defaults to **off**. * - Pass `false` to always render the full array. * - Pass a config object to tune page size options / summary. */ paginateLocally?: boolean | { hidePaginationIfSinglePage?: boolean; pageSize?: number; pageSizeOptions?: readonly number[]; showPageSizeSelector?: boolean; showSummary?: boolean; }; pagination?: WorkspacePaginationProps; paginationFooterProps?: Omit, "children">; /** * Rows to render. For Athena/server-paged data, pass the current page slice * with matching `pagination`. For a full local array, prefer {@link data}. */ rows?: readonly Row[]; scrollContainerClassName?: string; /** Controlled selected keys (Set of row keys). */ selectedKeys?: Set; /** Enable row selection. "single" or "multiple". */ selectionMode?: "single" | "multiple"; /** Controlled click-header sorting state (single descriptor, array, or null). */ sorting?: AthenaTableSortingState; /** * - `client` (default): reorders the provided `rows` in the browser. * - `server`: only updates sort UI state and fires `onSortingChange` so the * caller can push `orderBy` to Athena gateway (recommended for paged data). */ sortingMode?: AthenaTableSortingMode; /** Optional API endpoint used to hydrate and save per-table sort preferences server-side. */ sortingPreferencesEndpoint?: string; /** Unique id for this table instance (used for localStorage persistence via Zustand). */ tableId?: string; /** Additional content to render alongside or instead of the built-in controls. */ topContent?: ReactNode; /** * Buttons or custom actions to render at the top-right of the table * (visible on desktop breakpoint+). Useful for Refresh, Add New, etc. * Fully configurable (e.g. ) */ topRightActions?: ReactNode; /** Opt-in HeroUI virtualization for large desktop row sets. */ virtualization?: AthenaTableVirtualizationConfig; } export declare function AthenaTable({ actionBarActions, ariaLabel, asyncLoading, bulkActions, className, columns, controls, data, defaultRowsPerPage, desktopBreakpoint, emptyState, error, errorBanner, errorMessage, getRowKey, isLoading, maxHeight, onSelectionChange, onSortingChange, paginateLocally, pagination: paginationProp, paginationFooterProps, rows, scrollContainerClassName, selectedKeys: controlledSelectedKeys, selectionMode, sorting: controlledSorting, sortingMode, sortingPreferencesEndpoint, tableId, // fallback to ariaLabel for persistence key topContent, topRightActions, virtualization }: AthenaTableProps): import("react").JSX.Element;