Skip to content

Tables, columns and cells

Maintenance mode (deprecated)

@ahoo-wang/fetcher-viewer is deprecated and in maintenance mode: existing functionality is maintained, with no new features. Further data-view development belongs to @ahoo-wang/fetcher-view-engine; use View Engine for new projects. This page remains a maintenance reference for existing consumers. The packages use different models and APIs, so migration requires adaptation.

ViewTable<RecordType> maps FieldDefinition and ViewColumn to Ant Design columns and receives an array of records. It does not paginate/query the server. Required props are fields, columns, dataSource, enableRowSelection and viewTableSetting (false or settings); optional attributes forwards table props, tableSize defaults middle.

Rendering and selection

Column names are dotted paths. Rendering priority is field.render, primary-key renderer, registered typed cell, then TextCell fallback. Field attributes are also spread onto the column and can override generated settings: use them deliberately. Primary keys/fixed columns pin to the start; action column pins to end. A table settings popover is attached to the action-column header only when both actionColumn and viewTableSetting are supplied. TableSettingPanel edits initialColumns and emits onChange; TableFieldItem is its row control. Neither persists configuration.

Selection keys are local to useViewTableState; clearSelectedRowKeys/reset clear the key array. ViewTableRef exposes those functions. onSelectChange receives selected records, onSortChanged receives an array of Ant Design sorter results only for sort actions. Changing dataSource does not automatically clear selection. mapToTableRecord chooses the primary key, existing key or row index. Table attributes are spread before fixed scroll/size/onChange props; those final settings remain implementation-owned.

Cell contracts

All cells take data: {value,record,index} and optional renderer-specific attributes. typedCellRender(type, attributes?) returns a (value,record,index) => ReactNode function or undefined for unknown type. Built-ins are text, primary-key, action/actions, tag/tags, datetime, calendar-time, image/image-group, link, currency and avatar; use the exported *_CELL_TYPE values instead of guessing keys.

DateTimeCell defaults YYYY-MM-DD HH:mm:ss; invalid/missing dates render -. CalendarTimeCell builds a relative calendar formatter from DEFAULT_CALENDAR_FORMATS. formatCurrency accepts numbers/strings, uses Intl.NumberFormat, and defaults CNY/symbol/2 decimals/zh-CN/grouping true/fallback -. Nonfinite parsed input uses fallback; invalid Intl options can still throw. This is display formatting, not decimal-money arithmetic. ActionCell renders truthy data.value as a link button and passes the current record to attributes.onClick; ActionsCell combines primary and secondary actions. AvatarCell uses isValidImageSrc to choose an image versus initials/text; ImageCell only checks for an empty value, and ImageGroupCell checks for a nonempty array. None performs a network availability check. User render/actions are not caught by a universal error boundary.

CellValue / attributes / empty behavior
TextCellStringified value; null, undefined and empty string render -; TextProps.children overrides display.
PrimaryKeyCellValue is link text, copyable defaults true; attributes.onClick receives record.
TagCell / TagsCellBlank tag renders nothing; tags uses a string array and attributes keyed by tag text, optional Space props.
LinkCellEmail values get mailto; other values default target blank and rel noopener noreferrer. Explicit href wins; javascript/data/vbscript schemes become #. Caller-supplied target/rel remain caller-owned.
ImageCellEmpty value renders Empty; ImageProps can override src and other image settings.
ImageGroupCellEmpty/nonarray value renders Empty; first image is the preview, more than one adds a count badge; default alt is Preview image.
AvatarCellEmpty value renders an empty Avatar, valid source an image, other text initials; attributes can override native Avatar props.
CurrencyCellformat in attributes configures formatCurrency; children overrides formatted text.
CalendarTimeCellDefault sameDay/nextDay/lastDay labels are Chinese today/tomorrow/yesterday with HH:mm; other dates use the full default date format.

Cell-specific props, CurrencyFormatOptions, CalendarFormats and all exact constants appear below. The component examples in Cells.stories.tsx cover interactive rendering.

Complete example

