@kanunilabs/datagrid 1.9.0 → 1.9.2

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 (44) hide show
  1. package/dist/datagrid.umd.js +8 -8
  2. package/dist/index.cjs +2 -2
  3. package/dist/index.d.cts +123 -11
  4. package/dist/index.d.ts +123 -11
  5. package/dist/index.js +2 -2
  6. package/dist/styles.css +541 -1
  7. package/dist/themes/all.css +108 -0
  8. package/dist/themes/amber.css +3 -0
  9. package/dist/themes/aubergine.css +3 -0
  10. package/dist/themes/azure.css +3 -0
  11. package/dist/themes/burgundy.css +3 -0
  12. package/dist/themes/charcoal.css +3 -0
  13. package/dist/themes/contrast-dark.css +3 -0
  14. package/dist/themes/contrast-light.css +3 -0
  15. package/dist/themes/coral.css +3 -0
  16. package/dist/themes/corporate.css +3 -0
  17. package/dist/themes/deep-sea.css +3 -0
  18. package/dist/themes/editorial.css +3 -0
  19. package/dist/themes/ember.css +3 -0
  20. package/dist/themes/emerald.css +3 -0
  21. package/dist/themes/forest.css +3 -0
  22. package/dist/themes/glacier.css +3 -0
  23. package/dist/themes/graphite.css +3 -0
  24. package/dist/themes/indigo-night.css +3 -0
  25. package/dist/themes/indigo.css +3 -0
  26. package/dist/themes/ivory.css +3 -0
  27. package/dist/themes/lagoon.css +3 -0
  28. package/dist/themes/linen.css +3 -0
  29. package/dist/themes/midnight.css +3 -0
  30. package/dist/themes/mist.css +3 -0
  31. package/dist/themes/monochrome.css +3 -0
  32. package/dist/themes/onyx.css +3 -0
  33. package/dist/themes/orchid.css +3 -0
  34. package/dist/themes/porcelain.css +3 -0
  35. package/dist/themes/rose.css +3 -0
  36. package/dist/themes/sandstone.css +3 -0
  37. package/dist/themes/slate-night.css +3 -0
  38. package/dist/themes/slate.css +3 -0
  39. package/dist/themes/steel.css +3 -0
  40. package/dist/themes/stone.css +3 -0
  41. package/dist/themes/taupe.css +3 -0
  42. package/dist/themes/teal.css +3 -0
  43. package/dist/themes/terminal.css +3 -0
  44. package/package.json +4 -4
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { GridRowData, DataGridController, GridDictionary, GridDataType, LookupItem, LookupMatchMode, EditingEngineOptions, RowKey, EditingEngine, RowChange, RowNode, GridColumnDef, DataGridCoreConfig, FilterRenderContextBase, FilterNode, GridThemeName, GridPaletteName, GridDensity, DescribeFilterOptions, CardViewOptions, StateStoringConfig, InferColumnsOptions } from '@kanunilabs/datagrid-core';
1
+ import { GridRowData, DataGridController, GridDictionary, GridDataType, LookupItem, LookupMatchMode, RowKey, EditingEngineOptions, EditingEngine, RowChange, EditMode, RowNode, GridColumnDef, DataGridCoreConfig, FilterRenderContextBase, FilterNode, GridThemeName, GridPaletteName, GridDensity, DescribeFilterOptions, CardViewOptions, StateStoringConfig, InferColumnsOptions, RowStatusSource } from '@kanunilabs/datagrid-core';
2
2
  export { CustomFilterOperator, CustomFilterOperatorId, DENSITY_ROW_HEIGHT, DataGridController, FilterNode, GRID_COLOR_SCHEMES, GridColorScheme, GridColumnDef, GridDensity, GridPaletteName, GridRowData, GridTheme, GridThemeName, RowKey, RowNode, SortDescriptor, THEME_ROW_HEIGHT, isPackagedTheme, presetRowHeight } from '@kanunilabs/datagrid-core';
3
3
 
4
4
  /** What a header menu is opened against — the React shape, verbatim. */
