import { default as ExcelJS } from 'exceljs'; import { default as React } from 'react'; export type CellEditorType = "text" | "number" | "select" | "checkbox" | "date" | "custom"; export type SpreadsheetMode = "view" | "edit" | "create"; export type SpreadsheetVariant = "default" | "compact" | "pointage" | "tasks"; export type CellPosition = { rowIndex: number; columnKey: string; }; export type SelectionRange = { startRow: number; endRow: number; startCol: number; endCol: number; }; export type SelectionMode = "cell" | "row" | "column"; export type NavigationDirection = "down" | "up" | "right" | "left"; export interface PersistedSheetState { searchTerm: string; sortColumn: string | null; sortDirection: "asc" | "desc"; columnFilters: Record; } /** * SpreadsheetColumn is structurally identical to CoreColumn + React render extensions. * Fields below duplicate CoreColumn (from @polycyphers/spreadsheet-core) so the published * .d.ts is self-contained and doesn't force consumers to install the core package. */ export interface SpreadsheetColumn { key: string; label: string; width: number; minWidth?: number; maxWidth?: number; align?: "left" | "center" | "right"; editable?: boolean; sortable?: boolean; filterable?: boolean; type?: CellEditorType; options?: Array<{ label: string; value: any; }>; headerRender?: (column: SpreadsheetColumn) => React.ReactNode; render?: (value: any, row: T, index: number) => React.ReactNode; renderEditor?: (value: any, row: T, index: number, onChange: (value: any) => void, onClose: () => void, onValueChange?: (value: any) => void) => React.ReactNode; formatter?: (value: any, row: T, index: number) => any; parser?: (value: any, row: T, index: number, column: SpreadsheetColumn) => any; cellClassName?: (value: any, row: T, index: number) => string | undefined; } export interface SpreadsheetExcelConfig { fileName?: string; sheetName?: string; exportBuilder?: (rows: T[], columns: SpreadsheetColumn[]) => Promise; importParser?: (workbook: ExcelJS.Workbook, columns: SpreadsheetColumn[], rows: T[]) => Promise; /** When true, always auto-generate columns from Excel headers (ignores existing column definitions) */ freeFormImport?: boolean; /** * When true, import the workbook as a faithful raw grid — Excel-letter columns * (A, B, C…), every sheet row kept as data (no header row consumed), merges + * styles preserved, and formula cells shown as their cached result. Use for * read-only viewers that must mirror the source file (banners, merged titles, * totals) rather than inferring a header row. Takes precedence over `freeFormImport`. */ rawGrid?: boolean; } export interface CellBorder { style: "thin" | "medium" | "thick" | "dashed" | "dotted" | "double" | "hair" | "mediumDashed" | "dashDot" | "mediumDashDot" | "dashDotDot" | "mediumDashDotDot" | "slantDashDot"; color?: string; } export interface CellStyle { fontBold?: boolean; fontItalic?: boolean; fontUnderline?: boolean; fontStrikethrough?: boolean; fontSize?: number; fontColor?: string; fontName?: string; bgColor?: string; textAlign?: "left" | "center" | "right"; verticalAlign?: "top" | "middle" | "bottom"; numFmt?: string; wrapText?: boolean; borderTop?: CellBorder; borderBottom?: CellBorder; borderLeft?: CellBorder; borderRight?: CellBorder; } /** * Key format: "rowIndex:colIndex" (both 0-based, data rows only — header excluded) * Example: "0:2" = first data row, third column */ export type CellStyleMap = Record; export interface ExcelImportMeta { mergedCells?: Array<{ row: number; col: number; rowspan: number; colspan: number; }>; pinning?: { columns?: number; rows?: number; }; /** column key → width in px */ columnWidths?: Record; /** rowIndex (0-based data rows) → height in px */ rowHeights?: Record; cellStyles?: CellStyleMap; sheetNames?: string[]; /** All parsed sheets, populated for multi-sheet workbooks */ allSheets?: ExcelSheetData[]; } export interface ExcelSheetData { name: string; rows: Record[]; columns: SpreadsheetColumn[]; cellStyles?: CellStyleMap; mergedCells?: Array<{ row: number; col: number; rowspan: number; colspan: number; }>; columnWidths?: Record; rowHeights?: Record; pinning?: { columns?: number; rows?: number; }; } export interface SpreadsheetRef { exportToExcel: () => Promise; importFromExcel: (file: File) => Promise; exportToCSV: (fileName?: string) => void; undo: () => void; redo: () => void; resetColumnWidths: () => void; getData: () => T[]; } /** Inline row creation feature (from SiteTasks) */ export interface InlineRowCreationConfig { /** Template function to create empty row data */ template: () => Partial; /** Callback when row is created */ onCreateRow: (data: T) => Promise; /** Optional validation before create */ validateBeforeCreate?: (data: Partial) => { valid: boolean; errors?: string[]; }; /** Position of the creation row */ position?: "top" | "bottom"; /** Button text */ buttonText?: string; /** Button icon */ buttonIcon?: string; } /** Row height resize feature (from SiteTasks) */ export interface RowHeightResizeConfig { enabled: boolean; minHeight?: number; maxHeight?: number; /** LocalStorage key for persisting heights */ persistKey?: string; } /** Context menu feature (from SiteTasks) */ export interface ContextMenuItem { label: string; action: string; icon?: string; disabled?: boolean | ((row: any, index: number) => boolean); danger?: boolean; divider?: boolean; } export interface ContextMenuConfig { items: ContextMenuItem[]; onAction: (action: string, row: any, rowIndex: number) => void; } /** Cost code dialog feature (from Pointage) */ export interface CostCodeDialogConfig { enabled: boolean; fetchCostCodes: () => Promise; onSelect: (rowIndex: number, costCodeId: number, costCode: any) => void; /** Column key that triggers cost code dialog */ triggerColumn?: string; } /** Hour validation feature (from Pointage) */ export interface HourValidationConfig { maxCellHours: number; maxDailyHours: number; hourColumns: string[]; onValidationError?: (errors: HourValidationError[]) => void; } export interface HourValidationError { rowIndex: number; columnKey: string; type: "cell_limit" | "daily_limit"; value: number; limit: number; message: string; } /** Calculated fields feature (from Progress) */ export interface CalculatedFieldConfig { /** Target column to update */ targetColumn: string; /** Calculate function */ calculate: (row: T, allRows: T[]) => any; /** Columns that trigger recalculation */ dependencies: string[]; /** Optional format function for display */ format?: (value: any) => string; } /** Dirty tracking feature (from Progress) */ export interface DirtyTrackingConfig { enabled: boolean; /** CSS class for dirty rows */ dirtyClassName?: string; /** Callback when dirty state changes */ onDirtyChange?: (dirtyRowIds: (string | number)[]) => void; } /** Dynamic columns feature (from MaterialBudget) */ export interface DynamicColumnConfig { enabled: boolean; /** Patterns to exclude from auto-generation */ excludePatterns?: RegExp[]; /** Custom formatters by column key pattern */ formatters?: Record string>; /** Custom width map by column key pattern */ widthMap?: Record; /** Custom label map */ labelMap?: Record; /** Sort columns alphabetically */ sortAlphabetically?: boolean; /** Filter out columns with all empty/zero values */ filterEmptyColumns?: boolean; } /** Multi-row selection feature (from SiteTasks) */ export interface MultiRowSelectionConfig { enabled: boolean; /** Callback when selection changes */ onSelectionChange?: (selectedRowIndexes: number[]) => void; /** Allow Ctrl+click for non-contiguous selection */ allowNonContiguous?: boolean; } /** Position summary view feature (from Pointage) */ export interface PositionSummaryConfig { enabled: boolean; /** Field to group by */ groupByField: string; /** Summary columns to display */ summaryColumns?: Array<{ key: string; label: string; aggregate: "sum" | "count" | "avg" | "min" | "max"; sourceColumn: string; formatter?: (value: any) => string; }>; } export interface SpreadsheetFeatures { /** Inline row creation (SiteTasks feature) */ inlineRowCreation?: InlineRowCreationConfig; /** Row height resize (SiteTasks feature) */ rowHeightResize?: boolean | RowHeightResizeConfig; /** Context menu (SiteTasks feature) */ contextMenu?: ContextMenuConfig; /** Multi-row selection (SiteTasks feature) */ multiRowSelection?: boolean | MultiRowSelectionConfig; /** Cost code dialog (Pointage feature) */ costCodeDialog?: CostCodeDialogConfig; /** Hour validation (Pointage feature) */ hourValidation?: HourValidationConfig; /** Position summary view (Pointage feature) */ positionSummary?: PositionSummaryConfig; /** Calculated fields (Progress feature) */ calculatedFields?: CalculatedFieldConfig[]; /** Dirty tracking (Progress feature) */ dirtyTracking?: boolean | DirtyTrackingConfig; /** Dynamic columns (MaterialBudget feature) */ dynamicColumns?: DynamicColumnConfig; } export interface CellInfo { row: T; rowIndex: number; column: SpreadsheetColumn; columnKey: string; columnIndex: number; value: any; } export interface PluginContext { /** Current data */ data: T[]; /** Column definitions */ columns: SpreadsheetColumn[]; /** Current mode */ mode: SpreadsheetMode; /** Currently selected cell */ selectedCell: CellPosition | null; /** Selection range */ selectionRange: SelectionRange | null; /** Update cell value */ updateCellValue: (rowIndex: number, columnKey: string, value: any) => void; /** Set selected cell */ setSelectedCell: (cell: CellPosition | null) => void; /** Get row by index */ getRow: (index: number) => T | undefined; /** Get column by key */ getColumn: (key: string) => SpreadsheetColumn | undefined; /** Force re-render */ forceUpdate: () => void; } export interface SpreadsheetPlugin { /** Unique plugin name */ name: string; onMount?: (context: PluginContext) => void | (() => void); onUnmount?: () => void; onDataChange?: (data: T[], prevData: T[]) => void; renderCellOverlay?: (cell: CellInfo) => React.ReactNode; renderRowOverlay?: (row: T, index: number) => React.ReactNode; renderToolbarExtension?: (context: PluginContext) => React.ReactNode; renderFooterExtension?: (context: PluginContext) => React.ReactNode; onCellClick?: (cell: CellInfo, event: React.MouseEvent) => boolean | void; onCellDoubleClick?: (cell: CellInfo, event: React.MouseEvent) => boolean | void; onCellChange?: (cell: CellInfo, newValue: any, prevValue: any) => any; onRowClick?: (row: T, index: number, event: React.MouseEvent) => boolean | void; onKeyDown?: (event: React.KeyboardEvent, cell: CellInfo | null) => boolean | void; onContextMenu?: (row: T, index: number, event: React.MouseEvent) => boolean | void; transformData?: (data: T[]) => T[]; transformColumns?: (columns: SpreadsheetColumn[]) => SpreadsheetColumn[]; validateCell?: (cell: CellInfo, newValue: any) => { valid: boolean; message?: string; }; } export interface SheetTab { key: string; label: string; icon?: string; count?: number | string; disabled?: boolean; } export interface SpreadsheetProps { data: T[]; columns: SpreadsheetColumn[]; mode?: SpreadsheetMode; editContextKey?: string | number | null; loading?: boolean; emptyMessage?: string; containerClassName?: string; persistKey?: string; overscan?: number; rowHeight?: number | ((row: T, index: number) => number); maxHeight?: number | string; minBufferRows?: number; minRenderRows?: number; summaryRow?: (rows: T[], context?: { gridTemplateColumns: string; columnWidths: Record; }) => React.ReactNode; footer?: React.ReactNode; slotBelowHeader?: React.ReactNode; toolbar?: React.ReactNode; sheetTabs?: SheetTab[]; activeSheetTab?: string; onSheetTabChange?: (key: string) => void; onCellChange?: (rowIndex: number, columnKey: string, value: any, row: T) => void; onRowChange?: (rowIndex: number, row: T) => void; onDataChange?: (rows: T[]) => void; onRowClick?: (row: T, index: number) => void; onRowDoubleClick?: (row: T, index: number) => void; onRowContextMenu?: (row: T, index: number, event: React.MouseEvent) => void; onSelectionChange?: (cell: CellPosition | null, row?: T | null) => void; rowClassName?: (row: T, index: number) => string | undefined; /** * Per-row inline style. Wins over package CSS regardless of stylesheet order * (use this when a Tailwind class like `bg-primary/10` gets clobbered by the * package's row background rules). */ rowStyle?: (row: T, index: number) => React.CSSProperties | undefined; rowNumberRender?: (row: T, index: number) => React.ReactNode; rowNumberTitle?: (row: T, index: number) => string | undefined; isCellEditable?: (row: T, column: SpreadsheetColumn, index: number) => boolean; actionsRender?: (row: T, index: number) => React.ReactNode; actionsColumnWidth?: number; actionsColumnResizable?: boolean; getRowId?: (row: T, index: number) => string | number; scrollToRowId?: string | number | null; toolbarLeft?: React.ReactNode; /** Content rendered at the very start (left) of the formula bar, before cell ref */ formulaBarStart?: React.ReactNode; hideFormulaBar?: boolean; /** * When `false`, the formula bar is hidden and its vertical space is collapsed. * Defaults to `true` (formula bar visible) for backwards compatibility. * Equivalent to (and overrides) the legacy `hideFormulaBar` prop when set. */ showFormulaBar?: boolean; /** * When `false`, only `data.length` rows are rendered (plus the header) — no * empty padding rows are added to fill the viewport. Useful for small bounded * lists (cost ledgers, approvals, phase trees) where padding leaves a big * empty band at the bottom. * * Defaults to `true` (Excel-style padding) for backwards compatibility. */ padRows?: boolean; /** When provided, search is delegated to the parent (e.g. server-side) instead of filtering client-side */ onSearchChange?: (search: string) => void; /** AI integration: when set, adds data-ai-id attributes to rows, cells, tabs, and controls. */ aiId?: string; allowKeyboardNavigation?: boolean; allowColumnResize?: boolean; allowFilters?: boolean; allowSorting?: boolean; excelConfig?: SpreadsheetExcelConfig; pinning?: { columns?: number; rows?: number; }; mergedCells?: Array<{ row: number; col: number; rowspan: number; colspan: number; }>; showStatusBar?: boolean; plugins?: SpreadsheetPlugin[]; features?: SpreadsheetFeatures; variant?: SpreadsheetVariant; } export type DeepPartial = { [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]; }; /** Helper type for extracting row type from SpreadsheetProps */ export type ExtractRowType

= P extends SpreadsheetProps ? T : never; export declare const DEFAULT_ROW_HEIGHT = 32; export declare const DEFAULT_OVERSCAN = 8; export declare const DEFAULT_MIN_BUFFER_ROWS = 8; export declare const DEFAULT_MIN_RENDER_ROWS = 30; export declare const DEFAULT_COLUMN_MIN_WIDTH = 60; export declare const DEFAULT_COLUMN_MAX_WIDTH = 600; //# sourceMappingURL=types.d.ts.map