qlik-oss/sn-table

View on GitHub
src/table/types.ts

Summary

Maintainability
A
3 hrs
Test Coverage
import { Direction, TableCellProps } from "@mui/material";
import { stardust } from "@nebula.js/stardust";
import type { ExtendedTheme } from "@qlik/nebula-table-utils/lib/hooks/use-extended-theme/types";
import {
  Announce,
  ApplyColumnWidths,
  Cell,
  ChangeSortOrder,
  Column,
  ExtendedSelectionAPI,
  PageInfo,
  Row,
  SetPageInfo,
  TableData,
  TableLayout,
  TotalsPosition,
  ViewService,
} from "../types";
import { FocusTypes, SelectionActions } from "./constants";

interface Action<T = any> {
  type: T;
}

export interface SelectPayload {
  cell: Cell;
  announce: Announce;
  evt: React.KeyboardEvent | React.MouseEvent;
}

export interface SelectAction extends Action<SelectionActions.SELECT> {
  payload: SelectPayload;
}
export interface SelectMouseDownAction extends Action<SelectionActions.SELECT_MOUSE_DOWN> {
  payload: { cell: Cell; mouseupOutsideCallback(): void };
}
export interface SelectMouseUpAction extends Action<SelectionActions.SELECT_MOUSE_UP> {
  payload: SelectPayload;
}
export interface SelectMultiAddAction extends Action<SelectionActions.SELECT_MULTI_ADD> {
  payload: SelectPayload;
}
export type SelectMultiEndAction = Action<SelectionActions.SELECT_MULTI_END>;
export type ResetAction = Action<SelectionActions.RESET>;
export type ClearAction = Action<SelectionActions.CLEAR>;
export interface UpdatePageRowsAction extends Action<SelectionActions.UPDATE_PAGE_ROWS> {
  payload: { pageRows: Row[] };
}

export type SelectionActionTypes =
  | SelectAction
  | SelectMouseDownAction
  | SelectMouseUpAction
  | SelectMultiAddAction
  | SelectMultiEndAction
  | ResetAction
  | ClearAction
  | UpdatePageRowsAction;

export type SelectionDispatch = React.Dispatch<SelectionActionTypes>;

export interface SelectionState {
  pageRows: Row[];
  rows: Record<string, number>;
  colIdx: number;
  api: ExtendedSelectionAPI | undefined;
  isSelectMultiValues: boolean;
  firstCell?: Cell;
  mouseupOutsideCallback?(): void;
}
export interface GeneratedStyling {
  borderBottomColor: string;
  borderTopColor: string;
  borderLeftColor: string;
  borderRightColor: string;
  lastRowBottomBorder?: string;
  padding?: string;
  fontFamily?: string;
  color?: string;
  fontSize?: string; // following the theme format so this should always be a string
  background?: string;
  hoverBackground?: string;
  activeBackground?: string;
  hoverColors?: {
    background: string;
    color: string;
  };
}

export interface TableStyling {
  head: GeneratedStyling;
  body: GeneratedStyling;
  totals: GeneratedStyling;
}

export interface ExtendedApp extends EngineAPI.IApp {
  id?: string;
}

export type FocusedCellCoord = [number, number];
export type SetFocusedCellCoord = React.Dispatch<React.SetStateAction<FocusedCellCoord>>;