@@ -33,13 +33,18 @@ interface CellLookupEditorSpec {
33
33
  matchMode?: LookupMatchMode;
34
34
  allowCustom?: boolean;
35
35
  invalid?: boolean;
36
+ /** Take focus once connected. A cell editor does; row/form fields do not. */
37
+ autoFocus?: boolean;
36
38
  testId?: string;
39
+ columnId?: string;
37
40
  ariaLabel?: string;
38
41
  surfaceClass?: string;
39
42
  onPortalOpen?: (close: () => void) => void;
40
43
  noMatchText: string;
41
44
  onChange: (value: unknown) => void;
42
45
  onCommit: () => void;
46
+ /** Picking an item commits (a cell). False in row/form mode, where only Save ends it. */
47
+ commitOnPick?: boolean;
43
48
  onCancel: () => void;
44
49
  onTab?: (shiftKey: boolean) => void;
45
50
  }
@@ -99,6 +104,60 @@ interface CellEditorSpec {
99
104
  /** Build the editor. The caller drops the fragment into the CELL. */
100
105
  declare function buildCellEditor(spec: CellEditorSpec): DocumentFragment;
101
106
 
107
+ interface EditFormField {
108
+ columnId: string;
109
+ label: string;
110
+ dataType: GridDataType | undefined;
111
+ editable: boolean;
112
+ dateFormat?: string;
113
+ lookup?: {
114
+ /** `null` = loading (dynamic list in flight). */
115
+ options: readonly LookupItem[] | null;
116
+ allowCustom?: boolean;
117
+ matchMode?: LookupMatchMode;
118
+ };
119
+ }
120
+ interface EditFormSpec {
121
+ rowKey: RowKey;
122
+ fields: readonly EditFormField[];
123
+ /** Current (pending) value per column. */
124
+ getValue: (columnId: string) => unknown;
125
+ /** Validation message per column id; only invalid columns appear. */
126
+ getErrors: () => Record<string, string>;
127
+ getSaving: () => boolean;
128
+ getSaveError: () => string | null;
129
+ isNew: boolean;
130
+ /** Rendered as a modal dialog rather than inline in a row. */
131
+ popup?: boolean;
132
+ /** Drawn INSIDE the grid, in the row flow (`mode: 'form'`) — drops the
133
+ * floating chrome so the panel does not draw a card inside the row. */
134
+ inline?: boolean;
135
+ /** The portal surface classes (popup mode + nested editors). */
136
+ surfaceClass?: string;
137
+ /**
138
+ * Builds the combo box for a lookup field. Supplied by the Enterprise
139
+ * edition; without it a lookup field renders read-only, showing its label.
140
+ */
141
+ renderLookup?: (spec: CellLookupEditorSpec) => HTMLElement;
142
+ /** Called when a nested editor opens a layer on `document.body`. */
143
+ onPortalOpen?: (close: () => void) => void;
144
+ t: GridDictionary;
145
+ /** Reports the height the form WANTS, in px, once it is in the DOM. */
146
+ onNaturalHeight?: (px: number) => void;
147
+ onChange: (columnId: string, value: unknown) => void;
148
+ onSave: () => void;
149
+ onCancel: () => void;
150
+ }
151
+ interface EditFormHandle {
152
+ element: HTMLElement;
153
+ /** Re-paint errors / saving / banner in place. Never touches inputs. */
154
+ refresh(): void;
155
+ /** Swap a lookup field's control once its async list arrives. */
156
+ setLookupOptions(columnId: string, options: readonly LookupItem[]): void;
157
+ dispose(): void;
158
+ }
159
+ declare function buildEditForm(spec: EditFormSpec): EditFormHandle;
160
+
102
161
  /**
103
162
  * The Community `editing` option of `createGrid`. Passing the object turns
104
163
  * single-cell editing on; `{ enabled: false }` turns it off again. Columns
@@ -119,10 +178,31 @@ interface CellEditingOptions<TRow = GridRowData> {
119
178
  focusCellOnTab?: boolean;
120
179
  /** Tab past the end of a row wraps to the next one. Default true. */
121
180
  focusCellOnCycle?: boolean;
181
+ /**
182
+ * How edits are collected (Community since 2026-10-16). `'cell'` (default)
183
+ * saves every commit; `'batch'` keeps changes pending until the Save strip
184
+ * above the grid is pressed; `'row'` opens the whole row (double-click) with
185
+ * Save/Cancel, Enter/Escape; `'form'` opens a form inside the grid and
186
+ * `'popup'` the same form in a dialog. In the buffered modes `onSave`
187
+ * receives the changes and must write them to the app's data.
188
+ */
189
+ mode?: EditMode;
190
+ /**
191
+ * Rename the built-in strings for THIS grid (`save`, `cancel`,
192
+ * `editSaveChanges`…). Merged over the locale's dictionary.
193
+ */
194
+ formLabels?: Record<string, string>;
195
+ /**
196
+ * Starting height in px for the in-grid form (`mode: 'form'`) before it
197
+ * has been measured — only worth setting to stop the one-frame resize.
198
+ */
199
+ formHeight?: number;
122
200
  }
