@alaarab/ogrid-core 1.9.0 → 2.0.0
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 +6 -20
- package/dist/esm/index.js +5 -15
- package/dist/esm/types/index.js +2 -1
- package/dist/esm/utils/clientSideData.js +1 -1
- package/dist/esm/utils/gridRowComparator.js +11 -1
- package/dist/esm/utils/index.js +1 -2
- package/dist/types/index.d.ts +3 -23
- package/dist/types/types/columnTypes.d.ts +3 -6
- package/dist/types/types/dataGridTypes.d.ts +1 -150
- package/dist/types/types/index.d.ts +3 -3
- package/dist/types/utils/gridRowComparator.d.ts +8 -0
- package/dist/types/utils/index.d.ts +1 -3
- package/package.json +6 -24
- package/dist/esm/components/BaseInlineCellEditor.js +0 -112
- package/dist/esm/components/CellErrorBoundary.js +0 -43
- package/dist/esm/components/EmptyState.js +0 -19
- package/dist/esm/components/GridContextMenu.js +0 -35
- package/dist/esm/components/MarchingAntsOverlay.js +0 -110
- package/dist/esm/components/OGridLayout.js +0 -91
- package/dist/esm/components/SideBar.js +0 -122
- package/dist/esm/components/StatusBar.js +0 -6
- package/dist/esm/hooks/index.js +0 -25
- package/dist/esm/hooks/useActiveCell.js +0 -62
- package/dist/esm/hooks/useCellEditing.js +0 -15
- package/dist/esm/hooks/useCellSelection.js +0 -324
- package/dist/esm/hooks/useClipboard.js +0 -162
- package/dist/esm/hooks/useColumnChooserState.js +0 -62
- package/dist/esm/hooks/useColumnHeaderFilterState.js +0 -180
- package/dist/esm/hooks/useColumnResize.js +0 -92
- package/dist/esm/hooks/useContextMenu.js +0 -21
- package/dist/esm/hooks/useDataGridState.js +0 -314
- package/dist/esm/hooks/useDateFilterState.js +0 -34
- package/dist/esm/hooks/useDebounce.js +0 -35
- package/dist/esm/hooks/useFillHandle.js +0 -196
- package/dist/esm/hooks/useFilterOptions.js +0 -40
- package/dist/esm/hooks/useInlineCellEditorState.js +0 -44
- package/dist/esm/hooks/useKeyboardNavigation.js +0 -420
- package/dist/esm/hooks/useLatestRef.js +0 -11
- package/dist/esm/hooks/useMultiSelectFilterState.js +0 -59
- package/dist/esm/hooks/useOGrid.js +0 -467
- package/dist/esm/hooks/usePeopleFilterState.js +0 -68
- package/dist/esm/hooks/useRichSelectState.js +0 -58
- package/dist/esm/hooks/useRowSelection.js +0 -78
- package/dist/esm/hooks/useSideBarState.js +0 -39
- package/dist/esm/hooks/useTableLayout.js +0 -77
- package/dist/esm/hooks/useTextFilterState.js +0 -25
- package/dist/esm/hooks/useUndoRedo.js +0 -83
- package/dist/esm/storybook/index.js +0 -1
- package/dist/esm/storybook/mockData.js +0 -73
- package/dist/esm/utils/dataGridViewModel.js +0 -233
- package/dist/types/components/BaseInlineCellEditor.d.ts +0 -33
- package/dist/types/components/CellErrorBoundary.d.ts +0 -25
- package/dist/types/components/EmptyState.d.ts +0 -26
- package/dist/types/components/GridContextMenu.d.ts +0 -18
- package/dist/types/components/MarchingAntsOverlay.d.ts +0 -15
- package/dist/types/components/OGridLayout.d.ts +0 -37
- package/dist/types/components/SideBar.d.ts +0 -30
- package/dist/types/components/StatusBar.d.ts +0 -24
- package/dist/types/hooks/index.d.ts +0 -48
- package/dist/types/hooks/useActiveCell.d.ts +0 -13
- package/dist/types/hooks/useCellEditing.d.ts +0 -16
- package/dist/types/hooks/useCellSelection.d.ts +0 -22
- package/dist/types/hooks/useClipboard.d.ts +0 -30
- package/dist/types/hooks/useColumnChooserState.d.ts +0 -27
- package/dist/types/hooks/useColumnHeaderFilterState.d.ts +0 -73
- package/dist/types/hooks/useColumnResize.d.ts +0 -23
- package/dist/types/hooks/useContextMenu.d.ts +0 -19
- package/dist/types/hooks/useDataGridState.d.ts +0 -137
- package/dist/types/hooks/useDateFilterState.d.ts +0 -19
- package/dist/types/hooks/useDebounce.d.ts +0 -9
- package/dist/types/hooks/useFillHandle.d.ts +0 -33
- package/dist/types/hooks/useFilterOptions.d.ts +0 -16
- package/dist/types/hooks/useInlineCellEditorState.d.ts +0 -24
- package/dist/types/hooks/useKeyboardNavigation.d.ts +0 -47
- package/dist/types/hooks/useLatestRef.d.ts +0 -6
- package/dist/types/hooks/useMultiSelectFilterState.d.ts +0 -24
- package/dist/types/hooks/useOGrid.d.ts +0 -52
- package/dist/types/hooks/usePeopleFilterState.d.ts +0 -25
- package/dist/types/hooks/useRichSelectState.d.ts +0 -22
- package/dist/types/hooks/useRowSelection.d.ts +0 -22
- package/dist/types/hooks/useSideBarState.d.ts +0 -20
- package/dist/types/hooks/useTableLayout.d.ts +0 -27
- package/dist/types/hooks/useTextFilterState.d.ts +0 -16
- package/dist/types/hooks/useUndoRedo.d.ts +0 -23
- package/dist/types/storybook/index.d.ts +0 -2
- package/dist/types/storybook/mockData.d.ts +0 -37
- package/dist/types/utils/dataGridViewModel.d.ts +0 -169
package/README.md
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<strong>OGrid Core</strong> —
|
|
2
|
+
<strong>OGrid Core</strong> — Pure TypeScript types, algorithms, and utilities for OGrid data grids.
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
6
|
<a href="https://www.npmjs.com/package/@alaarab/ogrid-core"><img src="https://img.shields.io/npm/v/@alaarab/ogrid-core?color=%23217346&label=npm" alt="npm version" /></a>
|
|
7
7
|
<a href="https://github.com/alaarab/ogrid/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License" /></a>
|
|
8
|
-
<img src="https://img.shields.io/badge/React-17%20%7C%2018%20%7C%2019-blue" alt="React 17, 18, 19" />
|
|
9
8
|
<img src="https://img.shields.io/badge/TypeScript-strict-blue" alt="TypeScript strict" />
|
|
10
9
|
</p>
|
|
11
10
|
|
|
@@ -15,20 +14,11 @@
|
|
|
15
14
|
|
|
16
15
|
---
|
|
17
16
|
|
|
18
|
-
Framework-agnostic foundation for [OGrid](https://github.com/alaarab/ogrid) data grids.
|
|
17
|
+
Framework-agnostic foundation for [OGrid](https://github.com/alaarab/ogrid) data grids. **Zero dependencies** — pure TypeScript types and utilities shared by [`@alaarab/ogrid-react`](https://www.npmjs.com/package/@alaarab/ogrid-react) and [`@alaarab/ogrid-js`](https://www.npmjs.com/package/@alaarab/ogrid-js).
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
### Hooks
|
|
19
|
+
You typically don't need to install this directly — the UI packages re-export everything from core.
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
- `useDataGridState` — All DataGridTable state: layout, selection, editing, interaction, context menu, view models
|
|
26
|
-
- `useColumnHeaderFilterState` — Filter popover (open, temp values, apply/clear, people search debounce)
|
|
27
|
-
- `useColumnChooserState` — Column visibility dropdown
|
|
28
|
-
- `useInlineCellEditorState` — Inline cell editor
|
|
29
|
-
- `useRichSelectState` — Searchable rich select dropdown
|
|
30
|
-
- `useSideBarState` — Side bar panel management
|
|
31
|
-
- `useActiveCell`, `useCellSelection`, `useCellEditing`, `useRowSelection`, `useKeyboardNavigation`, `useClipboard`, `useFillHandle`, `useUndoRedo`, `useContextMenu`, `useColumnResize`, `useFilterOptions`, `useDebounce`
|
|
21
|
+
## What's Inside
|
|
32
22
|
|
|
33
23
|
### Types
|
|
34
24
|
|
|
@@ -36,11 +26,7 @@ Framework-agnostic foundation for [OGrid](https://github.com/alaarab/ogrid) data
|
|
|
36
26
|
|
|
37
27
|
### Utilities
|
|
38
28
|
|
|
39
|
-
`
|
|
40
|
-
|
|
41
|
-
### Headless Components
|
|
42
|
-
|
|
43
|
-
`OGridLayout` · `StatusBar` · `GridContextMenu` · `SideBar` · `MarchingAntsOverlay`
|
|
29
|
+
`getCellValue` · `buildHeaderRows` · `parseValue` · `normalizeSelectionRange` · `isInSelectionRange` · `toUserLike`
|
|
44
30
|
|
|
45
31
|
## Install
|
|
46
32
|
|
|
@@ -48,7 +34,7 @@ Framework-agnostic foundation for [OGrid](https://github.com/alaarab/ogrid) data
|
|
|
48
34
|
npm install @alaarab/ogrid-core
|
|
49
35
|
```
|
|
50
36
|
|
|
51
|
-
|
|
37
|
+
No peer dependencies. No framework dependencies.
|
|
52
38
|
|
|
53
39
|
## Documentation
|
|
54
40
|
|
package/dist/esm/index.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
+
// Types
|
|
2
|
+
export * from './types';
|
|
3
|
+
// Utils
|
|
4
|
+
export * from './utils';
|
|
1
5
|
// Constants
|
|
2
|
-
export
|
|
3
|
-
export { toUserLike, isInSelectionRange, normalizeSelectionRange } from './types';
|
|
4
|
-
// Hooks
|
|
5
|
-
export { useFilterOptions, useOGrid, useActiveCell, useCellEditing, useContextMenu, useCellSelection, useClipboard, useRowSelection, useKeyboardNavigation, useUndoRedo, useDebounce, useFillHandle, useDataGridState, useColumnHeaderFilterState, useTextFilterState, useMultiSelectFilterState, usePeopleFilterState, useDateFilterState, useColumnChooserState, useInlineCellEditorState, useColumnResize, useRichSelectState, useSideBarState, useTableLayout, useLatestRef, } from './hooks';
|
|
6
|
-
// Components
|
|
7
|
-
export { OGridLayout } from './components/OGridLayout';
|
|
8
|
-
export { StatusBar } from './components/StatusBar';
|
|
9
|
-
export { BaseInlineCellEditor, editorWrapperStyle, editorInputStyle, richSelectWrapperStyle, richSelectDropdownStyle, richSelectOptionStyle, richSelectOptionHighlightedStyle, richSelectNoMatchesStyle, selectEditorStyle, } from './components/BaseInlineCellEditor';
|
|
10
|
-
export { GridContextMenu } from './components/GridContextMenu';
|
|
11
|
-
export { MarchingAntsOverlay } from './components/MarchingAntsOverlay';
|
|
12
|
-
export { SideBar } from './components/SideBar';
|
|
13
|
-
export { CellErrorBoundary } from './components/CellErrorBoundary';
|
|
14
|
-
export { EmptyState } from './components/EmptyState';
|
|
15
|
-
// Utilities
|
|
16
|
-
export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, GRID_CONTEXT_MENU_ITEMS, getContextMenuHandlers, formatShortcut, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, getHeaderFilterConfig, getCellRenderDescriptor, isRowInRange, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, areGridRowPropsEqual, } from './utils';
|
|
6
|
+
export * from './constants';
|
package/dist/esm/types/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
// Utility functions
|
|
2
|
+
export { toUserLike, isInSelectionRange, normalizeSelectionRange, } from './dataGridTypes';
|
|
@@ -60,7 +60,7 @@ export function processClientSideData(data, columns, filters, sortBy, sortDirect
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
const rows = predicates.length > 0
|
|
64
64
|
? data.filter((row) => {
|
|
65
65
|
for (let i = 0; i < predicates.length; i++) {
|
|
66
66
|
if (!predicates[i](row))
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a given row index falls within a selection range.
|
|
3
|
+
* O(1) — used by React.memo comparators to skip unchanged rows.
|
|
4
|
+
*/
|
|
5
|
+
export function isRowInRange(range, rowIndex) {
|
|
6
|
+
if (!range)
|
|
7
|
+
return false;
|
|
8
|
+
const minR = Math.min(range.startRow, range.endRow);
|
|
9
|
+
const maxR = Math.max(range.startRow, range.endRow);
|
|
10
|
+
return rowIndex >= minR && rowIndex <= maxR;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* Shared React.memo comparator for GridRow components across all 3 UI packages.
|
|
4
14
|
* Skips re-render for rows unaffected by selection/editing/interaction changes.
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -6,8 +6,7 @@ export { getStatusBarParts } from './statusBarHelpers';
|
|
|
6
6
|
export { getDataGridStatusBarConfig } from './dataGridStatusBar';
|
|
7
7
|
export { getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, } from './paginationHelpers';
|
|
8
8
|
export { GRID_CONTEXT_MENU_ITEMS, getContextMenuHandlers, formatShortcut } from './gridContextMenuHelpers';
|
|
9
|
-
export { getHeaderFilterConfig, getCellRenderDescriptor, isRowInRange, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, } from './dataGridViewModel';
|
|
10
9
|
export { parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, } from './valueParsers';
|
|
11
10
|
export { computeAggregations } from './aggregationUtils';
|
|
12
11
|
export { processClientSideData } from './clientSideData';
|
|
13
|
-
export { areGridRowPropsEqual } from './gridRowComparator';
|
|
12
|
+
export { areGridRowPropsEqual, isRowInRange } from './gridRowComparator';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export { useFilterOptions, useOGrid, useActiveCell, useCellEditing, useContextMenu, useCellSelection, useClipboard, useRowSelection, useKeyboardNavigation, useUndoRedo, useDebounce, useFillHandle, useDataGridState, useColumnHeaderFilterState, useTextFilterState, useMultiSelectFilterState, usePeopleFilterState, useDateFilterState, useColumnChooserState, useInlineCellEditorState, useColumnResize, useRichSelectState, useSideBarState, useTableLayout, useLatestRef, } from './hooks';
|
|
5
|
-
export type { UseFilterOptionsResult, UseOGridResult, UseOGridPagination, UseOGridColumnChooser, UseOGridLayout, UseOGridFilters, ColumnChooserPlacement, UseActiveCellResult, UseCellEditingResult, EditingCell, UseContextMenuResult, ContextMenuPosition, UseCellSelectionResult, UseCellSelectionParams, UseClipboardResult, UseClipboardParams, UseRowSelectionResult, UseRowSelectionParams, UseKeyboardNavigationResult, UseKeyboardNavigationParams, UseUndoRedoResult, UseUndoRedoParams, UseFillHandleResult, UseFillHandleParams, UseDataGridStateParams, UseDataGridStateResult, DataGridLayoutState, DataGridRowSelectionState, DataGridEditingState, DataGridCellInteractionState, DataGridContextMenuState, DataGridViewModelState, UseColumnHeaderFilterStateParams, UseColumnHeaderFilterStateResult, UseTextFilterStateParams, UseTextFilterStateResult, UseMultiSelectFilterStateParams, UseMultiSelectFilterStateResult, UsePeopleFilterStateParams, UsePeopleFilterStateResult, UseDateFilterStateParams, UseDateFilterStateResult, UseColumnChooserStateParams, UseColumnChooserStateResult, UseInlineCellEditorStateParams, UseInlineCellEditorStateResult, InlineCellEditorType, UseColumnResizeParams, UseColumnResizeResult, UseRichSelectStateParams, UseRichSelectStateResult, UseSideBarStateParams, UseSideBarStateResult, UseTableLayoutParams, UseTableLayoutResult, } from './hooks';
|
|
6
|
-
export { OGridLayout } from './components/OGridLayout';
|
|
7
|
-
export type { OGridLayoutProps } from './components/OGridLayout';
|
|
8
|
-
export { StatusBar } from './components/StatusBar';
|
|
9
|
-
export type { StatusBarProps, StatusBarClassNames } from './components/StatusBar';
|
|
10
|
-
export { BaseInlineCellEditor, editorWrapperStyle, editorInputStyle, richSelectWrapperStyle, richSelectDropdownStyle, richSelectOptionStyle, richSelectOptionHighlightedStyle, richSelectNoMatchesStyle, selectEditorStyle, } from './components/BaseInlineCellEditor';
|
|
11
|
-
export type { BaseInlineCellEditorProps } from './components/BaseInlineCellEditor';
|
|
12
|
-
export { GridContextMenu } from './components/GridContextMenu';
|
|
13
|
-
export type { GridContextMenuProps, GridContextMenuClassNames } from './components/GridContextMenu';
|
|
14
|
-
export { MarchingAntsOverlay } from './components/MarchingAntsOverlay';
|
|
15
|
-
export type { MarchingAntsOverlayProps } from './components/MarchingAntsOverlay';
|
|
16
|
-
export { SideBar } from './components/SideBar';
|
|
17
|
-
export type { SideBarProps, SideBarFilterColumn } from './components/SideBar';
|
|
18
|
-
export { CellErrorBoundary } from './components/CellErrorBoundary';
|
|
19
|
-
export type { CellErrorBoundaryProps } from './components/CellErrorBoundary';
|
|
20
|
-
export { EmptyState } from './components/EmptyState';
|
|
21
|
-
export type { EmptyStateProps } from './components/EmptyState';
|
|
22
|
-
export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, GRID_CONTEXT_MENU_ITEMS, getContextMenuHandlers, formatShortcut, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, getHeaderFilterConfig, getCellRenderDescriptor, isRowInRange, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, areGridRowPropsEqual, } from './utils';
|
|
23
|
-
export type { CsvColumn, StatusBarPart, StatusBarPartsInput, GridContextMenuItem, GridContextMenuHandlerProps, PaginationViewModel, HeaderFilterConfigInput, HeaderFilterConfig, CellRenderDescriptorInput, CellRenderDescriptor, CellRenderMode, CellInteractionHandlers, ParseValueResult, AggregationResult, GridRowComparatorProps, } from './utils';
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './utils';
|
|
3
|
+
export * from './constants';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
export type ColumnFilterType = 'none' | 'text' | 'multiSelect' | 'people' | 'date';
|
|
3
2
|
/** Date range filter value (ISO YYYY-MM-DD strings). Both fields optional for open-ended ranges. */
|
|
4
3
|
export interface IDateFilterValue {
|
|
@@ -40,7 +39,6 @@ export interface IValueParserParams<T = unknown> {
|
|
|
40
39
|
column: IColumnDef<T>;
|
|
41
40
|
}
|
|
42
41
|
export interface IColumnDef<T = unknown> extends IColumnMeta {
|
|
43
|
-
renderCell?: (item: T) => React.ReactNode;
|
|
44
42
|
compare?: (a: T, b: T) => number;
|
|
45
43
|
/** Compute cell value from row data (used for filtering, sorting, display when no renderCell). */
|
|
46
44
|
valueGetter?: (item: T) => unknown;
|
|
@@ -52,12 +50,11 @@ export interface IColumnDef<T = unknown> extends IColumnMeta {
|
|
|
52
50
|
* Return the parsed value to use, or `undefined` to reject (skip) the change.
|
|
53
51
|
*/
|
|
54
52
|
valueParser?: (params: IValueParserParams<T>) => unknown;
|
|
55
|
-
/** Static or per-row cell inline styles. */
|
|
56
|
-
cellStyle?: React.CSSProperties | ((item: T) => React.CSSProperties);
|
|
57
53
|
/** Whether the cell is editable (per-column or per-row). */
|
|
58
54
|
editable?: boolean | ((item: T) => boolean);
|
|
59
|
-
/** Built-in editor type or custom React component.
|
|
60
|
-
|
|
55
|
+
/** Built-in editor type or framework-specific custom editor (e.g. React component).
|
|
56
|
+
* Core utilities never inspect this value — framework packages narrow the type. */
|
|
57
|
+
cellEditor?: unknown;
|
|
61
58
|
/** When true, custom cell editor is rendered in a popover/popper instead of inline. */
|
|
62
59
|
cellEditorPopup?: boolean;
|
|
63
60
|
/** Params passed to the cell editor (e.g. { values: string[] } for select). */
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { IColumnDef, IColumnGroupDef, ICellValueChangedEvent, IDateFilterValue } from './columnTypes';
|
|
1
|
+
import type { IDateFilterValue } from './columnTypes';
|
|
3
2
|
/** Row identifier type — grids accept string or number IDs. */
|
|
4
3
|
export type RowId = string | number;
|
|
5
4
|
export interface UserLike {
|
|
@@ -162,151 +161,3 @@ export interface IOGridApi<T> {
|
|
|
162
161
|
/** Re-trigger a data fetch (server-side only; no-op for client-side). */
|
|
163
162
|
refreshData: () => void;
|
|
164
163
|
}
|
|
165
|
-
/** Base props shared by both client-side and server-side OGrid modes. */
|
|
166
|
-
interface IOGridBaseProps<T> {
|
|
167
|
-
columns: (IColumnDef<T> | IColumnGroupDef<T>)[];
|
|
168
|
-
getRowId: (item: T) => RowId;
|
|
169
|
-
page?: number;
|
|
170
|
-
pageSize?: number;
|
|
171
|
-
sort?: {
|
|
172
|
-
field: string;
|
|
173
|
-
direction: 'asc' | 'desc';
|
|
174
|
-
};
|
|
175
|
-
filters?: IFilters;
|
|
176
|
-
visibleColumns?: Set<string>;
|
|
177
|
-
isLoading?: boolean;
|
|
178
|
-
onPageChange?: (page: number) => void;
|
|
179
|
-
onPageSizeChange?: (size: number) => void;
|
|
180
|
-
onSortChange?: (sort: {
|
|
181
|
-
field: string;
|
|
182
|
-
direction: 'asc' | 'desc';
|
|
183
|
-
}) => void;
|
|
184
|
-
onFiltersChange?: (filters: IFilters) => void;
|
|
185
|
-
onVisibleColumnsChange?: (cols: Set<string>) => void;
|
|
186
|
-
columnOrder?: string[];
|
|
187
|
-
onColumnOrderChange?: (order: string[]) => void;
|
|
188
|
-
/** Called when a column is resized by the user. */
|
|
189
|
-
onColumnResized?: (columnId: string, width: number) => void;
|
|
190
|
-
/** Called when a column is pinned or unpinned. */
|
|
191
|
-
onColumnPinned?: (columnId: string, pinned: 'left' | 'right' | null) => void;
|
|
192
|
-
freezeRows?: number;
|
|
193
|
-
freezeCols?: number;
|
|
194
|
-
editable?: boolean;
|
|
195
|
-
/** Enable spreadsheet-like cell selection (active cell, range, fill handle, clipboard, context menu). Default: true. */
|
|
196
|
-
cellSelection?: boolean;
|
|
197
|
-
onCellValueChanged?: (event: ICellValueChangedEvent<T>) => void;
|
|
198
|
-
onUndo?: () => void;
|
|
199
|
-
onRedo?: () => void;
|
|
200
|
-
canUndo?: boolean;
|
|
201
|
-
canRedo?: boolean;
|
|
202
|
-
rowSelection?: RowSelectionMode;
|
|
203
|
-
selectedRows?: Set<RowId>;
|
|
204
|
-
onSelectionChange?: (event: IRowSelectionChangeEvent<T>) => void;
|
|
205
|
-
statusBar?: boolean | IStatusBarProps;
|
|
206
|
-
defaultPageSize?: number;
|
|
207
|
-
defaultSortBy?: string;
|
|
208
|
-
defaultSortDirection?: 'asc' | 'desc';
|
|
209
|
-
toolbar?: ReactNode;
|
|
210
|
-
/** Secondary toolbar row rendered below the primary toolbar (e.g. active filter chips). */
|
|
211
|
-
toolbarBelow?: ReactNode;
|
|
212
|
-
emptyState?: {
|
|
213
|
-
message?: ReactNode;
|
|
214
|
-
render?: () => ReactNode;
|
|
215
|
-
};
|
|
216
|
-
entityLabelPlural?: string;
|
|
217
|
-
className?: string;
|
|
218
|
-
/** Where the column chooser renders.
|
|
219
|
-
* - `true` or `'toolbar'` (default): column chooser button in the toolbar strip.
|
|
220
|
-
* - `'sidebar'`: column chooser only available via the sidebar columns panel.
|
|
221
|
-
* - `false`: column chooser hidden entirely. */
|
|
222
|
-
columnChooser?: boolean | 'toolbar' | 'sidebar';
|
|
223
|
-
layoutMode?: 'content' | 'fill';
|
|
224
|
-
/** When true, horizontal scrolling is suppressed (overflow-x hidden). */
|
|
225
|
-
suppressHorizontalScroll?: boolean;
|
|
226
|
-
/** Side bar configuration. `true` shows default panels (columns + filters). Pass ISideBarDef for options. */
|
|
227
|
-
sideBar?: boolean | ISideBarDef;
|
|
228
|
-
/** Page size options shown in the pagination dropdown. Default: [10, 20, 50, 100]. */
|
|
229
|
-
pageSizeOptions?: number[];
|
|
230
|
-
/** Fires once when the grid first renders with data (useful for restoring column state). */
|
|
231
|
-
onFirstDataRendered?: () => void;
|
|
232
|
-
/** Called when server-side fetchPage fails. */
|
|
233
|
-
onError?: (error: unknown) => void;
|
|
234
|
-
/** Called when a cell renderer or custom editor throws an error. */
|
|
235
|
-
onCellError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
236
|
-
'aria-label'?: string;
|
|
237
|
-
'aria-labelledby'?: string;
|
|
238
|
-
}
|
|
239
|
-
/** Client-side mode: pass a data array. */
|
|
240
|
-
export interface IOGridClientProps<T> extends IOGridBaseProps<T> {
|
|
241
|
-
data: T[];
|
|
242
|
-
dataSource?: never;
|
|
243
|
-
}
|
|
244
|
-
/** Server-side mode: pass a dataSource. */
|
|
245
|
-
export interface IOGridServerProps<T> extends IOGridBaseProps<T> {
|
|
246
|
-
data?: never;
|
|
247
|
-
dataSource: IDataSource<T>;
|
|
248
|
-
}
|
|
249
|
-
/** Props for the OGrid wrapper component (shared across Fluent, Material, Radix).
|
|
250
|
-
* Must provide either `data` (client-side) or `dataSource` (server-side), not both. */
|
|
251
|
-
export type IOGridProps<T> = IOGridClientProps<T> | IOGridServerProps<T>;
|
|
252
|
-
/** Props passed from useOGrid to the framework-specific DataGridTable. */
|
|
253
|
-
export interface IOGridDataGridProps<T> {
|
|
254
|
-
items: T[];
|
|
255
|
-
columns: (IColumnDef<T> | IColumnGroupDef<T>)[];
|
|
256
|
-
getRowId: (item: T) => RowId;
|
|
257
|
-
sortBy?: string;
|
|
258
|
-
sortDirection: 'asc' | 'desc';
|
|
259
|
-
onColumnSort: (columnKey: string) => void;
|
|
260
|
-
visibleColumns: Set<string>;
|
|
261
|
-
/** Optional column display order (column ids). When set, visible columns are ordered by this array. */
|
|
262
|
-
columnOrder?: string[];
|
|
263
|
-
onColumnOrderChange?: (order: string[]) => void;
|
|
264
|
-
/** Called when a column is resized by the user. */
|
|
265
|
-
onColumnResized?: (columnId: string, width: number) => void;
|
|
266
|
-
/** Called when a column is pinned or unpinned. */
|
|
267
|
-
onColumnPinned?: (columnId: string, pinned: 'left' | 'right' | null) => void;
|
|
268
|
-
/** Runtime pin overrides (from restored state or programmatic changes). */
|
|
269
|
-
pinnedColumns?: Record<string, 'left' | 'right'>;
|
|
270
|
-
/** Initial column width overrides (from restored state). */
|
|
271
|
-
initialColumnWidths?: Record<string, number>;
|
|
272
|
-
/** Number of rows to freeze (sticky), e.g. 1 = header row. */
|
|
273
|
-
freezeRows?: number;
|
|
274
|
-
/** Number of data columns to freeze (sticky left). */
|
|
275
|
-
freezeCols?: number;
|
|
276
|
-
layoutMode?: 'content' | 'fill';
|
|
277
|
-
/** When true, horizontal scrolling is suppressed (overflow-x hidden). */
|
|
278
|
-
suppressHorizontalScroll?: boolean;
|
|
279
|
-
isLoading?: boolean;
|
|
280
|
-
loadingMessage?: string;
|
|
281
|
-
editable?: boolean;
|
|
282
|
-
/** Enable spreadsheet-like cell selection. Default: true. */
|
|
283
|
-
cellSelection?: boolean;
|
|
284
|
-
onCellValueChanged?: (event: ICellValueChangedEvent<T>) => void;
|
|
285
|
-
onUndo?: () => void;
|
|
286
|
-
onRedo?: () => void;
|
|
287
|
-
canUndo?: boolean;
|
|
288
|
-
canRedo?: boolean;
|
|
289
|
-
rowSelection?: RowSelectionMode;
|
|
290
|
-
selectedRows?: Set<RowId>;
|
|
291
|
-
onSelectionChange?: (event: IRowSelectionChangeEvent<T>) => void;
|
|
292
|
-
statusBar?: IStatusBarProps;
|
|
293
|
-
/** Unified filter model (discriminated union values). */
|
|
294
|
-
filters: IFilters;
|
|
295
|
-
/** Single callback for all filter changes. Pass undefined to clear. */
|
|
296
|
-
onFilterChange: (key: string, value: FilterValue | undefined) => void;
|
|
297
|
-
filterOptions: Record<string, string[]>;
|
|
298
|
-
loadingFilterOptions: Record<string, boolean>;
|
|
299
|
-
peopleSearch?: (query: string) => Promise<UserLike[]>;
|
|
300
|
-
getUserByEmail?: (email: string) => Promise<UserLike | undefined>;
|
|
301
|
-
emptyState?: {
|
|
302
|
-
onClearAll: () => void;
|
|
303
|
-
hasActiveFilters: boolean;
|
|
304
|
-
message?: ReactNode;
|
|
305
|
-
render?: () => ReactNode;
|
|
306
|
-
};
|
|
307
|
-
/** Called when a cell renderer or custom editor throws an error. */
|
|
308
|
-
onCellError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
309
|
-
'aria-label'?: string;
|
|
310
|
-
'aria-labelledby'?: string;
|
|
311
|
-
}
|
|
312
|
-
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { ColumnFilterType, IColumnFilterDef, IColumnMeta,
|
|
2
|
-
export type { RowId, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState,
|
|
3
|
-
export { toUserLike, isInSelectionRange, normalizeSelectionRange } from './dataGridTypes';
|
|
1
|
+
export type { ColumnFilterType, IDateFilterValue, IColumnFilterDef, IColumnMeta, IValueParserParams, IColumnDef, ICellValueChangedEvent, ICellEditorProps, CellEditorParams, IColumnGroupDef, HeaderCell, HeaderRow, IColumnDefinition, } from './columnTypes';
|
|
2
|
+
export type { RowId, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState, RowSelectionMode, IRowSelectionChangeEvent, StatusBarPanel, IStatusBarProps, IActiveCell, ISelectionRange, SideBarPanelId, ISideBarDef, IOGridApi, } from './dataGridTypes';
|
|
3
|
+
export { toUserLike, isInSelectionRange, normalizeSelectionRange, } from './dataGridTypes';
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a given row index falls within a selection range.
|
|
3
|
+
* O(1) — used by React.memo comparators to skip unchanged rows.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isRowInRange(range: {
|
|
6
|
+
startRow: number;
|
|
7
|
+
endRow: number;
|
|
8
|
+
} | null, rowIndex: number): boolean;
|
|
1
9
|
/**
|
|
2
10
|
* Props for GridRow comparator (generic to work with all 3 UI frameworks).
|
|
3
11
|
* Includes both render props and comparator-only props used to decide re-renders.
|
|
@@ -7,8 +7,6 @@ export { getDataGridStatusBarConfig } from './dataGridStatusBar';
|
|
|
7
7
|
export { getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, } from './paginationHelpers';
|
|
8
8
|
export type { PaginationViewModel } from './paginationHelpers';
|
|
9
9
|
export { GRID_CONTEXT_MENU_ITEMS, getContextMenuHandlers, formatShortcut } from './gridContextMenuHelpers';
|
|
10
|
-
export { getHeaderFilterConfig, getCellRenderDescriptor, isRowInRange, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, } from './dataGridViewModel';
|
|
11
|
-
export type { HeaderFilterConfigInput, HeaderFilterConfig, CellRenderDescriptorInput, CellRenderDescriptor, CellRenderMode, CellInteractionHandlers, } from './dataGridViewModel';
|
|
12
10
|
export type { CsvColumn } from './exportToCsv';
|
|
13
11
|
export type { StatusBarPart, StatusBarPartsInput } from './statusBarHelpers';
|
|
14
12
|
export type { GridContextMenuItem, GridContextMenuHandlerProps } from './gridContextMenuHelpers';
|
|
@@ -17,5 +15,5 @@ export type { ParseValueResult } from './valueParsers';
|
|
|
17
15
|
export { computeAggregations } from './aggregationUtils';
|
|
18
16
|
export type { AggregationResult } from './aggregationUtils';
|
|
19
17
|
export { processClientSideData } from './clientSideData';
|
|
20
|
-
export { areGridRowPropsEqual } from './gridRowComparator';
|
|
18
|
+
export { areGridRowPropsEqual, isRowInRange } from './gridRowComparator';
|
|
21
19
|
export type { GridRowComparatorProps } from './gridRowComparator';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-core",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "OGrid core – framework-agnostic types,
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "OGrid core – framework-agnostic types, algorithms, and utilities for OGrid data grids.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/types/index.d.ts",
|
|
@@ -16,28 +16,10 @@
|
|
|
16
16
|
"build": "rimraf dist && tsc -p tsconfig.build.json",
|
|
17
17
|
"test": "jest"
|
|
18
18
|
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"ogrid",
|
|
21
|
-
"datatable",
|
|
22
|
-
"react",
|
|
23
|
-
"typescript",
|
|
24
|
-
"grid",
|
|
25
|
-
"core"
|
|
26
|
-
],
|
|
19
|
+
"keywords": ["ogrid", "datatable", "typescript", "grid", "core"],
|
|
27
20
|
"author": "Ala Arab",
|
|
28
21
|
"license": "MIT",
|
|
29
|
-
"files": [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"LICENSE"
|
|
33
|
-
],
|
|
34
|
-
"engines": {
|
|
35
|
-
"node": ">=18"
|
|
36
|
-
},
|
|
37
|
-
"peerDependencies": {
|
|
38
|
-
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
39
|
-
},
|
|
40
|
-
"publishConfig": {
|
|
41
|
-
"access": "public"
|
|
42
|
-
}
|
|
22
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
23
|
+
"engines": { "node": ">=18" },
|
|
24
|
+
"publishConfig": { "access": "public" }
|
|
43
25
|
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { useInlineCellEditorState, useRichSelectState } from '../hooks';
|
|
4
|
-
// ── Shared editor style constants (used across all 3 UI packages) ──
|
|
5
|
-
export const editorWrapperStyle = {
|
|
6
|
-
width: '100%',
|
|
7
|
-
height: '100%',
|
|
8
|
-
display: 'flex',
|
|
9
|
-
alignItems: 'center',
|
|
10
|
-
padding: '6px 10px',
|
|
11
|
-
boxSizing: 'border-box',
|
|
12
|
-
overflow: 'hidden',
|
|
13
|
-
minWidth: 0,
|
|
14
|
-
};
|
|
15
|
-
export const editorInputStyle = {
|
|
16
|
-
width: '100%',
|
|
17
|
-
padding: 0,
|
|
18
|
-
border: 'none',
|
|
19
|
-
background: 'transparent',
|
|
20
|
-
color: 'inherit',
|
|
21
|
-
font: 'inherit',
|
|
22
|
-
fontSize: '13px',
|
|
23
|
-
outline: 'none',
|
|
24
|
-
minWidth: 0,
|
|
25
|
-
};
|
|
26
|
-
export const richSelectWrapperStyle = {
|
|
27
|
-
...editorWrapperStyle,
|
|
28
|
-
position: 'relative',
|
|
29
|
-
};
|
|
30
|
-
export const richSelectDropdownStyle = {
|
|
31
|
-
position: 'absolute',
|
|
32
|
-
top: '100%',
|
|
33
|
-
left: 0,
|
|
34
|
-
right: 0,
|
|
35
|
-
maxHeight: 200,
|
|
36
|
-
overflowY: 'auto',
|
|
37
|
-
background: 'var(--ogrid-bg, #fff)',
|
|
38
|
-
border: '1px solid var(--ogrid-border, #ccc)',
|
|
39
|
-
zIndex: 10,
|
|
40
|
-
boxShadow: '0 4px 16px rgba(0,0,0,0.2)',
|
|
41
|
-
};
|
|
42
|
-
export const richSelectOptionStyle = {
|
|
43
|
-
padding: '6px 8px',
|
|
44
|
-
cursor: 'pointer',
|
|
45
|
-
color: 'var(--ogrid-fg, #242424)',
|
|
46
|
-
};
|
|
47
|
-
export const richSelectOptionHighlightedStyle = {
|
|
48
|
-
...richSelectOptionStyle,
|
|
49
|
-
background: 'var(--ogrid-bg-hover, #e8f0fe)',
|
|
50
|
-
};
|
|
51
|
-
export const richSelectNoMatchesStyle = {
|
|
52
|
-
padding: '6px 8px',
|
|
53
|
-
color: 'var(--ogrid-muted, #999)',
|
|
54
|
-
};
|
|
55
|
-
export const selectEditorStyle = {
|
|
56
|
-
width: '100%',
|
|
57
|
-
padding: 0,
|
|
58
|
-
border: 'none',
|
|
59
|
-
background: 'transparent',
|
|
60
|
-
color: 'inherit',
|
|
61
|
-
font: 'inherit',
|
|
62
|
-
fontSize: '13px',
|
|
63
|
-
cursor: 'pointer',
|
|
64
|
-
outline: 'none',
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* Base inline cell editor with shared logic for all editor types except checkbox and select
|
|
68
|
-
* (which are framework-specific). Used by all 3 UI packages to avoid duplication.
|
|
69
|
-
*
|
|
70
|
-
* Usage:
|
|
71
|
-
* - Radix: Pass Radix Checkbox/native select via render props
|
|
72
|
-
* - Fluent: Pass Fluent Checkbox/Select via render props
|
|
73
|
-
* - Material: Pass MUI Checkbox/Select via render props
|
|
74
|
-
*/
|
|
75
|
-
export function BaseInlineCellEditor(props) {
|
|
76
|
-
const { value, column, editorType, onCommit, onCancel, renderCheckbox, renderSelect } = props;
|
|
77
|
-
const wrapperRef = React.useRef(null);
|
|
78
|
-
const { localValue, setLocalValue, handleKeyDown, handleBlur, commit, cancel } = useInlineCellEditorState({ value, editorType, onCommit, onCancel });
|
|
79
|
-
const richSelectValues = column.cellEditorParams?.values ?? [];
|
|
80
|
-
const richSelectFormatValue = column.cellEditorParams?.formatValue;
|
|
81
|
-
const richSelect = useRichSelectState({
|
|
82
|
-
values: richSelectValues,
|
|
83
|
-
formatValue: richSelectFormatValue,
|
|
84
|
-
initialValue: value,
|
|
85
|
-
onCommit,
|
|
86
|
-
onCancel,
|
|
87
|
-
});
|
|
88
|
-
React.useEffect(() => {
|
|
89
|
-
const input = wrapperRef.current?.querySelector('input');
|
|
90
|
-
input?.focus();
|
|
91
|
-
}, []);
|
|
92
|
-
// Rich select (shared across all frameworks)
|
|
93
|
-
if (editorType === 'richSelect') {
|
|
94
|
-
return (_jsxs("div", { ref: wrapperRef, style: richSelectWrapperStyle, children: [_jsx("input", { type: "text", value: richSelect.searchText, onChange: (e) => richSelect.setSearchText(e.target.value), onKeyDown: richSelect.handleKeyDown, placeholder: "Search...", autoFocus: true, style: editorInputStyle }), _jsxs("div", { style: richSelectDropdownStyle, role: "listbox", children: [richSelect.filteredValues.map((v, i) => (_jsx("div", { role: "option", "aria-selected": i === richSelect.highlightedIndex, onClick: () => richSelect.selectValue(v), style: i === richSelect.highlightedIndex ? richSelectOptionHighlightedStyle : richSelectOptionStyle, children: richSelect.getDisplayText(v) }, String(v)))), richSelect.filteredValues.length === 0 && (_jsx("div", { style: richSelectNoMatchesStyle, children: "No matches" }))] })] }));
|
|
95
|
-
}
|
|
96
|
-
// Checkbox (framework-specific)
|
|
97
|
-
if (editorType === 'checkbox') {
|
|
98
|
-
const checked = value === true;
|
|
99
|
-
return _jsx(_Fragment, { children: renderCheckbox(checked, (val) => commit(val), cancel) });
|
|
100
|
-
}
|
|
101
|
-
// Select (framework-specific)
|
|
102
|
-
if (editorType === 'select') {
|
|
103
|
-
const values = column.cellEditorParams?.values ?? [];
|
|
104
|
-
return _jsx(_Fragment, { children: renderSelect(value, values, commit, cancel) });
|
|
105
|
-
}
|
|
106
|
-
// Date editor (shared across all frameworks)
|
|
107
|
-
if (editorType === 'date') {
|
|
108
|
-
return (_jsx("div", { ref: wrapperRef, style: editorWrapperStyle, children: _jsx("input", { type: "date", value: localValue, onChange: (e) => setLocalValue(e.target.value), onBlur: handleBlur, onKeyDown: handleKeyDown, style: editorInputStyle, autoFocus: true }) }));
|
|
109
|
-
}
|
|
110
|
-
// Text editor (default, shared across all frameworks)
|
|
111
|
-
return (_jsx("div", { ref: wrapperRef, style: editorWrapperStyle, children: _jsx("input", { type: "text", value: localValue, onChange: (e) => setLocalValue(e.target.value), onBlur: handleBlur, onKeyDown: handleKeyDown, style: editorInputStyle, autoFocus: true }) }));
|
|
112
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
const DEFAULT_FALLBACK_STYLE = {
|
|
4
|
-
color: '#d32f2f',
|
|
5
|
-
fontSize: '0.75rem',
|
|
6
|
-
padding: '2px 4px',
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Error boundary for cell renderers and custom editors.
|
|
10
|
-
* Prevents a runtime error in a cell from crashing the entire grid.
|
|
11
|
-
*/
|
|
12
|
-
export class CellErrorBoundary extends React.Component {
|
|
13
|
-
constructor(props) {
|
|
14
|
-
super(props);
|
|
15
|
-
this.state = { hasError: false };
|
|
16
|
-
}
|
|
17
|
-
static getDerivedStateFromError() {
|
|
18
|
-
return { hasError: true };
|
|
19
|
-
}
|
|
20
|
-
componentDidCatch(error, errorInfo) {
|
|
21
|
-
if (this.props.onError) {
|
|
22
|
-
this.props.onError(error, errorInfo);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
componentDidUpdate(prevProps) {
|
|
26
|
-
// Reset error state when children change (e.g., navigating to a different cell)
|
|
27
|
-
if (prevProps.children !== this.props.children && this.state.hasError) {
|
|
28
|
-
this.setState({ hasError: false });
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
resetErrorBoundary() {
|
|
32
|
-
this.setState({ hasError: false });
|
|
33
|
-
}
|
|
34
|
-
render() {
|
|
35
|
-
if (this.state.hasError) {
|
|
36
|
-
if (this.props.fallback !== undefined) {
|
|
37
|
-
return this.props.fallback;
|
|
38
|
-
}
|
|
39
|
-
return _jsx("span", { style: DEFAULT_FALLBACK_STYLE, children: "\u26A0 Error" });
|
|
40
|
-
}
|
|
41
|
-
return this.props.children;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
const clearButtonStyle = { background: 'none', border: 'none', color: 'inherit', textDecoration: 'underline', cursor: 'pointer', padding: 0, font: 'inherit' };
|
|
3
|
-
/**
|
|
4
|
-
* Headless empty state component with default rendering logic.
|
|
5
|
-
* Framework-specific wrappers provide styling.
|
|
6
|
-
*
|
|
7
|
-
* Default behavior:
|
|
8
|
-
* - Shows "No results found" title
|
|
9
|
-
* - If hasActiveFilters=true: shows "clear all filters" link
|
|
10
|
-
* - If message provided: shows custom message
|
|
11
|
-
* - If render provided: uses custom renderer
|
|
12
|
-
*/
|
|
13
|
-
export function EmptyState(props) {
|
|
14
|
-
const { message, hasActiveFilters, onClearAll, render } = props;
|
|
15
|
-
if (render) {
|
|
16
|
-
return _jsx(_Fragment, { children: render() });
|
|
17
|
-
}
|
|
18
|
-
return (_jsx(_Fragment, { children: message != null ? (message) : hasActiveFilters ? (_jsxs(_Fragment, { children: ["No items match your current filters. Try adjusting your search or", ' ', _jsx("button", { type: "button", onClick: onClearAll, style: clearButtonStyle, children: "clear all filters" }), ' ', "to see all items."] })) : ('There are no items available at this time.') }));
|
|
19
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { GRID_CONTEXT_MENU_ITEMS, getContextMenuHandlers, formatShortcut } from '../utils/gridContextMenuHelpers';
|
|
4
|
-
const menuPositionStyle = (x, y) => ({ left: x, top: y });
|
|
5
|
-
export function GridContextMenu(props) {
|
|
6
|
-
const { x, y, hasSelection, canUndo, canRedo, onClose, onCopy, onCut, onPaste, onSelectAll, onUndo, onRedo, classNames } = props;
|
|
7
|
-
const ref = React.useRef(null);
|
|
8
|
-
const handlers = React.useMemo(() => getContextMenuHandlers({ onCopy, onCut, onPaste, onSelectAll, onUndo, onRedo, onClose }), [onCopy, onCut, onPaste, onSelectAll, onUndo, onRedo, onClose]);
|
|
9
|
-
const isDisabled = React.useCallback((item) => {
|
|
10
|
-
if (item.disabledWhenNoSelection && !hasSelection)
|
|
11
|
-
return true;
|
|
12
|
-
if (item.id === 'undo' && !canUndo)
|
|
13
|
-
return true;
|
|
14
|
-
if (item.id === 'redo' && !canRedo)
|
|
15
|
-
return true;
|
|
16
|
-
return false;
|
|
17
|
-
}, [hasSelection, canUndo, canRedo]);
|
|
18
|
-
React.useEffect(() => {
|
|
19
|
-
const handleClickOutside = (e) => {
|
|
20
|
-
if (ref.current && !ref.current.contains(e.target))
|
|
21
|
-
onClose();
|
|
22
|
-
};
|
|
23
|
-
const handleKeyDown = (e) => {
|
|
24
|
-
if (e.key === 'Escape')
|
|
25
|
-
onClose();
|
|
26
|
-
};
|
|
27
|
-
document.addEventListener('mousedown', handleClickOutside, true);
|
|
28
|
-
document.addEventListener('keydown', handleKeyDown, true);
|
|
29
|
-
return () => {
|
|
30
|
-
document.removeEventListener('mousedown', handleClickOutside, true);
|
|
31
|
-
document.removeEventListener('keydown', handleKeyDown, true);
|
|
32
|
-
};
|
|
33
|
-
}, [onClose]);
|
|
34
|
-
return (_jsx("div", { ref: ref, className: classNames?.contextMenu, role: "menu", style: menuPositionStyle(x, y), "aria-label": "Grid context menu", children: GRID_CONTEXT_MENU_ITEMS.map((item) => (_jsxs(React.Fragment, { children: [item.dividerBefore && _jsx("div", { className: classNames?.contextMenuDivider }), _jsxs("button", { type: "button", className: classNames?.contextMenuItem, onClick: handlers[item.id], disabled: isDisabled(item), children: [_jsx("span", { className: classNames?.contextMenuItemLabel, children: item.label }), item.shortcut && (_jsx("span", { className: classNames?.contextMenuItemShortcut, children: formatShortcut(item.shortcut) }))] })] }, item.id))) }));
|
|
35
|
-
}
|