tsx
import { ViewTable } from '@ahoo-wang/fetcher-viewer';
interface Item {
  id: string;
  price: number;
}
export function Prices() {
  return (
    <ViewTable<Item>
      fields={[
        { name: 'id', label: 'ID', type: 'text', primaryKey: true },
        { name: 'price', label: 'Price', type: 'currency', primaryKey: false },
      ]}
      columns={['id', 'price'].map(name => ({
        name,
        key: name,
        fixed: false,
        hidden: false,
      }))}
      dataSource={[{ id: '1', price: 12.5 }]}
      enableRowSelection={false}
      viewTableSetting={false}
      attributes={{ pagination: false }}
    />
  );
}

Public signatures and types

These signatures follow declarations reachable from the current root entry. ? marks optional input; generics/interfaces only constrain compile-time types. Locate inherited and related types through the symbol index. Runtime defaults and failure behavior are described above.

isActionCellProps

ts
export function isActionCellProps(obj: any): obj is ActionCellProps;

packages/viewer/src/table/cell/ActionCell.tsx:58

ActionCell

ts
export function ActionCell<RecordType = any>(
  props: ActionCellProps<RecordType>,
): import('react').JSX.Element | null;

packages/viewer/src/table/cell/ActionCell.tsx:122

ACTION_CELL_TYPE

ts
declare const ACTION_CELL_TYPE: string;

packages/viewer/src/table/cell/ActionCell.tsx:23

ActionCellProps

ts
export interface ActionCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  Omit<ButtonProps, 'onClick'> & {
    onClick?: (record: RecordType) => void;
  }
> {}

packages/viewer/src/table/cell/ActionCell.tsx:50

ActionsCell

ts
export function ActionsCell<RecordType = any>(
  props: ActionsCellProps<RecordType>,
): React.JSX.Element;

packages/viewer/src/table/cell/ActionsCell.tsx:241

ACTIONS_CELL_TYPE

ts
declare const ACTIONS_CELL_TYPE: string;

packages/viewer/src/table/cell/ActionsCell.tsx:28

ActionsData

ts
export interface ActionsData<RecordType = any> {
  primaryAction:
    ActionCellProps<RecordType> | ((record: RecordType) => React.ReactNode);
  moreActionTitle?: string;
  secondaryActions:
    ActionCellProps<RecordType>[] | ((record: RecordType) => React.ReactNode[]);
}

packages/viewer/src/table/cell/ActionsCell.tsx:59

ActionsCellProps

ts
export interface ActionsCellProps<RecordType = any> extends CellProps<
  ActionsData<RecordType>,
  RecordType,
  {
    onClick: (actionKey: string, value: RecordType) => void;
  }
> {}

packages/viewer/src/table/cell/ActionsCell.tsx:97

AvatarCell