123
201
  interface CellEditingHelpers {
124
202
  /** Theme classes for portalled layers (the dialog, the date calendar). */
125
203
  surfaceClass(): string;
204
+ /** Where the batch / row Save-Cancel strip is mounted. */
205
+ barHost?: HTMLElement;
126
206
  }
127
207
  /**
128
208
  * What the Enterprise layer adds. Not part of the Community surface: the
@@ -149,6 +229,14 @@ interface CellEditingExtension<TRow = GridRowData> {
149
229
  customEditors?: boolean;
150
230
  /** Something drawn into a cell that is NOT being edited (the fill handle). */
151
231
  cellAdornment?: (ctx: CellSlotContext<TRow>) => Node | null;
232
+ /**
233
+ * A form field's lookup list (with the combo box): static lists returned,
234
+ * async ones delivered later through `update`. Default: the static list,
235
+ * shown read-only by label.
236
+ */
237
+ formLookup?: (rowKey: RowKey, columnId: string, update: (options: readonly LookupItem[]) => void) => EditFormField['lookup'];
238
+ /** Add buttons to the edit strip ahead of the base's (the Add button). */
239
+ decorateBar?: (bar: HTMLElement) => void;
152
240
  }
153
241
  interface CellEditingLayer<TRow = GridRowData> {
154
242
  engine: EditingEngine<TRow>;
@@ -172,6 +260,16 @@ interface CellEditingLayer<TRow = GridRowData> {
172
260
  trackPortal(close: () => void): void;
173
261
  /** What the Community renderer would paint for `value` in this cell. */
174
262
  defaultContent(ctx: CellSlotContext<TRow>, value: unknown): Node | string;
263
+ /** The `renderEditForm` slot — the in-grid form's body (`mode: 'form'`). */
264
+ renderEditForm(rowKey: RowKey, row: TRow | undefined): Node | string | undefined;
265
+ /** Open a whole row (row / form / popup). False when it cannot be. */
266
+ beginRowEdit(rowKey: RowKey): boolean;
267
+ /** Validate and save the open row; true when it saved and closed. */
268
+ saveRowEdit(): Promise<boolean>;
269
+ cancelRowEdit(): void;
270
+ /** Save every pending change (batch); a refusal is shown in the strip. */
271
+ saveChanges(): Promise<void>;
272
+ cancelChanges(): void;
175
273
  dispose(): void;
176
274
  }
177
275
  declare function attachCellEditing<TRow = GridRowData>(grid: Pick<GridApi<TRow>, 'controller' | 'element'>, options: CellEditingOptions<TRow>, t: GridDictionary, helpers: CellEditingHelpers, extension?: CellEditingExtension<TRow>): CellEditingLayer<TRow>;
@@ -783,18 +881,24 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
783
881
  /** Search box debounce, ms. React's default. */
784
882
  searchDebounce?: number;
785
883
  /**
786
- * Single-cell editing (Community since 2026-10-12). Off unless passed:
884
+ * Editing (single-cell Community since 2026-10-12; batch / row / form /
885
+ * popup Community since 2026-10-16, owner decision). Off unless passed:
787
886
  * `editing: {}` turns it on, `{ enabled: false }` off again. Double-click,
788
887
  * F2 or typing opens the in-cell editor (text, number, date, checkbox);
789
888
  * Enter commits and moves down, Tab / Shift+Tab commit and move to the next
790
- * editable cell, Escape cancels. Each commit is written to the row and
791
- * handed to `onSave`. Columns with `editable: false` stay read-only, and so
792
- * do lookup and cell-formula columns, whose editors are Enterprise.
889
+ * editable cell, Escape cancels. In the default `mode: 'cell'` each commit
890
+ * is written to the row and handed to `onSave`. `mode: 'batch'` keeps
891
+ * changes pending until the Save strip above the grid; `'row'` opens the
892
+ * whole row on double-click (Save/Cancel strip, Enter/Escape); `'form'` and
893
+ * `'popup'` open a form inside the grid or in a dialog. In those modes
894
+ * `onSave` receives the changes and the app writes them to its data.
895
+ * Columns with `editable: false` stay read-only, and so do lookup,
896
+ * custom-editor and cell-formula columns, whose editors are Enterprise.
793
897
  *
794
- * Batch/row/form/popup modes, validation rules, CRUD handlers, permissions,
795
- * custom and lookup editors, undo/redo and range selection are Enterprise
796
- * (`createEnterpriseGrid`); passed here they are ignored, and named in the
797
- * console under `debugMode`.
898
+ * Validation rules, CRUD handlers, adding and deleting rows, per-row
899
+ * permissions, the command column, custom and lookup editors, undo/redo and
900
+ * range selection are Enterprise (`createEnterpriseGrid`); passed here they
901
+ * are ignored, and named in the console under `debugMode`.
798
902
  */
799
903
  editing?: CellEditingOptions<TRow>;
800
904
  /** Replace a body cell's content. `undefined` = the default painter runs. */
@@ -806,7 +910,9 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
806
910
  */
807
911
  renderDetail?: (row: TRow) => Node | string;
808
912
  /**
809
- * Body for an in-grid edit form row (`mode: 'form'`). `row` is undefined
913
+ * Body for an in-grid edit form row (`mode: 'form'`). With `editing` on,
914
+ * the grid's own form answers first; this slot covers any row it does not
915
+ * claim. `row` is undefined
810
916
  * for a record that does not exist yet — the form still opens, because the
811
917
  * alternative is pressing "New row" and seeing nothing happen.
812
918
  */
@@ -820,6 +926,12 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
820
926
  enterpriseEdition?: boolean;
821
927
  /** Extra classes for a body cell (pending edit, range, fill preview…). */
822
928
  getCellClassName?: (ctx: CellSlotContext<TRow>) => string | undefined;
929
+ /**
930
+ * Where `rowStatus` reads the grid's own save status — the Enterprise
931
+ * wrapper's editing engine. With `editing` on here, the grid's own engine
932
+ * answers and this is not asked.
933
+ */
934
+ getRowStatusSource?: () => RowStatusSource | null;
823
935
  onCellPointerDown?: (ctx: CellSlotContext<TRow>, event: MouseEvent) => void;
824
936
  onCellPointerEnter?: (ctx: CellSlotContext<TRow>, event: MouseEvent) => void;
825
937
  onCellDoubleClick?: (ctx: CellSlotContext<TRow>) => void;
@@ -902,4 +1014,4 @@ interface ConfirmDialogSpec {
902
1014
  /** Open the dialog; resolves the user's answer and removes itself. */
903
1015
  declare function openConfirmDialog(spec: ConfirmDialogSpec): Promise<boolean>;
904
1016
 
905
- export { CHECKBOX_COLUMN_WIDTH, type CellEditingExtension, type CellEditingHelpers, type CellEditingLayer, type CellEditingOptions, type CellEditorSpec, type CellLookupEditorSpec, type CellMenuOptions, type CellRenderContext, type CellSlotContext, type ConfirmDialogSpec, type CreateGridConfig, DETAIL_COLUMN_WIDTH, type DateEditorSpec, type ExportKind, type GridApi, type GridMenuItem, type GridNotesConfig, type HeaderMenuContext, type HeaderMenuDeps, type NoteCellContext, PRINT_MAX_ROWS, type PrintLayoutOptions, ROW_DRAG_MIME, ROW_NUMBER_COLUMN_WIDTH, type RowDragConfig, type RowDragPayload, type RowDropEvent, type RowMenuContext, type RowReorderEvent, type RowTemplateContext, type VanillaColumnDef, type VanillaEditorRenderContext, type VanillaFilterRenderApi, attachCellEditing, buildCellEditor, buildDateEditor, buildHeaderMenu, createGrid, measureBestFitWidth, openConfirmDialog };
1017
+ export { CHECKBOX_COLUMN_WIDTH, type CellEditingExtension, type CellEditingHelpers, type CellEditingLayer, type CellEditingOptions, type CellEditorSpec, type CellLookupEditorSpec, type CellMenuOptions, type CellRenderContext, type CellSlotContext, type ConfirmDialogSpec, type CreateGridConfig, DETAIL_COLUMN_WIDTH, type DateEditorSpec, type EditFormField, type EditFormHandle, type EditFormSpec, type ExportKind, type GridApi, type GridMenuItem, type GridNotesConfig, type HeaderMenuContext, type HeaderMenuDeps, type NoteCellContext, PRINT_MAX_ROWS, type PrintLayoutOptions, ROW_DRAG_MIME, ROW_NUMBER_COLUMN_WIDTH, type RowDragConfig, type RowDragPayload, type RowDropEvent, type RowMenuContext, type RowReorderEvent, type RowTemplateContext, type VanillaColumnDef, type VanillaEditorRenderContext, type VanillaFilterRenderApi, attachCellEditing, buildCellEditor, buildDateEditor, buildEditForm, buildHeaderMenu, createGrid, measureBestFitWidth, openConfirmDialog };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GridRowData, DataGridController, GridDictionary, GridDataType, LookupItem, LookupMatchMode, EditingEngineOptions, RowKey, EditingEngine, RowChange, RowNode, GridColumnDef, DataGridCoreConfig, FilterRenderContextBase, FilterNode, GridThemeName, GridPaletteName, GridDensity, DescribeFilterOptions, CardViewOptions, StateStoringConfig, InferColumnsOptions } from '@kanunilabs/datagrid-core';
1
+ import { GridRowData, DataGridController, GridDictionary, GridDataType, LookupItem, LookupMatchMode, RowKey, EditingEngineOptions, EditingEngine, RowChange, EditMode, RowNode, GridColumnDef, DataGridCoreConfig, FilterRenderContextBase, FilterNode, GridThemeName, GridPaletteName, GridDensity, DescribeFilterOptions, CardViewOptions, StateStoringConfig, InferColumnsOptions, RowStatusSource } from '@kanunilabs/datagrid-core';
2
2
  export { CustomFilterOperator, CustomFilterOperatorId, DENSITY_ROW_HEIGHT, DataGridController, FilterNode, GRID_COLOR_SCHEMES, GridColorScheme, GridColumnDef, GridDensity, GridPaletteName, GridRowData, GridTheme, GridThemeName, RowKey, RowNode, SortDescriptor, THEME_ROW_HEIGHT, isPackagedTheme, presetRowHeight } from '@kanunilabs/datagrid-core';
3
3
 
4
4
  /** What a header menu is opened against — the React shape, verbatim. */
@@ -33,13 +33,18 @@ interface CellLookupEditorSpec {
33
33
  matchMode?: LookupMatchMode;
34
34
  allowCustom?: boolean;
35
35
  invalid?: boolean;
36
+ /** Take focus once connected. A cell editor does; row/form fields do not. */
37
+ autoFocus?: boolean;
36
38
  testId?: string;
39
+ columnId?: string;
37
40
  ariaLabel?: string;
38
41
  surfaceClass?: string;
39
42
  onPortalOpen?: (close: () => void) => void;
40
43
  noMatchText: string;
41
44
  onChange: (value: unknown) => void;
42
45
  onCommit: () => void;
46
+ /** Picking an item commits (a cell). False in row/form mode, where only Save ends it. */
47
+ commitOnPick?: boolean;
43
48
  onCancel: () => void;
44
49
  onTab?: (shiftKey: boolean) => void;
45
50
  }
@@ -99,6 +104,60 @@ interface CellEditorSpec {
99
104
  /** Build the editor. The caller drops the fragment into the CELL. */
100
105
  declare function buildCellEditor(spec: CellEditorSpec): DocumentFragment;
101
106
 
107
+ interface EditFormField {
108
+ columnId: string;
109
+ label: string;
110
+ dataType: GridDataType | undefined;
111
+ editable: boolean;
112
+ dateFormat?: string;
113
+ lookup?: {
114
+ /** `null` = loading (dynamic list in flight). */
115
+ options: readonly LookupItem[] | null;
116
+ allowCustom?: boolean;
117
+ matchMode?: LookupMatchMode;
118
+ };
119
+ }
120
+ interface EditFormSpec {
121
+ rowKey: RowKey;
122
+ fields: readonly EditFormField[];
123
+ /** Current (pending) value per column. */
124
+ getValue: (columnId: string) => unknown;
125
+ /** Validation message per column id; only invalid columns appear. */
126
+ getErrors: () => Record<string, string>;
127
+ getSaving: () => boolean;
128
+ getSaveError: () => string | null;
129
+ isNew: boolean;
130
+ /** Rendered as a modal dialog rather than inline in a row. */
131
+ popup?: boolean;
132
+ /** Drawn INSIDE the grid, in the row flow (`mode: 'form'`) — drops the
133
+ * floating chrome so the panel does not draw a card inside the row. */
134
+ inline?: boolean;
135
+ /** The portal surface classes (popup mode + nested editors). */
136
+ surfaceClass?: string;
137
+ /**
138
+ * Builds the combo box for a lookup field. Supplied by the Enterprise
139
+ * edition; without it a lookup field renders read-only, showing its label.
140
+ */
141
+ renderLookup?: (spec: CellLookupEditorSpec) => HTMLElement;
142
+ /** Called when a nested editor opens a layer on `document.body`. */
143
+ onPortalOpen?: (close: () => void) => void;
144
+ t: GridDictionary;
145
+ /** Reports the height the form WANTS, in px, once it is in the DOM. */
146
+ onNaturalHeight?: (px: number) => void;
147
+ onChange: (columnId: string, value: unknown) => void;
148
+ onSave: () => void;
149
+ onCancel: () => void;
150
+ }
151
+ interface EditFormHandle {
152
+ element: HTMLElement;
153
+ /** Re-paint errors / saving / banner in place. Never touches inputs. */
154
+ refresh(): void;
155
+ /** Swap a lookup field's control once its async list arrives. */
156
+ setLookupOptions(columnId: string, options: readonly LookupItem[]): void;
157
+ dispose(): void;
158
+ }
159
+ declare function buildEditForm(spec: EditFormSpec): EditFormHandle;
160
+
102
161
  /**
103
162
  * The Community `editing` option of `createGrid`. Passing the object turns
104
163
  * single-cell editing on; `{ enabled: false }` turns it off again. Columns
@@ -119,10 +178,31 @@ interface CellEditingOptions<TRow = GridRowData> {
119
178
  focusCellOnTab?: boolean;
120
179
  /** Tab past the end of a row wraps to the next one. Default true. */
121
180
  focusCellOnCycle?: boolean;
181
+ /**
182
+ * How edits are collected (Community since 2026-10-16). `'cell'` (default)
183
+ * saves every commit; `'batch'` keeps changes pending until the Save strip
184
+ * above the grid is pressed; `'row'` opens the whole row (double-click) with
185
+ * Save/Cancel, Enter/Escape; `'form'` opens a form inside the grid and
186
+ * `'popup'` the same form in a dialog. In the buffered modes `onSave`
187
+ * receives the changes and must write them to the app's data.
188
+ */
189
+ mode?: EditMode;
190
+ /**
191
+ * Rename the built-in strings for THIS grid (`save`, `cancel`,
192
+ * `editSaveChanges`…). Merged over the locale's dictionary.
193
+ */
194
+ formLabels?: Record<string, string>;
195
+ /**
196
+ * Starting height in px for the in-grid form (`mode: 'form'`) before it
197
+ * has been measured — only worth setting to stop the one-frame resize.
198
+ */
199
+ formHeight?: number;
122
200
  }
123
201
  interface CellEditingHelpers {
124
202
  /** Theme classes for portalled layers (the dialog, the date calendar). */
125
203
  surfaceClass(): string;
204
+ /** Where the batch / row Save-Cancel strip is mounted. */
205
+ barHost?: HTMLElement;
126
206
  }
127
207
  /**
128
208
  * What the Enterprise layer adds. Not part of the Community surface: the
@@ -149,6 +229,14 @@ interface CellEditingExtension<TRow = GridRowData> {
149
229
  customEditors?: boolean;
150
230
  /** Something drawn into a cell that is NOT being edited (the fill handle). */
151
231
  cellAdornment?: (ctx: CellSlotContext<TRow>) => Node | null;
232
+ /**
233
+ * A form field's lookup list (with the combo box): static lists returned,
234
+ * async ones delivered later through `update`. Default: the static list,
235
+ * shown read-only by label.
236
+ */
237
+ formLookup?: (rowKey: RowKey, columnId: string, update: (options: readonly LookupItem[]) => void) => EditFormField['lookup'];
238
+ /** Add buttons to the edit strip ahead of the base's (the Add button). */
239
+ decorateBar?: (bar: HTMLElement) => void;
152
240
  }
