@alaarab/ogrid-react 2.0.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/dist/esm/components/BaseInlineCellEditor.js +112 -0
- package/dist/esm/components/CellErrorBoundary.js +43 -0
- package/dist/esm/components/EmptyState.js +19 -0
- package/dist/esm/components/GridContextMenu.js +35 -0
- package/dist/esm/components/MarchingAntsOverlay.js +110 -0
- package/dist/esm/components/OGridLayout.js +91 -0
- package/dist/esm/components/SideBar.js +122 -0
- package/dist/esm/components/StatusBar.js +6 -0
- package/dist/esm/hooks/index.js +25 -0
- package/dist/esm/hooks/useActiveCell.js +62 -0
- package/dist/esm/hooks/useCellEditing.js +15 -0
- package/dist/esm/hooks/useCellSelection.js +327 -0
- package/dist/esm/hooks/useClipboard.js +161 -0
- package/dist/esm/hooks/useColumnChooserState.js +62 -0
- package/dist/esm/hooks/useColumnHeaderFilterState.js +180 -0
- package/dist/esm/hooks/useColumnResize.js +92 -0
- package/dist/esm/hooks/useContextMenu.js +21 -0
- package/dist/esm/hooks/useDataGridState.js +313 -0
- package/dist/esm/hooks/useDateFilterState.js +34 -0
- package/dist/esm/hooks/useDebounce.js +35 -0
- package/dist/esm/hooks/useFillHandle.js +195 -0
- package/dist/esm/hooks/useFilterOptions.js +40 -0
- package/dist/esm/hooks/useInlineCellEditorState.js +44 -0
- package/dist/esm/hooks/useKeyboardNavigation.js +419 -0
- package/dist/esm/hooks/useLatestRef.js +11 -0
- package/dist/esm/hooks/useMultiSelectFilterState.js +59 -0
- package/dist/esm/hooks/useOGrid.js +465 -0
- package/dist/esm/hooks/usePeopleFilterState.js +68 -0
- package/dist/esm/hooks/useRichSelectState.js +58 -0
- package/dist/esm/hooks/useRowSelection.js +80 -0
- package/dist/esm/hooks/useSideBarState.js +39 -0
- package/dist/esm/hooks/useTableLayout.js +77 -0
- package/dist/esm/hooks/useTextFilterState.js +25 -0
- package/dist/esm/hooks/useUndoRedo.js +83 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/storybook/index.js +1 -0
- package/dist/esm/storybook/mockData.js +73 -0
- package/dist/esm/types/columnTypes.js +1 -0
- package/dist/esm/types/dataGridTypes.js +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utils/dataGridViewModel.js +220 -0
- package/dist/esm/utils/gridRowComparator.js +2 -0
- package/dist/esm/utils/index.js +5 -0
- package/dist/types/components/BaseInlineCellEditor.d.ts +33 -0
- package/dist/types/components/CellErrorBoundary.d.ts +25 -0
- package/dist/types/components/EmptyState.d.ts +26 -0
- package/dist/types/components/GridContextMenu.d.ts +18 -0
- package/dist/types/components/MarchingAntsOverlay.d.ts +15 -0
- package/dist/types/components/OGridLayout.d.ts +37 -0
- package/dist/types/components/SideBar.d.ts +30 -0
- package/dist/types/components/StatusBar.d.ts +24 -0
- package/dist/types/hooks/index.d.ts +48 -0
- package/dist/types/hooks/useActiveCell.d.ts +13 -0
- package/dist/types/hooks/useCellEditing.d.ts +16 -0
- package/dist/types/hooks/useCellSelection.d.ts +22 -0
- package/dist/types/hooks/useClipboard.d.ts +30 -0
- package/dist/types/hooks/useColumnChooserState.d.ts +27 -0
- package/dist/types/hooks/useColumnHeaderFilterState.d.ts +73 -0
- package/dist/types/hooks/useColumnResize.d.ts +23 -0
- package/dist/types/hooks/useContextMenu.d.ts +19 -0
- package/dist/types/hooks/useDataGridState.d.ts +137 -0
- package/dist/types/hooks/useDateFilterState.d.ts +19 -0
- package/dist/types/hooks/useDebounce.d.ts +9 -0
- package/dist/types/hooks/useFillHandle.d.ts +33 -0
- package/dist/types/hooks/useFilterOptions.d.ts +16 -0
- package/dist/types/hooks/useInlineCellEditorState.d.ts +24 -0
- package/dist/types/hooks/useKeyboardNavigation.d.ts +47 -0
- package/dist/types/hooks/useLatestRef.d.ts +6 -0
- package/dist/types/hooks/useMultiSelectFilterState.d.ts +24 -0
- package/dist/types/hooks/useOGrid.d.ts +52 -0
- package/dist/types/hooks/usePeopleFilterState.d.ts +25 -0
- package/dist/types/hooks/useRichSelectState.d.ts +22 -0
- package/dist/types/hooks/useRowSelection.d.ts +22 -0
- package/dist/types/hooks/useSideBarState.d.ts +20 -0
- package/dist/types/hooks/useTableLayout.d.ts +27 -0
- package/dist/types/hooks/useTextFilterState.d.ts +16 -0
- package/dist/types/hooks/useUndoRedo.d.ts +23 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/storybook/index.d.ts +2 -0
- package/dist/types/storybook/mockData.d.ts +37 -0
- package/dist/types/types/columnTypes.d.ts +25 -0
- package/dist/types/types/dataGridTypes.d.ts +152 -0
- package/dist/types/types/index.d.ts +3 -0
- package/dist/types/utils/dataGridViewModel.d.ts +161 -0
- package/dist/types/utils/gridRowComparator.d.ts +2 -0
- package/dist/types/utils/index.d.ts +6 -0
- package/package.json +46 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { GridContextMenuHandlerProps } from '../utils';
|
|
3
|
+
export interface GridContextMenuClassNames {
|
|
4
|
+
contextMenu?: string;
|
|
5
|
+
contextMenuItem?: string;
|
|
6
|
+
contextMenuItemLabel?: string;
|
|
7
|
+
contextMenuItemShortcut?: string;
|
|
8
|
+
contextMenuDivider?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GridContextMenuProps extends GridContextMenuHandlerProps {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
hasSelection: boolean;
|
|
14
|
+
canUndo: boolean;
|
|
15
|
+
canRedo: boolean;
|
|
16
|
+
classNames?: GridContextMenuClassNames;
|
|
17
|
+
}
|
|
18
|
+
export declare function GridContextMenu(props: GridContextMenuProps): React.ReactElement;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ISelectionRange } from '../types';
|
|
3
|
+
export interface MarchingAntsOverlayProps {
|
|
4
|
+
/** Ref to the positioned container that wraps the table (must have position: relative) */
|
|
5
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
6
|
+
/** Current selection range — solid green border */
|
|
7
|
+
selectionRange: ISelectionRange | null;
|
|
8
|
+
/** Copy range — animated dashed border */
|
|
9
|
+
copyRange: ISelectionRange | null;
|
|
10
|
+
/** Cut range — animated dashed border */
|
|
11
|
+
cutRange: ISelectionRange | null;
|
|
12
|
+
/** Column offset — 1 when checkbox column is present, else 0 */
|
|
13
|
+
colOffset: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function MarchingAntsOverlay({ containerRef, selectionRange, copyRange, cutRange, colOffset, }: MarchingAntsOverlayProps): React.ReactElement | null;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single layout structure for OGrid: unified bordered container with
|
|
3
|
+
* toolbar strip, grid area (optionally with sidebar), and footer strip.
|
|
4
|
+
* UI packages supply Container (Fluent/Radix: div, Material: Box).
|
|
5
|
+
*/
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import type { SideBarProps } from './SideBar';
|
|
8
|
+
export interface OGridLayoutProps {
|
|
9
|
+
/** Root container element (default: 'div'). Material can pass Box. */
|
|
10
|
+
containerComponent?: React.ElementType;
|
|
11
|
+
/** Extra props for the root container (e.g. sx for MUI Box). */
|
|
12
|
+
containerProps?: Record<string, unknown>;
|
|
13
|
+
className?: string;
|
|
14
|
+
/** Custom toolbar content (left-aligned in toolbar strip). */
|
|
15
|
+
toolbar?: React.ReactNode;
|
|
16
|
+
/** Built-in toolbar items rendered on the right side (column chooser, etc.). */
|
|
17
|
+
toolbarEnd?: React.ReactNode;
|
|
18
|
+
/** Secondary toolbar row below the primary toolbar (e.g. active filter chips). Full width. */
|
|
19
|
+
toolbarBelow?: React.ReactNode;
|
|
20
|
+
/** Grid content (DataGridTable). */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/** Pagination controls (rendered in footer strip inside the bordered container). */
|
|
23
|
+
pagination?: React.ReactNode;
|
|
24
|
+
/** Side bar props. When provided, renders SideBar alongside the grid. */
|
|
25
|
+
sideBar?: SideBarProps | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Renders OGrid layout as a unified bordered container:
|
|
29
|
+
* ┌────────────────────────────────────┐
|
|
30
|
+
* │ [toolbar strip] │
|
|
31
|
+
* ├────────────────────────────────────┤
|
|
32
|
+
* │ [sidebar]? [grid] │
|
|
33
|
+
* ├────────────────────────────────────┤
|
|
34
|
+
* │ [footer strip / pagination] │
|
|
35
|
+
* └────────────────────────────────────┘
|
|
36
|
+
*/
|
|
37
|
+
export declare function OGridLayout(props: OGridLayoutProps): React.ReactElement;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless SideBar component rendered by OGridLayout.
|
|
3
|
+
* Contains a tab strip (toggle buttons) and a panel area (columns or filters).
|
|
4
|
+
* Uses inline styles for framework-agnostic rendering.
|
|
5
|
+
*/
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import type { IColumnDefinition, SideBarPanelId, IFilters, FilterValue } from '../types';
|
|
8
|
+
/** Describes a filterable column for the sidebar filters panel. */
|
|
9
|
+
export interface SideBarFilterColumn {
|
|
10
|
+
columnId: string;
|
|
11
|
+
name: string;
|
|
12
|
+
filterField: string;
|
|
13
|
+
filterType: 'text' | 'multiSelect' | 'people' | 'date';
|
|
14
|
+
}
|
|
15
|
+
export interface SideBarProps {
|
|
16
|
+
activePanel: SideBarPanelId | null;
|
|
17
|
+
onPanelChange: (panel: SideBarPanelId | null) => void;
|
|
18
|
+
panels: SideBarPanelId[];
|
|
19
|
+
position: 'left' | 'right';
|
|
20
|
+
columns: IColumnDefinition[];
|
|
21
|
+
visibleColumns: Set<string>;
|
|
22
|
+
onVisibilityChange: (columnKey: string, visible: boolean) => void;
|
|
23
|
+
/** Batch-set all visible columns at once (used by Select All / Clear All). */
|
|
24
|
+
onSetVisibleColumns: (columns: Set<string>) => void;
|
|
25
|
+
filterableColumns: SideBarFilterColumn[];
|
|
26
|
+
filters: IFilters;
|
|
27
|
+
onFilterChange: (key: string, value: FilterValue | undefined) => void;
|
|
28
|
+
filterOptions: Record<string, string[]>;
|
|
29
|
+
}
|
|
30
|
+
export declare function SideBar(props: SideBarProps): React.ReactElement;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface StatusBarClassNames {
|
|
3
|
+
statusBar?: string;
|
|
4
|
+
statusBarItem?: string;
|
|
5
|
+
statusBarLabel?: string;
|
|
6
|
+
statusBarValue?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface StatusBarProps {
|
|
9
|
+
totalCount: number;
|
|
10
|
+
filteredCount?: number;
|
|
11
|
+
selectedCount?: number;
|
|
12
|
+
selectedCellCount?: number;
|
|
13
|
+
/** Aggregation values for selected numeric cells. */
|
|
14
|
+
aggregation?: {
|
|
15
|
+
sum: number;
|
|
16
|
+
avg: number;
|
|
17
|
+
min: number;
|
|
18
|
+
max: number;
|
|
19
|
+
count: number;
|
|
20
|
+
} | null;
|
|
21
|
+
suppressRowCount?: boolean;
|
|
22
|
+
classNames?: StatusBarClassNames;
|
|
23
|
+
}
|
|
24
|
+
export declare function StatusBar({ classNames, ...rest }: StatusBarProps): React.ReactElement;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export { useFilterOptions } from './useFilterOptions';
|
|
2
|
+
export type { UseFilterOptionsResult } from './useFilterOptions';
|
|
3
|
+
export { useOGrid } from './useOGrid';
|
|
4
|
+
export type { UseOGridResult, UseOGridPagination, UseOGridColumnChooser, UseOGridLayout, UseOGridFilters, ColumnChooserPlacement, } from './useOGrid';
|
|
5
|
+
export { useActiveCell } from './useActiveCell';
|
|
6
|
+
export type { UseActiveCellResult } from './useActiveCell';
|
|
7
|
+
export { useCellEditing } from './useCellEditing';
|
|
8
|
+
export type { UseCellEditingResult, EditingCell } from './useCellEditing';
|
|
9
|
+
export { useContextMenu } from './useContextMenu';
|
|
10
|
+
export type { UseContextMenuResult, ContextMenuPosition } from './useContextMenu';
|
|
11
|
+
export { useCellSelection } from './useCellSelection';
|
|
12
|
+
export type { UseCellSelectionResult, UseCellSelectionParams } from './useCellSelection';
|
|
13
|
+
export { useClipboard } from './useClipboard';
|
|
14
|
+
export type { UseClipboardResult, UseClipboardParams } from './useClipboard';
|
|
15
|
+
export { useRowSelection } from './useRowSelection';
|
|
16
|
+
export type { UseRowSelectionResult, UseRowSelectionParams } from './useRowSelection';
|
|
17
|
+
export { useKeyboardNavigation } from './useKeyboardNavigation';
|
|
18
|
+
export type { UseKeyboardNavigationResult, UseKeyboardNavigationParams, } from './useKeyboardNavigation';
|
|
19
|
+
export { useUndoRedo } from './useUndoRedo';
|
|
20
|
+
export type { UseUndoRedoResult, UseUndoRedoParams } from './useUndoRedo';
|
|
21
|
+
export { useDebounce } from './useDebounce';
|
|
22
|
+
export { useFillHandle } from './useFillHandle';
|
|
23
|
+
export type { UseFillHandleResult, UseFillHandleParams } from './useFillHandle';
|
|
24
|
+
export { useDataGridState } from './useDataGridState';
|
|
25
|
+
export type { UseDataGridStateParams, UseDataGridStateResult, DataGridLayoutState, DataGridRowSelectionState, DataGridEditingState, DataGridCellInteractionState, DataGridContextMenuState, DataGridViewModelState, } from './useDataGridState';
|
|
26
|
+
export { useColumnHeaderFilterState } from './useColumnHeaderFilterState';
|
|
27
|
+
export type { UseColumnHeaderFilterStateParams, UseColumnHeaderFilterStateResult, } from './useColumnHeaderFilterState';
|
|
28
|
+
export { useTextFilterState } from './useTextFilterState';
|
|
29
|
+
export type { UseTextFilterStateParams, UseTextFilterStateResult, } from './useTextFilterState';
|
|
30
|
+
export { useMultiSelectFilterState } from './useMultiSelectFilterState';
|
|
31
|
+
export type { UseMultiSelectFilterStateParams, UseMultiSelectFilterStateResult, } from './useMultiSelectFilterState';
|
|
32
|
+
export { usePeopleFilterState } from './usePeopleFilterState';
|
|
33
|
+
export type { UsePeopleFilterStateParams, UsePeopleFilterStateResult, } from './usePeopleFilterState';
|
|
34
|
+
export { useDateFilterState } from './useDateFilterState';
|
|
35
|
+
export type { UseDateFilterStateParams, UseDateFilterStateResult, } from './useDateFilterState';
|
|
36
|
+
export { useColumnChooserState } from './useColumnChooserState';
|
|
37
|
+
export type { UseColumnChooserStateParams, UseColumnChooserStateResult, } from './useColumnChooserState';
|
|
38
|
+
export { useInlineCellEditorState } from './useInlineCellEditorState';
|
|
39
|
+
export type { UseInlineCellEditorStateParams, UseInlineCellEditorStateResult, InlineCellEditorType, } from './useInlineCellEditorState';
|
|
40
|
+
export { useColumnResize } from './useColumnResize';
|
|
41
|
+
export type { UseColumnResizeParams, UseColumnResizeResult, } from './useColumnResize';
|
|
42
|
+
export { useRichSelectState } from './useRichSelectState';
|
|
43
|
+
export type { UseRichSelectStateParams, UseRichSelectStateResult } from './useRichSelectState';
|
|
44
|
+
export { useSideBarState } from './useSideBarState';
|
|
45
|
+
export type { UseSideBarStateParams, UseSideBarStateResult } from './useSideBarState';
|
|
46
|
+
export { useTableLayout } from './useTableLayout';
|
|
47
|
+
export type { UseTableLayoutParams, UseTableLayoutResult } from './useTableLayout';
|
|
48
|
+
export { useLatestRef } from './useLatestRef';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IActiveCell, RowId } from '../types';
|
|
2
|
+
export interface UseActiveCellResult {
|
|
3
|
+
activeCell: IActiveCell | null;
|
|
4
|
+
setActiveCell: (cell: IActiveCell | null) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Tracks the active cell for keyboard navigation.
|
|
8
|
+
* When wrapperRef and editingCell are provided, scrolls the active cell into view when it changes (and not editing).
|
|
9
|
+
*/
|
|
10
|
+
export declare function useActiveCell(wrapperRef?: React.RefObject<HTMLElement | null>, editingCell?: {
|
|
11
|
+
rowId: RowId;
|
|
12
|
+
columnId: string;
|
|
13
|
+
} | null): UseActiveCellResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RowId } from '../types';
|
|
2
|
+
export interface EditingCell {
|
|
3
|
+
rowId: RowId;
|
|
4
|
+
columnId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface UseCellEditingResult {
|
|
7
|
+
editingCell: EditingCell | null;
|
|
8
|
+
setEditingCell: (cell: EditingCell | null) => void;
|
|
9
|
+
pendingEditorValue: unknown;
|
|
10
|
+
setPendingEditorValue: (value: unknown) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Manages cell editing state: which cell is being edited and its pending value.
|
|
14
|
+
* @returns Current editing cell, setter, pending editor value, and setter.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useCellEditing(): UseCellEditingResult;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ISelectionRange, IActiveCell } from '../types';
|
|
2
|
+
export interface UseCellSelectionParams {
|
|
3
|
+
colOffset: number;
|
|
4
|
+
rowCount: number;
|
|
5
|
+
visibleColCount: number;
|
|
6
|
+
setActiveCell: (cell: IActiveCell | null) => void;
|
|
7
|
+
wrapperRef: React.RefObject<HTMLElement | null>;
|
|
8
|
+
}
|
|
9
|
+
export interface UseCellSelectionResult {
|
|
10
|
+
selectionRange: ISelectionRange | null;
|
|
11
|
+
setSelectionRange: (range: ISelectionRange | null) => void;
|
|
12
|
+
handleCellMouseDown: (e: React.MouseEvent, rowIndex: number, globalColIndex: number) => void;
|
|
13
|
+
handleSelectAllCells: () => void;
|
|
14
|
+
/** True while the user is drag-selecting cells (mousedown → mousemove → mouseup). */
|
|
15
|
+
isDragging: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Manages cell selection range with drag-to-select and select-all support.
|
|
19
|
+
* @param params - Row/col counts, active cell setter, and wrapper ref for auto-scroll.
|
|
20
|
+
* @returns Selection range, setters, mouse/keyboard handlers, and drag state.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useCellSelection(params: UseCellSelectionParams): UseCellSelectionResult;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ISelectionRange, IActiveCell, ICellValueChangedEvent, IColumnDef } from '../types';
|
|
2
|
+
export interface UseClipboardParams<T> {
|
|
3
|
+
items: T[];
|
|
4
|
+
visibleCols: IColumnDef<T>[];
|
|
5
|
+
colOffset: number;
|
|
6
|
+
selectionRange: ISelectionRange | null;
|
|
7
|
+
activeCell: IActiveCell | null;
|
|
8
|
+
editable?: boolean;
|
|
9
|
+
onCellValueChanged: ((event: ICellValueChangedEvent<T>) => void) | undefined;
|
|
10
|
+
beginBatch?: () => void;
|
|
11
|
+
endBatch?: () => void;
|
|
12
|
+
}
|
|
13
|
+
export interface UseClipboardResult {
|
|
14
|
+
handleCopy: () => void;
|
|
15
|
+
handleCut: () => void;
|
|
16
|
+
handlePaste: () => Promise<void>;
|
|
17
|
+
cutRangeRef: React.MutableRefObject<ISelectionRange | null>;
|
|
18
|
+
/** Current cut range for UI (marching ants). Null when no cut or after paste. */
|
|
19
|
+
cutRange: ISelectionRange | null;
|
|
20
|
+
/** Current copy range for UI (marching ants). Null when no copy or after paste/cut. */
|
|
21
|
+
copyRange: ISelectionRange | null;
|
|
22
|
+
/** Clear both copy and cut ranges (dismisses marching ants). Called on Escape. */
|
|
23
|
+
clearClipboardRanges: () => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Manages copy, cut, and paste operations for cell ranges with TSV clipboard format.
|
|
27
|
+
* @param params - Items, columns, selection, editability, and value change callback.
|
|
28
|
+
* @returns Copy/cut/paste handlers, cut/copy ranges, and range clear function.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useClipboard<T>(params: UseClipboardParams<T>): UseClipboardResult;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless column chooser state and handlers for Fluent, Material, and Radix.
|
|
3
|
+
* UI packages use this hook and render only trigger + popover (checkboxes, Select All, Clear All).
|
|
4
|
+
*/
|
|
5
|
+
import type { IColumnDefinition } from '../types/columnTypes';
|
|
6
|
+
export interface UseColumnChooserStateParams {
|
|
7
|
+
columns: IColumnDefinition[];
|
|
8
|
+
visibleColumns: Set<string>;
|
|
9
|
+
onVisibilityChange: (columnKey: string, visible: boolean) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface UseColumnChooserStateResult {
|
|
12
|
+
open: boolean;
|
|
13
|
+
setOpen: (open: boolean) => void;
|
|
14
|
+
handleToggle: () => void;
|
|
15
|
+
handleClose: () => void;
|
|
16
|
+
handleCheckboxChange: (columnKey: string) => (visible: boolean) => void;
|
|
17
|
+
handleSelectAll: () => void;
|
|
18
|
+
handleClearAll: () => void;
|
|
19
|
+
visibleCount: number;
|
|
20
|
+
totalCount: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns open/setOpen, handleToggle, handleClose (Escape handled in hook),
|
|
24
|
+
* handleCheckboxChange(columnKey)(visible), handleSelectAll, handleClearAll,
|
|
25
|
+
* visibleCount, totalCount. UI renders trigger + popover and wires handlers.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useColumnChooserState(params: UseColumnChooserStateParams): UseColumnChooserStateResult;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless column header filter state and handlers for Fluent, Material, and Radix.
|
|
3
|
+
* UI packages use this hook and render only presentation (popover, inputs, buttons).
|
|
4
|
+
* Composes 4 sub-hooks for each filter type's state management.
|
|
5
|
+
*/
|
|
6
|
+
import { type RefObject, type Dispatch, type SetStateAction } from 'react';
|
|
7
|
+
import type { ColumnFilterType, IDateFilterValue } from '../types/columnTypes';
|
|
8
|
+
import type { UserLike } from '../types/dataGridTypes';
|
|
9
|
+
export interface UseColumnHeaderFilterStateParams {
|
|
10
|
+
filterType: ColumnFilterType;
|
|
11
|
+
isSorted?: boolean;
|
|
12
|
+
isSortedDescending?: boolean;
|
|
13
|
+
onSort?: () => void;
|
|
14
|
+
selectedValues?: string[];
|
|
15
|
+
onFilterChange?: (values: string[]) => void;
|
|
16
|
+
options?: string[];
|
|
17
|
+
isLoadingOptions?: boolean;
|
|
18
|
+
textValue?: string;
|
|
19
|
+
onTextChange?: (value: string) => void;
|
|
20
|
+
selectedUser?: UserLike;
|
|
21
|
+
onUserChange?: (user: UserLike | undefined) => void;
|
|
22
|
+
peopleSearch?: (query: string) => Promise<UserLike[]>;
|
|
23
|
+
dateValue?: IDateFilterValue;
|
|
24
|
+
onDateChange?: (value: IDateFilterValue | undefined) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface UseColumnHeaderFilterStateResult {
|
|
27
|
+
headerRef: RefObject<HTMLDivElement | null>;
|
|
28
|
+
popoverRef: RefObject<HTMLDivElement | null>;
|
|
29
|
+
peopleInputRef: RefObject<HTMLInputElement | null>;
|
|
30
|
+
isFilterOpen: boolean;
|
|
31
|
+
setFilterOpen: (open: boolean) => void;
|
|
32
|
+
tempSelected: Set<string>;
|
|
33
|
+
setTempSelected: Dispatch<SetStateAction<Set<string>>>;
|
|
34
|
+
tempTextValue: string;
|
|
35
|
+
setTempTextValue: (v: string) => void;
|
|
36
|
+
searchText: string;
|
|
37
|
+
setSearchText: (v: string) => void;
|
|
38
|
+
debouncedSearchText: string;
|
|
39
|
+
filteredOptions: string[];
|
|
40
|
+
peopleSuggestions: UserLike[];
|
|
41
|
+
isPeopleLoading: boolean;
|
|
42
|
+
peopleSearchText: string;
|
|
43
|
+
setPeopleSearchText: (v: string) => void;
|
|
44
|
+
tempDateFrom: string;
|
|
45
|
+
setTempDateFrom: (v: string) => void;
|
|
46
|
+
tempDateTo: string;
|
|
47
|
+
setTempDateTo: (v: string) => void;
|
|
48
|
+
hasActiveFilter: boolean;
|
|
49
|
+
popoverPosition: {
|
|
50
|
+
top: number;
|
|
51
|
+
left: number;
|
|
52
|
+
} | null;
|
|
53
|
+
handlers: {
|
|
54
|
+
handleFilterIconClick: (e: React.MouseEvent) => void;
|
|
55
|
+
handleApplyMultiSelect: () => void;
|
|
56
|
+
handleTextApply: () => void;
|
|
57
|
+
handleTextClear: () => void;
|
|
58
|
+
handleUserSelect: (user: UserLike) => void;
|
|
59
|
+
handleClearUser: () => void;
|
|
60
|
+
handleCheckboxChange: (option: string, checked: boolean) => void;
|
|
61
|
+
handleSelectAll: () => void;
|
|
62
|
+
handleClearSelection: () => void;
|
|
63
|
+
handlePopoverClick: (e: React.MouseEvent) => void;
|
|
64
|
+
handleInputFocus: (e: React.FocusEvent) => void;
|
|
65
|
+
handleInputMouseDown: (e: React.MouseEvent) => void;
|
|
66
|
+
handleInputClick: (e: React.MouseEvent) => void;
|
|
67
|
+
handleInputKeyDown: (e: React.KeyboardEvent) => void;
|
|
68
|
+
handleDateApply: () => void;
|
|
69
|
+
handleDateClear: () => void;
|
|
70
|
+
handleSortClick: (e: React.MouseEvent) => void;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export declare function useColumnHeaderFilterState(params: UseColumnHeaderFilterStateParams): UseColumnHeaderFilterStateResult;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IColumnDef } from '../types';
|
|
2
|
+
export interface UseColumnResizeParams {
|
|
3
|
+
columnSizingOverrides: Record<string, {
|
|
4
|
+
widthPx: number;
|
|
5
|
+
}>;
|
|
6
|
+
setColumnSizingOverrides: React.Dispatch<React.SetStateAction<Record<string, {
|
|
7
|
+
widthPx: number;
|
|
8
|
+
}>>>;
|
|
9
|
+
minWidth?: number;
|
|
10
|
+
defaultWidth?: number;
|
|
11
|
+
/** Called when a column resize completes (mouseup). */
|
|
12
|
+
onColumnResized?: (columnId: string, width: number) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface UseColumnResizeResult<T> {
|
|
15
|
+
handleResizeStart: (e: React.MouseEvent, col: IColumnDef<T>) => void;
|
|
16
|
+
getColumnWidth: (col: IColumnDef<T>) => number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Manages column resize drag interactions with RAF-throttled state updates.
|
|
20
|
+
* @param params - Sizing overrides, setter, min/default widths, and resize callback.
|
|
21
|
+
* @returns Resize start handler and column width getter.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useColumnResize<T>({ columnSizingOverrides, setColumnSizingOverrides, minWidth, defaultWidth, onColumnResized, }: UseColumnResizeParams): UseColumnResizeResult<T>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ContextMenuPosition {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export interface UseContextMenuResult {
|
|
6
|
+
contextMenuPosition: ContextMenuPosition | null;
|
|
7
|
+
setContextMenuPosition: (pos: ContextMenuPosition | null) => void;
|
|
8
|
+
handleCellContextMenu: (e: {
|
|
9
|
+
clientX: number;
|
|
10
|
+
clientY: number;
|
|
11
|
+
preventDefault?: () => void;
|
|
12
|
+
}) => void;
|
|
13
|
+
closeContextMenu: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Manages context menu position state for right-click menus.
|
|
17
|
+
* @returns Menu position, setter, right-click handler, and close handler.
|
|
18
|
+
*/
|
|
19
|
+
export declare function useContextMenu(): UseContextMenuResult;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
import type { HeaderFilterConfigInput, CellRenderDescriptorInput } from '../utils';
|
|
3
|
+
import type { RowId, IOGridDataGridProps, IStatusBarProps, IColumnDef } from '../types';
|
|
4
|
+
export interface UseDataGridStateParams<T> {
|
|
5
|
+
props: IOGridDataGridProps<T>;
|
|
6
|
+
wrapperRef: RefObject<HTMLDivElement | null>;
|
|
7
|
+
}
|
|
8
|
+
/** Column layout, visibility, and sizing state. */
|
|
9
|
+
export interface DataGridLayoutState<T> {
|
|
10
|
+
flatColumns: IColumnDef<T>[];
|
|
11
|
+
visibleCols: IColumnDef<T>[];
|
|
12
|
+
visibleColumnCount: number;
|
|
13
|
+
totalColCount: number;
|
|
14
|
+
colOffset: number;
|
|
15
|
+
hasCheckboxCol: boolean;
|
|
16
|
+
rowIndexByRowId: Map<RowId, number>;
|
|
17
|
+
containerWidth: number;
|
|
18
|
+
minTableWidth: number;
|
|
19
|
+
desiredTableWidth: number;
|
|
20
|
+
columnSizingOverrides: Record<string, {
|
|
21
|
+
widthPx: number;
|
|
22
|
+
}>;
|
|
23
|
+
setColumnSizingOverrides: React.Dispatch<React.SetStateAction<Record<string, {
|
|
24
|
+
widthPx: number;
|
|
25
|
+
}>>>;
|
|
26
|
+
onColumnResized?: (columnId: string, width: number) => void;
|
|
27
|
+
}
|
|
28
|
+
/** Row selection (checkboxes, single-row click). */
|
|
29
|
+
export interface DataGridRowSelectionState {
|
|
30
|
+
selectedRowIds: Set<RowId>;
|
|
31
|
+
updateSelection: (newSelectedIds: Set<RowId>) => void;
|
|
32
|
+
handleRowCheckboxChange: (rowId: RowId, checked: boolean, rowIndex: number, shiftKey: boolean) => void;
|
|
33
|
+
handleSelectAll: (checked: boolean) => void;
|
|
34
|
+
allSelected: boolean;
|
|
35
|
+
someSelected: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** Cell editing, popover editor, and commit/cancel helpers. */
|
|
38
|
+
export interface DataGridEditingState<T> {
|
|
39
|
+
editingCell: {
|
|
40
|
+
rowId: RowId;
|
|
41
|
+
columnId: string;
|
|
42
|
+
} | null;
|
|
43
|
+
setEditingCell: (cell: {
|
|
44
|
+
rowId: RowId;
|
|
45
|
+
columnId: string;
|
|
46
|
+
} | null) => void;
|
|
47
|
+
pendingEditorValue: unknown;
|
|
48
|
+
setPendingEditorValue: (value: unknown) => void;
|
|
49
|
+
commitCellEdit: (item: T, columnId: string, oldValue: unknown, newValue: unknown, rowIndex: number, globalColIndex: number) => void;
|
|
50
|
+
cancelPopoverEdit: () => void;
|
|
51
|
+
popoverAnchorEl: HTMLElement | null;
|
|
52
|
+
setPopoverAnchorEl: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
|
|
53
|
+
}
|
|
54
|
+
/** Cell selection, active cell, keyboard, clipboard, fill handle, undo/redo. */
|
|
55
|
+
export interface DataGridCellInteractionState {
|
|
56
|
+
activeCell: {
|
|
57
|
+
rowIndex: number;
|
|
58
|
+
columnIndex: number;
|
|
59
|
+
} | null;
|
|
60
|
+
setActiveCell: (cell: {
|
|
61
|
+
rowIndex: number;
|
|
62
|
+
columnIndex: number;
|
|
63
|
+
} | null) => void;
|
|
64
|
+
selectionRange: {
|
|
65
|
+
startRow: number;
|
|
66
|
+
startCol: number;
|
|
67
|
+
endRow: number;
|
|
68
|
+
endCol: number;
|
|
69
|
+
} | null;
|
|
70
|
+
setSelectionRange: (range: DataGridCellInteractionState['selectionRange']) => void;
|
|
71
|
+
handleCellMouseDown: (e: React.MouseEvent, rowIndex: number, globalColIndex: number) => void;
|
|
72
|
+
handleSelectAllCells: () => void;
|
|
73
|
+
hasCellSelection: boolean;
|
|
74
|
+
handleGridKeyDown: (e: React.KeyboardEvent) => void;
|
|
75
|
+
handleFillHandleMouseDown: (e: React.MouseEvent) => void;
|
|
76
|
+
handleCopy: () => void;
|
|
77
|
+
handleCut: () => void;
|
|
78
|
+
handlePaste: () => Promise<void>;
|
|
79
|
+
cutRange: {
|
|
80
|
+
startRow: number;
|
|
81
|
+
startCol: number;
|
|
82
|
+
endRow: number;
|
|
83
|
+
endCol: number;
|
|
84
|
+
} | null;
|
|
85
|
+
copyRange: {
|
|
86
|
+
startRow: number;
|
|
87
|
+
startCol: number;
|
|
88
|
+
endRow: number;
|
|
89
|
+
endCol: number;
|
|
90
|
+
} | null;
|
|
91
|
+
clearClipboardRanges: () => void;
|
|
92
|
+
canUndo: boolean;
|
|
93
|
+
canRedo: boolean;
|
|
94
|
+
onUndo?: () => void;
|
|
95
|
+
onRedo?: () => void;
|
|
96
|
+
/** True while user is drag-selecting cells (mousedown → mouseup). */
|
|
97
|
+
isDragging: boolean;
|
|
98
|
+
}
|
|
99
|
+
/** Context menu position and handlers. */
|
|
100
|
+
export interface DataGridContextMenuState {
|
|
101
|
+
menuPosition: {
|
|
102
|
+
x: number;
|
|
103
|
+
y: number;
|
|
104
|
+
} | null;
|
|
105
|
+
setMenuPosition: (pos: {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
} | null) => void;
|
|
109
|
+
handleCellContextMenu: (e: {
|
|
110
|
+
clientX: number;
|
|
111
|
+
clientY: number;
|
|
112
|
+
preventDefault?: () => void;
|
|
113
|
+
}) => void;
|
|
114
|
+
closeContextMenu: () => void;
|
|
115
|
+
}
|
|
116
|
+
/** View model inputs and derived display state. */
|
|
117
|
+
export interface DataGridViewModelState<T> {
|
|
118
|
+
headerFilterInput: HeaderFilterConfigInput;
|
|
119
|
+
cellDescriptorInput: CellRenderDescriptorInput<T>;
|
|
120
|
+
statusBarConfig: IStatusBarProps | null;
|
|
121
|
+
showEmptyInGrid: boolean;
|
|
122
|
+
onCellError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
123
|
+
}
|
|
124
|
+
/** Grouped result from useDataGridState. */
|
|
125
|
+
export interface UseDataGridStateResult<T> {
|
|
126
|
+
layout: DataGridLayoutState<T>;
|
|
127
|
+
rowSelection: DataGridRowSelectionState;
|
|
128
|
+
editing: DataGridEditingState<T>;
|
|
129
|
+
interaction: DataGridCellInteractionState;
|
|
130
|
+
contextMenu: DataGridContextMenuState;
|
|
131
|
+
viewModels: DataGridViewModelState<T>;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Single orchestration hook for DataGridTable. Takes grid props and wrapper ref,
|
|
135
|
+
* returns all derived state and handlers so Fluent/Material/Radix can be thin view layers.
|
|
136
|
+
*/
|
|
137
|
+
export declare function useDataGridState<T>(params: UseDataGridStateParams<T>): UseDataGridStateResult<T>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date filter state sub-hook for column header filters.
|
|
3
|
+
* Manages temporary date from/to values and apply/clear handlers.
|
|
4
|
+
*/
|
|
5
|
+
import type { IDateFilterValue } from '../types/columnTypes';
|
|
6
|
+
export interface UseDateFilterStateParams {
|
|
7
|
+
dateValue?: IDateFilterValue;
|
|
8
|
+
onDateChange?: (value: IDateFilterValue | undefined) => void;
|
|
9
|
+
isFilterOpen: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface UseDateFilterStateResult {
|
|
12
|
+
tempDateFrom: string;
|
|
13
|
+
setTempDateFrom: (v: string) => void;
|
|
14
|
+
tempDateTo: string;
|
|
15
|
+
setTempDateTo: (v: string) => void;
|
|
16
|
+
handleDateApply: () => void;
|
|
17
|
+
handleDateClear: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function useDateFilterState(params: UseDateFilterStateParams): UseDateFilterStateResult;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a debounced value that updates after the specified delay when the source value changes.
|
|
3
|
+
*/
|
|
4
|
+
export declare function useDebounce<T>(value: T, delayMs: number): T;
|
|
5
|
+
/**
|
|
6
|
+
* Returns a stable callback that invokes the given function after the specified delay.
|
|
7
|
+
* Each new call resets the timer.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useDebouncedCallback<T extends (...args: unknown[]) => void>(fn: T, delayMs: number): T;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
import type { ISelectionRange, IActiveCell } from '../types';
|
|
3
|
+
import type { IColumnDef, ICellValueChangedEvent } from '../types/columnTypes';
|
|
4
|
+
export interface UseFillHandleParams<T> {
|
|
5
|
+
items: T[];
|
|
6
|
+
visibleCols: IColumnDef<T>[];
|
|
7
|
+
editable?: boolean;
|
|
8
|
+
onCellValueChanged?: (event: ICellValueChangedEvent<T>) => void;
|
|
9
|
+
selectionRange: ISelectionRange | null;
|
|
10
|
+
setSelectionRange: (range: ISelectionRange | null) => void;
|
|
11
|
+
setActiveCell: (cell: IActiveCell | null) => void;
|
|
12
|
+
colOffset: number;
|
|
13
|
+
wrapperRef: RefObject<HTMLDivElement | null>;
|
|
14
|
+
beginBatch?: () => void;
|
|
15
|
+
endBatch?: () => void;
|
|
16
|
+
}
|
|
17
|
+
export interface UseFillHandleResult {
|
|
18
|
+
fillDrag: {
|
|
19
|
+
startRow: number;
|
|
20
|
+
startCol: number;
|
|
21
|
+
} | null;
|
|
22
|
+
setFillDrag: (value: {
|
|
23
|
+
startRow: number;
|
|
24
|
+
startCol: number;
|
|
25
|
+
} | null) => void;
|
|
26
|
+
handleFillHandleMouseDown: (e: React.MouseEvent) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Manages Excel-style fill handle drag-to-fill for cell ranges.
|
|
30
|
+
* @param params - Items, columns, selection range, editability, and value change callback.
|
|
31
|
+
* @returns Fill drag state, setter, and mousedown handler for the fill handle.
|
|
32
|
+
*/
|
|
33
|
+
export declare function useFillHandle<T>(params: UseFillHandleParams<T>): UseFillHandleResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IDataSource } from '../types/dataGridTypes';
|
|
2
|
+
export interface UseFilterOptionsResult {
|
|
3
|
+
filterOptions: Record<string, string[]>;
|
|
4
|
+
loadingOptions: Record<string, boolean>;
|
|
5
|
+
}
|
|
6
|
+
/** Accepted data source shapes for useFilterOptions. */
|
|
7
|
+
type FilterOptionsSource = IDataSource<unknown> | {
|
|
8
|
+
fetchFilterOptions?: (field: string) => Promise<string[]>;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Load filter options for the given fields from a data source.
|
|
12
|
+
*
|
|
13
|
+
* Accepts `IDataSource<T>` or a plain `{ fetchFilterOptions }` object.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useFilterOptions(dataSource: FilterOptionsSource, fields: string[]): UseFilterOptionsResult;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless inline cell editor state for Fluent, Material, and Radix InlineCellEditor.
|
|
3
|
+
* UI packages use this hook and render only the framework input (Input, TextField, select, Checkbox).
|
|
4
|
+
*/
|
|
5
|
+
export type InlineCellEditorType = 'text' | 'select' | 'checkbox' | 'richSelect' | 'date';
|
|
6
|
+
export interface UseInlineCellEditorStateParams {
|
|
7
|
+
value: unknown;
|
|
8
|
+
editorType: InlineCellEditorType;
|
|
9
|
+
onCommit: (value: unknown) => void;
|
|
10
|
+
onCancel: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface UseInlineCellEditorStateResult {
|
|
13
|
+
localValue: string;
|
|
14
|
+
setLocalValue: (value: string) => void;
|
|
15
|
+
handleKeyDown: (e: React.KeyboardEvent) => void;
|
|
16
|
+
handleBlur: () => void;
|
|
17
|
+
commit: (value: unknown) => void;
|
|
18
|
+
cancel: () => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns localValue/setLocalValue (for text), handleKeyDown (Escape cancel, Enter commit for text),
|
|
22
|
+
* handleBlur (commit on blur for text), commit(value), cancel(). UI renders only the input.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useInlineCellEditorState(params: UseInlineCellEditorStateParams): UseInlineCellEditorStateResult;
|