ts
export function AvatarCell<RecordType = any>(
  props: AvatarCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/AvatarCell.tsx:142

AVATAR_CELL_TYPE

ts
declare const AVATAR_CELL_TYPE: string;

packages/viewer/src/table/cell/AvatarCell.tsx:39

AvatarCellProps

ts
export interface AvatarCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  AvatarProps
> {}

packages/viewer/src/table/cell/AvatarCell.tsx:69

CalendarTimeCell

ts
export function CalendarTimeCell<RecordType = any>(
  props: CalendarTimeProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/CalendarTime.tsx:208

CalendarFormats

ts
export interface CalendarFormats {
  sameDay?: string;
  nextDay?: string;
  nextWeek?: string;
  lastDay?: string;
  lastWeek?: string;
  sameElse?: string;
}

packages/viewer/src/table/cell/CalendarTime.tsx:40

CALENDAR_CELL_TYPE

ts
declare const CALENDAR_CELL_TYPE: 'calendar-time';

packages/viewer/src/table/cell/CalendarTime.tsx:78

DEFAULT_CALENDAR_FORMATS

ts
declare const DEFAULT_CALENDAR_FORMATS: CalendarFormats;

packages/viewer/src/table/cell/CalendarTime.tsx:89

CalendarTimeProps

ts
export interface CalendarTimeProps<RecordType = any> extends CellProps<
  string | number | Date | Dayjs,
  RecordType,
  TextProps & {
    formats?: CalendarFormats;
  }
> {}

packages/viewer/src/table/cell/CalendarTime.tsx:129

cellRegistry

ts
declare const cellRegistry: TypedComponentRegistry<
  string,
  CellProps<any, any, any>
>;

packages/viewer/src/table/cell/cellRegistry.ts:67

formatCurrency

ts
export function formatCurrency(
  amount: number | string | null,
  options?: CurrencyFormatOptions,
): string;

Implementation defaults: options = DEFAULT_CURRENCY_FORMAT_OPTIONS.

packages/viewer/src/table/cell/currencyFormatter.ts:200

CurrencyFormatOptions

ts
export interface CurrencyFormatOptions {
  currency?: string;
  currencyDisplay?: Intl.NumberFormatOptionsCurrencyDisplay;
  decimals?: number;
  locale?: string;
  useGrouping?: boolean;
  fallback?: string;
}

packages/viewer/src/table/cell/currencyFormatter.ts:35

DEFAULT_CURRENCY_FORMAT_OPTIONS

ts
declare const DEFAULT_CURRENCY_FORMAT_OPTIONS: CurrencyFormatOptions;

packages/viewer/src/table/cell/currencyFormatter.ts:117

CurrencyCell

ts
export function CurrencyCell<RecordType = any>(
  props: CurrencyCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/CurrencyCell.tsx:298

CURRENCY_CELL_TYPE

ts
declare const CURRENCY_CELL_TYPE: string;

packages/viewer/src/table/cell/CurrencyCell.tsx:58

CurrencyAttributes

ts
export interface CurrencyAttributes extends TextProps {
  format?: CurrencyFormatOptions;
}

packages/viewer/src/table/cell/CurrencyCell.tsx:102

CurrencyCellProps

ts
export interface CurrencyCellProps<RecordType = any> extends CellProps<
  number | string,
  RecordType,
  CurrencyAttributes
> {}

packages/viewer/src/table/cell/CurrencyCell.tsx:163

DateTimeCell

ts
export function DateTimeCell<RecordType = any>(
  props: DateTimeCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/DateTimeCell.tsx:146

DATETIME_CELL_TYPE

ts
declare const DATETIME_CELL_TYPE: string;

packages/viewer/src/table/cell/DateTimeCell.tsx:42

DateTimeCellProps

ts
export interface DateTimeCellProps<RecordType = any> extends CellProps<
  string | number | Date | Dayjs,
  RecordType,
  TextProps & {
    format?: string | ((dayjs: Dayjs) => string);
  }
> {}

packages/viewer/src/table/cell/DateTimeCell.tsx:72

DEFAULT_DATE_TIME_FORMAT

ts
declare const DEFAULT_DATE_TIME_FORMAT: 'YYYY-MM-DD HH:mm:ss';

packages/viewer/src/table/cell/DateTimeCell.tsx:78

ImageCell

ts
export function ImageCell<RecordType = any>(
  props: ImageCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/ImageCell.tsx:148

IMAGE_CELL_TYPE

ts
declare const IMAGE_CELL_TYPE: string;

packages/viewer/src/table/cell/ImageCell.tsx:39

ImageCellProps

ts
export interface ImageCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  ImageProps
> {}

packages/viewer/src/table/cell/ImageCell.tsx:70

ImageGroupCell

ts
export function ImageGroupCell<RecordType = any>(
  props: ImageGroupCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/ImageGroupCell.tsx:149

IMAGE_GROUP_CELL_TYPE

ts
declare const IMAGE_GROUP_CELL_TYPE: string;

packages/viewer/src/table/cell/ImageGroupCell.tsx:40

ImageGroupCellProps

ts
export interface ImageGroupCellProps<RecordType = any> extends CellProps<
  string[],
  RecordType,
  PreviewGroupProps & Pick<ImageProps, 'alt'>
> {}

packages/viewer/src/table/cell/ImageGroupCell.tsx:71

LinkCell

ts
export function LinkCell<RecordType = any>(
  props: LinkCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/LinkCell.tsx:142

ts
declare const LINK_CELL_TYPE: string;

packages/viewer/src/table/cell/LinkCell.tsx:52

LinkCellProps

ts
export interface LinkCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  LinkProps
> {}

packages/viewer/src/table/cell/LinkCell.tsx:79

PrimaryKeyCell

ts
export function PrimaryKeyCell<RecordType>(
  props: PrimaryKeyCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/PrimaryKeyCell.tsx:29

PRIMARY_KEY_CELL_TYPE

ts
declare const PRIMARY_KEY_CELL_TYPE: string;

packages/viewer/src/table/cell/PrimaryKeyCell.tsx:19

PrimaryKeyCellProps

ts
export interface PrimaryKeyCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  Omit<LinkProps, 'onClick'> & {
    onClick?: (record: RecordType) => void;
  }
> {}

packages/viewer/src/table/cell/PrimaryKeyCell.tsx:21

TagCell

ts
export function TagCell<RecordType = any>(
  props: TagCellProps<RecordType>,
): import('react').JSX.Element | null;

packages/viewer/src/table/cell/TagCell.tsx:120

TAG_CELL_TYPE

ts
declare const TAG_CELL_TYPE: string;

packages/viewer/src/table/cell/TagCell.tsx:36

TagCellProps

ts
export interface TagCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  TagProps
> {}

packages/viewer/src/table/cell/TagCell.tsx:63

TagsCell

ts
export function TagsCell<RecordType = any>(
  props: TagsCellProps<RecordType>,
): import('react').JSX.Element | null;

packages/viewer/src/table/cell/TagsCell.tsx:149

TAGS_CELL_TYPE

ts
declare const TAGS_CELL_TYPE: string;

packages/viewer/src/table/cell/TagsCell.tsx:41

TagsCellProps

ts
export interface TagsCellProps<RecordType = any> extends CellProps<
  string[],
  RecordType,
  Record<string, TagProps>
> {
  space?: SpaceProps;
}

packages/viewer/src/table/cell/TagsCell.tsx:72

TextCell

ts
export function TextCell<RecordType = any>(
  props: TextCellProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/cell/TextCell.tsx:122

TEXT_CELL_TYPE

ts
declare const TEXT_CELL_TYPE: string;

packages/viewer/src/table/cell/TextCell.tsx:38

TextCellProps

ts
export interface TextCellProps<RecordType = any> extends CellProps<
  string,
  RecordType,
  TextProps
> {}

packages/viewer/src/table/cell/TextCell.tsx:64

typedCellRender

ts
export function typedCellRender<RecordType = any, Attributes = any>(
  type: CellType,
  attributes?: Attributes,
): CellRenderer<RecordType> | undefined;

packages/viewer/src/table/cell/TypedCell.tsx:117

CellType

ts
export type CellType = string;

packages/viewer/src/table/cell/TypedCell.tsx:31

CellRenderer

ts
export type CellRenderer<RecordType = any> = (
  value: any,
  record: RecordType,
  index: number,
) => React.ReactNode;

packages/viewer/src/table/cell/TypedCell.tsx:60

CellData

ts
export interface CellData<ValueType = any, RecordType = any> {
  value: ValueType;
  record: RecordType;
  index: number;
}

packages/viewer/src/table/cell/types.ts:47

CellProps

ts
export interface CellProps<
  ValueType = any,
  RecordType = any,
  Attributes = any,
> extends AttributesCapable<Attributes> {
  data: CellData<ValueType, RecordType>;
}

packages/viewer/src/table/cell/types.ts:100

CellComponent

ts
export type CellComponent<
  ValueType = any,
  RecordType = any,
  Attributes = any,
> = React.FC<CellProps<ValueType, RecordType, Attributes>>;

packages/viewer/src/table/cell/types.ts:147

parseDayjs

ts
export function parseDayjs(value: string | number | Date | Dayjs): Dayjs;

packages/viewer/src/table/cell/utils.ts:17

isNullOrUndefined

ts
export function isNullOrUndefined(value: any): value is null | undefined;

packages/viewer/src/table/cell/utils.ts:24

isValidImageSrc

ts
export function isValidImageSrc(value: any): value is string;

packages/viewer/src/table/cell/utils.ts:47

TableFieldItem

ts
export function TableFieldItem(
  props: TableFieldItemProps,
): import('react').JSX.Element;

packages/viewer/src/table/setting/TableFieldItem.tsx:69

TableFieldItemProps

ts
export interface TableFieldItemProps {
  columnDefinition: FieldDefinition;
  fixed: boolean;
  hidden: boolean;
  onVisibleChange: (hidden: boolean) => void;
}

packages/viewer/src/table/setting/TableFieldItem.tsx:47

TableSettingPanel

ts
export function TableSettingPanel(
  props: TableSettingPanelProps,
): React.JSX.Element;

packages/viewer/src/table/setting/TableSettingPanel.tsx:66

TableSettingPanelRef

ts
export interface TableSettingPanelRef {
  reset(): void;
}

packages/viewer/src/table/setting/TableSettingPanel.tsx:22

TableSettingPanelProps

ts
export interface TableSettingPanelProps extends RefAttributes<TableSettingPanelRef> {
  initialColumns: ViewColumn[];
  onChange?: (columns: ViewColumn[]) => void;
  fields: FieldDefinition[];
  className?: string;
}

packages/viewer/src/table/setting/TableSettingPanel.tsx:31

ColumnsCell

ts
export interface ColumnsCell {
  type: string;
  attributes?: any;
}

packages/viewer/src/table/types.ts:20

ViewTableActionColumn

ts
export interface ViewTableActionColumn<RecordType = any> {
  title: string;
  dataIndex?: string;
  actions: (record: RecordType) => ActionsData<RecordType>;
}

packages/viewer/src/table/types.ts:60

ViewTable

ts
export function ViewTable<RecordType>(
  props: ViewTableProps<RecordType>,
): import('react').JSX.Element;

packages/viewer/src/table/ViewTable.tsx:115

ViewTableRef

ts
export interface ViewTableRef {
  clearSelectedRowKeys: () => void;
  reset: () => void;
}

packages/viewer/src/table/ViewTable.tsx:44

ViewTableProps

ts
export interface ViewTableProps<RecordType = any>
  extends
    AttributesCapable<Omit<TableProps<RecordType>, 'columns' | 'dataSource'>>,
    PrimaryKeyClickHandlerCapable<RecordType>,
    ViewTableSettingCapable,
    TableSizeCapable,
    RefAttributes<ViewTableRef> {
  fields: FieldDefinition[];
  columns: ViewColumn[];
  onColumnsChange?: (columns: ViewColumn[]) => void;
  actionColumn?: ViewTableActionColumn<RecordType>;
  dataSource: RecordType[];
  enableRowSelection: boolean;
  onSortChanged?: (sorter: SorterResult<RecordType>[]) => void;
  onSelectChange?: (items: RecordType[]) => void;
  viewTableSetting: false | ViewTableSetting;
  loading?: boolean;
}

packages/viewer/src/table/ViewTable.tsx:57

useViewTableState

ts
export function useViewTableState(): ViewTableStateReturn;

packages/viewer/src/table/hooks/useViewTableState.ts:52

ViewTableStateReturn

ts
export interface ViewTableStateReturn {
  selectedRowKeys: Key[];
  setSelectedRowKeys: (keys: Key[]) => void;
  reset: () => void;
  clearSelectedRowKeys: () => void;
}

packages/viewer/src/table/hooks/useViewTableState.ts:21

Models and state ownership · View and Viewer composition · Saved-view panels and persistence callbacks · FetcherViewer remote integration · Filters and editable panels · Registries, inputs and fullscreen button · Toolbar, refresh and locale

Released under the Apache License 2.0.