153
241
  interface CellEditingLayer<TRow = GridRowData> {
154
242
  engine: EditingEngine<TRow>;
@@ -172,6 +260,16 @@ interface CellEditingLayer<TRow = GridRowData> {
172
260
  trackPortal(close: () => void): void;
173
261
  /** What the Community renderer would paint for `value` in this cell. */
174
262
  defaultContent(ctx: CellSlotContext<TRow>, value: unknown): Node | string;
263
+ /** The `renderEditForm` slot — the in-grid form's body (`mode: 'form'`). */
264
+ renderEditForm(rowKey: RowKey, row: TRow | undefined): Node | string | undefined;
265
+ /** Open a whole row (row / form / popup). False when it cannot be. */
266
+ beginRowEdit(rowKey: RowKey): boolean;
267
+ /** Validate and save the open row; true when it saved and closed. */
268
+ saveRowEdit(): Promise<boolean>;
269
+ cancelRowEdit(): void;
270
+ /** Save every pending change (batch); a refusal is shown in the strip. */
271
+ saveChanges(): Promise<void>;
272
+ cancelChanges(): void;
175
273
  dispose(): void;
176
274
  }
177
275
  declare function attachCellEditing<TRow = GridRowData>(grid: Pick<GridApi<TRow>, 'controller' | 'element'>, options: CellEditingOptions<TRow>, t: GridDictionary, helpers: CellEditingHelpers, extension?: CellEditingExtension<TRow>): CellEditingLayer<TRow>;
@@ -783,18 +881,24 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
783
881
  /** Search box debounce, ms. React's default. */
784
882
  searchDebounce?: number;
785
883
  /**
786
- * Single-cell editing (Community since 2026-10-12). Off unless passed:
884
+ * Editing (single-cell Community since 2026-10-12; batch / row / form /
885
+ * popup Community since 2026-10-16, owner decision). Off unless passed:
787
886
  * `editing: {}` turns it on, `{ enabled: false }` off again. Double-click,
788
887
  * F2 or typing opens the in-cell editor (text, number, date, checkbox);
789
888
  * Enter commits and moves down, Tab / Shift+Tab commit and move to the next
790
- * editable cell, Escape cancels. Each commit is written to the row and
791
- * handed to `onSave`. Columns with `editable: false` stay read-only, and so
792
- * do lookup and cell-formula columns, whose editors are Enterprise.
889
+ * editable cell, Escape cancels. In the default `mode: 'cell'` each commit
890
+ * is written to the row and handed to `onSave`. `mode: 'batch'` keeps
891
+ * changes pending until the Save strip above the grid; `'row'` opens the
892
+ * whole row on double-click (Save/Cancel strip, Enter/Escape); `'form'` and
893
+ * `'popup'` open a form inside the grid or in a dialog. In those modes
894
+ * `onSave` receives the changes and the app writes them to its data.
895
+ * Columns with `editable: false` stay read-only, and so do lookup,
896
+ * custom-editor and cell-formula columns, whose editors are Enterprise.
793
897
  *
794
- * Batch/row/form/popup modes, validation rules, CRUD handlers, permissions,
795
- * custom and lookup editors, undo/redo and range selection are Enterprise
796
- * (`createEnterpriseGrid`); passed here they are ignored, and named in the
797
- * console under `debugMode`.
898
+ * Validation rules, CRUD handlers, adding and deleting rows, per-row
899
+ * permissions, the command column, custom and lookup editors, undo/redo and
900
+ * range selection are Enterprise (`createEnterpriseGrid`); passed here they
901
+ * are ignored, and named in the console under `debugMode`.
798
902
  */
799
903
  editing?: CellEditingOptions<TRow>;
800
904
  /** Replace a body cell's content. `undefined` = the default painter runs. */
@@ -806,7 +910,9 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
806
910
  */
807
911
  renderDetail?: (row: TRow) => Node | string;
808
912
  /**
809
- * Body for an in-grid edit form row (`mode: 'form'`). `row` is undefined
913
+ * Body for an in-grid edit form row (`mode: 'form'`). With `editing` on,
914
+ * the grid's own form answers first; this slot covers any row it does not
915
+ * claim. `row` is undefined
810
916
  * for a record that does not exist yet — the form still opens, because the
811
917
  * alternative is pressing "New row" and seeing nothing happen.
812
918
  */
@@ -820,6 +926,12 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
820
926
  enterpriseEdition?: boolean;
821
927
  /** Extra classes for a body cell (pending edit, range, fill preview…). */
822
928
  getCellClassName?: (ctx: CellSlotContext<TRow>) => string | undefined;
929
+ /**
930
+ * Where `rowStatus` reads the grid's own save status — the Enterprise
931
+ * wrapper's editing engine. With `editing` on here, the grid's own engine
932
+ * answers and this is not asked.
933
+ */
934
+ getRowStatusSource?: () => RowStatusSource | null;
823
935
  onCellPointerDown?: (ctx: CellSlotContext<TRow>, event: MouseEvent) => void;
824
936
  onCellPointerEnter?: (ctx: CellSlotContext<TRow>, event: MouseEvent) => void;
825
937
  onCellDoubleClick?: (ctx: CellSlotContext<TRow>) => void;
@@ -902,4 +1014,4 @@ interface ConfirmDialogSpec {
902
1014
  /** Open the dialog; resolves the user's answer and removes itself. */
903
1015
  declare function openConfirmDialog(spec: ConfirmDialogSpec): Promise<boolean>;
904
1016
 
905
- export { CHECKBOX_COLUMN_WIDTH, type CellEditingExtension, type CellEditingHelpers, type CellEditingLayer, type CellEditingOptions, type CellEditorSpec, type CellLookupEditorSpec, type CellMenuOptions, type CellRenderContext, type CellSlotContext, type ConfirmDialogSpec, type CreateGridConfig, DETAIL_COLUMN_WIDTH, type DateEditorSpec, type ExportKind, type GridApi, type GridMenuItem, type GridNotesConfig, type HeaderMenuContext, type HeaderMenuDeps, type NoteCellContext, PRINT_MAX_ROWS, type PrintLayoutOptions, ROW_DRAG_MIME, ROW_NUMBER_COLUMN_WIDTH, type RowDragConfig, type RowDragPayload, type RowDropEvent, type RowMenuContext, type RowReorderEvent, type RowTemplateContext, type VanillaColumnDef, type VanillaEditorRenderContext, type VanillaFilterRenderApi, attachCellEditing, buildCellEditor, buildDateEditor, buildHeaderMenu, createGrid, measureBestFitWidth, openConfirmDialog };
1017
+ export { CHECKBOX_COLUMN_WIDTH, type CellEditingExtension, type CellEditingHelpers, type CellEditingLayer, type CellEditingOptions, type CellEditorSpec, type CellLookupEditorSpec, type CellMenuOptions, type CellRenderContext, type CellSlotContext, type ConfirmDialogSpec, type CreateGridConfig, DETAIL_COLUMN_WIDTH, type DateEditorSpec, type EditFormField, type EditFormHandle, type EditFormSpec, type ExportKind, type GridApi, type GridMenuItem, type GridNotesConfig, type HeaderMenuContext, type HeaderMenuDeps, type NoteCellContext, PRINT_MAX_ROWS, type PrintLayoutOptions, ROW_DRAG_MIME, ROW_NUMBER_COLUMN_WIDTH, type RowDragConfig, type RowDragPayload, type RowDropEvent, type RowMenuContext, type RowReorderEvent, type RowTemplateContext, type VanillaColumnDef, type VanillaEditorRenderContext, type VanillaFilterRenderApi, attachCellEditing, buildCellEditor, buildDateEditor, buildEditForm, buildHeaderMenu, createGrid, measureBestFitWidth, openConfirmDialog };