@rovula/ui 0.1.28 → 0.1.30

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.
Files changed (65) hide show
  1. package/dist/cjs/bundle.css +522 -67
  2. package/dist/cjs/bundle.js +589 -589
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/DataTable/DataTable.d.ts +195 -4
  5. package/dist/cjs/types/components/DataTable/DataTable.editing.d.ts +20 -0
  6. package/dist/cjs/types/components/DataTable/DataTable.editing.types.d.ts +145 -0
  7. package/dist/cjs/types/components/DataTable/DataTable.stories.d.ts +294 -6
  8. package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +22 -0
  9. package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +4 -0
  10. package/dist/cjs/types/components/ScrollArea/ScrollArea.d.ts +3 -3
  11. package/dist/cjs/types/components/ScrollArea/ScrollArea.stories.d.ts +4 -0
  12. package/dist/cjs/types/components/Table/Table.d.ts +33 -3
  13. package/dist/cjs/types/components/Table/Table.stories.d.ts +86 -4
  14. package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +8 -0
  15. package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +1 -0
  16. package/dist/components/DataTable/DataTable.editing.js +385 -0
  17. package/dist/components/DataTable/DataTable.editing.types.js +1 -0
  18. package/dist/components/DataTable/DataTable.js +993 -50
  19. package/dist/components/DataTable/DataTable.stories.js +1137 -25
  20. package/dist/components/Dropdown/Dropdown.js +8 -6
  21. package/dist/components/ScrollArea/ScrollArea.js +2 -2
  22. package/dist/components/ScrollArea/ScrollArea.stories.js +68 -2
  23. package/dist/components/Table/Table.js +103 -13
  24. package/dist/components/Table/Table.stories.js +226 -9
  25. package/dist/components/TextInput/TextInput.js +6 -4
  26. package/dist/components/TextInput/TextInput.stories.js +8 -0
  27. package/dist/components/TextInput/TextInput.styles.js +7 -1
  28. package/dist/esm/bundle.css +522 -67
  29. package/dist/esm/bundle.js +1545 -1545
  30. package/dist/esm/bundle.js.map +1 -1
  31. package/dist/esm/types/components/DataTable/DataTable.d.ts +195 -4
  32. package/dist/esm/types/components/DataTable/DataTable.editing.d.ts +20 -0
  33. package/dist/esm/types/components/DataTable/DataTable.editing.types.d.ts +145 -0
  34. package/dist/esm/types/components/DataTable/DataTable.stories.d.ts +294 -6
  35. package/dist/esm/types/components/Dropdown/Dropdown.d.ts +22 -0
  36. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +4 -0
  37. package/dist/esm/types/components/ScrollArea/ScrollArea.d.ts +3 -3
  38. package/dist/esm/types/components/ScrollArea/ScrollArea.stories.d.ts +4 -0
  39. package/dist/esm/types/components/Table/Table.d.ts +33 -3
  40. package/dist/esm/types/components/Table/Table.stories.d.ts +86 -4
  41. package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +8 -0
  42. package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +1 -0
  43. package/dist/index.d.ts +493 -122
  44. package/dist/src/theme/global.css +775 -96
  45. package/package.json +14 -2
  46. package/src/components/DataTable/DataTable.editing.tsx +861 -0
  47. package/src/components/DataTable/DataTable.editing.types.ts +192 -0
  48. package/src/components/DataTable/DataTable.stories.tsx +2310 -31
  49. package/src/components/DataTable/DataTable.test.tsx +696 -0
  50. package/src/components/DataTable/DataTable.tsx +2275 -94
  51. package/src/components/Dropdown/Dropdown.tsx +22 -6
  52. package/src/components/ScrollArea/ScrollArea.stories.tsx +146 -3
  53. package/src/components/ScrollArea/ScrollArea.tsx +6 -6
  54. package/src/components/Table/Table.stories.tsx +789 -44
  55. package/src/components/Table/Table.tsx +306 -28
  56. package/src/components/TextInput/TextInput.stories.tsx +80 -0
  57. package/src/components/TextInput/TextInput.styles.ts +7 -1
  58. package/src/components/TextInput/TextInput.tsx +21 -14
  59. package/src/test/setup.ts +50 -0
  60. package/src/theme/global.css +81 -42
  61. package/src/theme/presets/colors.js +12 -0
  62. package/src/theme/themes/variable.css +27 -28
  63. package/src/theme/tokens/baseline.css +2 -1
  64. package/src/theme/tokens/components/scrollbar.css +9 -4
  65. package/src/theme/tokens/components/table.css +63 -0