export interface ContextValue {
  headRowHeight: number;
  setHeadRowHeight: React.Dispatch<React.SetStateAction<number>>;
  focusedCellCoord: FocusedCellCoord;
  setFocusedCellCoord: SetFocusedCellCoord;
  selectionState: SelectionState;
  selectionDispatch: SelectionDispatch;
  hoverIndex: number;
  setHoverIndex: React.Dispatch<React.SetStateAction<number>>;
  columnWidths: number[];
  setColumnWidths: React.Dispatch<React.SetStateAction<number[]>>;
  baseProps: {
    app: ExtendedApp | undefined;
    selectionsAPI: ExtendedSelectionAPI | undefined;
    layout: TableLayout;
    model: EngineAPI.IGenericObject | undefined;
    translator: stardust.Translator;
    interactions: stardust.Interactions;
    theme: ExtendedTheme;
    keyboard: stardust.Keyboard;
    rootElement: HTMLElement;
    embed: stardust.Embed;
    changeSortOrder: ChangeSortOrder;
    applyColumnWidths: ApplyColumnWidths;
    styling: TableStyling;
    rect: stardust.Rect;
    viewService: ViewService;
  };
  tableData: TableData;
  setYScrollbarWidth: (width: number) => void;
  pageInfo?: PageInfo;
  setPage?: stardust.SetStateFn<number>;
  initialDataPages?: EngineAPI.INxDataPage[];
  showRightBorder: boolean;
  featureFlags: FeatureFlags;
}

export type FeatureFlags = Record<keyof typeof AvaliableFlags, boolean>;

export enum AvaliableFlags {
  isNewHeadCellMenuEnabled,
}

export interface CellStyle {
  background: string | undefined; // This is always set but could be undefined in the theme
  color: string;
  selectedCellClass?: string;
}

export interface HandleWrapperKeyDownProps {
  evt: React.KeyboardEvent;
  totalRowCount: number;
  page: number;
  rowsPerPage: number;
  handleChangePage(pageIdx: number): void;
  setShouldRefocus(): void;
  keyboard: stardust.Keyboard;
  isSelectionMode: boolean | undefined;
}

export interface HandleHeadKeyDownProps {
  evt: React.KeyboardEvent;
  rootElement: HTMLElement;
  cellCoord: FocusedCellCoord;
  setFocusedCellCoord: SetFocusedCellCoord;
  isInteractionEnabled: boolean;
  handleOpenMenu?: (evt: React.KeyboardEvent) => void;
  isNewHeadCellMenuEnabled: boolean;
}

export interface HandleHeadMouseDownProps {
  evt: React.MouseEvent;
  rootElement: HTMLElement;
  cellCoord: FocusedCellCoord;
  setFocusedCellCoord: SetFocusedCellCoord;
  keyboard: stardust.Keyboard;
  isInteractionEnabled: boolean;
}

export interface BodyArrowHelperProps {
  evt: React.KeyboardEvent;
  rootElement: HTMLElement;
  cell: Cell;
  selectionDispatch: SelectionDispatch;
  isSelectionsEnabled: boolean;
  setFocusedCellCoord: SetFocusedCellCoord;
  announce: Announce;
  totalsPosition: TotalsPosition;
  isSelectionMode: boolean | undefined;
  isNewHeadCellMenuEnabled: boolean;
}

export interface HandleBodyKeyDownProps {
  evt: React.KeyboardEvent;
  rootElement: HTMLElement;
  cell: Cell;
  selectionDispatch: SelectionDispatch;
  isSelectionsEnabled: boolean;
  setFocusedCellCoord: SetFocusedCellCoord;
  announce: Announce;
  keyboard: stardust.Keyboard;
  totalsPosition: TotalsPosition;
  paginationNeeded: boolean;
  selectionsAPI: ExtendedSelectionAPI | undefined;
  isNewHeadCellMenuEnabled: boolean;
}

export interface CellFocusProps {
  focusType: FocusTypes;
  cell: HTMLElement | null | undefined;
}

export interface MoveFocusWithArrowProps {
  evt: React.KeyboardEvent;
  rootElement: HTMLElement;
  cellCoord: FocusedCellCoord;
  setFocusedCellCoord: SetFocusedCellCoord;
  focusType: FocusTypes;
  allowedRows?: {
    top: number;
    bottom: number;
  };
}

export interface HandleResetFocusProps {
  focusedCellCoord: FocusedCellCoord;
  rootElement: HTMLElement;
  shouldRefocus: React.MutableRefObject<boolean>;
  isSelectionMode: boolean | undefined;
  setFocusedCellCoord: SetFocusedCellCoord;
  keyboard: stardust.Keyboard;
  announce: Announce;
  totalsPosition: TotalsPosition;
  isNewHeadCellMenuEnabled: boolean;
}

