@jh-grid/jhgrid-js 0.1.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/LICENSE +67 -0
- package/NOTICE +4 -0
- package/README.md +182 -0
- package/dist/jhgrid.esm.js +11895 -0
- package/dist/jhgrid.js +11919 -0
- package/dist/jhgrid.min.js +149 -0
- package/index.d.ts +1294 -0
- package/package.json +52 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,1294 @@
|
|
|
1
|
+
// Theme
|
|
2
|
+
|
|
3
|
+
export interface GridTheme {
|
|
4
|
+
headerBg?: string;
|
|
5
|
+
headerText?: string;
|
|
6
|
+
headerBorder?: string;
|
|
7
|
+
rowEven?: string;
|
|
8
|
+
rowOdd?: string;
|
|
9
|
+
cellBorder?: string;
|
|
10
|
+
cellText?: string;
|
|
11
|
+
loadingText?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Bar drawn in a cell whose row has not arrived yet, in place of leaving it blank. Defaults to
|
|
14
|
+
* `'#E4E7EB'`.
|
|
15
|
+
*/
|
|
16
|
+
skeletonBar?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The lighter band that sweeps across those bars, drawn over them so it reads as light passing
|
|
19
|
+
* rather than as a second thing on the row. Held still when the viewer has asked for reduced
|
|
20
|
+
* motion. Defaults to `'rgba(255,255,255,0.65)'`.
|
|
21
|
+
*/
|
|
22
|
+
skeletonSheen?: string;
|
|
23
|
+
cellPadding?: number;
|
|
24
|
+
selectionColor?: string;
|
|
25
|
+
selectionFill?: string;
|
|
26
|
+
selRowBg?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Wash painted over the row under the pointer. Defaults to a neutral `rgba(0,0,0,0.045)`, kept
|
|
29
|
+
* distinct from `selRowBg` so hover and selection stay tellable apart on the same row. A theme
|
|
30
|
+
* with a dark body should set a light value instead; a falsy value turns the highlight off.
|
|
31
|
+
*/
|
|
32
|
+
hoverRowBg?: string | null;
|
|
33
|
+
scrollbarBg?: string;
|
|
34
|
+
scrollbarThumb?: string;
|
|
35
|
+
scrollbarRadius?:number;
|
|
36
|
+
frozenBorder?: string;
|
|
37
|
+
groupHeaderBg?: string;
|
|
38
|
+
groupHeaderText?:string;
|
|
39
|
+
footerBg?: string;
|
|
40
|
+
footerText?: string;
|
|
41
|
+
filterIconBg?: string;
|
|
42
|
+
sortIconBg?: string;
|
|
43
|
+
filterIconColor?: string;
|
|
44
|
+
sortIconColor?: string;
|
|
45
|
+
headerIconColor?: string;
|
|
46
|
+
/** Border color for the Excel-style double-line drawn on column headers adjacent to hidden columns. Defaults to `'#94A3B8'`. */
|
|
47
|
+
hiddenColIndicator?: string;
|
|
48
|
+
/** Background tint applied to editable cells when `editableCols` is not `'*'`. Defaults to `undefined` (no tint). */
|
|
49
|
+
editableCellBg?: string;
|
|
50
|
+
/** Background tint applied to readonly cells when `editableCols` is not `'*'`. Defaults to `'#F5F5F5'` (light gray). */
|
|
51
|
+
readonlyCellBg?: string;
|
|
52
|
+
/** `CellRenderers.image()` cell background while an image is loading. Defaults to `'#F1F5F9'`. */
|
|
53
|
+
imagePlaceholderBg?: string;
|
|
54
|
+
/** `CellRenderers.image()` cell background on load failure. Defaults to `'#FEE2E2'`. */
|
|
55
|
+
imageErrorBg?: string;
|
|
56
|
+
/** `CellRenderers.image()` "broken image" X glyph color. Defaults to `'#DC2626'`. */
|
|
57
|
+
imageErrorIcon?: string;
|
|
58
|
+
fontSize?: number;
|
|
59
|
+
/** Header cell font size in px. Defaults to `fontSize` when omitted. */
|
|
60
|
+
headerFontSize?: number;
|
|
61
|
+
fontFamily?: string;
|
|
62
|
+
/** BCP-47 tag (e.g. `'en-US'`, `'ko-KR'`) that `CellRenderers.number/date/currency` fall back to when a column doesn't pin its own `locale`. Set from {@link JHGridOptions.locale}. */
|
|
63
|
+
locale?: string;
|
|
64
|
+
|
|
65
|
+
// ── Cell state ───────────────────────────────────────────────────────────────────────────
|
|
66
|
+
/** Outline drawn around a cell whose value fails its column's `validation`. Defaults to `'#dc2626'`. */
|
|
67
|
+
invalidCellBorder?: string;
|
|
68
|
+
|
|
69
|
+
// ── Rows marked for deletion ─────────────────────────────────────────────────────────────
|
|
70
|
+
/** Wash over a row marked by `deleteRow()` but not yet committed. Defaults to `'rgba(239,68,68,0.10)'`. */
|
|
71
|
+
deletedRowFill?: string;
|
|
72
|
+
/** Strike-through line drawn across that row's text. Defaults to `'rgba(239,68,68,0.55)'`. */
|
|
73
|
+
deletedRowStrike?: string;
|
|
74
|
+
|
|
75
|
+
// ── Drag feedback ────────────────────────────────────────────────────────────────────────
|
|
76
|
+
/** Drop shadow under the ghost that follows the pointer during a column-header drag. Defaults to `'rgba(15,23,42,0.30)'`. */
|
|
77
|
+
dragGhostShadow?: string;
|
|
78
|
+
/** Fill of the band showing where a dragged column or row would land. Defaults to `'rgba(59,130,246,0.12)'`. */
|
|
79
|
+
dragIndicatorFill?: string;
|
|
80
|
+
/** The insertion line itself, at the edge of that band. Defaults to `'#3b82f6'`. */
|
|
81
|
+
dragIndicatorLine?: string;
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* ── DOM surfaces ─────────────────────────────────────────────────────────────────────────
|
|
85
|
+
* Everything below styles the parts of the grid that are real DOM rather than canvas — the
|
|
86
|
+
* filter panel, context menus, the column chooser, cell editors, and the pager. They are
|
|
87
|
+
* listed here because `theme` reaches them, but they are also bridged to CSS custom
|
|
88
|
+
* properties (`--jhg-overlay-bg`, `--jhg-pager-bg`, …; see `GRID_CLASSES`). Each is emitted
|
|
89
|
+
* as `var(--jhg-…, <theme value>)`: nothing in the library sets the variable, so the theme
|
|
90
|
+
* value normally wins and a consumer who declares the variable takes over. Style through
|
|
91
|
+
* whichever suits — the theme for a value known at construction, the variable for one a
|
|
92
|
+
* stylesheet decides.
|
|
93
|
+
*/
|
|
94
|
+
/** Background of panels, menus and dialogs. Defaults to `'#FFFFFF'`. */
|
|
95
|
+
overlayBg?: string;
|
|
96
|
+
/** Their outer border. Defaults to `'#D0D0D0'`. */
|
|
97
|
+
overlayBorder?: string;
|
|
98
|
+
/** Header strip inside a panel or dialog. Defaults to `'#F5F5F5'`. */
|
|
99
|
+
overlayHeaderBg?: string;
|
|
100
|
+
/** Hairline between sections of a panel. Defaults to `'#E0E0E0'`. */
|
|
101
|
+
overlayDivider?: string;
|
|
102
|
+
/** Primary text on those surfaces. Defaults to `'#212121'`. */
|
|
103
|
+
overlayText?: string;
|
|
104
|
+
/** Secondary text — labels, counts. Defaults to `'#595959'`. */
|
|
105
|
+
overlayMutedText?: string;
|
|
106
|
+
/** Placeholder and hint text. Defaults to `'#909090'`. */
|
|
107
|
+
overlayHintText?: string;
|
|
108
|
+
/** Hover background for a row in a list, such as a filter checklist. Defaults to `'#F5F5F5'`. */
|
|
109
|
+
overlayHoverBg?: string;
|
|
110
|
+
/** Hover — and keyboard-focus — background for a menu item. Defaults to `'#F0F0F0'`. */
|
|
111
|
+
overlayItemHoverBg?: string;
|
|
112
|
+
/** Shadow under panels and dialogs. Defaults to `'0 4px 16px rgba(0,0,0,0.15)'`. */
|
|
113
|
+
overlayShadow?: string;
|
|
114
|
+
/** Shadow under context menus, which sit closer to the surface. Defaults to `'0 4px 12px rgba(0,0,0,0.15)'`. */
|
|
115
|
+
overlayMenuShadow?: string;
|
|
116
|
+
/** Text on an accent-filled control, such as the filter panel's apply button. Defaults to `'#FFFFFF'`. */
|
|
117
|
+
overlayAccentText?: string;
|
|
118
|
+
|
|
119
|
+
/** Pager bar background. Only rendered with `pagination` enabled. Defaults to `'#f8fafc'`. */
|
|
120
|
+
pagerBg?: string;
|
|
121
|
+
/** Pager bar text. Defaults to `'#1e293b'`. */
|
|
122
|
+
pagerText?: string;
|
|
123
|
+
/** Border between the pager bar and the grid. Defaults to `'#e2e8f0'`. */
|
|
124
|
+
pagerBorder?: string;
|
|
125
|
+
/** Page-button background. Defaults to `'#ffffff'`. */
|
|
126
|
+
pagerButtonBg?: string;
|
|
127
|
+
/** Page-button border. Defaults to `'#cbd5e1'`. */
|
|
128
|
+
pagerButtonBorder?: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Cell Renderers
|
|
132
|
+
|
|
133
|
+
export interface CellRendererArgs {
|
|
134
|
+
x: number;
|
|
135
|
+
y: number;
|
|
136
|
+
w: number;
|
|
137
|
+
h: number;
|
|
138
|
+
value: unknown;
|
|
139
|
+
rowData: Record<string, unknown>;
|
|
140
|
+
rowIndex: number;
|
|
141
|
+
colIndex: number;
|
|
142
|
+
theme: Required<GridTheme>;
|
|
143
|
+
padding: number;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export type CellRendererFn = (ctx: CanvasRenderingContext2D, args: CellRendererArgs) => void;
|
|
147
|
+
|
|
148
|
+
// Cell context menu extension point (see JHGridOptions.cellContextMenuExtraItems)
|
|
149
|
+
|
|
150
|
+
export interface CellContextMenuItemContext {
|
|
151
|
+
row: number;
|
|
152
|
+
col: number;
|
|
153
|
+
field: string;
|
|
154
|
+
rowData: Record<string, unknown> | null;
|
|
155
|
+
/** Viewport coordinates of the invoking click (unlike the grid's internal canvas-local x/y) —
|
|
156
|
+
* for positioning a host-built DOM overlay (e.g. a comment editor) at the invoked cell. */
|
|
157
|
+
clientX: number;
|
|
158
|
+
clientY: number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface CellContextMenuItem {
|
|
162
|
+
label: string;
|
|
163
|
+
onClick: (ctx: CellContextMenuItemContext) => void;
|
|
164
|
+
disabled?: boolean;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Cell decorator extension point (see JHGridOptions.cellDecorator)
|
|
168
|
+
|
|
169
|
+
export interface CellDecoratorArgs extends CellRendererArgs {
|
|
170
|
+
field: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export declare const CellRenderers: {
|
|
174
|
+
progressBar(opts?: { max?: number; showLabel?: boolean }): CellRendererFn;
|
|
175
|
+
badge(opts?: { colorMap?: Record<string, { bg?: string; fg?: string }> }): CellRendererFn;
|
|
176
|
+
checkmark(opts?: { trueColor?: string; falseColor?: string; showFalse?: boolean }): CellRendererFn;
|
|
177
|
+
/**
|
|
178
|
+
* Renders `value` (an image URL or `data:` URI) scaled to fill the cell, via a shared,
|
|
179
|
+
* byte-budgeted LRU cache that decodes through `fetch()` + `createImageBitmap()` resized to
|
|
180
|
+
* the cell's on-screen size — a large source image shown as a small thumbnail only ever costs
|
|
181
|
+
* a small decoded bitmap, not a full-resolution one. Non-blocking: shows a placeholder while
|
|
182
|
+
* loading and redraws itself automatically once the image resolves. `fit: 'cover'` (default)
|
|
183
|
+
* crops to fill like CSS `object-fit: cover`; `'contain'` letterboxes to show the whole image.
|
|
184
|
+
*/
|
|
185
|
+
image(opts?: { fit?: 'cover' | 'contain'; radius?: number }): CellRendererFn;
|
|
186
|
+
number(opts?: { locale?: string; decimals?: number }): CellRendererFn;
|
|
187
|
+
/**
|
|
188
|
+
* `format` accepts a `YYYY`/`MM`/`DD`/`HH`/`mm`/`ss` pattern (locale-agnostic), or the
|
|
189
|
+
* special value `'locale'` to format via `Intl.DateTimeFormat` using `locale` (or the
|
|
190
|
+
* grid's {@link JHGridOptions.locale} when omitted).
|
|
191
|
+
*/
|
|
192
|
+
date(opts?: { format?: string; locale?: string; dateStyle?: 'full' | 'long' | 'medium' | 'short'; align?: 'left' | 'center' | 'right' }): CellRendererFn;
|
|
193
|
+
currency(opts?: { locale?: string; currency?: string }): CellRendererFn;
|
|
194
|
+
/** 드롭다운 셀 렌더러: 현재 값 + ▾ 화살표 표시 */
|
|
195
|
+
dropdown(opts?: { placeholder?: string }): CellRendererFn;
|
|
196
|
+
/** 다중선택 셀 렌더러: 선택된 값 목록 + ▾ 화살표 표시 */
|
|
197
|
+
multiselect(opts?: { placeholder?: string }): CellRendererFn;
|
|
198
|
+
/** 체크박스 셀 렌더러: 체크/미체크 박스 표시 */
|
|
199
|
+
checkbox(opts?: { checkedColor?: string; size?: number }): CellRendererFn;
|
|
200
|
+
/** 버튼 셀 렌더러: 셀 전체를 하나의 클릭 가능한 버튼으로 표시 */
|
|
201
|
+
button(opts?: {
|
|
202
|
+
label?: string | ((rowData: Record<string, unknown> | null, rowIndex: number) => string | null);
|
|
203
|
+
disabled?: boolean | ((rowData: Record<string, unknown> | null, rowIndex: number) => boolean);
|
|
204
|
+
variant?: ButtonVariant | ((rowData: Record<string, unknown> | null, rowIndex: number) => ButtonVariant);
|
|
205
|
+
}): CellRendererFn;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/** Registers (or overrides) a `CellRenderers` entry. */
|
|
209
|
+
export declare function registerCellRenderer(name: string, factory: (...args: any[]) => CellRendererFn): void;
|
|
210
|
+
|
|
211
|
+
/** Alias exported from Renderer */
|
|
212
|
+
export { CellRenderers as BuiltinRenderers };
|
|
213
|
+
|
|
214
|
+
// Cell Editors
|
|
215
|
+
|
|
216
|
+
export declare const CellEditors: Record<string, (...args: any[]) => unknown>;
|
|
217
|
+
|
|
218
|
+
/** Registers (or overrides) a `CellEditors` entry — the editor counterpart of `registerCellRenderer`. */
|
|
219
|
+
export declare function registerCellEditor(name: string, factory: (...args: any[]) => unknown): void;
|
|
220
|
+
|
|
221
|
+
// Column Definition
|
|
222
|
+
|
|
223
|
+
/** 드롭다운 옵션 항목 — 문자열 또는 { value, label } 객체 */
|
|
224
|
+
export type DropdownOption = string | { value: string; label?: string };
|
|
225
|
+
|
|
226
|
+
export interface ColumnDef {
|
|
227
|
+
field: string;
|
|
228
|
+
label?: string;
|
|
229
|
+
align?: 'left' | 'center' | 'right';
|
|
230
|
+
headerAlign?: 'left' | 'center' | 'right';
|
|
231
|
+
/**
|
|
232
|
+
* Group-header path, outermost → innermost: a single label (`'개인정보'`, one level) or an
|
|
233
|
+
* array (`['역량평가', '정량평가']`, N levels). Consecutive columns sharing the same label at a
|
|
234
|
+
* given depth render under one merged header cell (see {@link HeaderRowDef}), without having to
|
|
235
|
+
* hand-write `opts.headerRows`. Ignored when `opts.headerRows` is set explicitly (needed for
|
|
236
|
+
* non-contiguous groups).
|
|
237
|
+
*/
|
|
238
|
+
group?: string | string[];
|
|
239
|
+
width?: number;
|
|
240
|
+
/** Built-in renderer name (e.g. 'progressBar') or a custom renderer function */
|
|
241
|
+
renderer?: string | CellRendererFn;
|
|
242
|
+
/** 컬럼 편집 타입. 'dropdown' / 'multiselect' / 'checkbox' / 'button' / 'date' / 'image' 지정 시 렌더러도 자동 적용 */
|
|
243
|
+
type?: 'text' | 'dropdown' | 'multiselect' | 'checkbox' | 'button' | 'date' | 'image';
|
|
244
|
+
/** Date format for type: 'date' columns (e.g. 'YYYY-MM-DD', 'YY/MM/DD'). Applied to both rendering and clipboard copy. Default: 'YYYY-MM-DD'. */
|
|
245
|
+
format?: string;
|
|
246
|
+
/** Custom editor: a CellEditors key (e.g. 'date') or a direct editor function receiving the editor context */
|
|
247
|
+
editor?: string | ((ctx: Record<string, unknown>) => { value: string; remove: () => void } | null | undefined);
|
|
248
|
+
/** Options forwarded to the named CellEditors factory when editor is a string key */
|
|
249
|
+
editorOptions?: Record<string, unknown>;
|
|
250
|
+
/**
|
|
251
|
+
* 드롭다운 옵션 목록. type이 'dropdown'일 때 사용.
|
|
252
|
+
* - 문자열 배열: ['선택1', '선택2']
|
|
253
|
+
* - 객체 배열: [{ value: 'A', label: '선택 A' }]
|
|
254
|
+
* - 함수: (rowData) => DropdownOption[] (행 데이터 기반 동적 옵션)
|
|
255
|
+
*/
|
|
256
|
+
options?: DropdownOption[] | ((rowData: Record<string, unknown>) => DropdownOption[]);
|
|
257
|
+
editable?: boolean;
|
|
258
|
+
/** Declarative validation rules, checked on every commit to this column's cells. */
|
|
259
|
+
validation?: ColumnValidation;
|
|
260
|
+
/** 버튼 설정. type이 'button'일 때 사용. */
|
|
261
|
+
button?: ButtonColumnDef;
|
|
262
|
+
/**
|
|
263
|
+
* 그룹헤더 행/푸터에 표시할 집계 함수. 내장 타입(`sum`/`avg`/`min`/`max`)은 `Number(row[field])`로
|
|
264
|
+
* 캐스팅해 계산하며 `NaN`은 무시한다. `count`는 non-null 값 개수. 커스텀 `fn`은 그룹(또는 전체)에
|
|
265
|
+
* 속한 원본 row 배열을 받아 값을 계산하고, `format`으로 표시 문자열을 지정할 수 있다.
|
|
266
|
+
*
|
|
267
|
+
* 행 그룹핑을 제공하는 플러그인(`setGrouping`)이 설치되어 있을 때만 의미가 있다. 플러그인 없이
|
|
268
|
+
* 지정하면 값은 보관되지만 아무 곳에도 표시되지 않는다 — 집계를 읽고 그리는 쪽이 플러그인이다.
|
|
269
|
+
*/
|
|
270
|
+
aggregate?: 'sum' | 'avg' | 'count' | 'min' | 'max' | {
|
|
271
|
+
fn: (rows: Record<string, unknown>[], field: string) => number | string;
|
|
272
|
+
format?: (value: number | string) => string;
|
|
273
|
+
};
|
|
274
|
+
/** When true, renders a clickable checkbox in this column's last header row. Fires `onHeaderCheckboxChange` on click. */
|
|
275
|
+
headerCheckbox?: boolean;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export type ButtonVariant = 'primary' | 'success' | 'danger' | 'neutral';
|
|
279
|
+
|
|
280
|
+
export interface ButtonColumnDef {
|
|
281
|
+
/**
|
|
282
|
+
* 버튼 라벨. 고정 문자열 또는 (rowData, rowIndex) => string|null 함수.
|
|
283
|
+
* 함수가 null/''을 반환하면 해당 행에는 버튼을 그리지 않는다 (조건부 숨김).
|
|
284
|
+
*/
|
|
285
|
+
label?: string | ((rowData: Record<string, unknown> | null, rowIndex: number) => string | null);
|
|
286
|
+
/** 버튼 클릭(또는 셀 선택 후 Space/Enter/F2) 시 호출된다. editableCols 여부와 무관하게 동작한다. */
|
|
287
|
+
onClick: (rowIndex: number, rowData: Record<string, unknown> | null, field: string) => void;
|
|
288
|
+
/** 고정 또는 행별 비활성화 여부. true인 동안은 onClick이 호출되지 않는다. */
|
|
289
|
+
disabled?: boolean | ((rowData: Record<string, unknown> | null, rowIndex: number) => boolean);
|
|
290
|
+
/** 버튼 색상. 고정값 또는 (rowData, rowIndex) => ButtonVariant 함수. 기본값 'primary'. */
|
|
291
|
+
variant?: ButtonVariant | ((rowData: Record<string, unknown> | null, rowIndex: number) => ButtonVariant);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface ColumnValidation {
|
|
295
|
+
/** Value must be non-empty (after trimming) to pass. */
|
|
296
|
+
required?: boolean;
|
|
297
|
+
/** Value must match this pattern (ignored when empty and not required). */
|
|
298
|
+
pattern?: RegExp | string;
|
|
299
|
+
/** Numeric minimum (value is coerced with Number()). */
|
|
300
|
+
min?: number;
|
|
301
|
+
/** Numeric maximum (value is coerced with Number()). */
|
|
302
|
+
max?: number;
|
|
303
|
+
/** Minimum string length. */
|
|
304
|
+
minLength?: number;
|
|
305
|
+
/** Maximum string length. */
|
|
306
|
+
maxLength?: number;
|
|
307
|
+
/**
|
|
308
|
+
* Custom check, run after all built-in rules pass. Return `true` (valid),
|
|
309
|
+
* `false` (invalid — uses `message` or the default i18n message), or a
|
|
310
|
+
* string (invalid — used verbatim as the error message).
|
|
311
|
+
*/
|
|
312
|
+
validator?: (value: string, rowData: Record<string, unknown>) => boolean | string;
|
|
313
|
+
/** Overrides the default i18n message for every built-in rule above. */
|
|
314
|
+
message?: string;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Header Group
|
|
318
|
+
|
|
319
|
+
export interface HeaderRowDef {
|
|
320
|
+
label?: string;
|
|
321
|
+
/** Field names this group spans — updates automatically after column reorder */
|
|
322
|
+
fields?: string[];
|
|
323
|
+
colspan?: number;
|
|
324
|
+
rowspan?: number;
|
|
325
|
+
align?: 'left' | 'center' | 'right';
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Computes grouped-header cell layout from `opts.headerRows` + the current column order — the
|
|
330
|
+
* same layout engine the canvas header draw uses internally, exposed publicly so a custom
|
|
331
|
+
* exporter/renderer can reproduce the same merged-header shape. Returns the same cell shape as
|
|
332
|
+
* {@link ExcelHeaderCell} (declared further below, alongside `ExcelExportSchema`).
|
|
333
|
+
*/
|
|
334
|
+
export declare function computeHeaderCells(headerRows: HeaderRowDef[][] | undefined, columns: string[]): ExcelHeaderCell[];
|
|
335
|
+
|
|
336
|
+
// Data Source
|
|
337
|
+
|
|
338
|
+
export interface GridMeta {
|
|
339
|
+
totalRows: number;
|
|
340
|
+
columns: string[];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export interface GridData {
|
|
344
|
+
rows: Record<string, unknown>[];
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export interface GridFilterState {
|
|
348
|
+
sorts: { field: string; dir: 'asc' | 'desc' }[];
|
|
349
|
+
/**
|
|
350
|
+
* Per-column filter values. A plain `string` is a substring-match text filter
|
|
351
|
+
* (setFilter()); a `string[]` is a Set filter's exact-match checkbox selection
|
|
352
|
+
* (setFilterValues()) — interpretation of both is entirely up to fetchData/fetchMeta.
|
|
353
|
+
*/
|
|
354
|
+
filters: Record<string, string | string[]>;
|
|
355
|
+
/** Global quick filter term (setQuickFilter()), '' when inactive. Interpretation (which
|
|
356
|
+
* columns it searches, substring vs exact) is entirely up to fetchData/fetchMeta. */
|
|
357
|
+
quickFilter: string;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Grid State (serializable snapshot)
|
|
361
|
+
|
|
362
|
+
export interface GridState {
|
|
363
|
+
columns: string[];
|
|
364
|
+
columnWidths: Record<string, number>;
|
|
365
|
+
hiddenColumns: string[];
|
|
366
|
+
frozenCols: number;
|
|
367
|
+
frozenColsRight: number;
|
|
368
|
+
sorts: { field: string; dir: 'asc' | 'desc' }[];
|
|
369
|
+
/** See {@link GridFilterState.filters} — string (text filter) or string[] (Set filter) per field. */
|
|
370
|
+
filters: Record<string, string | string[]>;
|
|
371
|
+
/** See {@link GridFilterState.quickFilter}. */
|
|
372
|
+
quickFilter: string;
|
|
373
|
+
/**
|
|
374
|
+
* Row-grouping state, or `null` when the grid isn't grouped. Always present in the snapshot
|
|
375
|
+
* shape (even as `null`), so a `getState()`/`setState()` round-trip never drops this key.
|
|
376
|
+
* Single-field grouping keeps the legacy shape; multi-field grouping's `collapsedKeys` are
|
|
377
|
+
* path arrays.
|
|
378
|
+
*/
|
|
379
|
+
grouping: { field: string; collapsedKeys: string[] } | { fields: string[]; collapsedKeys: string[][] } | null;
|
|
380
|
+
/** Tree/hierarchical row state, or `null` when unused. Same always-present shape as {@link GridState.grouping}. */
|
|
381
|
+
treeData: { idField: string; parentField: string; collapsedKeys: string[][] } | null;
|
|
382
|
+
/**
|
|
383
|
+
* Active color filters, field → color (e.g. `{ COL_4: 'rgba(22,163,74,0.14)' }`), or `null`
|
|
384
|
+
* when none are set. Same always-present shape as {@link GridState.grouping}.
|
|
385
|
+
*/
|
|
386
|
+
colorFilters: Record<string, string> | null;
|
|
387
|
+
/** Selected row indices (rowSelection mode 'single'|'multi'). Always present (as `[]` when nothing is selected) — row selection is installed unconditionally, even on a base `@jhgrid/jhgrid` import. */
|
|
388
|
+
selectedRows: number[];
|
|
389
|
+
/** `field -> checked` for every `headerCheckbox` column's header checkbox (see `setHeaderCheckbox`/`getHeaderCheckbox`). */
|
|
390
|
+
headerCheckboxState: Record<string, boolean>;
|
|
391
|
+
/**
|
|
392
|
+
* Definitions of columns added via `addColumn()` that haven't been committed yet (see
|
|
393
|
+
* `getNewColumns()`/`commitColumns()`) — restored via `_addColumnImpl` before column order, so a
|
|
394
|
+
* `setState()` round-trip doesn't silently drop a locally-added column. Function-valued def
|
|
395
|
+
* fields (a custom `renderer`/`editor`, function-form `options`, a `validation.validator`, a
|
|
396
|
+
* `button.onClick`) survive an in-memory round-trip but won't survive `JSON.stringify`/`parse` —
|
|
397
|
+
* same inherent limitation as any function-valued columnDefs entry.
|
|
398
|
+
*/
|
|
399
|
+
localColumns: (Omit<ColumnDef, 'field'> & { field: string })[];
|
|
400
|
+
/** Field names of server columns marked for deletion via `deleteColumn()` but not yet committed (see `getDeletedColumns()`/`commitColumns()`). */
|
|
401
|
+
deletedColumns: string[];
|
|
402
|
+
/**
|
|
403
|
+
* Unsaved row work — the row counterpart of {@link GridState.localColumns} /
|
|
404
|
+
* {@link GridState.deletedColumns}, which have always been carried here.
|
|
405
|
+
*
|
|
406
|
+
* Everything is named by **server index**, never by screen position: a screen position only
|
|
407
|
+
* means something alongside the exact arrangement that produced it, and the point of a snapshot
|
|
408
|
+
* is to outlive that. `restoring` therefore assumes the same result set — the same query, the
|
|
409
|
+
* same underlying rows. Restore against changed server data and the indices name different
|
|
410
|
+
* records, the same way {@link GridState.filters} assumes the fields still exist.
|
|
411
|
+
*
|
|
412
|
+
* `setState` treats it as a replacement, not an addition: restoring twice does not duplicate.
|
|
413
|
+
* A snapshot taken before this field existed leaves the grid's current row work alone.
|
|
414
|
+
*/
|
|
415
|
+
rowChanges: {
|
|
416
|
+
/**
|
|
417
|
+
* Rows from `addRow()`. `anchor` is the server index the row sits in front of (equal to the
|
|
418
|
+
* row count when it was appended at the end). Each row carries its own cell edits, because
|
|
419
|
+
* keyed separately they would be two lists that have to agree about ordering.
|
|
420
|
+
*/
|
|
421
|
+
added: { anchor: number; data: Record<string, unknown>; edits: Record<string, string> }[];
|
|
422
|
+
/** Server indices removed from the screen — see {@link JHGrid.getRemovedRows}. */
|
|
423
|
+
removed: number[];
|
|
424
|
+
/** Server indices marked for deletion — see {@link JHGrid.getDeletedRows}. */
|
|
425
|
+
marked: number[];
|
|
426
|
+
/** Unsaved cell edits on server rows, as `serverIndex -> field -> value`. */
|
|
427
|
+
edits: Record<number, Record<string, string>>;
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// i18n
|
|
432
|
+
|
|
433
|
+
export interface GridI18n {
|
|
434
|
+
loading?: string;
|
|
435
|
+
loadError?: string;
|
|
436
|
+
/** Shown when a paste (`Ctrl+V`) drops some values because they fell outside the pasted range. */
|
|
437
|
+
pasteTruncated?: (n: number) => string;
|
|
438
|
+
/** Shown when a copy (`Ctrl+C`) omits some rows because they hadn't loaded yet. */
|
|
439
|
+
copyIncomplete?: (n: number) => string;
|
|
440
|
+
noData?: string;
|
|
441
|
+
emptyCell?: string;
|
|
442
|
+
ariaGrid?: string;
|
|
443
|
+
sortAsc?: string;
|
|
444
|
+
sortDesc?: string;
|
|
445
|
+
sortShiftHint?: string;
|
|
446
|
+
rowNumberLabel?: string;
|
|
447
|
+
filterLabel?: string;
|
|
448
|
+
filterPlaceholder?: string;
|
|
449
|
+
filterApply?: string;
|
|
450
|
+
filterReset?: string;
|
|
451
|
+
filterResetAll?: string;
|
|
452
|
+
filterClose?: string;
|
|
453
|
+
filterDialog?: (col: string) => string;
|
|
454
|
+
filterColorLabel?: string;
|
|
455
|
+
filterValuesLabel?: string;
|
|
456
|
+
filterSelectAll?: string;
|
|
457
|
+
/** Placeholder for the tag filter's search box (see {@link JHGridOptions.fetchFilterValues}). */
|
|
458
|
+
filterTagPlaceholder?: string;
|
|
459
|
+
/** Prefixes the tag filter's suggestion list when it was scanned from loaded rows rather than {@link JHGridOptions.fetchFilterValues}. */
|
|
460
|
+
filterTagLocalScope?: string;
|
|
461
|
+
/** Shown in the tag filter's suggestion list when nothing matches the typed query. */
|
|
462
|
+
filterTagNoMatch?: string;
|
|
463
|
+
/** Shown below the tag filter's minimum-character threshold (see {@link JHGridOptions.filterValueMinChars}). */
|
|
464
|
+
filterTagMinChars?: (n: number) => string;
|
|
465
|
+
/** Shown when every matching value in the tag filter's suggestion list has already been picked. */
|
|
466
|
+
filterTagAllSelected?: string;
|
|
467
|
+
/** Shown when the tag filter's suggestion list is capped and more matches exist than are shown. */
|
|
468
|
+
filterTagMore?: (n: number) => string;
|
|
469
|
+
/** Label above the tag filter's tray of picked values. */
|
|
470
|
+
filterTagSelected?: (n: number) => string;
|
|
471
|
+
/** Label for the tag filter's "contains" substring-match fallback chip/option. */
|
|
472
|
+
filterTagContains?: (q: string) => string;
|
|
473
|
+
/** `aria-label` for a tag filter chip's remove ("×") button. */
|
|
474
|
+
filterTagRemove?: (v: string) => string;
|
|
475
|
+
colFreeze?: string;
|
|
476
|
+
colUnfreeze?: string;
|
|
477
|
+
colFreezeRight?: string;
|
|
478
|
+
colUnfreezeRight?: string;
|
|
479
|
+
colVisibility?: string;
|
|
480
|
+
colChooserTitle?: string;
|
|
481
|
+
colChooserApply?: string;
|
|
482
|
+
colChooserCancel?: string;
|
|
483
|
+
colChooserSelectAll?: string;
|
|
484
|
+
/** Column header context menu: insert a new column to the left. */
|
|
485
|
+
colInsertLeft?: string;
|
|
486
|
+
/** Column header context menu: insert a new column to the right. */
|
|
487
|
+
colInsertRight?: string;
|
|
488
|
+
/** Title of the dialog opened by {@link colInsertLeft}/{@link colInsertRight}. */
|
|
489
|
+
colInsertTitle?: string;
|
|
490
|
+
/** Placeholder of the new-column-name input in that dialog. */
|
|
491
|
+
colInsertPlaceholder?: string;
|
|
492
|
+
/** Confirm button label in that dialog. */
|
|
493
|
+
colInsertConfirm?: string;
|
|
494
|
+
/** Cancel button label in that dialog. */
|
|
495
|
+
colInsertCancel?: string;
|
|
496
|
+
/** Column header context menu: mark this column for deletion (see {@link JHGrid.deleteColumn}). */
|
|
497
|
+
colDelete?: string;
|
|
498
|
+
/** Column header context menu: clear a pending deletion mark (see {@link JHGrid.undeleteColumn}). */
|
|
499
|
+
colUndelete?: string;
|
|
500
|
+
/** Row context menu: insert a blank row at the very top of the dataset. */
|
|
501
|
+
rowInsertTop?: string;
|
|
502
|
+
/** Row context menu: insert a blank row at the very bottom of the dataset. */
|
|
503
|
+
rowInsertBottom?: string;
|
|
504
|
+
/** Row context menu: insert a blank row directly above this one. */
|
|
505
|
+
rowInsertAbove?: string;
|
|
506
|
+
/** Row context menu: insert a blank row directly below this one. */
|
|
507
|
+
rowInsertBelow?: string;
|
|
508
|
+
/** Label for the "add row" control (e.g. a toolbar button a host wires up itself). */
|
|
509
|
+
rowAddEnd?: string;
|
|
510
|
+
/** Row context menu label for deleting a locally-added (unsaved) row — always removed outright. */
|
|
511
|
+
rowDelete?: string;
|
|
512
|
+
/** Row context menu label for marking a server row deleted (`deleteRow(i, { permanent: false })`). */
|
|
513
|
+
rowDeleteMark?: string;
|
|
514
|
+
/** Row context menu label for permanently removing a server row (`deleteRow(i, { permanent: true })`). */
|
|
515
|
+
rowDeletePermanent?: string;
|
|
516
|
+
/** Row context menu: clear a deletion mark, or restore a permanently-removed row. */
|
|
517
|
+
rowUndelete?: string;
|
|
518
|
+
editAriaLabel?: (col: string, row: number) => string;
|
|
519
|
+
announceCell?: (row: number, col: string, value: string) => string;
|
|
520
|
+
/** Screen-reader announcement when a column header receives keyboard focus. */
|
|
521
|
+
columnHeaderAnnounce?: (col: string) => string;
|
|
522
|
+
/** Screen-reader announcement when a row-number cell receives keyboard focus. */
|
|
523
|
+
rowHeaderAnnounce?: (row: number) => string;
|
|
524
|
+
/** Screen-reader announcement after a row drag-reorder completes (see {@link JHGridOptions.rowReorder}). */
|
|
525
|
+
rowReorderAnnounce?: (from: number, to: number) => string;
|
|
526
|
+
/** Screen-reader announcement after a sort is applied from the filter/sort panel. */
|
|
527
|
+
sortAppliedAnnounce?: (col: string, dir: 'asc' | 'desc') => string;
|
|
528
|
+
/** Screen-reader announcement after a filter is applied from the filter/sort panel. */
|
|
529
|
+
filterAppliedAnnounce?: (col: string) => string;
|
|
530
|
+
/** Screen-reader announcement after a single column's filter is cleared. */
|
|
531
|
+
filterClearedAnnounce?: (col: string) => string;
|
|
532
|
+
/** Screen-reader announcement after {@link JHGrid.clearFilters} clears every filter and sort. */
|
|
533
|
+
allFiltersClearedAnnounce?: string;
|
|
534
|
+
/** Screen-reader announcement when the row-selection set changes (`n` = newly selected count, `0` = cleared). */
|
|
535
|
+
rowsSelectedAnnounce?: (n: number) => string;
|
|
536
|
+
unsavedEditsWarning?: string;
|
|
537
|
+
exportCsvFilename?: string;
|
|
538
|
+
/** Default filename for an Excel-format export, kept separate from `exportCsvFilename` above since `exportCsv()` always uses that one. */
|
|
539
|
+
exportExcelFilename?: string;
|
|
540
|
+
exportSheetName?: string;
|
|
541
|
+
printButton?: string;
|
|
542
|
+
validationRequired?: (col: string) => string;
|
|
543
|
+
validationPattern?: (col: string) => string;
|
|
544
|
+
validationMin?: (col: string, min: number) => string;
|
|
545
|
+
validationMax?: (col: string, max: number) => string;
|
|
546
|
+
validationMinLength?: (col: string, len: number) => string;
|
|
547
|
+
validationMaxLength?: (col: string, len: number) => string;
|
|
548
|
+
validationInvalid?: (col: string) => string;
|
|
549
|
+
pagerFirst?: string;
|
|
550
|
+
pagerPrev?: string;
|
|
551
|
+
pagerNext?: string;
|
|
552
|
+
pagerLast?: string;
|
|
553
|
+
pagerPageLabel?: (page: number, pageCount: number) => string;
|
|
554
|
+
aggSum?: string;
|
|
555
|
+
aggAvg?: string;
|
|
556
|
+
aggCount?: string;
|
|
557
|
+
aggMin?: string;
|
|
558
|
+
aggMax?: string;
|
|
559
|
+
groupLabel?: (field: string, key: string, count: number) => string;
|
|
560
|
+
groupFooterLabel?: string;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/** Korean locale strings — pass as i18n option for Korean UI */
|
|
564
|
+
export declare const KO_I18N: Required<GridI18n>;
|
|
565
|
+
|
|
566
|
+
/** Japanese locale strings — pass as i18n option for Japanese UI */
|
|
567
|
+
export declare const JA_I18N: Required<GridI18n>;
|
|
568
|
+
|
|
569
|
+
/** Simplified Chinese locale strings — pass as i18n option for Chinese UI */
|
|
570
|
+
export declare const ZH_I18N: Required<GridI18n>;
|
|
571
|
+
|
|
572
|
+
// Pagination
|
|
573
|
+
|
|
574
|
+
export interface PaginationOptions {
|
|
575
|
+
/** Switches from continuous virtual scrolling to classic fixed-size pages. */
|
|
576
|
+
enabled: boolean;
|
|
577
|
+
/**
|
|
578
|
+
* Rows per page. Fixed at construction time (not changeable at runtime).
|
|
579
|
+
* Also becomes the effective `chunkSize` — `chunkSize` is ignored when set.
|
|
580
|
+
* Default: 50.
|
|
581
|
+
*/
|
|
582
|
+
pageSize?: number;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// Constructor Options
|
|
586
|
+
|
|
587
|
+
export interface JHGridOptions {
|
|
588
|
+
container: string | Element;
|
|
589
|
+
/**
|
|
590
|
+
* Exactly one data source is required: `fetchMeta`+`fetchData` (server-paged), `fetchPage`
|
|
591
|
+
* (single-callback server variant), or `data` (in-memory array, see below). Typed as optional
|
|
592
|
+
* here because either alternative also satisfies the grid; the constructor throws at runtime
|
|
593
|
+
* if none of the three is provided.
|
|
594
|
+
*/
|
|
595
|
+
fetchMeta?: (state?: GridFilterState | null) => Promise<GridMeta>;
|
|
596
|
+
fetchData?: (page: number, size: number, state?: GridFilterState | null) => Promise<GridData>;
|
|
597
|
+
/**
|
|
598
|
+
* `fetchMeta`+`fetchData` collapsed into one call, for a backend that returns the page and the
|
|
599
|
+
* total together — a `COUNT(*) OVER()` alongside the paged rows, say. Resolve
|
|
600
|
+
* `{ rows, totalRows }`, plus `columns` unless `columnDefs` names them.
|
|
601
|
+
*
|
|
602
|
+
* `state` is the sort and filter the grid wants applied, exactly as {@link fetchData} receives
|
|
603
|
+
* it: honour it server-side and return `totalRows` for the filtered result, not the table. A
|
|
604
|
+
* callback that ignores the argument still works — it simply never filters or sorts, which is
|
|
605
|
+
* what every `fetchPage` grid did before the argument was passed at all.
|
|
606
|
+
*
|
|
607
|
+
* The grid asks for chunk 0 once at boot even though it needs both the count and the rows from
|
|
608
|
+
* it, so a plain `(page, size) => …` implementation is not called twice for the same page.
|
|
609
|
+
*
|
|
610
|
+
* Only one data source applies; supplying this alongside `fetchMeta`/`fetchData` leaves those
|
|
611
|
+
* two in charge.
|
|
612
|
+
*/
|
|
613
|
+
fetchPage?: (page: number, size: number, state?: GridFilterState | null) => Promise<GridData & { totalRows: number; columns?: string[] }>;
|
|
614
|
+
/**
|
|
615
|
+
* Convenience alternative to `fetchMeta`+`fetchData` for a dataset that already fits in
|
|
616
|
+
* memory (prototyping, small/medium lookup tables, tests). Columns are inferred from
|
|
617
|
+
* `columnDefs` if given, else from the keys of `data[0]`. Filtering/sorting/quick-filter are
|
|
618
|
+
* applied against the array directly with the same semantics a host's own `fetchMeta`/
|
|
619
|
+
* `fetchData` are expected to follow (see {@link GridFilterState}) — there is no indexing, so
|
|
620
|
+
* this re-scans the full array on every state change and isn't a fit for very large datasets.
|
|
621
|
+
* Ignored if `fetchMeta`/`fetchData`/`fetchPage` is also provided.
|
|
622
|
+
*/
|
|
623
|
+
data?: Record<string, unknown>[];
|
|
624
|
+
width?: number;
|
|
625
|
+
height?: number;
|
|
626
|
+
rowHeight?: number;
|
|
627
|
+
colWidth?: number;
|
|
628
|
+
headerHeight?: number;
|
|
629
|
+
/**
|
|
630
|
+
* Fade duration in ms for the row-hover highlight as it appears and disappears. The highlight
|
|
631
|
+
* itself always tracks the pointer instantly; only the entrance/exit eases. `0` makes it
|
|
632
|
+
* instant. Forced to 0 when the user has `prefers-reduced-motion: reduce` set. Default: 110.
|
|
633
|
+
*/
|
|
634
|
+
hoverFadeMs?: number;
|
|
635
|
+
/**
|
|
636
|
+
* Travel time in ms for the selection box when it moves to a new cell or range. Snaps instead
|
|
637
|
+
* of easing during a range/fill drag, when the selection appears or clears, and when a move
|
|
638
|
+
* arrives before the previous one has landed (held arrow keys). `0` disables it. Forced to 0
|
|
639
|
+
* under `prefers-reduced-motion: reduce`. Default: 90.
|
|
640
|
+
*/
|
|
641
|
+
selectionMoveMs?: number;
|
|
642
|
+
/**
|
|
643
|
+
* Glide length in ms for mouse-wheel scrolling. Deltas smaller than one row — a precision
|
|
644
|
+
* trackpad's dense stream, which is already smooth — are applied immediately regardless.
|
|
645
|
+
* `0` applies every wheel delta immediately. Forced to 0 under
|
|
646
|
+
* `prefers-reduced-motion: reduce`. Default: 120.
|
|
647
|
+
*/
|
|
648
|
+
scrollEaseMs?: number;
|
|
649
|
+
/**
|
|
650
|
+
* How long a displaced column takes to travel to its new slot during a column-header drag. The
|
|
651
|
+
* reorder itself happens as the pointer crosses each boundary either way; this only controls
|
|
652
|
+
* whether the columns it displaces slide there or appear there. A reorder arriving before the
|
|
653
|
+
* previous slide has landed snaps it. `0` puts columns straight into place. Forced to 0 under
|
|
654
|
+
* `prefers-reduced-motion: reduce`. Default: 220.
|
|
655
|
+
*/
|
|
656
|
+
columnSlideMs?: number;
|
|
657
|
+
/** When true, header cell labels wrap across multiple lines instead of being clipped with ellipsis. Default: false. */
|
|
658
|
+
wrapHeader?: boolean;
|
|
659
|
+
scrollbarSize?: number;
|
|
660
|
+
chunkSize?: number;
|
|
661
|
+
/** Maximum number of chunks kept in memory (LRU). Default: 50 */
|
|
662
|
+
maxCachedChunks?: number;
|
|
663
|
+
/**
|
|
664
|
+
* Enables classic fixed-size pagination (a built-in pager bar with
|
|
665
|
+
* Prev/Next/page-number controls) instead of continuous virtual scrolling.
|
|
666
|
+
* Row indices everywhere in the public API (getEdits(), onCellChange, setCellValue())
|
|
667
|
+
* stay global/absolute regardless of this option — pagination only changes what's
|
|
668
|
+
* scrollable/visible at once.
|
|
669
|
+
*/
|
|
670
|
+
pagination?: PaginationOptions;
|
|
671
|
+
frozenCols?: number;
|
|
672
|
+
frozenColsRight?: number;
|
|
673
|
+
/**
|
|
674
|
+
* Enables drag-to-reorder rows from the row-number gutter (requires `showRowNumbers: true`
|
|
675
|
+
* to have somewhere to grab). Unlike column reorder, this requires materializing the entire
|
|
676
|
+
* filtered/sorted dataset client-side first (row data, unlike column metadata, isn't
|
|
677
|
+
* normally resident in memory under server-paged virtualization).
|
|
678
|
+
* Runs one full-dataset scan via `fetchData` after every load/reload; dragging is disabled
|
|
679
|
+
* until that scan completes, and while row grouping or tree data is active. Default: false.
|
|
680
|
+
*/
|
|
681
|
+
rowReorder?: boolean;
|
|
682
|
+
editableCols?: string[] | '*';
|
|
683
|
+
/**
|
|
684
|
+
* What {@link JHGrid.deleteRow} does to a **server** row when the call doesn't say.
|
|
685
|
+
*
|
|
686
|
+
* - `'mark'` (default) — the row stays on screen, dimmed with a strikethrough, and is reported
|
|
687
|
+
* by {@link JHGrid.getDeletedRows}. Suits a screen with an explicit save step, where the user
|
|
688
|
+
* should be able to change their mind before committing.
|
|
689
|
+
* - `'permanent'` — the row comes off the screen and is reported by
|
|
690
|
+
* {@link JHGrid.getRemovedRows}. Suits a list that commits as you go.
|
|
691
|
+
*
|
|
692
|
+
* Either way the server is untouched; the grid only records the choice. Rows added with
|
|
693
|
+
* {@link JHGrid.addRow} ignore this — they were never sent anywhere, so there is nothing to
|
|
694
|
+
* mark and they always go immediately.
|
|
695
|
+
*
|
|
696
|
+
* `deleteRow(i, { permanent })` overrides it per call, because one screen can legitimately need
|
|
697
|
+
* both — marking a saved record while discarding a draft, say.
|
|
698
|
+
*/
|
|
699
|
+
deleteMode?: 'mark' | 'permanent';
|
|
700
|
+
/**
|
|
701
|
+
* Narrows which items appear in the right-click row menu (opened from the row-number gutter).
|
|
702
|
+
* `false` turns the menu off entirely; an array keeps only the named items; omitted (default)
|
|
703
|
+
* shows all of them, unchanged from before this option existed.
|
|
704
|
+
*
|
|
705
|
+
* Valid keys: `'row-insert-above'`, `'row-insert-below'`, `'row-insert-top'`,
|
|
706
|
+
* `'row-insert-bottom'`, `'row-delete'`. The four insert placements are each their own key;
|
|
707
|
+
* every delete-related item (mark / permanent / plain delete / undelete) is gated by the single
|
|
708
|
+
* `'row-delete'` key, since which of those actually renders for a given row is row state, not
|
|
709
|
+
* something a host would pick independently.
|
|
710
|
+
*/
|
|
711
|
+
rowContextMenuItems?: false | ('row-insert-above' | 'row-insert-below' | 'row-insert-top' | 'row-insert-bottom' | 'row-delete')[];
|
|
712
|
+
/**
|
|
713
|
+
* Narrows which items appear in the column header's right-click menu. Same shape as
|
|
714
|
+
* {@link JHGridOptions.rowContextMenuItems}: `false` disables the menu, an array keeps only the
|
|
715
|
+
* named items, omitted shows all of them.
|
|
716
|
+
*
|
|
717
|
+
* Valid keys: `'freeze'`, `'freeze-right'`, `'visibility'`, `'insert-left'`, `'insert-right'`,
|
|
718
|
+
* `'delete'`. `'freeze'`/`'freeze-right'` each cover both their freeze and unfreeze label/action
|
|
719
|
+
* for that slot, and `'delete'` covers both delete and undelete, same reasoning as the row menu.
|
|
720
|
+
*/
|
|
721
|
+
colContextMenuItems?: false | ('freeze' | 'freeze-right' | 'visibility' | 'insert-left' | 'insert-right' | 'delete')[];
|
|
722
|
+
/**
|
|
723
|
+
* Narrows which items appear in the plain-cell right-click menu. Same shape as
|
|
724
|
+
* {@link JHGridOptions.rowContextMenuItems}: `false` disables the menu, an array keeps only the
|
|
725
|
+
* named items, omitted shows all of them.
|
|
726
|
+
*
|
|
727
|
+
* Valid keys: `'col-insert-left'`, `'col-insert-right'`, `'col-delete'`, `'row-insert-below'`,
|
|
728
|
+
* `'row-delete'`. Unrelated to {@link JHGridOptions.cellContextMenuExtraItems} below — that adds
|
|
729
|
+
* items instead of filtering these, and always applies regardless of this option.
|
|
730
|
+
*/
|
|
731
|
+
cellContextMenuItems?: false | ('col-insert-left' | 'col-insert-right' | 'col-delete' | 'row-insert-below' | 'row-delete')[];
|
|
732
|
+
/**
|
|
733
|
+
* Adds custom items to the plain-cell right-click menu, after whichever built-in items
|
|
734
|
+
* {@link JHGridOptions.cellContextMenuItems} left in place (if any). Called fresh each time the
|
|
735
|
+
* menu opens for a given cell; return `null`/`undefined`/`[]` to add nothing for that cell.
|
|
736
|
+
*
|
|
737
|
+
* This is the one general-purpose extension point for host- or plugin-supplied context menu
|
|
738
|
+
* actions — the grid renders the label, routes the click to `onClick`, and closes the menu
|
|
739
|
+
* afterwards, same as a built-in item. It has no opinion about what `onClick` does.
|
|
740
|
+
*/
|
|
741
|
+
cellContextMenuExtraItems?: (ctx: CellContextMenuItemContext) => CellContextMenuItem[] | null | undefined;
|
|
742
|
+
columnDefs?: ColumnDef[];
|
|
743
|
+
/** Multi-row header groups. Each element is one group-header row. */
|
|
744
|
+
headerRows?: HeaderRowDef[][];
|
|
745
|
+
/** Show a built-in row-number column on the left. Default: true. */
|
|
746
|
+
showRowNumbers?: boolean;
|
|
747
|
+
/** Width of the row-number column in pixels. Default: 50. */
|
|
748
|
+
rowNumberWidth?: number;
|
|
749
|
+
responsive?: boolean;
|
|
750
|
+
rowSelection?: 'none' | 'single' | 'multi';
|
|
751
|
+
/** Fields to hide on initial render */
|
|
752
|
+
hiddenColumns?: string[];
|
|
753
|
+
theme?: GridTheme;
|
|
754
|
+
/**
|
|
755
|
+
* BCP-47 tag (e.g. `'en'`, `'ko'`, `'ko-KR'`) selecting a built-in UI text pack
|
|
756
|
+
* (see {@link KO_I18N}; unmatched tags fall back to English) and the default
|
|
757
|
+
* locale `CellRenderers.number/date/currency` format with. Default: `'en-US'`.
|
|
758
|
+
* `i18n` (below) is applied on top and always wins per-key.
|
|
759
|
+
*/
|
|
760
|
+
locale?: string;
|
|
761
|
+
i18n?: GridI18n;
|
|
762
|
+
ariaLabel?: string;
|
|
763
|
+
|
|
764
|
+
// Callbacks
|
|
765
|
+
/** oldValue is the pre-edit value: the prior edit if the cell was already dirty, otherwise the row's original data. */
|
|
766
|
+
onCellChange?: (params: { row: number; field: string; newValue: string; oldValue: string }) => void;
|
|
767
|
+
/** Fired when the cell/range selection changes. null = selection cleared. */
|
|
768
|
+
onSelectionChange?: (sel: { type: 'single'; row: number; col: number } | { type: 'range'; r1: number; c1: number; r2: number; c2: number } | null) => void;
|
|
769
|
+
/** Fired after sorts are applied or cleared. Empty array = all sorts cleared. */
|
|
770
|
+
onSort?: (sorts: { field: string; dir: 'asc' | 'desc' }[] | null) => void;
|
|
771
|
+
/** Fired after any filter is applied, reset, or cleared. */
|
|
772
|
+
onFilter?: (filters: Record<string, string | string[]>) => void;
|
|
773
|
+
/**
|
|
774
|
+
* Looks up candidate values for a column's header filter, given whatever the user has typed.
|
|
775
|
+
* Return a bounded list; only what fits the query is useful, and the panel shows it as-is.
|
|
776
|
+
*
|
|
777
|
+
* The tag picker itself is **not** conditional on this — it appears on any column whose values
|
|
778
|
+
* could not be enumerated locally (the ones where the checklist does not appear). What this
|
|
779
|
+
* changes is where the candidates come from. Omit it and they are scanned out of the rows
|
|
780
|
+
* already loaded, and the list is labelled as covering only those; supply it and it answers for
|
|
781
|
+
* the whole column, label included. Worth supplying whenever the grid is paging a table far
|
|
782
|
+
* larger than what is cached, since that is exactly when the local sample is thinnest.
|
|
783
|
+
*
|
|
784
|
+
* Tags are combined with OR and applied as a `string[]`, the same shape the value checklist
|
|
785
|
+
* sends. If the typed text matches nothing the user can still fall back to a substring filter,
|
|
786
|
+
* which arrives as a plain `string`. A column carries one or the other, never both.
|
|
787
|
+
*/
|
|
788
|
+
fetchFilterValues?: (field: string, query: string) => Promise<Array<string | number | null>>;
|
|
789
|
+
/**
|
|
790
|
+
* Characters the tag filter waits for before looking candidates up. Below it the panel says what
|
|
791
|
+
* it is waiting for and still offers the substring fallback, which needs no lookup. One
|
|
792
|
+
* character against a large column is the most expensive query this control can issue and the
|
|
793
|
+
* least selective answer it can get. Applies to the built-in local scan as much as to
|
|
794
|
+
* {@link fetchFilterValues}. Set `1` for the pre-existing behaviour. Default: 2.
|
|
795
|
+
*/
|
|
796
|
+
filterValueMinChars?: number;
|
|
797
|
+
/** Fired after column drag-reorder completes. columns = new visible field order. */
|
|
798
|
+
onColumnReorder?: (columns: string[]) => void;
|
|
799
|
+
/** Fired after a column is resized (mouse-up). */
|
|
800
|
+
onColumnResize?: (field: string, width: number) => void;
|
|
801
|
+
/** Fired after a row's individual height is resized by dragging a boundary in the row-number gutter (mouse-up). */
|
|
802
|
+
onRowHeightResize?: (rowIndex: number, height: number) => void;
|
|
803
|
+
/**
|
|
804
|
+
* Fired after a row drag-reorder completes (requires `rowReorder: true`).
|
|
805
|
+
* `fromIndex`/`toIndex` are absolute row indices at drop time; `rowData` is the moved row's
|
|
806
|
+
* raw data. Row-indexed transient state (edits, selection, undo history) is cleared on
|
|
807
|
+
* reorder the same way it is on a sort/filter change — persist `toIndex` server-side here if
|
|
808
|
+
* the new order needs to survive a refresh.
|
|
809
|
+
*/
|
|
810
|
+
onRowReorder?: (fromIndex: number, toIndex: number, rowData: Record<string, unknown>) => void;
|
|
811
|
+
/** Fired when the row-selection set changes. */
|
|
812
|
+
onRowSelect?: (selectedRows: number[]) => void;
|
|
813
|
+
/** Fired after the current page changes (goToPage/nextPage/prevPage), only when it actually changed. */
|
|
814
|
+
onPageChange?: (page: number, pageCount: number) => void;
|
|
815
|
+
onRender?: () => void;
|
|
816
|
+
/** Fired when a data chunk fails to load. */
|
|
817
|
+
onChunkError?: (err: Error) => void;
|
|
818
|
+
/**
|
|
819
|
+
* Fired whenever a cell's validity changes as a result of an edit (or undo/redo
|
|
820
|
+
* of one). `message` is the validation error, or null when the cell becomes valid.
|
|
821
|
+
*/
|
|
822
|
+
onValidationError?: (row: number, field: string, message: string | null) => void;
|
|
823
|
+
/** Fired when a header checkbox (column with `headerCheckbox: true`) is clicked. */
|
|
824
|
+
onHeaderCheckboxChange?: (field: string, checked: boolean) => void;
|
|
825
|
+
/**
|
|
826
|
+
* Optional callback returning a CSS color string for a row, or null/undefined for default.
|
|
827
|
+
* Called on every render — keep it fast.
|
|
828
|
+
* @example rowHighlighter: (row) => row.status === 'ERROR' ? 'rgba(239,68,68,0.12)' : null
|
|
829
|
+
*/
|
|
830
|
+
rowHighlighter?: (rowData: Record<string, unknown> | null, rowIndex: number) => string | null | undefined;
|
|
831
|
+
/**
|
|
832
|
+
* Optional callback returning a CSS color string for an individual cell's background,
|
|
833
|
+
* or null/undefined for no override. Painted on top of the row background/highlight
|
|
834
|
+
* (rowHighlighter, selection) and beneath cell content/renderers. Called for every
|
|
835
|
+
* visible cell on every render — keep it fast. `rowData` is null for rows not yet
|
|
836
|
+
* loaded from the server, so check for that before reading fields. Exceptions thrown
|
|
837
|
+
* here are caught and logged; they don't interrupt rendering.
|
|
838
|
+
* @example cellBackground: (row, rowIndex, field) => row && field === 'score' && row.score < 60 ? '#fee2e2' : null
|
|
839
|
+
*/
|
|
840
|
+
cellBackground?: (rowData: Record<string, unknown> | null, rowIndex: number, field: string, colIndex: number) => string | null | undefined;
|
|
841
|
+
/**
|
|
842
|
+
* Optional callback that draws on top of a cell after everything else in it (content,
|
|
843
|
+
* gridlines, strikethrough, validation border) — close to the call shape of a
|
|
844
|
+
* `columnDefs[i].renderer` (`(ctx, args) => void`), but invoked for every rendered cell instead
|
|
845
|
+
* of replacing one column's content, and `args` includes `field` since a decorator (unlike a
|
|
846
|
+
* column renderer, already scoped to one column) needs it to tell columns apart. Use it for a
|
|
847
|
+
* small corner mark, icon, or badge that layers on top of whatever the cell already shows.
|
|
848
|
+
* Called for every visible, loaded cell on every render — keep it fast, and do nothing (return
|
|
849
|
+
* without drawing) for cells that need no mark. Exceptions thrown here are caught and logged;
|
|
850
|
+
* they don't interrupt rendering.
|
|
851
|
+
* @example cellDecorator: (ctx, { x, y, w, field, rowIndex }) => { if (hasFlag(rowIndex, field)) { ctx.fillStyle = 'red'; ctx.beginPath(); ctx.moveTo(x + w - 8, y); ctx.lineTo(x + w, y); ctx.lineTo(x + w, y + 8); ctx.fill(); } }
|
|
852
|
+
*/
|
|
853
|
+
cellDecorator?: (ctx: CanvasRenderingContext2D, args: CellDecoratorArgs) => void;
|
|
854
|
+
/**
|
|
855
|
+
* Optional callback returning tooltip text to show while the pointer idles over a cell, or
|
|
856
|
+
* null/undefined for none. Same call shape as `cellBackground`. Shown immediately (no hover
|
|
857
|
+
* delay), and takes priority over the built-in overflow-text tooltip and over anything a plugin
|
|
858
|
+
* supplies via its own `cellTooltip` — a validation error on the cell still wins over this.
|
|
859
|
+
* `rowData` is null for rows not yet loaded from the server.
|
|
860
|
+
* @example cellTooltip: (row, rowIndex, field) => hasNote(rowIndex, field) ? getNote(rowIndex, field) : null
|
|
861
|
+
*/
|
|
862
|
+
cellTooltip?: (rowData: Record<string, unknown> | null, rowIndex: number, field: string, colIndex: number) => string | null | undefined;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// Excel export schema
|
|
866
|
+
|
|
867
|
+
export interface ExcelHeaderCell {
|
|
868
|
+
row: number;
|
|
869
|
+
col: number;
|
|
870
|
+
colspan: number;
|
|
871
|
+
rowspan: number;
|
|
872
|
+
label: string | null;
|
|
873
|
+
align: string | null;
|
|
874
|
+
isLeaf: boolean;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
export interface ExcelExportSchema {
|
|
878
|
+
sheetName: string;
|
|
879
|
+
columns: string[];
|
|
880
|
+
columnLabels: string[];
|
|
881
|
+
headerCells: ExcelHeaderCell[] | undefined;
|
|
882
|
+
includeHeaders: boolean;
|
|
883
|
+
colWidths: number[];
|
|
884
|
+
headerBg: string;
|
|
885
|
+
headerText: string;
|
|
886
|
+
headerBorder: string;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// JHGrid
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* A plugin object passed to {@link JHGrid.use}. Every hook is optional; core calls whichever
|
|
893
|
+
* ones a plugin happens to implement and falls back to plain behavior everywhere else, which
|
|
894
|
+
* is why this is an open shape rather than a fixed list of members.
|
|
895
|
+
*/
|
|
896
|
+
export interface JHGridPlugin {
|
|
897
|
+
/** Called once when the plugin is first installed. */
|
|
898
|
+
install?: (grid: typeof JHGrid) => void;
|
|
899
|
+
[hook: string]: unknown;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
export declare class JHGrid {
|
|
903
|
+
/**
|
|
904
|
+
* Installs a plugin. Installing the same object twice is a no-op. Plugin packages call this
|
|
905
|
+
* on import, so an application normally never has to — import the package and its API appears
|
|
906
|
+
* on the grid instance.
|
|
907
|
+
*/
|
|
908
|
+
static use(plugin: JHGridPlugin): void;
|
|
909
|
+
|
|
910
|
+
constructor(opts: JHGridOptions);
|
|
911
|
+
|
|
912
|
+
// Boot
|
|
913
|
+
/**
|
|
914
|
+
* Resolves once the first `fetchMeta`/`fetchData` boot has settled — either way, including
|
|
915
|
+
* on failure — so that `this._columns` and friends are populated and any structural API will
|
|
916
|
+
* actually run instead of silently no-op'ing while a boot is still in flight.
|
|
917
|
+
*
|
|
918
|
+
* Await it before calling one straight after construction:
|
|
919
|
+
* ```js
|
|
920
|
+
* const grid = new JHGrid({ ... });
|
|
921
|
+
* await grid.ready();
|
|
922
|
+
* grid.hideColumn('email');
|
|
923
|
+
* ```
|
|
924
|
+
* Not needed inside a user-triggered handler (a button's `onclick`, say) — by then the page,
|
|
925
|
+
* and therefore the initial boot, has necessarily finished.
|
|
926
|
+
*/
|
|
927
|
+
ready(): Promise<void>;
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* Schedules a repaint without touching data, scroll, edits, filters, or sort — for when
|
|
931
|
+
* something a `cellBackground`/`rowHighlighter` callback reads changed outside the grid (host
|
|
932
|
+
* state a plugin keeps, say) and the next frame needs to pick it up. Much cheaper than
|
|
933
|
+
* {@link JHGrid.refresh} when nothing about the data itself changed.
|
|
934
|
+
*/
|
|
935
|
+
repaint(): void;
|
|
936
|
+
|
|
937
|
+
// Data reload
|
|
938
|
+
/** Reload all data from scratch (clears edits, filters, column widths, scroll). */
|
|
939
|
+
refresh(): void;
|
|
940
|
+
|
|
941
|
+
// Scroll
|
|
942
|
+
/**
|
|
943
|
+
* Scroll so that rowIndex is at the top of the viewport. When pagination is
|
|
944
|
+
* enabled, switches to the page containing rowIndex first.
|
|
945
|
+
*/
|
|
946
|
+
scrollTo(rowIndex: number): void;
|
|
947
|
+
|
|
948
|
+
// Pagination
|
|
949
|
+
/** Jumps to a 0-based page, clamped to a valid page. No-op if pagination is not enabled. */
|
|
950
|
+
goToPage(page: number): void;
|
|
951
|
+
/** Advances to the next page. No-op at the last page or if pagination is not enabled. */
|
|
952
|
+
nextPage(): void;
|
|
953
|
+
/** Goes back to the previous page. No-op at the first page or if pagination is not enabled. */
|
|
954
|
+
prevPage(): void;
|
|
955
|
+
/** Returns the current 0-based page index, or 0 if pagination is not enabled. */
|
|
956
|
+
getCurrentPage(): number;
|
|
957
|
+
/** Returns the total number of pages, or 1 if pagination is not enabled. */
|
|
958
|
+
getPageCount(): number;
|
|
959
|
+
|
|
960
|
+
// Edit management
|
|
961
|
+
/** Return all unsaved edits: { [rowIndex]: { [fieldName]: value } } */
|
|
962
|
+
getEdits(): Record<number, Record<string, string>>;
|
|
963
|
+
/** Discard all unsaved edits and re-draw. */
|
|
964
|
+
clearEdits(): void;
|
|
965
|
+
/**
|
|
966
|
+
* Programmatically sets a single cell's value through the same edit/validation/
|
|
967
|
+
* undo/onCellChange pipeline as a manual edit (checkbox toggle, paste, fill).
|
|
968
|
+
* Throws if `row`/`field`/`value` are the wrong type, or `field` names an
|
|
969
|
+
* unknown column.
|
|
970
|
+
*/
|
|
971
|
+
setCellValue(row: number, field: string, value: string): void;
|
|
972
|
+
/**
|
|
973
|
+
* Bulk counterpart to setCellValue() — applies every entry through the same
|
|
974
|
+
* pipeline as one edit/undo step and a single redraw, instead of one redraw
|
|
975
|
+
* per cell. Use this for large-scale updates (e.g. a header checkbox toggling
|
|
976
|
+
* every filtered row) where looping setCellValue() would redraw once per row.
|
|
977
|
+
* Throws under the same conditions as setCellValue().
|
|
978
|
+
*/
|
|
979
|
+
setCellValues(entries: Array<{ row: number; field: string; value: string }>): void;
|
|
980
|
+
|
|
981
|
+
// Validation
|
|
982
|
+
/** Returns true if no cell currently fails its column's `validation` rules. */
|
|
983
|
+
isValid(): boolean;
|
|
984
|
+
/** Return all currently invalid cells: { [rowIndex]: { [fieldName]: message } } */
|
|
985
|
+
getInvalidCells(): Record<number, Record<string, string>>;
|
|
986
|
+
/**
|
|
987
|
+
* Re-validates every currently loaded (cached) row plus locally added rows
|
|
988
|
+
* against each column's `validation` rules. Like autoFitColumns()/printGrid(),
|
|
989
|
+
* only rows already loaded into the client cache are checked.
|
|
990
|
+
*/
|
|
991
|
+
validateAll(): Record<number, Record<string, string>>;
|
|
992
|
+
|
|
993
|
+
// Undo / Redo
|
|
994
|
+
/**
|
|
995
|
+
* Undoes the last undoable action: a cell edit (single, paste, fill, or clear),
|
|
996
|
+
* or row/column add/delete/undelete.
|
|
997
|
+
* Also bound to Ctrl/Cmd+Z. No-op if there is nothing to undo.
|
|
998
|
+
*/
|
|
999
|
+
undo(): void;
|
|
1000
|
+
/** Re-applies the last undone action. Also bound to Ctrl/Cmd+Y and Ctrl/Cmd+Shift+Z. No-op if there is nothing to redo. */
|
|
1001
|
+
redo(): void;
|
|
1002
|
+
/** Returns true if undo() would currently have an effect. */
|
|
1003
|
+
canUndo(): boolean;
|
|
1004
|
+
/** Returns true if redo() would currently have an effect. */
|
|
1005
|
+
canRedo(): boolean;
|
|
1006
|
+
|
|
1007
|
+
// Row selection
|
|
1008
|
+
/** Return the list of currently selected row indices (sorted ascending). Requires `rowSelection: 'single' | 'multi'`. */
|
|
1009
|
+
getSelectedRows(): number[];
|
|
1010
|
+
/** Deselect all rows. */
|
|
1011
|
+
clearRowSelection(): void;
|
|
1012
|
+
|
|
1013
|
+
// Filter / sort
|
|
1014
|
+
/** Remove all active filters/sort and reload data. */
|
|
1015
|
+
clearFilters(): void;
|
|
1016
|
+
/** Set a single column filter programmatically and reload. Pass null/'' to remove. */
|
|
1017
|
+
setFilter(field: string, value: string | null): void;
|
|
1018
|
+
/**
|
|
1019
|
+
* Set a Set-filter (exact-match checkbox selection, as opposed to setFilter()'s substring
|
|
1020
|
+
* match) for a single column and reload. Pass null/undefined to remove.
|
|
1021
|
+
*/
|
|
1022
|
+
setFilterValues(field: string, values: string[] | null): void;
|
|
1023
|
+
/** Remove a single column filter (text or Set) and reload. */
|
|
1024
|
+
removeFilter(field: string): void;
|
|
1025
|
+
/**
|
|
1026
|
+
* Set the global quick filter (a single term searched across every column — interpretation
|
|
1027
|
+
* is entirely up to fetchData/fetchMeta, via state.quickFilter) and reload. Pass null/''
|
|
1028
|
+
* to clear. There is no built-in search box; wire this to your own input.
|
|
1029
|
+
*/
|
|
1030
|
+
setQuickFilter(value: string | null): void;
|
|
1031
|
+
/** Current quick filter term ('' when inactive). */
|
|
1032
|
+
getQuickFilter(): string;
|
|
1033
|
+
/** Shorthand for setQuickFilter(''). */
|
|
1034
|
+
clearQuickFilter(): void;
|
|
1035
|
+
/** Replace all active sorts with a single sort key, then reload. */
|
|
1036
|
+
setSort(field: string, dir?: 'asc' | 'desc'): void;
|
|
1037
|
+
/** Remove the sort for a specific field and reload. No-op if not sorted. */
|
|
1038
|
+
removeSort(field: string): void;
|
|
1039
|
+
/** Clear all active sorts and reload. */
|
|
1040
|
+
clearSort(): void;
|
|
1041
|
+
|
|
1042
|
+
// Row data
|
|
1043
|
+
/** Return the current data for a row (with unsaved edits applied), or null if not loaded. */
|
|
1044
|
+
getRowData(rowIndex: number): Record<string, unknown> | null;
|
|
1045
|
+
/**
|
|
1046
|
+
* Returns the row's pre-edit snapshot -- what {@link getRowData} would have returned for this
|
|
1047
|
+
* index before any unsaved cell edits were applied. Stays correct across any
|
|
1048
|
+
* {@link addRow}/{@link deleteRow} calls that happen afterward (including ones from the
|
|
1049
|
+
* built-in row context menu), unlike a snapshot the caller took itself at fetch time. Useful
|
|
1050
|
+
* for a "what changed" diff, or as a stable WHERE-clause anchor on tables with no primary key.
|
|
1051
|
+
*/
|
|
1052
|
+
getOriginalRowData(rowIndex: number): Record<string, unknown> | null;
|
|
1053
|
+
/** True if the row at this index was added via {@link addRow} and has no server-side counterpart yet. */
|
|
1054
|
+
isNewRow(rowIndex: number): boolean;
|
|
1055
|
+
/**
|
|
1056
|
+
* Tells the grid that the row at `rowIndex` has just been persisted with `savedData` as its
|
|
1057
|
+
* confirmed server-side value. Patches the cache in place and drops any pending edit for that
|
|
1058
|
+
* row, so the next edit's {@link getOriginalRowData}/{@link getEdits} picks up from here --
|
|
1059
|
+
* without the full reset (scroll position, filters, sort, selection) {@link refresh} does.
|
|
1060
|
+
* Meant for a host that saves incrementally (e.g. auto-save on commit).
|
|
1061
|
+
*
|
|
1062
|
+
* No-op if {@link isNewRow} is true for this index -- a brand new row has no server slot yet to
|
|
1063
|
+
* patch. Use {@link acknowledgeInsert} once that row's own create request lands instead.
|
|
1064
|
+
*/
|
|
1065
|
+
acknowledgeSave(rowIndex: number, savedData: Record<string, unknown>): void;
|
|
1066
|
+
/**
|
|
1067
|
+
* Tells the grid that the row at `rowIndex` (added via {@link addRow}, anywhere -- a plain
|
|
1068
|
+
* append, an explicit `index`, or the row context menu) has just been created on the server with
|
|
1069
|
+
* `savedData` as its confirmed value. Turns it into an ordinary server row in place -- so the
|
|
1070
|
+
* next edit on it is treated as an update, not another insert -- without {@link refresh}'s full
|
|
1071
|
+
* reset (scroll position, filters, sort, selection).
|
|
1072
|
+
*
|
|
1073
|
+
* Returns `true` if the promotion happened, `false` if `rowIndex` was not a local (still-unsaved)
|
|
1074
|
+
* row -- nothing to promote.
|
|
1075
|
+
*/
|
|
1076
|
+
acknowledgeInsert(rowIndex: number, savedData: Record<string, unknown>): boolean;
|
|
1077
|
+
|
|
1078
|
+
// Column auto-fit
|
|
1079
|
+
/**
|
|
1080
|
+
* Resizes one or more columns to fit their content (header label + cached data).
|
|
1081
|
+
* Columns with a custom renderer are skipped.
|
|
1082
|
+
* Pass no arguments to fit all visible columns.
|
|
1083
|
+
*/
|
|
1084
|
+
autoFitColumns(...fields: string[]): void;
|
|
1085
|
+
|
|
1086
|
+
// Row height
|
|
1087
|
+
/** Changes the default pixel height used by every row without its own override. Throws if height is not a positive finite number. */
|
|
1088
|
+
setRowHeight(height: number): void;
|
|
1089
|
+
/** Sets rowIndex's individual pixel height (Excel-style row resize — same as dragging a row-number gutter boundary). Throws if height is not a positive finite number or rowIndex is out of range. */
|
|
1090
|
+
setRowHeight(rowIndex: number, height: number): void;
|
|
1091
|
+
/** Returns rowIndex's current pixel height (its own override, or the shared default). */
|
|
1092
|
+
getRowHeight(rowIndex: number): number;
|
|
1093
|
+
/** Clears rowIndex's individual height override, if any, back to the shared default. */
|
|
1094
|
+
resetRowHeight(rowIndex: number): void;
|
|
1095
|
+
|
|
1096
|
+
// Column visibility
|
|
1097
|
+
/** Hide a column. Has no effect if already hidden. */
|
|
1098
|
+
hideColumn(field: string): void;
|
|
1099
|
+
/** Show a hidden column, restoring it at its original position. */
|
|
1100
|
+
showColumn(field: string): void;
|
|
1101
|
+
/** Returns true if the column is currently visible. */
|
|
1102
|
+
isColumnVisible(field: string): boolean;
|
|
1103
|
+
/** Returns the list of currently hidden field names. */
|
|
1104
|
+
getHiddenColumns(): string[];
|
|
1105
|
+
|
|
1106
|
+
// Column add / delete (client-side)
|
|
1107
|
+
/**
|
|
1108
|
+
* Adds a new column (client-side only). Returns false if the field already exists
|
|
1109
|
+
* (visible, hidden, or deleted). Pass `index` to insert at a specific visual
|
|
1110
|
+
* position; defaults to the end. If both immediate neighbors of the insertion
|
|
1111
|
+
* point belong to the same opts.headerRows group, the new column is folded into
|
|
1112
|
+
* that group too.
|
|
1113
|
+
*/
|
|
1114
|
+
addColumn(field: string, def?: Omit<ColumnDef, 'field'>, opts?: { index?: number }): boolean;
|
|
1115
|
+
/**
|
|
1116
|
+
* Deletes a column. Local columns (added via addColumn) are removed immediately.
|
|
1117
|
+
* Server columns are hidden from view — call getDeletedColumns() to collect
|
|
1118
|
+
* their field names for server-side processing, or undeleteColumn() to restore.
|
|
1119
|
+
*/
|
|
1120
|
+
deleteColumn(field: string): boolean;
|
|
1121
|
+
/** Removes the deletion mark from a server column, restoring it at its original position. */
|
|
1122
|
+
undeleteColumn(field: string): void;
|
|
1123
|
+
/** Returns shallow copies of the definitions of all locally added columns (via addColumn). */
|
|
1124
|
+
getNewColumns(): (Omit<ColumnDef, 'field'> & { field: string })[];
|
|
1125
|
+
/** Returns the field names of all server columns marked for deletion. */
|
|
1126
|
+
getDeletedColumns(): string[];
|
|
1127
|
+
/**
|
|
1128
|
+
* Call after your own save request has persisted pending column changes to the server — marks
|
|
1129
|
+
* them as no longer pending (getNewColumns() / getDeletedColumns() stop reporting them) without
|
|
1130
|
+
* touching the rendered grid. Pass a field name, an array of field names, or omit to commit every
|
|
1131
|
+
* pending column change at once. Fields with no pending add/delete are silently ignored.
|
|
1132
|
+
*/
|
|
1133
|
+
commitColumns(fields?: string | string[]): void;
|
|
1134
|
+
|
|
1135
|
+
// State serialization
|
|
1136
|
+
/** Serialize current column order, widths, visibility, sort and filters. */
|
|
1137
|
+
getState(): GridState;
|
|
1138
|
+
/**
|
|
1139
|
+
* Restore a previously serialized state. Unknown fields are ignored, so a snapshot from an
|
|
1140
|
+
* older version still applies as far as it goes.
|
|
1141
|
+
*
|
|
1142
|
+
* Resolves once the grid is showing that state. If the snapshot carries `sorts`, `filters` or
|
|
1143
|
+
* `quickFilter`, those only describe what the *server* should return, so the grid asks again and
|
|
1144
|
+
* the promise waits for the answer — otherwise the header would claim a filter over rows that
|
|
1145
|
+
* were never re-fetched. A snapshot that only moves columns around has nothing to ask for and
|
|
1146
|
+
* resolves immediately.
|
|
1147
|
+
*
|
|
1148
|
+
* Awaiting it matters when you read the grid afterwards; the synchronous parts (columns, widths,
|
|
1149
|
+
* visibility) are already applied by the time it returns, so a caller that just restores and
|
|
1150
|
+
* walks away can ignore it.
|
|
1151
|
+
*/
|
|
1152
|
+
setState(state: Partial<GridState>): Promise<void>;
|
|
1153
|
+
|
|
1154
|
+
// Print
|
|
1155
|
+
/** Open a print-ready popup window containing the currently loaded rows. */
|
|
1156
|
+
printGrid(opts?: { title?: string; includeHeaders?: boolean }): void;
|
|
1157
|
+
|
|
1158
|
+
// Export
|
|
1159
|
+
/**
|
|
1160
|
+
* Download data as a CSV file.
|
|
1161
|
+
* By default only loaded (cached) chunks are included — pass `full: true`
|
|
1162
|
+
* to fetch every row matching the current filter/sort state (text filters
|
|
1163
|
+
* via the server, plus any active color filter) and export the complete
|
|
1164
|
+
* filtered dataset.
|
|
1165
|
+
*/
|
|
1166
|
+
exportCsv(opts?: {
|
|
1167
|
+
filename?: string;
|
|
1168
|
+
delimiter?: string;
|
|
1169
|
+
includeHeaders?: boolean;
|
|
1170
|
+
bom?: boolean;
|
|
1171
|
+
/** When true, fetches every row matching the current filter/sort state (including any active color filter) and exports the complete filtered dataset. Default: false. */
|
|
1172
|
+
full?: boolean;
|
|
1173
|
+
}): Promise<void>;
|
|
1174
|
+
|
|
1175
|
+
// Row add / delete (client-side)
|
|
1176
|
+
/**
|
|
1177
|
+
* Adds a new row (client-side only). By default it appends at the bottom; `{ index }` puts it
|
|
1178
|
+
* at that visual position instead — **anywhere**, including between server rows. Returns the
|
|
1179
|
+
* zero-based visual index of the new row.
|
|
1180
|
+
*
|
|
1181
|
+
* The row is anchored to the record it precedes, not to the screen position, so it stays where
|
|
1182
|
+
* you put it as rows above are added or removed. A sort or filter is the one thing that moves
|
|
1183
|
+
* it: the anchor described a place in the old ordering, which the new one replaces, so the row
|
|
1184
|
+
* survives but goes to the end. It is never hidden by a filter — a blank new row matches
|
|
1185
|
+
* almost nothing, and hiding it is indistinguishable from having lost it.
|
|
1186
|
+
*/
|
|
1187
|
+
addRow(rowData?: Record<string, unknown>, opts?: { index?: number }): number;
|
|
1188
|
+
/**
|
|
1189
|
+
* Deletes a row. What that means depends on where the row came from:
|
|
1190
|
+
*
|
|
1191
|
+
* - A local row (added via `addRow`) is always removed outright, whatever `permanent` says.
|
|
1192
|
+
* It was never sent anywhere, so there is nothing to tell a server about and nothing to mark.
|
|
1193
|
+
* - A server row is **marked** by default: dimmed with a strikethrough, still on screen, still
|
|
1194
|
+
* undoable, and reported by {@link getDeletedRows}.
|
|
1195
|
+
* - `{ permanent: true }` takes the server row off the screen instead. Rows below it move up.
|
|
1196
|
+
* It is reported by {@link getRemovedRows} and can still be brought back with
|
|
1197
|
+
* {@link undeleteRow}.
|
|
1198
|
+
*
|
|
1199
|
+
* Neither server case touches the server — the grid only records what you chose. A sort or
|
|
1200
|
+
* filter discards both kinds, since they are recorded against a row numbering the reload
|
|
1201
|
+
* replaces.
|
|
1202
|
+
*/
|
|
1203
|
+
deleteRow(rowIndex: number, opts?: { permanent?: boolean }): void;
|
|
1204
|
+
/**
|
|
1205
|
+
* Undoes a `deleteRow`: clears the mark, or puts back a row removed with
|
|
1206
|
+
* `{ permanent: true }`. A removed row has no screen position while it is gone, so name it by
|
|
1207
|
+
* the server index {@link getRemovedRows} reported. No-op if the row is neither.
|
|
1208
|
+
*/
|
|
1209
|
+
undeleteRow(rowIndex: number): void;
|
|
1210
|
+
/** Returns shallow copies of all locally added rows (via addRow). */
|
|
1211
|
+
getNewRows(): Record<string, unknown>[];
|
|
1212
|
+
/**
|
|
1213
|
+
* Server indices of rows marked for deletion — the ones still on screen with a strikethrough.
|
|
1214
|
+
* Server indices rather than screen positions, so removing some other row cannot change what
|
|
1215
|
+
* this names.
|
|
1216
|
+
*/
|
|
1217
|
+
getDeletedRows(): number[];
|
|
1218
|
+
/**
|
|
1219
|
+
* Server indices of rows removed from the screen via `deleteRow(i, { permanent: true })`.
|
|
1220
|
+
* Kept separate from {@link getDeletedRows} because the two mean different things to whoever
|
|
1221
|
+
* chose them — a mark is still being decided, a removal has been decided — but both still need
|
|
1222
|
+
* deleting server-side.
|
|
1223
|
+
*/
|
|
1224
|
+
getRemovedRows(): number[];
|
|
1225
|
+
|
|
1226
|
+
// Header checkbox
|
|
1227
|
+
/** Programmatically set the checked state of a header checkbox column and redraw. */
|
|
1228
|
+
setHeaderCheckbox(field: string, checked: boolean): void;
|
|
1229
|
+
/** Returns the current checked state of a header checkbox column. */
|
|
1230
|
+
getHeaderCheckbox(field: string): boolean;
|
|
1231
|
+
|
|
1232
|
+
// Lifecycle
|
|
1233
|
+
/** Remove all event listeners and clear the container DOM. */
|
|
1234
|
+
destroy(): void;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// Renderer (advanced use)
|
|
1238
|
+
|
|
1239
|
+
export declare const DEFAULT_THEME: Required<GridTheme>;
|
|
1240
|
+
|
|
1241
|
+
export declare class Renderer {
|
|
1242
|
+
constructor(canvas: HTMLCanvasElement, opts: JHGridOptions & { theme: Required<GridTheme> });
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
// DataManager (advanced use)
|
|
1246
|
+
|
|
1247
|
+
export declare class DataManager {
|
|
1248
|
+
onChunkLoaded: (() => void) | null;
|
|
1249
|
+
constructor(opts: {
|
|
1250
|
+
fetchData: JHGridOptions['fetchData'];
|
|
1251
|
+
chunkSize?: number;
|
|
1252
|
+
/** LRU limit — evicts oldest chunk when exceeded. Default: 50 */
|
|
1253
|
+
maxChunks?: number;
|
|
1254
|
+
});
|
|
1255
|
+
getRow(rowIndex: number): Record<string, unknown> | null;
|
|
1256
|
+
prefetch(startRow: number, endRow: number): void;
|
|
1257
|
+
setFetch(fn: JHGridOptions['fetchData']): void;
|
|
1258
|
+
forEachLoaded(callback: (row: Record<string, unknown>, rowIndex: number) => void): void;
|
|
1259
|
+
clear(): void;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// Misc
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* Class names applied to the grid's DOM surfaces (the canvas-painted body is styled through
|
|
1266
|
+
* {@link GridTheme} instead). Exposed so consumer code can target a surface without hardcoding
|
|
1267
|
+
* the strings — see "Styling with your own CSS" in the README for the full table and the
|
|
1268
|
+
* matching `--jhg-*` custom properties.
|
|
1269
|
+
*/
|
|
1270
|
+
export declare const GRID_CLASSES: {
|
|
1271
|
+
root: string;
|
|
1272
|
+
loading: string;
|
|
1273
|
+
empty: string;
|
|
1274
|
+
tooltip: string;
|
|
1275
|
+
overlay: string;
|
|
1276
|
+
panel: string;
|
|
1277
|
+
dialog: string;
|
|
1278
|
+
menu: string;
|
|
1279
|
+
menuItem: string;
|
|
1280
|
+
btn: string;
|
|
1281
|
+
swatch: string;
|
|
1282
|
+
pager: string;
|
|
1283
|
+
pagerBtn: string;
|
|
1284
|
+
editor: string;
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1287
|
+
export declare const VERSION: string;
|
|
1288
|
+
|
|
1289
|
+
export declare const SUPPORTED_BROWSERS: {
|
|
1290
|
+
chrome: number;
|
|
1291
|
+
edge: number;
|
|
1292
|
+
firefox: number;
|
|
1293
|
+
safari: number;
|
|
1294
|
+
};
|