@kanunilabs/datagrid 1.7.0 → 1.9.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/dist/datagrid.umd.js +8 -8
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +270 -5
- package/dist/index.d.ts +270 -5
- package/dist/index.js +2 -2
- package/dist/styles.css +633 -10
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { GridRowData, DataGridController, GridDictionary, RowNode, GridColumnDef, DataGridCoreConfig, GridThemeName, GridPaletteName, GridDensity, DescribeFilterOptions,
|
|
2
|
-
export { DENSITY_ROW_HEIGHT, DataGridController, GRID_COLOR_SCHEMES, GridColorScheme, GridColumnDef, GridDensity, GridPaletteName, GridRowData, GridTheme, GridThemeName, RowKey, RowNode, SortDescriptor, THEME_ROW_HEIGHT, isPackagedTheme, presetRowHeight } from '@kanunilabs/datagrid-core';
|
|
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';
|
|
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. */
|
|
5
5
|
interface HeaderMenuContext {
|
|
@@ -26,6 +26,156 @@ declare function buildHeaderMenu<TRow = GridRowData>(context: HeaderMenuContext,
|
|
|
26
26
|
/** Formats an export menu can offer. */
|
|
27
27
|
type ExportKind = 'csv' | 'excel' | 'excel-selected' | 'pdf';
|
|
28
28
|
|
|
29
|
+
/** What the cell editor hands a lookup builder — the Enterprise `buildLookupEditor` takes it as is. */
|
|
30
|
+
interface CellLookupEditorSpec {
|
|
31
|
+
options: readonly LookupItem[];
|
|
32
|
+
value: unknown;
|
|
33
|
+
matchMode?: LookupMatchMode;
|
|
34
|
+
allowCustom?: boolean;
|
|
35
|
+
invalid?: boolean;
|
|
36
|
+
testId?: string;
|
|
37
|
+
ariaLabel?: string;
|
|
38
|
+
surfaceClass?: string;
|
|
39
|
+
onPortalOpen?: (close: () => void) => void;
|
|
40
|
+
noMatchText: string;
|
|
41
|
+
onChange: (value: unknown) => void;
|
|
42
|
+
onCommit: () => void;
|
|
43
|
+
onCancel: () => void;
|
|
44
|
+
onTab?: (shiftKey: boolean) => void;
|
|
45
|
+
}
|
|
46
|
+
interface CellEditorSpec {
|
|
47
|
+
value: unknown;
|
|
48
|
+
dataType: GridDataType | undefined;
|
|
49
|
+
/** Validation message for the current value; null when valid. */
|
|
50
|
+
error: string | null;
|
|
51
|
+
/**
|
|
52
|
+
* The editor was opened by TYPING, so `value` is the character the user
|
|
53
|
+
* just pressed. The caret goes after it instead of selecting it — selecting
|
|
54
|
+
* would make the second keystroke erase the first.
|
|
55
|
+
*/
|
|
56
|
+
seeded?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Choices for a lookup column. `null` = the list is still being fetched —
|
|
59
|
+
* the control renders disabled rather than empty, so the user cannot
|
|
60
|
+
* commit a blank over a value while the options are in flight (E3).
|
|
61
|
+
*/
|
|
62
|
+
options?: readonly LookupItem[] | null;
|
|
63
|
+
allowCustom?: boolean;
|
|
64
|
+
matchMode?: LookupMatchMode;
|
|
65
|
+
/** Format for a `date` column — governs both the mask and the display. */
|
|
66
|
+
dateFormat?: string;
|
|
67
|
+
ariaLabel?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Called when the editor opens a layer on `document.body` (the lookup list,
|
|
70
|
+
* the date calendar), handing back the function that closes it again.
|
|
71
|
+
*
|
|
72
|
+
* The layer outlives its cell by design — it is portalled so the grid's
|
|
73
|
+
* scroller cannot clip it — which means removing the grid's DOM does not
|
|
74
|
+
* remove it. Without this the layer stayed on screen after
|
|
75
|
+
* `grid.destroy()`, hanging over whatever the app rendered next, until the
|
|
76
|
+
* next scroll or resize let `place()` notice the input was gone.
|
|
77
|
+
*
|
|
78
|
+
* The editing layer keeps the closer and calls it on dispose. Scoped per
|
|
79
|
+
* grid on purpose: a global registry would let one grid's teardown close
|
|
80
|
+
* another grid's open dropdown.
|
|
81
|
+
*/
|
|
82
|
+
onPortalOpen?: (close: () => void) => void;
|
|
83
|
+
/** The portal surface classes for the calendar / lookup list. */
|
|
84
|
+
surfaceClass?: string;
|
|
85
|
+
/** Dictionary — the date calendar's captions and the no-match text. */
|
|
86
|
+
t?: GridDictionary;
|
|
87
|
+
/**
|
|
88
|
+
* Builds the combo box for a lookup column (`options` non-empty). Supplied
|
|
89
|
+
* by the Enterprise edition; without it a lookup column falls back to the
|
|
90
|
+
* plain editor for its data type.
|
|
91
|
+
*/
|
|
92
|
+
renderLookup?: (spec: CellLookupEditorSpec) => HTMLElement;
|
|
93
|
+
onChange: (value: unknown) => void;
|
|
94
|
+
onCommit: (move: 'down' | 'none') => void;
|
|
95
|
+
/** Tab / Shift+Tab: commit here and keep going in the adjacent cell. */
|
|
96
|
+
onTab: (direction: 1 | -1) => void;
|
|
97
|
+
onCancel: () => void;
|
|
98
|
+
}
|
|
99
|
+
/** Build the editor. The caller drops the fragment into the CELL. */
|
|
100
|
+
declare function buildCellEditor(spec: CellEditorSpec): DocumentFragment;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The Community `editing` option of `createGrid`. Passing the object turns
|
|
104
|
+
* single-cell editing on; `{ enabled: false }` turns it off again. Columns
|
|
105
|
+
* with `editable: false` stay read-only.
|
|
106
|
+
*/
|
|
107
|
+
interface CellEditingOptions<TRow = GridRowData> {
|
|
108
|
+
/** Default true once `editing` is passed. */
|
|
109
|
+
enabled?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Persist a committed cell. Called once per commit with the change (the
|
|
112
|
+
* Enterprise `onSave` shape). A rejection is shown in a dialog and the user
|
|
113
|
+
* is put back on the cell.
|
|
114
|
+
*/
|
|
115
|
+
onSave?: (changes: RowChange<TRow>[]) => Promise<void> | void;
|
|
116
|
+
/** Typing a printable key on a focused cell starts editing. Default true. */
|
|
117
|
+
editOnKeyPress?: boolean;
|
|
118
|
+
/** Tab moves between editable cells inside the grid. Default true. */
|
|
119
|
+
focusCellOnTab?: boolean;
|
|
120
|
+
/** Tab past the end of a row wraps to the next one. Default true. */
|
|
121
|
+
focusCellOnCycle?: boolean;
|
|
122
|
+
}
|
|
123
|
+
interface CellEditingHelpers {
|
|
124
|
+
/** Theme classes for portalled layers (the dialog, the date calendar). */
|
|
125
|
+
surfaceClass(): string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* What the Enterprise layer adds. Not part of the Community surface: the
|
|
129
|
+
* Community grid never builds one.
|
|
130
|
+
*/
|
|
131
|
+
interface CellEditingExtension<TRow = GridRowData> {
|
|
132
|
+
/** Engine options beyond the Community set — mode, rules, CRUD, permissions. */
|
|
133
|
+
engine?: Partial<EditingEngineOptions<TRow>>;
|
|
134
|
+
/** Column-level editability. Default: the column's `editable` flag. */
|
|
135
|
+
isColumnEditable?: (columnId: string) => boolean;
|
|
136
|
+
/** Keep the editor open when Tab moves. Default false. */
|
|
137
|
+
keepEditingOnTab?: boolean;
|
|
138
|
+
/** After every engine change and the repaint it requests. */
|
|
139
|
+
onChange?: () => void;
|
|
140
|
+
/** The choices for a lookup cell; `options: undefined` = not a lookup. */
|
|
141
|
+
resolveLookup?: (rowKey: RowKey, columnId: string) => {
|
|
142
|
+
options: readonly LookupItem[] | null | undefined;
|
|
143
|
+
allowCustom?: boolean;
|
|
144
|
+
matchMode?: LookupMatchMode;
|
|
145
|
+
};
|
|
146
|
+
/** The lookup combo box builder, for `buildCellEditor`. */
|
|
147
|
+
renderLookup?: CellEditorSpec['renderLookup'];
|
|
148
|
+
/** Honour a column's `renderEditor`. Default false. */
|
|
149
|
+
customEditors?: boolean;
|
|
150
|
+
/** Something drawn into a cell that is NOT being edited (the fill handle). */
|
|
151
|
+
cellAdornment?: (ctx: CellSlotContext<TRow>) => Node | null;
|
|
152
|
+
}
|
|
153
|
+
interface CellEditingLayer<TRow = GridRowData> {
|
|
154
|
+
engine: EditingEngine<TRow>;
|
|
155
|
+
renderCellContent(ctx: CellSlotContext<TRow>): Node | string | undefined;
|
|
156
|
+
getCellClassName(ctx: CellSlotContext<TRow>): string | undefined;
|
|
157
|
+
onCellDoubleClick(ctx: CellSlotContext<TRow>): void;
|
|
158
|
+
/** Capture-phase keyboard. True = consumed. */
|
|
159
|
+
handleKeyDown(event: KeyboardEvent): boolean;
|
|
160
|
+
/** Escape over an orphaned session, and Tab with no editor open. */
|
|
161
|
+
handleSessionKeys(event: KeyboardEvent): boolean;
|
|
162
|
+
/** F2 and type-to-edit — checked last so they never shadow a binding. */
|
|
163
|
+
handleOpenKeys(event: KeyboardEvent): boolean;
|
|
164
|
+
/** Commit the open editor and move to the next (1) or previous (-1) editable cell. */
|
|
165
|
+
editAdjacentCell(direction: 1 | -1, opts?: {
|
|
166
|
+
open?: boolean;
|
|
167
|
+
cycle?: boolean;
|
|
168
|
+
}): boolean;
|
|
169
|
+
/** Put DOM focus back on the grid after an editor closed. */
|
|
170
|
+
focusGrid(): void;
|
|
171
|
+
/** Hands a portalled layer's closer to `dispose()`. */
|
|
172
|
+
trackPortal(close: () => void): void;
|
|
173
|
+
/** What the Community renderer would paint for `value` in this cell. */
|
|
174
|
+
defaultContent(ctx: CellSlotContext<TRow>, value: unknown): Node | string;
|
|
175
|
+
dispose(): void;
|
|
176
|
+
}
|
|
177
|
+
declare function attachCellEditing<TRow = GridRowData>(grid: Pick<GridApi<TRow>, 'controller' | 'element'>, options: CellEditingOptions<TRow>, t: GridDictionary, helpers: CellEditingHelpers, extension?: CellEditingExtension<TRow>): CellEditingLayer<TRow>;
|
|
178
|
+
|
|
29
179
|
/** Same value as the React renderer's lead column. */
|
|
30
180
|
declare const ROW_NUMBER_COLUMN_WIDTH = 60;
|
|
31
181
|
/** Same value as the React renderer's CHECKBOX_COLUMN_WIDTH. */
|
|
@@ -221,12 +371,38 @@ interface VanillaEditorRenderContext<TRow = GridRowData> {
|
|
|
221
371
|
commit: () => void;
|
|
222
372
|
cancel: () => void;
|
|
223
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* What a column's own filter UI is handed (`renderFilter`) — the React
|
|
376
|
+
* `FilterRenderContext`, DOM-flavoured. The control is built ONCE into its
|
|
377
|
+
* host, so instead of a `value` that re-renders it reads `getValue()` and
|
|
378
|
+
* subscribes with `onValueChange` (a cleared filter, a restored view).
|
|
379
|
+
*/
|
|
380
|
+
interface VanillaFilterRenderApi<TRow = GridRowData> extends FilterRenderContextBase<TRow> {
|
|
381
|
+
/** The filter this surface holds now. */
|
|
382
|
+
getValue: () => FilterNode | null;
|
|
383
|
+
/** Called with the surface's filter after every filter change; returns an unsubscribe. */
|
|
384
|
+
onValueChange: (listener: (value: FilterNode | null) => void) => () => void;
|
|
385
|
+
}
|
|
224
386
|
type VanillaColumnDef<TRow = GridRowData> = GridColumnDef<TRow> & {
|
|
225
387
|
renderCell?: (ctx: CellRenderContext<TRow>) => string | Node;
|
|
388
|
+
/**
|
|
389
|
+
* Replace this column's filter UI with your own — the React `renderFilter`,
|
|
390
|
+
* DOM-typed. Build the control into `host`; return a teardown if it holds
|
|
391
|
+
* anything to release. Drawn in the filter row's cell (`api.surface ===
|
|
392
|
+
* 'row'`) when `filterRow` is on, and as the header popup's content
|
|
393
|
+
* (`'popup'`) when `headerFilter` is on.
|
|
394
|
+
*
|
|
395
|
+
* `api.setValue` takes any filter for this column — a built-in condition, a
|
|
396
|
+
* group, or one using a custom operator from `filterOperators` — or null to
|
|
397
|
+
* clear, through the same `setColumnFilter` the built-in surfaces use. The
|
|
398
|
+
* filter row repaints its cells on column changes and horizontal scroll, so
|
|
399
|
+
* the control may be built more than once: seed it from `api.getValue()`.
|
|
400
|
+
*/
|
|
401
|
+
renderFilter?: (host: HTMLElement, api: VanillaFilterRenderApi<TRow>) => (() => void) | void;
|
|
226
402
|
/**
|
|
227
403
|
* Replace this column's cell editor outright — the React `renderEditor`,
|
|
228
|
-
* DOM-typed. Enterprise: `
|
|
229
|
-
*
|
|
404
|
+
* DOM-typed. Enterprise: a Community grid with `editing` on edits this
|
|
405
|
+
* column with the built-in editor for its data type and ignores this.
|
|
230
406
|
*
|
|
231
407
|
* Return the control itself (an `<input>`, a fragment, a whole widget). The
|
|
232
408
|
* grid focuses it, routes Escape/Tab around it and tears it down; everything
|
|
@@ -352,6 +528,21 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
|
|
|
352
528
|
* it keeps its caret.
|
|
353
529
|
*/
|
|
354
530
|
renderRow?: (context: RowTemplateContext<TRow>) => string | Node | null | undefined;
|
|
531
|
+
/**
|
|
532
|
+
* Rows as cards on a narrow grid — a phone, a side panel. Below
|
|
533
|
+
* `breakpoint` pixels (default 600) each data row is drawn as a card: the
|
|
534
|
+
* first field as its title, the rest as "Header value" lines, as wide as
|
|
535
|
+
* the grid. The column headers give way to a sort control.
|
|
536
|
+
*
|
|
537
|
+
* Sort, filter, search, selection, grouping, virtual scrolling and remote
|
|
538
|
+
* data keep working. What needs a cell does not apply while cards are shown:
|
|
539
|
+
* in-cell editing, range selection, the fill handle and column resizing. A
|
|
540
|
+
* card shows each field's TEXT (formatters and lookups included). While
|
|
541
|
+
* cards are shown they replace `renderRow`. The React prop, unchanged.
|
|
542
|
+
*/
|
|
543
|
+
cardView?: boolean | CardViewOptions;
|
|
544
|
+
/** The grid switched between cards (`true`) and the table, as its width crossed the breakpoint. */
|
|
545
|
+
onCardViewChange?: (active: boolean) => void;
|
|
355
546
|
/**
|
|
356
547
|
* A polite live region reporting row count, sort and selection to screen
|
|
357
548
|
* readers. Default true.
|
|
@@ -380,6 +571,14 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
|
|
|
380
571
|
resizable?: boolean;
|
|
381
572
|
/** Drag a header onto another to reorder. Default true. */
|
|
382
573
|
reorderable?: boolean;
|
|
574
|
+
/**
|
|
575
|
+
* Let the header row grow to fit its tallest caption — the partner of a
|
|
576
|
+
* column's `wrapHeaderText`. Default false: the header keeps the theme's
|
|
577
|
+
* fixed height. The React prop, unchanged: the height is measured after
|
|
578
|
+
* layout (only the columns on screen), and everything stuck under the
|
|
579
|
+
* header moves with it.
|
|
580
|
+
*/
|
|
581
|
+
autoHeaderHeight?: boolean;
|
|
383
582
|
/** Per-column text inputs under the header. */
|
|
384
583
|
filterRow?: boolean;
|
|
385
584
|
/** ms before typed filter text reaches the engine. Same default as React:
|
|
@@ -583,6 +782,21 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
|
|
|
583
782
|
* `grouping.panel` exactly like the React prop shape. */
|
|
584
783
|
/** Search box debounce, ms. React's default. */
|
|
585
784
|
searchDebounce?: number;
|
|
785
|
+
/**
|
|
786
|
+
* Single-cell editing (Community since 2026-10-12). Off unless passed:
|
|
787
|
+
* `editing: {}` turns it on, `{ enabled: false }` off again. Double-click,
|
|
788
|
+
* F2 or typing opens the in-cell editor (text, number, date, checkbox);
|
|
789
|
+
* 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.
|
|
793
|
+
*
|
|
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`.
|
|
798
|
+
*/
|
|
799
|
+
editing?: CellEditingOptions<TRow>;
|
|
586
800
|
/** Replace a body cell's content. `undefined` = the default painter runs. */
|
|
587
801
|
renderCellContent?: (ctx: CellSlotContext<TRow>) => Node | string | undefined;
|
|
588
802
|
/**
|
|
@@ -637,4 +851,55 @@ declare function createGrid<TRow = GridRowData>(container: HTMLElement, config:
|
|
|
637
851
|
*/
|
|
638
852
|
declare function measureBestFitWidth(root: HTMLElement, columnId: string): number | null;
|
|
639
853
|
|
|
640
|
-
|
|
854
|
+
interface DateEditorSpec {
|
|
855
|
+
value: unknown;
|
|
856
|
+
/** Column format. Defaults to `yyyy-MM-dd`. */
|
|
857
|
+
format?: string;
|
|
858
|
+
invalid?: boolean;
|
|
859
|
+
disabled?: boolean;
|
|
860
|
+
autoFocus?: boolean;
|
|
861
|
+
testId?: string;
|
|
862
|
+
columnId?: string;
|
|
863
|
+
ariaLabel?: string;
|
|
864
|
+
/** The portal's surface classes, so the calendar resolves --dg tokens. */
|
|
865
|
+
surfaceClass?: string;
|
|
866
|
+
t: GridDictionary;
|
|
867
|
+
/** Commit shape follows the value the editor was GIVEN: a Date column gets
|
|
868
|
+
* a Date back, an ISO-string column gets a string. */
|
|
869
|
+
onChange: (value: unknown) => void;
|
|
870
|
+
onCommit: () => void;
|
|
871
|
+
onCancel: () => void;
|
|
872
|
+
/**
|
|
873
|
+
* Called when the editor opens a layer on `document.body` (the lookup list,
|
|
874
|
+
* the date calendar), handing back the function that closes it again.
|
|
875
|
+
*
|
|
876
|
+
* The layer outlives its cell by design — it is portalled so the grid's
|
|
877
|
+
* scroller cannot clip it — which means removing the grid's DOM does not
|
|
878
|
+
* remove it. Without this the layer stayed on screen after
|
|
879
|
+
* `grid.destroy()`, hanging over whatever the app rendered next, until the
|
|
880
|
+
* next scroll or resize let `place()` notice the input was gone.
|
|
881
|
+
*
|
|
882
|
+
* The editing layer keeps the closer and calls it on dispose. Scoped per
|
|
883
|
+
* grid on purpose: a global registry would let one grid's teardown close
|
|
884
|
+
* another grid's open dropdown.
|
|
885
|
+
*/
|
|
886
|
+
onPortalOpen?: (close: () => void) => void;
|
|
887
|
+
onTab?: (shiftKey: boolean) => void;
|
|
888
|
+
}
|
|
889
|
+
declare function buildDateEditor(spec: DateEditorSpec): HTMLElement;
|
|
890
|
+
|
|
891
|
+
interface ConfirmDialogSpec {
|
|
892
|
+
title: string;
|
|
893
|
+
message: string;
|
|
894
|
+
confirmLabel: string;
|
|
895
|
+
/** Omitted for an acknowledgement dialog, which gets only confirm. */
|
|
896
|
+
cancelLabel?: string;
|
|
897
|
+
/** Styles the confirm button as destructive. */
|
|
898
|
+
danger?: boolean;
|
|
899
|
+
/** The enterprise wrapper's theme/dark classes, re-established here. */
|
|
900
|
+
surfaceClass?: string;
|
|
901
|
+
}
|
|
902
|
+
/** Open the dialog; resolves the user's answer and removes itself. */
|
|
903
|
+
declare function openConfirmDialog(spec: ConfirmDialogSpec): Promise<boolean>;
|
|
904
|
+
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { GridRowData, DataGridController, GridDictionary, RowNode, GridColumnDef, DataGridCoreConfig, GridThemeName, GridPaletteName, GridDensity, DescribeFilterOptions,
|
|
2
|
-
export { DENSITY_ROW_HEIGHT, DataGridController, GRID_COLOR_SCHEMES, GridColorScheme, GridColumnDef, GridDensity, GridPaletteName, GridRowData, GridTheme, GridThemeName, RowKey, RowNode, SortDescriptor, THEME_ROW_HEIGHT, isPackagedTheme, presetRowHeight } from '@kanunilabs/datagrid-core';
|
|
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';
|
|
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. */
|
|
5
5
|
interface HeaderMenuContext {
|
|
@@ -26,6 +26,156 @@ declare function buildHeaderMenu<TRow = GridRowData>(context: HeaderMenuContext,
|
|
|
26
26
|
/** Formats an export menu can offer. */
|
|
27
27
|
type ExportKind = 'csv' | 'excel' | 'excel-selected' | 'pdf';
|
|
28
28
|
|
|
29
|
+
/** What the cell editor hands a lookup builder — the Enterprise `buildLookupEditor` takes it as is. */
|
|
30
|
+
interface CellLookupEditorSpec {
|
|
31
|
+
options: readonly LookupItem[];
|
|
32
|
+
value: unknown;
|
|
33
|
+
matchMode?: LookupMatchMode;
|
|
34
|
+
allowCustom?: boolean;
|
|
35
|
+
invalid?: boolean;
|
|
36
|
+
testId?: string;
|
|
37
|
+
ariaLabel?: string;
|
|
38
|
+
surfaceClass?: string;
|
|
39
|
+
onPortalOpen?: (close: () => void) => void;
|
|
40
|
+
noMatchText: string;
|
|
41
|
+
onChange: (value: unknown) => void;
|
|
42
|
+
onCommit: () => void;
|
|
43
|
+
onCancel: () => void;
|
|
44
|
+
onTab?: (shiftKey: boolean) => void;
|
|
45
|
+
}
|
|
46
|
+
interface CellEditorSpec {
|
|
47
|
+
value: unknown;
|
|
48
|
+
dataType: GridDataType | undefined;
|
|
49
|
+
/** Validation message for the current value; null when valid. */
|
|
50
|
+
error: string | null;
|
|
51
|
+
/**
|
|
52
|
+
* The editor was opened by TYPING, so `value` is the character the user
|
|
53
|
+
* just pressed. The caret goes after it instead of selecting it — selecting
|
|
54
|
+
* would make the second keystroke erase the first.
|
|
55
|
+
*/
|
|
56
|
+
seeded?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Choices for a lookup column. `null` = the list is still being fetched —
|
|
59
|
+
* the control renders disabled rather than empty, so the user cannot
|
|
60
|
+
* commit a blank over a value while the options are in flight (E3).
|
|
61
|
+
*/
|
|
62
|
+
options?: readonly LookupItem[] | null;
|
|
63
|
+
allowCustom?: boolean;
|
|
64
|
+
matchMode?: LookupMatchMode;
|
|
65
|
+
/** Format for a `date` column — governs both the mask and the display. */
|
|
66
|
+
dateFormat?: string;
|
|
67
|
+
ariaLabel?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Called when the editor opens a layer on `document.body` (the lookup list,
|
|
70
|
+
* the date calendar), handing back the function that closes it again.
|
|
71
|
+
*
|
|
72
|
+
* The layer outlives its cell by design — it is portalled so the grid's
|
|
73
|
+
* scroller cannot clip it — which means removing the grid's DOM does not
|
|
74
|
+
* remove it. Without this the layer stayed on screen after
|
|
75
|
+
* `grid.destroy()`, hanging over whatever the app rendered next, until the
|
|
76
|
+
* next scroll or resize let `place()` notice the input was gone.
|
|
77
|
+
*
|
|
78
|
+
* The editing layer keeps the closer and calls it on dispose. Scoped per
|
|
79
|
+
* grid on purpose: a global registry would let one grid's teardown close
|
|
80
|
+
* another grid's open dropdown.
|
|
81
|
+
*/
|
|
82
|
+
onPortalOpen?: (close: () => void) => void;
|
|
83
|
+
/** The portal surface classes for the calendar / lookup list. */
|
|
84
|
+
surfaceClass?: string;
|
|
85
|
+
/** Dictionary — the date calendar's captions and the no-match text. */
|
|
86
|
+
t?: GridDictionary;
|
|
87
|
+
/**
|
|
88
|
+
* Builds the combo box for a lookup column (`options` non-empty). Supplied
|
|
89
|
+
* by the Enterprise edition; without it a lookup column falls back to the
|
|
90
|
+
* plain editor for its data type.
|
|
91
|
+
*/
|
|
92
|
+
renderLookup?: (spec: CellLookupEditorSpec) => HTMLElement;
|
|
93
|
+
onChange: (value: unknown) => void;
|
|
94
|
+
onCommit: (move: 'down' | 'none') => void;
|
|
95
|
+
/** Tab / Shift+Tab: commit here and keep going in the adjacent cell. */
|
|
96
|
+
onTab: (direction: 1 | -1) => void;
|
|
97
|
+
onCancel: () => void;
|
|
98
|
+
}
|
|
99
|
+
/** Build the editor. The caller drops the fragment into the CELL. */
|
|
100
|
+
declare function buildCellEditor(spec: CellEditorSpec): DocumentFragment;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The Community `editing` option of `createGrid`. Passing the object turns
|
|
104
|
+
* single-cell editing on; `{ enabled: false }` turns it off again. Columns
|
|
105
|
+
* with `editable: false` stay read-only.
|
|
106
|
+
*/
|
|
107
|
+
interface CellEditingOptions<TRow = GridRowData> {
|
|
108
|
+
/** Default true once `editing` is passed. */
|
|
109
|
+
enabled?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Persist a committed cell. Called once per commit with the change (the
|
|
112
|
+
* Enterprise `onSave` shape). A rejection is shown in a dialog and the user
|
|
113
|
+
* is put back on the cell.
|
|
114
|
+
*/
|
|
115
|
+
onSave?: (changes: RowChange<TRow>[]) => Promise<void> | void;
|
|
116
|
+
/** Typing a printable key on a focused cell starts editing. Default true. */
|
|
117
|
+
editOnKeyPress?: boolean;
|
|
118
|
+
/** Tab moves between editable cells inside the grid. Default true. */
|
|
119
|
+
focusCellOnTab?: boolean;
|
|
120
|
+
/** Tab past the end of a row wraps to the next one. Default true. */
|
|
121
|
+
focusCellOnCycle?: boolean;
|
|
122
|
+
}
|
|
123
|
+
interface CellEditingHelpers {
|
|
124
|
+
/** Theme classes for portalled layers (the dialog, the date calendar). */
|
|
125
|
+
surfaceClass(): string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* What the Enterprise layer adds. Not part of the Community surface: the
|
|
129
|
+
* Community grid never builds one.
|
|
130
|
+
*/
|
|
131
|
+
interface CellEditingExtension<TRow = GridRowData> {
|
|
132
|
+
/** Engine options beyond the Community set — mode, rules, CRUD, permissions. */
|
|
133
|
+
engine?: Partial<EditingEngineOptions<TRow>>;
|
|
134
|
+
/** Column-level editability. Default: the column's `editable` flag. */
|
|
135
|
+
isColumnEditable?: (columnId: string) => boolean;
|
|
136
|
+
/** Keep the editor open when Tab moves. Default false. */
|
|
137
|
+
keepEditingOnTab?: boolean;
|
|
138
|
+
/** After every engine change and the repaint it requests. */
|
|
139
|
+
onChange?: () => void;
|
|
140
|
+
/** The choices for a lookup cell; `options: undefined` = not a lookup. */
|
|
141
|
+
resolveLookup?: (rowKey: RowKey, columnId: string) => {
|
|
142
|
+
options: readonly LookupItem[] | null | undefined;
|
|
143
|
+
allowCustom?: boolean;
|
|
144
|
+
matchMode?: LookupMatchMode;
|
|
145
|
+
};
|
|
146
|
+
/** The lookup combo box builder, for `buildCellEditor`. */
|
|
147
|
+
renderLookup?: CellEditorSpec['renderLookup'];
|
|
148
|
+
/** Honour a column's `renderEditor`. Default false. */
|
|
149
|
+
customEditors?: boolean;
|
|
150
|
+
/** Something drawn into a cell that is NOT being edited (the fill handle). */
|
|
151
|
+
cellAdornment?: (ctx: CellSlotContext<TRow>) => Node | null;
|
|
152
|
+
}
|
|
153
|
+
interface CellEditingLayer<TRow = GridRowData> {
|
|
154
|
+
engine: EditingEngine<TRow>;
|
|
155
|
+
renderCellContent(ctx: CellSlotContext<TRow>): Node | string | undefined;
|
|
156
|
+
getCellClassName(ctx: CellSlotContext<TRow>): string | undefined;
|
|
157
|
+
onCellDoubleClick(ctx: CellSlotContext<TRow>): void;
|
|
158
|
+
/** Capture-phase keyboard. True = consumed. */
|
|
159
|
+
handleKeyDown(event: KeyboardEvent): boolean;
|
|
160
|
+
/** Escape over an orphaned session, and Tab with no editor open. */
|
|
161
|
+
handleSessionKeys(event: KeyboardEvent): boolean;
|
|
162
|
+
/** F2 and type-to-edit — checked last so they never shadow a binding. */
|
|
163
|
+
handleOpenKeys(event: KeyboardEvent): boolean;
|
|
164
|
+
/** Commit the open editor and move to the next (1) or previous (-1) editable cell. */
|
|
165
|
+
editAdjacentCell(direction: 1 | -1, opts?: {
|
|
166
|
+
open?: boolean;
|
|
167
|
+
cycle?: boolean;
|
|
168
|
+
}): boolean;
|
|
169
|
+
/** Put DOM focus back on the grid after an editor closed. */
|
|
170
|
+
focusGrid(): void;
|
|
171
|
+
/** Hands a portalled layer's closer to `dispose()`. */
|
|
172
|
+
trackPortal(close: () => void): void;
|
|
173
|
+
/** What the Community renderer would paint for `value` in this cell. */
|
|
174
|
+
defaultContent(ctx: CellSlotContext<TRow>, value: unknown): Node | string;
|
|
175
|
+
dispose(): void;
|
|
176
|
+
}
|
|
177
|
+
declare function attachCellEditing<TRow = GridRowData>(grid: Pick<GridApi<TRow>, 'controller' | 'element'>, options: CellEditingOptions<TRow>, t: GridDictionary, helpers: CellEditingHelpers, extension?: CellEditingExtension<TRow>): CellEditingLayer<TRow>;
|
|
178
|
+
|
|
29
179
|
/** Same value as the React renderer's lead column. */
|
|
30
180
|
declare const ROW_NUMBER_COLUMN_WIDTH = 60;
|
|
31
181
|
/** Same value as the React renderer's CHECKBOX_COLUMN_WIDTH. */
|
|
@@ -221,12 +371,38 @@ interface VanillaEditorRenderContext<TRow = GridRowData> {
|
|
|
221
371
|
commit: () => void;
|
|
222
372
|
cancel: () => void;
|
|
223
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* What a column's own filter UI is handed (`renderFilter`) — the React
|
|
376
|
+
* `FilterRenderContext`, DOM-flavoured. The control is built ONCE into its
|
|
377
|
+
* host, so instead of a `value` that re-renders it reads `getValue()` and
|
|
378
|
+
* subscribes with `onValueChange` (a cleared filter, a restored view).
|
|
379
|
+
*/
|
|
380
|
+
interface VanillaFilterRenderApi<TRow = GridRowData> extends FilterRenderContextBase<TRow> {
|
|
381
|
+
/** The filter this surface holds now. */
|
|
382
|
+
getValue: () => FilterNode | null;
|
|
383
|
+
/** Called with the surface's filter after every filter change; returns an unsubscribe. */
|
|
384
|
+
onValueChange: (listener: (value: FilterNode | null) => void) => () => void;
|
|
385
|
+
}
|
|
224
386
|
type VanillaColumnDef<TRow = GridRowData> = GridColumnDef<TRow> & {
|
|
225
387
|
renderCell?: (ctx: CellRenderContext<TRow>) => string | Node;
|
|
388
|
+
/**
|
|
389
|
+
* Replace this column's filter UI with your own — the React `renderFilter`,
|
|
390
|
+
* DOM-typed. Build the control into `host`; return a teardown if it holds
|
|
391
|
+
* anything to release. Drawn in the filter row's cell (`api.surface ===
|
|
392
|
+
* 'row'`) when `filterRow` is on, and as the header popup's content
|
|
393
|
+
* (`'popup'`) when `headerFilter` is on.
|
|
394
|
+
*
|
|
395
|
+
* `api.setValue` takes any filter for this column — a built-in condition, a
|
|
396
|
+
* group, or one using a custom operator from `filterOperators` — or null to
|
|
397
|
+
* clear, through the same `setColumnFilter` the built-in surfaces use. The
|
|
398
|
+
* filter row repaints its cells on column changes and horizontal scroll, so
|
|
399
|
+
* the control may be built more than once: seed it from `api.getValue()`.
|
|
400
|
+
*/
|
|
401
|
+
renderFilter?: (host: HTMLElement, api: VanillaFilterRenderApi<TRow>) => (() => void) | void;
|
|
226
402
|
/**
|
|
227
403
|
* Replace this column's cell editor outright — the React `renderEditor`,
|
|
228
|
-
* DOM-typed. Enterprise: `
|
|
229
|
-
*
|
|
404
|
+
* DOM-typed. Enterprise: a Community grid with `editing` on edits this
|
|
405
|
+
* column with the built-in editor for its data type and ignores this.
|
|
230
406
|
*
|
|
231
407
|
* Return the control itself (an `<input>`, a fragment, a whole widget). The
|
|
232
408
|
* grid focuses it, routes Escape/Tab around it and tears it down; everything
|
|
@@ -352,6 +528,21 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
|
|
|
352
528
|
* it keeps its caret.
|
|
353
529
|
*/
|
|
354
530
|
renderRow?: (context: RowTemplateContext<TRow>) => string | Node | null | undefined;
|
|
531
|
+
/**
|
|
532
|
+
* Rows as cards on a narrow grid — a phone, a side panel. Below
|
|
533
|
+
* `breakpoint` pixels (default 600) each data row is drawn as a card: the
|
|
534
|
+
* first field as its title, the rest as "Header value" lines, as wide as
|
|
535
|
+
* the grid. The column headers give way to a sort control.
|
|
536
|
+
*
|
|
537
|
+
* Sort, filter, search, selection, grouping, virtual scrolling and remote
|
|
538
|
+
* data keep working. What needs a cell does not apply while cards are shown:
|
|
539
|
+
* in-cell editing, range selection, the fill handle and column resizing. A
|
|
540
|
+
* card shows each field's TEXT (formatters and lookups included). While
|
|
541
|
+
* cards are shown they replace `renderRow`. The React prop, unchanged.
|
|
542
|
+
*/
|
|
543
|
+
cardView?: boolean | CardViewOptions;
|
|
544
|
+
/** The grid switched between cards (`true`) and the table, as its width crossed the breakpoint. */
|
|
545
|
+
onCardViewChange?: (active: boolean) => void;
|
|
355
546
|
/**
|
|
356
547
|
* A polite live region reporting row count, sort and selection to screen
|
|
357
548
|
* readers. Default true.
|
|
@@ -380,6 +571,14 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
|
|
|
380
571
|
resizable?: boolean;
|
|
381
572
|
/** Drag a header onto another to reorder. Default true. */
|
|
382
573
|
reorderable?: boolean;
|
|
574
|
+
/**
|
|
575
|
+
* Let the header row grow to fit its tallest caption — the partner of a
|
|
576
|
+
* column's `wrapHeaderText`. Default false: the header keeps the theme's
|
|
577
|
+
* fixed height. The React prop, unchanged: the height is measured after
|
|
578
|
+
* layout (only the columns on screen), and everything stuck under the
|
|
579
|
+
* header moves with it.
|
|
580
|
+
*/
|
|
581
|
+
autoHeaderHeight?: boolean;
|
|
383
582
|
/** Per-column text inputs under the header. */
|
|
384
583
|
filterRow?: boolean;
|
|
385
584
|
/** ms before typed filter text reaches the engine. Same default as React:
|
|
@@ -583,6 +782,21 @@ interface CreateGridConfig<TRow = GridRowData> extends Omit<DataGridCoreConfig<T
|
|
|
583
782
|
* `grouping.panel` exactly like the React prop shape. */
|
|
584
783
|
/** Search box debounce, ms. React's default. */
|
|
585
784
|
searchDebounce?: number;
|
|
785
|
+
/**
|
|
786
|
+
* Single-cell editing (Community since 2026-10-12). Off unless passed:
|
|
787
|
+
* `editing: {}` turns it on, `{ enabled: false }` off again. Double-click,
|
|
788
|
+
* F2 or typing opens the in-cell editor (text, number, date, checkbox);
|
|
789
|
+
* 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.
|
|
793
|
+
*
|
|
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`.
|
|
798
|
+
*/
|
|
799
|
+
editing?: CellEditingOptions<TRow>;
|
|
586
800
|
/** Replace a body cell's content. `undefined` = the default painter runs. */
|
|
587
801
|
renderCellContent?: (ctx: CellSlotContext<TRow>) => Node | string | undefined;
|
|
588
802
|
/**
|
|
@@ -637,4 +851,55 @@ declare function createGrid<TRow = GridRowData>(container: HTMLElement, config:
|
|
|
637
851
|
*/
|
|
638
852
|
declare function measureBestFitWidth(root: HTMLElement, columnId: string): number | null;
|
|
639
853
|
|
|
640
|
-
|
|
854
|
+
interface DateEditorSpec {
|
|
855
|
+
value: unknown;
|
|
856
|
+
/** Column format. Defaults to `yyyy-MM-dd`. */
|
|
857
|
+
format?: string;
|
|
858
|
+
invalid?: boolean;
|
|
859
|
+
disabled?: boolean;
|
|
860
|
+
autoFocus?: boolean;
|
|
861
|
+
testId?: string;
|
|
862
|
+
columnId?: string;
|
|
863
|
+
ariaLabel?: string;
|
|
864
|
+
/** The portal's surface classes, so the calendar resolves --dg tokens. */
|
|
865
|
+
surfaceClass?: string;
|
|
866
|
+
t: GridDictionary;
|
|
867
|
+
/** Commit shape follows the value the editor was GIVEN: a Date column gets
|
|
868
|
+
* a Date back, an ISO-string column gets a string. */
|
|
869
|
+
onChange: (value: unknown) => void;
|
|
870
|
+
onCommit: () => void;
|
|
871
|
+
onCancel: () => void;
|
|
872
|
+
/**
|
|
873
|
+
* Called when the editor opens a layer on `document.body` (the lookup list,
|
|
874
|
+
* the date calendar), handing back the function that closes it again.
|
|
875
|
+
*
|
|
876
|
+
* The layer outlives its cell by design — it is portalled so the grid's
|
|
877
|
+
* scroller cannot clip it — which means removing the grid's DOM does not
|
|
878
|
+
* remove it. Without this the layer stayed on screen after
|
|
879
|
+
* `grid.destroy()`, hanging over whatever the app rendered next, until the
|
|
880
|
+
* next scroll or resize let `place()` notice the input was gone.
|
|
881
|
+
*
|
|
882
|
+
* The editing layer keeps the closer and calls it on dispose. Scoped per
|
|
883
|
+
* grid on purpose: a global registry would let one grid's teardown close
|
|
884
|
+
* another grid's open dropdown.
|
|
885
|
+
*/
|
|
886
|
+
onPortalOpen?: (close: () => void) => void;
|
|
887
|
+
onTab?: (shiftKey: boolean) => void;
|
|
888
|
+
}
|
|
889
|
+
declare function buildDateEditor(spec: DateEditorSpec): HTMLElement;
|
|
890
|
+
|
|
891
|
+
interface ConfirmDialogSpec {
|
|
892
|
+
title: string;
|
|
893
|
+
message: string;
|
|
894
|
+
confirmLabel: string;
|
|
895
|
+
/** Omitted for an acknowledgement dialog, which gets only confirm. */
|
|
896
|
+
cancelLabel?: string;
|
|
897
|
+
/** Styles the confirm button as destructive. */
|
|
898
|
+
danger?: boolean;
|
|
899
|
+
/** The enterprise wrapper's theme/dark classes, re-established here. */
|
|
900
|
+
surfaceClass?: string;
|
|
901
|
+
}
|
|
902
|
+
/** Open the dialog; resolves the user's answer and removes itself. */
|
|
903
|
+
declare function openConfirmDialog(spec: ConfirmDialogSpec): Promise<boolean>;
|
|
904
|
+
|
|
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 };
|