@@ -1,9 +1,200 @@
1
- import { ColumnDef, SortingState } from "@tanstack/react-table";
2
- export interface DataTableProps<TData, TValue> {
3
- columns: ColumnDef<TData, TValue>[];
1
+ import { Cell, ColumnDef, ExpandedState, Header, PaginationState, Row, RowSelectionState, RowData, SortingState } from "@tanstack/react-table";
2
+ import React from "react";
3
+ declare module "@tanstack/react-table" {
4
+ interface ColumnMeta<TData extends RowData, TValue> {
5
+ exactWidth?: number | string;
6
+ align?: "left" | "center" | "right";
7
+ cellClassName?: string;
8
+ headerCellClassName?: string;
9
+ colSpan?: number | ((row: Row<TData>) => number);
10
+ }
11
+ }
12
+ /** TanStack Table types used by `DataTable` props — import from `@rovula/ui` to stay aligned with this package and `ColumnMeta` augmentation. */
13
+ export type { Cell, ColumnDef, ExpandedState, Header, PaginationState, Row, RowData, RowSelectionState, SortingState, Table as TanstackTable, } from "@tanstack/react-table";
14
+ export type { EditableColumnDef, EditDisplayMode, EditTrigger, DataTableEditingProps, } from "./DataTable.editing.types";
15
+ import type { EditableColumnDef, DataTableEditingProps } from "./DataTable.editing.types";
16
+ export type DataTablePaginationMode = "server" | "client" | "infinite";
17
+ export interface DataTableProps<TData, TValue> extends DataTableEditingProps<TData> {
18
+ columns: (ColumnDef<TData, TValue> | EditableColumnDef<TData, TValue>)[];
4
19
  data: TData[];
5
20
  manualSorting?: boolean;
6
21
  onSorting?: (sorting: SortingState) => void;
22
+ /**
23
+ * "client" – DataTable manages page state internally with TanStack
24
+ * "server" – caller controls page state; pass pageIndex/pageSize/totalCount
25
+ * "infinite" – no pagination bar; fetchMoreData enables infinite scroll
26
+ */
27
+ paginationMode?: DataTablePaginationMode;
28
+ /** Required for "server" mode */
29
+ totalCount?: number;
30
+ pageIndex?: number;
31
+ pageSize?: number;
32
+ onPaginationChange?: (state: PaginationState) => void;
33
+ pageSizeOptions?: number[];
34
+ /** Called when user scrolls near bottom (infinite mode). */
7
35
  fetchMoreData?: () => void;
36
+ /**
37
+ * Threshold in pixels from the bottom of the scroll container at which
38
+ * `fetchMoreData` is triggered. Defaults to 10px.
39
+ */
40
+ fetchMoreOffset?: number;
41
+ /**
42
+ * When `paginationMode` is `"infinite"`, shows a built-in footer row (spinner +
43
+ * label) and suppresses additional `fetchMoreData` calls until this is false again.
44
+ */
45
+ fetchingMore?: boolean;
46
+ /** Accessible label next to the spinner (default: "Loading more…"). */
47
+ fetchingMoreLabel?: string;
48
+ /**
49
+ * When there are no rows yet, shows a built-in loading state instead of the
50
+ * empty placeholder. Also suppresses `fetchMoreData` while true (infinite mode).
51
+ */
52
+ loading?: boolean;
53
+ /** Label for the initial-loading state (default: "Loading…"). */
54
+ loadingLabel?: string;
55
+ /**
56
+ * When true, DataTable will only render a vertical window of rows based on
57
+ * the scroll position of its internal scroll container. This is a basic
58
+ * fixed-row-height virtualizer intended for large but finite lists.
59
+ *
60
+ * Notes / limitations:
61
+ * - Only vertical row virtualization is supported.
62
+ * - Assumes approximately fixed row height; pass `virtualRowEstimate` to tune.
63
+ * - Works with selection, row actions, and basic infinite scroll, but more
64
+ * complex combinations (tree rows, reorder, etc.) may have visual quirks.
65
+ */
66
+ virtualized?: boolean;
67
+ /**
68
+ * Estimated height in pixels for a single table row when `virtualized` is
69
+ * true. Used to compute how many rows fit in the viewport and the spacer
70
+ * heights above/below the rendered window.
71
+ * @default 40
72
+ */
73
+ virtualRowEstimate?: number;
74
+ /**
75
+ * Optional row id(s) to highlight visually. Highlighting is purely cosmetic
76
+ * and does not affect selection state.
77
+ */
78
+ highlightRowId?: string | string[];
79
+ /**
80
+ * When true and `highlightRowId` is set, moving the mouse pointer out of the
81
+ * scroll area will automatically scroll the first highlighted row back into
82
+ * view (centered).
83
+ */
84
+ scrollToHighlightOnMouseLeave?: boolean;
85
+ selectable?: boolean;
86
+ onRowSelectionChange?: (rows: RowSelectionState) => void;
87
+ /** Render actions into the last fixed-width column. Receives the TanStack Row. */
88
+ rowActions?: (row: Row<TData>) => React.ReactNode;
89
+ /**
90
+ * Enable drag-to-reorder rows. A grip handle column is prepended automatically.
91
+ * Requires each data item to have a unique `id` field (string | number)
92
+ * or supply `getRowId` to derive one.
93
+ */
94
+ reorderable?: boolean;
95
+ /** Return a unique string id for each row. Defaults to `(row) => row.id`. */
96
+ getRowId?: (row: TData) => string;
97
+ /** Called after the user drops a row into a new position. Receives the reordered data array. */
98
+ onRowReorder?: (data: TData[]) => void;
99
+ /**
100
+ * When `reorderable`, rows that return `true` are not draggable and are
101
+ * omitted from the sortable context (e.g. a pinned footer "add" row).
102
+ * Those rows are also kept **after** all sortable rows whenever column sort
103
+ * is applied (order among locked rows follows original `data` order).
104
+ */
105
+ isRowReorderLocked?: (row: Row<TData>) => boolean;
106
+ /** Fired when a body row is clicked. */
107
+ onRowClick?: (row: Row<TData>, event: React.MouseEvent) => void;
108
+ /** Fired when an individual body cell is clicked. */
109
+ onCellClick?: (cell: Cell<TData, unknown>, row: Row<TData>, event: React.MouseEvent) => void;
110
+ /** Return child rows to enable tree expansion */
111
+ getSubRows?: (row: TData) => TData[] | undefined;
112
+ /** Initial expanded state — `true` = all expanded, `{}` = all collapsed (uncontrolled) */
113
+ defaultExpanded?: ExpandedState | boolean;
114
+ /** Controlled expanded state — omit to let DataTable manage internally */
115
+ expanded?: ExpandedState;
116
+ onExpandedChange?: (expanded: ExpandedState) => void;
117
+ /**
118
+ * Rounded frame + `border-table-c-border` around the scroll area and pagination
119
+ * (same token as primitive `Table` `bordered`). Set `false` when embedding in
120
+ * another bordered surface.
121
+ */
122
+ bordered?: boolean;
123
+ /**
124
+ * `"panel"` sets `data-surface="panel"` for table token overrides (modal /
125
+ * drawer). `"default"` leaves surface to ancestors.
126
+ */
127
+ surface?: "default" | "panel";
128
+ /** Alternate row background colours (RowA / RowB) */
129
+ striped?: boolean;
130
+ /** Add vertical column dividers */
131
+ divided?: boolean;
132
+ /** Return a className string to apply to a specific body row. */
133
+ rowClassName?: string | ((row: Row<TData>, index: number) => string | undefined);
134
+ /** Return a className string to apply to a specific body cell. */
135
+ cellClassName?: string | ((cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined);
136
+ /** Return a className string to apply to a specific column header cell (`<th>`). */
137
+ headerCellClassName?: string | ((header: Header<TData, unknown>) => string | undefined);
138
+ /** Additional className for the header section (`<thead>`). */
139
+ headerClassName?: string;
140
+ /** Additional className for the header row (`<tr>` inside `<thead>`). */
141
+ headerRowClassName?: string;
142
+ /**
143
+ * Controls when the sort indicator button is visible on sortable columns.
144
+ * - `"hover"` – shown only when hovering the column header (default)
145
+ * - `"always"` – always visible
146
+ */
147
+ sortIndicatorVisibility?: "always" | "hover";
148
+ /**
149
+ * CSS `table-layout` mode.
150
+ * - `"auto"` – browser sizes columns based on content (default)
151
+ * - `"fixed"` – non-`exactWidth` columns use their `size` as pixel widths;
152
+ * the **last** visible non-exact column absorbs leftover width so the table
153
+ * stays full-width. `meta.exactWidth` (px) columns stay locked.
154
+ * - `"equal"` – all visible columns without `meta.exactWidth` share the
155
+ * remaining table width equally via
156
+ * `calc((100% - <sum of exactWidth>px) / <flex column count>)`.
157
+ * Columns with `meta.exactWidth` are still locked to their exact value.
158
+ * With `resizable`, drag-to-resize is disabled for `equal` so widths stay
159
+ * equal; `fixed`/`auto` keep column resize handles.
160
+ */
161
+ tableLayout?: "auto" | "fixed" | "equal";
162
+ /**
163
+ * Show a column menu (⋮) on each hideable column header: first a dropdown
164
+ * (“Hide … column”, “Manage columns”), then the full manage panel from the
165
+ * second action. Pass `true` or `ColumnManagementOptions` to tune features.
166
+ */
167
+ columnManagement?: boolean | ColumnManagementOptions;
168
+ /** Allow user to drag-resize column widths */
169
+ resizable?: boolean;
170
+ /**
171
+ * Global minimum column width in pixels when `resizable` is true.
172
+ * Individual columns can override with `minSize` in their column def.
173
+ * @default 60
174
+ */
175
+ columnMinSize?: number;
176
+ /**
177
+ * Global maximum column width in pixels when `resizable` is true.
178
+ * Individual columns can override with `maxSize` in their column def.
179
+ * @default Number.MAX_SAFE_INTEGER (no limit)
180
+ */
181
+ columnMaxSize?: number;
182
+ className?: string;
183
+ /**
184
+ * Sets `data-testid` on the root container and derives sub-ids for the
185
+ * table (`{testId}-table`), header (`{testId}-thead`), body (`{testId}-tbody`),
186
+ * rows (`{testId}-row-{rowId}`), and cells (`{testId}-cell-{rowId}-{colId}`).
187
+ */
188
+ testId?: string;
189
+ }
190
+ export interface ColumnManagementOptions {
191
+ /** Show drag-handle to reorder columns. @default true */
192
+ reorder?: boolean;
193
+ /** Show per-column visibility Switch. @default true */
194
+ visibility?: boolean;
195
+ /** Show "Hide all" button. @default true */
196
+ hideAll?: boolean;
197
+ /** Show "Show all" button. @default true */
198
+ showAll?: boolean;
8
199
  }
9
- export declare function DataTable<TData, TValue>({ data, columns, manualSorting, onSorting, fetchMoreData, }: DataTableProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
200
+ export declare function DataTable<TData, TValue>({ data, columns, manualSorting, onSorting, paginationMode, totalCount, pageIndex: controlledPageIndex, pageSize: controlledPageSize, onPaginationChange, pageSizeOptions, fetchMoreData, fetchMoreOffset, fetchingMore, fetchingMoreLabel, loading, loadingLabel, highlightRowId, scrollToHighlightOnMouseLeave, selectable, onRowSelectionChange, rowActions, reorderable, getRowId: getRowIdProp, onRowReorder, isRowReorderLocked, onRowClick, onCellClick, getSubRows, defaultExpanded, expanded: controlledExpanded, onExpandedChange, bordered, surface, striped, divided, rowClassName, cellClassName, headerCellClassName, headerClassName, headerRowClassName, sortIndicatorVisibility, tableLayout, columnManagement: columnManagementProp, resizable, columnMinSize, columnMaxSize, virtualized, virtualRowEstimate, className, enableEditing, editDisplayMode, editTrigger, onCellCommit, alwaysEditing, enableCellTabTraversal, editableColumnIds: editableColumnIdsProp, testId, }: DataTableProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import type { ColumnDef, Row, RowData } from "@tanstack/react-table";
3
+ import type { EditableColumnDef, EditDisplayMode, EditTrigger, EditingState } from "./DataTable.editing.types";
4
+ export declare const EditContext: React.Context<EditingState | null>;
5
+ export declare function useDataTableEditing<TData extends RowData>(opts: {
6
+ enabled: boolean;
7
+ editDisplayMode: EditDisplayMode;
8
+ editTrigger: EditTrigger;
9
+ editableColumnIds: string[];
10
+ }): EditingState;
11
+ type ResolveOpts<TData extends RowData> = {
12
+ editing: EditingState;
13
+ onCellCommit?: (rowId: string, columnId: string, patch: Partial<TData>) => void;
14
+ alwaysEditing?: (row: Row<TData>) => boolean;
15
+ enableCellTabTraversal: boolean;
16
+ editableColumnIds: string[];
17
+ };
18
+ export declare function resolveEditableColumns<TData extends RowData>(columns: EditableColumnDef<TData>[], opts: ResolveOpts<TData>): ColumnDef<TData, unknown>[];
19
+ export declare function detectEditableColumnIds<TData extends RowData>(columns: EditableColumnDef<TData>[]): string[];
20
+ export {};
@@ -0,0 +1,145 @@
1
+ import type { ColumnDef, Row, RowData } from "@tanstack/react-table";
2
+ import type { Options } from "@/components/Dropdown/Dropdown";
3
+ export type EditDisplayMode = "cell" | "row";
4
+ export type EditTrigger = "click" | "doubleClick";
5
+ export type EditableColumnDef<TData extends RowData = RowData, TValue = unknown> = ColumnDef<TData, TValue> & {
6
+ /**
7
+ * Enable inline editing for this column.
8
+ * - `true` — always editable
9
+ * - `(row) => boolean` — conditionally editable (e.g. dependent fields)
10
+ */
11
+ enableEditing?: boolean | ((row: Row<TData>) => boolean);
12
+ /**
13
+ * Which built-in editor to render.
14
+ * - `"text"` — `TextInput` (default when `enableEditing` is truthy)
15
+ * - `"select"` — `Dropdown`
16
+ * - `"number"` — `NumberInput`
17
+ * - `"checkbox"` — `Checkbox`
18
+ * - `"custom"` — user-provided renderer via `editCustomCell`
19
+ */
20
+ editVariant?: "text" | "select" | "number" | "checkbox" | "custom";
21
+ /** Props forwarded to the `TextInput` editor (variant `"text"`). */
22
+ editTextProps?: {
23
+ placeholder?: string;
24
+ };
25
+ /** Props forwarded to the `Dropdown` editor (variant `"select"`). */
26
+ editSelectProps?: {
27
+ options: Options[] | ((row: Row<TData>) => Options[]);
28
+ placeholder?: string;
29
+ };
30
+ /** Props forwarded to the `NumberInput` editor (variant `"number"`). */
31
+ editNumberProps?: {
32
+ placeholder?: string;
33
+ min?: number;
34
+ max?: number;
35
+ step?: number;
36
+ precision?: number;
37
+ allowDecimal?: boolean;
38
+ allowNegative?: boolean;
39
+ };
40
+ /** Props forwarded to the `Checkbox` editor (variant `"checkbox"`). */
41
+ editCheckboxProps?: {
42
+ label?: string;
43
+ };
44
+ /**
45
+ * Render function for a fully custom edit cell (variant `"custom"`).
46
+ *
47
+ * Receives the current row and a `commit` callback. Call `commit(rawValue)`
48
+ * to persist the change — the engine will run `onCommit` / `buildPatch`
49
+ * as usual.
50
+ *
51
+ * ```tsx
52
+ * editCustomCell: (row, { commit, errorMessage }) => (
53
+ * <MyColorPicker
54
+ * value={row.original.color}
55
+ * onChange={(c) => commit(c)}
56
+ * error={errorMessage}
57
+ * />
58
+ * )
59
+ * ```
60
+ */
61
+ editCustomCell?: (row: Row<TData>, ctx: {
62
+ /** Persist the edited value — runs `onCommit` / `buildPatch` as usual. */
63
+ commit: (rawValue: string) => void;
64
+ /** Exit edit mode without committing (same as pressing Escape). */
65
+ blur: () => void;
66
+ columnId: string;
67
+ autoFocus: boolean;
68
+ errorMessage?: string;
69
+ onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void;
70
+ }) => React.ReactNode;
71
+ /**
72
+ * Return an error message for the current cell value to display inline
73
+ * validation feedback. Return `undefined` or empty string when valid.
74
+ */
75
+ editError?: (row: Row<TData>) => string | undefined;
76
+ /**
77
+ * Build a custom `Partial<TData>` patch from the raw committed value.
78
+ * When omitted the engine defaults to `{ [columnId]: rawValue }`.
79
+ *
80
+ * Use this for dependent-field resets, value transforms, etc.
81
+ *
82
+ * ```ts
83
+ * onCommit: (_row, value) => ({
84
+ * dataCategory: value,
85
+ * dataType: "", format: "", source: "",
86
+ * })
87
+ * ```
88
+ */
89
+ onCommit?: (row: Row<TData>, value: string) => Partial<TData>;
90
+ /**
91
+ * When `true`, a cell whose `enableEditing` returns `false` renders a
92
+ * **disabled** TextInput / Dropdown (matching `editVariant`) instead of
93
+ * falling back to `displayCell` or plain text.
94
+ */
95
+ editShowDisabledField?: boolean;
96
+ /**
97
+ * Custom preview renderer shown when the cell is **not** in edit mode.
98
+ * Defaults to the plain string value of `row.original[key]`.
99
+ */
100
+ displayCell?: (row: Row<TData>) => React.ReactNode;
101
+ };
102
+ export interface DataTableEditingProps<TData extends RowData = RowData> {
103
+ /** Master switch — set `true` to enable editing features. */
104
+ enableEditing?: boolean;
105
+ /** How editing is activated visually. @default "cell" */
106
+ editDisplayMode?: EditDisplayMode;
107
+ /** Gesture that enters edit mode. @default "click" */
108
+ editTrigger?: EditTrigger;
109
+ /**
110
+ * Called every time a cell commits a new value. The `patch` object is
111
+ * built from the column's `commitResets` / `mapCommitValue` or defaults
112
+ * to `{ [columnId]: rawValue }`.
113
+ */
114
+ onCellCommit?: (rowId: string, columnId: string, patch: Partial<TData>) => void;
115
+ /**
116
+ * Rows that return `true` render their editable columns in edit mode
117
+ * **permanently** (e.g. an "add" footer row).
118
+ */
119
+ alwaysEditing?: (row: Row<TData>) => boolean;
120
+ /**
121
+ * When `true` (the default when `enableEditing` is set), Tab / Shift+Tab
122
+ * inside an editing cell moves focus to the next / previous editable
123
+ * column in the same row.
124
+ */
125
+ enableCellTabTraversal?: boolean;
126
+ /**
127
+ * Explicit ordered list of column ids for Tab traversal. When omitted
128
+ * the engine auto-detects editable columns in definition order.
129
+ */
130
+ editableColumnIds?: string[];
131
+ }
132
+ export interface EditingState {
133
+ editingRowId: string | null;
134
+ editingCell: {
135
+ rowId: string;
136
+ columnId: string;
137
+ } | null;
138
+ editDisplayMode: EditDisplayMode;
139
+ editTrigger: EditTrigger;
140
+ requestRowEdit: (rowId: string) => void;
141
+ requestCellEdit: (rowId: string, columnId: string) => void;
142
+ clearEdit: () => void;
143
+ onFieldBlur: (rowId: string, columnId: string) => void;
144
+ moveCellEdit: (rowId: string, fromColumnId: string, delta: -1 | 1) => "moved" | "exited";
145
+ }