export interface ContextProviderProps {
  children: JSX.Element;
  app: EngineAPI.IApp | undefined;
  tableData: TableData;
  selectionsAPI: ExtendedSelectionAPI | undefined;
  cellCoordMock?: FocusedCellCoord;
  layout: TableLayout;
  model: EngineAPI.IGenericObject;
  translator: stardust.Translator;
  interactions: stardust.Interactions;
  theme: ExtendedTheme;
  keyboard: stardust.Keyboard;
  rootElement: HTMLElement;
  embed: stardust.Embed;
  changeSortOrder: ChangeSortOrder;
  applyColumnWidths: ApplyColumnWidths;
  rect: stardust.Rect;
  pageInfo?: PageInfo;
  setPage?: stardust.SetStateFn<number>;
  initialDataPages?: EngineAPI.INxDataPage[];
  viewService: ViewService;
  isNewHeadCellMenuEnabled: boolean;
}

export interface RenderProps {
  direction: Direction | undefined;
  selectionsAPI: ExtendedSelectionAPI | undefined;
  rootElement: HTMLElement;
  layout: TableLayout;
  changeSortOrder: ChangeSortOrder;
  rect: stardust.Rect;
  tableData: TableData;
  pageInfo: PageInfo;
  setPageInfo: SetPageInfo;
  interactions: stardust.Interactions;
  translator: stardust.Translator;
  theme: ExtendedTheme;
  keyboard: stardust.Keyboard;
  footerContainer: HTMLElement | undefined;
  announce: Announce;
  model: EngineAPI.IGenericObject;
  app?: EngineAPI.IApp;
  embed: stardust.Embed;
  applyColumnWidths: ApplyColumnWidths;
  viewService: ViewService;
  isNewHeadCellMenuEnabled: boolean;
}

export interface TableWrapperProps {
  direction: Direction | undefined;
  pageInfo: PageInfo;
  setPageInfo: SetPageInfo;
  footerContainer: HTMLElement | undefined;
  announce: Announce;
}

export interface HeadCellContentProps {
  open: boolean;
  setOpen: React.Dispatch<React.SetStateAction<boolean>>;
  children: JSX.Element;
  column: Column;
  isInteractionEnabled: boolean;
}

export interface HeadCellMenuProps {
  column: Column;
  tabIndex: number;
}

export type MenuItemGroup = HeadCellMenuItem[];

export interface HeadCellMenuItem {
  autoFocus?: boolean;
  id: number;
  icon: React.ReactElement;
  itemTitle: string;
  enabled: boolean;
  onClick?: (evt: React.MouseEvent) => void;
  subMenus?: MenuItemGroup[];
}

export interface TableBodyWrapperProps {
  announce: Announce;
  setShouldRefocus(): void;
  tableWrapperRef: React.MutableRefObject<HTMLDivElement | null>;
}

export interface PaginationContentProps {
  direction?: "ltr" | "rtl";
  pageInfo: PageInfo;
  setPageInfo: SetPageInfo;
  footerContainer?: HTMLElement;
  announce: Announce;
  isSelectionMode: boolean | undefined;
  handleChangePage(pageIdx: number): void;
}

export interface AdjusterProps {
  column: Column;
  isLastColumn: boolean;
  onColumnResize?: () => void;
  setIsAdjustingWidth: (isAdjusting: boolean) => void;
}

export interface FooterWrapperProps {
  children: JSX.Element;
  footerContainer?: HTMLElement;
  withoutBorders?: boolean;
  paginationNeeded?: boolean;
}
export interface CellHOCProps extends TableCellProps {
  styling: CellStyle;
  cell: Cell;
  column: Column;
  announce: Announce;
}

export type CellHOC = (props: CellHOCProps) => JSX.Element;

export type EstimateWidth = (column: Column) => number;