infi-grid 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +141 -0
- package/README.md +654 -0
- package/fesm2022/infi-grid.mjs +10314 -0
- package/fesm2022/infi-grid.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/cell-editor.component.d.ts +42 -0
- package/lib/components/filter-popup.component.d.ts +89 -0
- package/lib/components/filter-row.component.d.ts +104 -0
- package/lib/components/grid.component.d.ts +155 -0
- package/lib/components/header-row.component.d.ts +76 -0
- package/lib/components/row.component.d.ts +106 -0
- package/lib/components/summary-row.component.d.ts +40 -0
- package/lib/components/tooltip-controller.d.ts +43 -0
- package/lib/components/viewport.component.d.ts +217 -0
- package/lib/core/accessor.d.ts +6 -0
- package/lib/core/config-resolver.d.ts +16 -0
- package/lib/core/defaults.d.ts +7 -0
- package/lib/core/filter-engine.d.ts +44 -0
- package/lib/core/format.d.ts +11 -0
- package/lib/core/keys.d.ts +24 -0
- package/lib/core/row-ops.d.ts +20 -0
- package/lib/core/sort-engine.d.ts +11 -0
- package/lib/core/summary-engine.d.ts +35 -0
- package/lib/core/template-registry.d.ts +27 -0
- package/lib/core/theme.d.ts +2 -0
- package/lib/core/tooltip-position.d.ts +24 -0
- package/lib/core/values.d.ts +21 -0
- package/lib/core/virtual-math.d.ts +57 -0
- package/lib/directives/grid-template-component.d.ts +16 -0
- package/lib/directives/outlet.directive.d.ts +25 -0
- package/lib/directives/template.directives.d.ts +98 -0
- package/lib/grid.module.d.ts +15 -0
- package/lib/models/api.types.d.ts +249 -0
- package/lib/models/column.types.d.ts +184 -0
- package/lib/models/config.types.d.ts +390 -0
- package/lib/models/crud.types.d.ts +179 -0
- package/lib/models/data.types.d.ts +41 -0
- package/lib/models/events.types.d.ts +98 -0
- package/lib/models/filter.types.d.ts +78 -0
- package/lib/models/index.d.ts +12 -0
- package/lib/models/selection.types.d.ts +173 -0
- package/lib/models/sort.types.d.ts +22 -0
- package/lib/models/summary.types.d.ts +78 -0
- package/lib/models/template.types.d.ts +126 -0
- package/lib/models/tooltip.types.d.ts +48 -0
- package/lib/state/filter-popup.service.d.ts +30 -0
- package/lib/state/grid-api.d.ts +4 -0
- package/lib/state/grid-store.d.ts +584 -0
- package/lib/state/tooltip.service.d.ts +38 -0
- package/package.json +41 -0
- package/public-api.d.ts +8 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
import { type OnDestroy, type Signal } from '@angular/core';
|
|
2
|
+
import type { GridApi, GridEditState, VirtualizationState } from '../models/api.types';
|
|
3
|
+
import type { ColumnConfig, ResolvedColumn } from '../models/column.types';
|
|
4
|
+
import type { GridConfig, ResolvedGridConfig } from '../models/config.types';
|
|
5
|
+
import type { GridAddPosition, GridAddRowOptions, GridBeginAddRowOptions, GridChangeSet, GridCrudResult, GridPendingChangeEvent, GridSaveFailedEvent, GridSaveResult, GridRowAddedEvent, GridRowAddingEvent, GridRowDeletedEvent, GridRowDeletingEvent, GridRowUpdatedEvent, GridRowUpdatingEvent } from '../models/crud.types';
|
|
6
|
+
import type { GridCellEvent, GridCellValueChangeEvent, GridRowEvent, GridViewportChangeEvent, GridColumnResizeEvent, GridEditEvent, GridErrorEvent, GridFilterChangeEvent, GridHeaderClickEvent, GridSortChangeEvent } from '../models/events.types';
|
|
7
|
+
import type { ColumnFilterModel, FilterModel } from '../models/filter.types';
|
|
8
|
+
import type { SortDirection, SortModelItem } from '../models/sort.types';
|
|
9
|
+
import type { GridSummaryResult } from '../models/summary.types';
|
|
10
|
+
import type { GridRowKey, GridDataRefreshEvent, GridDataRefreshReason, GridLoadingChangeEvent, GridRefreshOptions, GridRefreshResult } from '../models/data.types';
|
|
11
|
+
import type { GridCellSelectionChangeEvent, GridCellSelectionSource, GridRowSelectionEvent, GridSelectedCell, GridSelectionChangeEvent, GridSelectionClearedEvent, GridSelectionClickEvent, GridSelectionSource } from '../models/selection.types';
|
|
12
|
+
import { type KeyIndex } from '../core/keys';
|
|
13
|
+
import { type TemplateRegistry } from '../core/template-registry';
|
|
14
|
+
import * as i0 from "@angular/core";
|
|
15
|
+
/** One displayed column with its current position. */
|
|
16
|
+
export interface LayoutColumn<TRow = any> {
|
|
17
|
+
readonly key: string;
|
|
18
|
+
readonly col: ResolvedColumn<TRow>;
|
|
19
|
+
/** Position among displayed columns. */
|
|
20
|
+
readonly index: number;
|
|
21
|
+
/** Position among displayed columns that have a display template, or -1 (see the row component). */
|
|
22
|
+
readonly templateIndex: number;
|
|
23
|
+
/** Position among displayed columns that have a header template, or -1. */
|
|
24
|
+
readonly headerTemplateIndex: number;
|
|
25
|
+
/** Position among displayed columns that have a summary template, or -1. */
|
|
26
|
+
readonly summaryTemplateIndex: number;
|
|
27
|
+
readonly left: number;
|
|
28
|
+
readonly width: number;
|
|
29
|
+
}
|
|
30
|
+
export interface ColumnLayout<TRow = any> {
|
|
31
|
+
readonly columns: readonly LayoutColumn<TRow>[];
|
|
32
|
+
readonly offsets: readonly number[];
|
|
33
|
+
/** Width of every column plus the pinned regions. */
|
|
34
|
+
readonly totalWidth: number;
|
|
35
|
+
readonly byField: ReadonlyMap<string, LayoutColumn<TRow>>;
|
|
36
|
+
/** Pinned region at the left (the selection checkboxes); data columns start after it. */
|
|
37
|
+
readonly leadingWidth: number;
|
|
38
|
+
/** Pinned region at the right (the action column). */
|
|
39
|
+
readonly trailingWidth: number;
|
|
40
|
+
/** Added to a column's position for `aria-colindex` (the checkbox column is column 1). */
|
|
41
|
+
readonly ariaColOffset: number;
|
|
42
|
+
}
|
|
43
|
+
/** Mutable edit session (drafts are stored here, not in the DOM, so they survive row recycling). */
|
|
44
|
+
export interface EditSession<TRow = any> {
|
|
45
|
+
row: TRow;
|
|
46
|
+
/** View index of the row (-1 for the inline add row). */
|
|
47
|
+
rowIndex: number;
|
|
48
|
+
mode: 'cell' | 'row';
|
|
49
|
+
fields: string[];
|
|
50
|
+
focusField: string;
|
|
51
|
+
values: Record<string, unknown>;
|
|
52
|
+
original: Record<string, unknown>;
|
|
53
|
+
errors: Record<string, string | null>;
|
|
54
|
+
/** The inline add row: `row` is a draft that isn't in the data yet. */
|
|
55
|
+
isNew: boolean;
|
|
56
|
+
/** Where the add row is shown and the row is added (add row only). */
|
|
57
|
+
position: 'top' | 'bottom';
|
|
58
|
+
}
|
|
59
|
+
/** An open delete confirmation (built-in dialog or `infiGridDeleteConfirm` template). */
|
|
60
|
+
export interface DeleteRequest<TRow = any> {
|
|
61
|
+
readonly rows: readonly TRow[];
|
|
62
|
+
readonly keys: readonly GridRowKey[];
|
|
63
|
+
readonly source: 'ui' | 'api' | 'keyboard';
|
|
64
|
+
confirm(): void;
|
|
65
|
+
cancel(): void;
|
|
66
|
+
}
|
|
67
|
+
/** Implemented by the viewport; lets the API scroll and read what is rendered. */
|
|
68
|
+
export interface ViewportHandle {
|
|
69
|
+
scrollToRow(rowIndex: number, position: 'auto' | 'start' | 'center' | 'end'): void;
|
|
70
|
+
scrollToColumn(columnIndex: number, position: 'auto' | 'start' | 'center' | 'end'): void;
|
|
71
|
+
getVirtualizationState(): VirtualizationState;
|
|
72
|
+
focus(): void;
|
|
73
|
+
/** Moves the focus to a cell (with `cellSelection`, also the selected cell; `source` defaults to `'api'`). */
|
|
74
|
+
focusCell(rowIndex: number, field: string, source?: GridCellSelectionSource): void;
|
|
75
|
+
}
|
|
76
|
+
/** Implemented by the filter popup service. */
|
|
77
|
+
export interface FilterPopupHandle {
|
|
78
|
+
open(field: string, anchor: HTMLElement | null): void;
|
|
79
|
+
close(): void;
|
|
80
|
+
isOpen(): boolean;
|
|
81
|
+
}
|
|
82
|
+
export type GridListenedEvent = 'cellClick' | 'cellDoubleClick' | 'rowClick' | 'rowDoubleClick' | 'viewportChange' | 'selectionClick' | 'headerClick' | 'cellContextMenu' | 'cellMouseEnter' | 'cellMouseLeave' | 'cellSelectionChange';
|
|
83
|
+
/** Callbacks wired to the component outputs. */
|
|
84
|
+
export interface GridEventSink<TRow> {
|
|
85
|
+
/** Whether the host listens to a frequent event (avoids entering the zone for nothing). */
|
|
86
|
+
listens?(name: GridListenedEvent): boolean;
|
|
87
|
+
cellClick?(e: GridCellEvent<TRow>): void;
|
|
88
|
+
cellDoubleClick?(e: GridCellEvent<TRow>): void;
|
|
89
|
+
rowClick?(e: GridRowEvent<TRow>): void;
|
|
90
|
+
rowDoubleClick?(e: GridRowEvent<TRow>): void;
|
|
91
|
+
headerClick?(e: GridHeaderClickEvent<TRow>): void;
|
|
92
|
+
cellContextMenu?(e: GridCellEvent<TRow>): void;
|
|
93
|
+
cellMouseEnter?(e: GridCellEvent<TRow>): void;
|
|
94
|
+
cellMouseLeave?(e: GridCellEvent<TRow>): void;
|
|
95
|
+
viewportChange?(e: GridViewportChangeEvent): void;
|
|
96
|
+
sortChange?(e: GridSortChangeEvent): void;
|
|
97
|
+
filterChange?(e: GridFilterChangeEvent): void;
|
|
98
|
+
cellValueChange?(e: GridCellValueChangeEvent<TRow>): void;
|
|
99
|
+
editStart?(e: GridEditEvent<TRow>): void;
|
|
100
|
+
editCommit?(e: GridEditEvent<TRow>): void;
|
|
101
|
+
editCancel?(e: GridEditEvent<TRow>): void;
|
|
102
|
+
columnResize?(e: GridColumnResizeEvent<TRow>): void;
|
|
103
|
+
gridError?(e: GridErrorEvent): void;
|
|
104
|
+
dataRefresh?(e: GridDataRefreshEvent): void;
|
|
105
|
+
loadingChange?(e: GridLoadingChangeEvent): void;
|
|
106
|
+
selectionChange?(e: GridSelectionChangeEvent<TRow>): void;
|
|
107
|
+
rowSelected?(e: GridRowSelectionEvent<TRow>): void;
|
|
108
|
+
rowDeselected?(e: GridRowSelectionEvent<TRow>): void;
|
|
109
|
+
selectionCleared?(e: GridSelectionClearedEvent<TRow>): void;
|
|
110
|
+
selectionClick?(e: GridSelectionClickEvent<TRow>): void;
|
|
111
|
+
cellSelectionChange?(e: GridCellSelectionChangeEvent<TRow>): void;
|
|
112
|
+
rowAdding?(e: GridRowAddingEvent<TRow>): void;
|
|
113
|
+
rowAdded?(e: GridRowAddedEvent<TRow>): void;
|
|
114
|
+
rowUpdating?(e: GridRowUpdatingEvent<TRow>): void;
|
|
115
|
+
rowUpdated?(e: GridRowUpdatedEvent<TRow>): void;
|
|
116
|
+
rowDeleting?(e: GridRowDeletingEvent<TRow>): void;
|
|
117
|
+
rowDeleted?(e: GridRowDeletedEvent<TRow>): void;
|
|
118
|
+
/** The data array after an add or delete (for `[(data)]`). */
|
|
119
|
+
dataChange?(data: readonly TRow[]): void;
|
|
120
|
+
changesSaved?(e: GridChangeSet<TRow>): void;
|
|
121
|
+
changesCancelled?(e: GridChangeSet<TRow>): void;
|
|
122
|
+
changesSaveFailed?(e: GridSaveFailedEvent<TRow>): void;
|
|
123
|
+
pendingChange?(e: GridPendingChangeEvent): void;
|
|
124
|
+
}
|
|
125
|
+
export interface GridInputs<TRow> {
|
|
126
|
+
data: Signal<readonly TRow[] | null | undefined>;
|
|
127
|
+
columns: Signal<readonly ColumnConfig<TRow>[] | null | undefined>;
|
|
128
|
+
config: Signal<GridConfig<TRow> | null | undefined>;
|
|
129
|
+
loading: Signal<boolean>;
|
|
130
|
+
error: Signal<unknown>;
|
|
131
|
+
registry: Signal<TemplateRegistry>;
|
|
132
|
+
}
|
|
133
|
+
/** A row added in batch mode, not in the data until saved. */
|
|
134
|
+
interface PendingAdd<TRow> {
|
|
135
|
+
readonly row: TRow;
|
|
136
|
+
readonly key: GridRowKey;
|
|
137
|
+
/** Where it goes when saved; `'bottom'` rows are shown last, the others first. */
|
|
138
|
+
readonly position: GridAddPosition;
|
|
139
|
+
}
|
|
140
|
+
/** The rendering state of a row in batch mode. */
|
|
141
|
+
export interface RowChangeState {
|
|
142
|
+
readonly kind: 'added' | 'modified' | 'deleted';
|
|
143
|
+
/** Changed fields (modified rows). */
|
|
144
|
+
readonly fields: ReadonlyMap<string, unknown> | null;
|
|
145
|
+
}
|
|
146
|
+
/** A selection gesture (click, checkbox, key) worked out before it is applied, so `selectionClick` can cancel it. */
|
|
147
|
+
export interface SelectionPlan<TRow> {
|
|
148
|
+
row: TRow;
|
|
149
|
+
key: GridRowKey;
|
|
150
|
+
selecting: boolean;
|
|
151
|
+
apply(): void;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Per-grid state. Configuration, data, sort and filter state are signals; the row pipeline is
|
|
155
|
+
* `data → sort (indexes) → filter (keeps sort order) → view rows`. Changing a filter never re-sorts,
|
|
156
|
+
* and editing a cell never re-sorts or re-filters (call `refresh()` for that).
|
|
157
|
+
*/
|
|
158
|
+
export declare class GridStore<TRow = any> implements OnDestroy {
|
|
159
|
+
readonly api: GridApi<TRow>;
|
|
160
|
+
events: GridEventSink<TRow>;
|
|
161
|
+
viewport: ViewportHandle | null;
|
|
162
|
+
filterPopup: FilterPopupHandle | null;
|
|
163
|
+
/**
|
|
164
|
+
* `virtualization.syncScroll`: where the pinned regions (checkbox and action columns) are placed inside their row,
|
|
165
|
+
* header, filter or summary row (`left` of the start and end regions), or null without syncScroll (they are sticky).
|
|
166
|
+
* A plain object, not a signal: the viewport updates it and the regions already drawn on every sideways scroll frame
|
|
167
|
+
* (without change detection); rows read it when they are drawn.
|
|
168
|
+
*/
|
|
169
|
+
pinPlacement: {
|
|
170
|
+
start: number;
|
|
171
|
+
end: number;
|
|
172
|
+
} | null;
|
|
173
|
+
private inputs;
|
|
174
|
+
private readonly bound;
|
|
175
|
+
private readonly dataState;
|
|
176
|
+
private readonly columnState;
|
|
177
|
+
private readonly loadingState;
|
|
178
|
+
private readonly errorState;
|
|
179
|
+
readonly data: Signal<readonly TRow[]>;
|
|
180
|
+
readonly loading: Signal<boolean>;
|
|
181
|
+
readonly error: Signal<unknown>;
|
|
182
|
+
readonly config: Signal<ResolvedGridConfig<TRow>>;
|
|
183
|
+
private readonly registry;
|
|
184
|
+
readonly columns: Signal<readonly ResolvedColumn<TRow>[]>;
|
|
185
|
+
readonly columnsByField: Signal<Map<string, ResolvedColumn<TRow>>>;
|
|
186
|
+
/** The configured primary key (compared by value, so a new config object doesn't rebuild the index). */
|
|
187
|
+
private readonly primaryKey;
|
|
188
|
+
/** Key of a row: the primary key value, or the row object itself without a primary key. */
|
|
189
|
+
readonly keyOf: Signal<import("../core/keys").KeyAccessor<TRow>>;
|
|
190
|
+
readonly hasPrimaryKey: Signal<boolean>;
|
|
191
|
+
private readonly widthOverrides;
|
|
192
|
+
private readonly visibilityOverrides;
|
|
193
|
+
/** Width of the pinned checkbox column (0 without one). A number, so other config changes keep the layout. */
|
|
194
|
+
private readonly leadingWidth;
|
|
195
|
+
/** Width of the pinned action column (0 without one). */
|
|
196
|
+
private readonly trailingWidth;
|
|
197
|
+
readonly layout: Signal<ColumnLayout<TRow>>;
|
|
198
|
+
/**
|
|
199
|
+
* Height of the filter row (`filtering.mode` `'row'` or `'both'`): `filtering.rowHeight` while a displayed column
|
|
200
|
+
* is filterable, else 0. With filtering off there is no empty row under the header.
|
|
201
|
+
*/
|
|
202
|
+
readonly filterRowHeight: Signal<number>;
|
|
203
|
+
readonly sortModel: import("@angular/core").WritableSignal<readonly SortModelItem[]>;
|
|
204
|
+
readonly filterModel: import("@angular/core").WritableSignal<Readonly<Record<string, ColumnFilterModel>>>;
|
|
205
|
+
/** Bumped by `refresh()` to re-run sorting and filtering on mutated data. */
|
|
206
|
+
private readonly structureVersion;
|
|
207
|
+
/** Key → data position. Lazy: built the first time something needs a key lookup. */
|
|
208
|
+
readonly keyIndex: Signal<KeyIndex>;
|
|
209
|
+
private keyReportFor;
|
|
210
|
+
/** Bumped on every edit; drives summary recalculation and row re-rendering. */
|
|
211
|
+
readonly editVersion: import("@angular/core").WritableSignal<number>;
|
|
212
|
+
/** Bumped when every rendered row must rebuild (refresh, template changes). */
|
|
213
|
+
readonly renderNonce: import("@angular/core").WritableSignal<number>;
|
|
214
|
+
private readonly rowVersions;
|
|
215
|
+
private readonly fieldVersions;
|
|
216
|
+
private summaryForceAll;
|
|
217
|
+
private readonly summaryForce;
|
|
218
|
+
private readonly summaryNonce;
|
|
219
|
+
private readonly summaryEngine;
|
|
220
|
+
/** Data indexes in sorted order, or null for the natural order. */
|
|
221
|
+
readonly sortedIndices: Signal<readonly number[] | null>;
|
|
222
|
+
/** Data indexes of the sorted and filtered data rows, or null when nothing is sorted or filtered. */
|
|
223
|
+
private readonly dataViewIndices;
|
|
224
|
+
/**
|
|
225
|
+
* Data index of every displayed row in display order (-1 for pending adds of batch mode, which are shown
|
|
226
|
+
* first or last), or null when the view is the data itself.
|
|
227
|
+
*/
|
|
228
|
+
readonly viewIndices: Signal<readonly number[] | null>;
|
|
229
|
+
readonly viewRows: Signal<readonly TRow[]>;
|
|
230
|
+
readonly rowCount: Signal<number>;
|
|
231
|
+
readonly dataLength: Signal<number>;
|
|
232
|
+
readonly summaryColumns: Signal<ResolvedColumn<TRow>[]>;
|
|
233
|
+
/** Rows the summaries use: the displayed rows, without the pending deletes of batch mode. */
|
|
234
|
+
private readonly summaryRows;
|
|
235
|
+
/** Rows of `scope: 'all'` summaries: the data with the pending adds and without the pending deletes. */
|
|
236
|
+
private readonly summaryData;
|
|
237
|
+
readonly summaryVisible: Signal<boolean>;
|
|
238
|
+
/** The last summaries, returned again when every result came from the cache (the summary row doesn't re-render). */
|
|
239
|
+
private lastSummaries;
|
|
240
|
+
readonly summaries: Signal<Readonly<Record<string, GridSummaryResult>>>;
|
|
241
|
+
readonly editSession: import("@angular/core").WritableSignal<EditSession<TRow> | null>;
|
|
242
|
+
readonly gridEditMode: import("@angular/core").WritableSignal<boolean>;
|
|
243
|
+
/** Field whose filter popup is open. */
|
|
244
|
+
readonly openFilterField: import("@angular/core").WritableSignal<string | null>;
|
|
245
|
+
/** Wires the component inputs. Called once by the grid component. */
|
|
246
|
+
bind(inputs: GridInputs<TRow>): void;
|
|
247
|
+
/** Applies `initialSort`, `initialFilter` and `gridEditMode` from the configuration. */
|
|
248
|
+
applyInitialState(): void;
|
|
249
|
+
reportError(event: GridErrorEvent): void;
|
|
250
|
+
rowVersion(row: TRow): number;
|
|
251
|
+
private bumpRow;
|
|
252
|
+
private bumpField;
|
|
253
|
+
/**
|
|
254
|
+
* Marks what a changed field affects for summaries: the field, columns above or below it in a dot path
|
|
255
|
+
* (`customer` / `customer.name`), and computed columns (their inputs are unknown).
|
|
256
|
+
*/
|
|
257
|
+
private bumpChangedField;
|
|
258
|
+
/** Replaces the data (the API counterpart of a new `[data]` array). */
|
|
259
|
+
setData(data: readonly TRow[], options?: GridRefreshOptions): GridRefreshResult;
|
|
260
|
+
/** Re-reads the current data after it was changed in place (push, splice, edited objects). */
|
|
261
|
+
refreshData(options?: GridRefreshOptions): GridRefreshResult;
|
|
262
|
+
/**
|
|
263
|
+
* Called by the component when the `[data]` or `[loading]` input changed. Runs during change
|
|
264
|
+
* detection, so the resulting events are emitted right after it (in a microtask).
|
|
265
|
+
*/
|
|
266
|
+
inputsChanged(dataChanged: boolean, dataFirstChange: boolean, loadingChanged: boolean): void;
|
|
267
|
+
/** Applies the refresh policy and reconciles grid state with the new data. */
|
|
268
|
+
afterDataChange(reason: GridDataRefreshReason, options: GridRefreshOptions | undefined, defer: boolean): GridRefreshResult;
|
|
269
|
+
/** Keeps an open edit session on the same row (found again by key), or cancels it if the row is gone. */
|
|
270
|
+
private retargetEdit;
|
|
271
|
+
/**
|
|
272
|
+
* After a data change: drops selected keys whose rows are gone (and, with `onFilter: 'deselectHidden'`, rows the
|
|
273
|
+
* filter now hides), or everything with `reset`. Rows that still exist keep their selection, even as new objects.
|
|
274
|
+
*/
|
|
275
|
+
private reconcileSelection;
|
|
276
|
+
/** The row with this key, if it is in the data (or a pending add of batch mode). */
|
|
277
|
+
rowByKey(key: GridRowKey): TRow | undefined;
|
|
278
|
+
/** View index of the row with this key, or -1 when it isn't displayed. O(1) without sort/filter, else O(n). */
|
|
279
|
+
viewIndexOfKey(key: GridRowKey): number;
|
|
280
|
+
private reportKeyProblems;
|
|
281
|
+
private deferred;
|
|
282
|
+
private held;
|
|
283
|
+
/**
|
|
284
|
+
* Runs `fn` now, or right after the current change detection when the change came from an input.
|
|
285
|
+
* Inside `withHeldEvents()`, synchronous events wait until the operation has updated all state.
|
|
286
|
+
*/
|
|
287
|
+
private emit;
|
|
288
|
+
/** Runs an operation, then emits its events in order, so every handler sees the final state. */
|
|
289
|
+
private withHeldEvents;
|
|
290
|
+
setColumns(columns: readonly ColumnConfig<TRow>[]): void;
|
|
291
|
+
/** Called when the `[columns]` input changed (during change detection: events follow in a microtask). */
|
|
292
|
+
columnsChanged(): void;
|
|
293
|
+
refresh(): void;
|
|
294
|
+
refreshRows(rows: readonly TRow[]): void;
|
|
295
|
+
/** Writes a value into a row; re-renders only that row and recalculates only affected summaries. */
|
|
296
|
+
setCellValue(row: TRow, rowIndex: number, field: string, value: unknown, source: 'edit' | 'api'): boolean;
|
|
297
|
+
updateCell(rowIndex: number, field: string, value: unknown): void;
|
|
298
|
+
setSortModel(model: readonly SortModelItem[]): void;
|
|
299
|
+
/** Header click: cycles the column's direction. `multi` adds it to the existing sort. */
|
|
300
|
+
toggleSort(field: string, multi: boolean): void;
|
|
301
|
+
applySort(field: string, direction?: SortDirection, multi?: boolean): void;
|
|
302
|
+
clearSort(field?: string): void;
|
|
303
|
+
setFilterModel(model: FilterModel): void;
|
|
304
|
+
setColumnFilter(field: string, model: ColumnFilterModel | null): void;
|
|
305
|
+
clearFilter(field?: string): void;
|
|
306
|
+
private emitFilterChange;
|
|
307
|
+
openFilterPopup(field: string, anchor: HTMLElement | null): void;
|
|
308
|
+
closeFilterPopup(): void;
|
|
309
|
+
/** Selected rows by key, in selection order. Copy-on-write: every change creates a new map. */
|
|
310
|
+
readonly selection: import("@angular/core").WritableSignal<ReadonlyMap<GridRowKey, TRow>>;
|
|
311
|
+
/** Row of the last click (or Space): where Shift ranges start. */
|
|
312
|
+
private selectionAnchor;
|
|
313
|
+
/**
|
|
314
|
+
* The selection a Shift range is added to: the selection right after the click that set the anchor. Repeated Shift
|
|
315
|
+
* gestures recompute the range on top of it, so the range can grow and shrink. Any other change resets it.
|
|
316
|
+
*/
|
|
317
|
+
private rangeBase;
|
|
318
|
+
/** 1 for each data position that is displayed; null when every row is displayed. Cached per view. */
|
|
319
|
+
readonly displayedMask: Signal<Uint8Array<ArrayBufferLike> | null>;
|
|
320
|
+
/** Every row: the data and, in batch mode, the pending adds. */
|
|
321
|
+
private readonly allRows;
|
|
322
|
+
/** State of the header checkbox over the rows in `selectAllScope`. */
|
|
323
|
+
readonly headerSelectionState: Signal<"all" | "none" | "some">;
|
|
324
|
+
private countSelectable;
|
|
325
|
+
isRowSelectable(row: TRow): boolean;
|
|
326
|
+
isRowSelected(row: TRow): boolean;
|
|
327
|
+
/** Selects rows by key. `replace` replaces the selection; in single mode only the last key is kept. */
|
|
328
|
+
selectKeys(keys: readonly GridRowKey[], source: GridSelectionSource, replace?: boolean): number;
|
|
329
|
+
/** Selects the given rows (known key and object). Returns the number of rows newly selected. */
|
|
330
|
+
selectEntries(entries: readonly [GridRowKey, TRow][], source: GridSelectionSource, replace: boolean, acted: [GridRowKey, TRow] | null): number;
|
|
331
|
+
/** Deselects rows by key. Returns the number of rows deselected. */
|
|
332
|
+
deselectKeys(keys: Iterable<GridRowKey>, source: GridSelectionSource, acted?: [GridRowKey, TRow] | null): number;
|
|
333
|
+
/** Selects every row in scope (the filtered rows by default). Returns the number of rows newly selected. */
|
|
334
|
+
selectAll(source: GridSelectionSource, scope?: "filtered" | "all"): number;
|
|
335
|
+
/** Deselects the rows in scope (every selected row by default). Returns the number of rows deselected. */
|
|
336
|
+
deselectAll(source: GridSelectionSource, scope?: 'filtered' | 'all'): number;
|
|
337
|
+
/**
|
|
338
|
+
* Works out what a click, checkbox or key on the row at `rowIndex` does to the selection, without applying it.
|
|
339
|
+
* Returns null when the gesture changes nothing (selection off, row not selectable).
|
|
340
|
+
*
|
|
341
|
+
* Every gesture toggles the row: multiple mode keeps the other rows, single mode replaces the selected row (and
|
|
342
|
+
* deselects it when it is the clicked one). Ctrl/Cmd doesn't change that. In multiple mode, Shift selects the rows
|
|
343
|
+
* from the anchor (the last clicked row) to this one, on top of the selection the anchor click left.
|
|
344
|
+
*/
|
|
345
|
+
planSelection(rowIndex: number, gesture: 'click' | 'checkbox' | 'toggle', modifiers: {
|
|
346
|
+
ctrl: boolean;
|
|
347
|
+
shift: boolean;
|
|
348
|
+
}, source: GridSelectionSource): SelectionPlan<TRow> | null;
|
|
349
|
+
/** Multiple mode: the selection becomes `base` plus the selectable rows of `range` (both in that order). */
|
|
350
|
+
private selectRange;
|
|
351
|
+
/**
|
|
352
|
+
* After a `selection.mode` change: `'none'` deselects every row and `'single'` keeps only the last selected row
|
|
353
|
+
* (`selectionChange` with source `'api'`, after the change detection that applied the config).
|
|
354
|
+
*/
|
|
355
|
+
private reconcileSelectionMode;
|
|
356
|
+
/** Applies a plan after `(selectionClick)` had the chance to cancel it. Returns false when cancelled. */
|
|
357
|
+
runSelectionPlan(plan: SelectionPlan<TRow>, source: GridSelectionClickEvent['source'], rowIndex: number, event: Event): boolean;
|
|
358
|
+
/** Header checkbox: selects every row in scope, or deselects them when all are selected. */
|
|
359
|
+
toggleSelectAll(event: Event): void;
|
|
360
|
+
/** Selects the rows between the anchor and `rowIndex` (Shift+arrow keys). */
|
|
361
|
+
extendSelectionTo(rowIndex: number, fromIndex: number): void;
|
|
362
|
+
/** With `onFilter` set, deselects the rows a new filter hides (or everything with `'clear'`). */
|
|
363
|
+
private syncSelectionWithFilter;
|
|
364
|
+
/** Stores a new selection and emits the selection events. Returns false when nothing changed. */
|
|
365
|
+
private commitSelection;
|
|
366
|
+
/**
|
|
367
|
+
* The selected cell, by row key and field, so it follows its row through sort, filter, scrolling and refresh. `hint`
|
|
368
|
+
* is the view index where it was selected: finding the row again right after a click costs nothing.
|
|
369
|
+
*/
|
|
370
|
+
readonly selectedCell: import("@angular/core").WritableSignal<{
|
|
371
|
+
readonly key: GridRowKey;
|
|
372
|
+
readonly field: string;
|
|
373
|
+
readonly hint: number;
|
|
374
|
+
} | null>;
|
|
375
|
+
/** View index of the selected cell's row: -1 without one, or while a filter hides it. Cached per view. */
|
|
376
|
+
readonly selectedCellIndex: Signal<number>;
|
|
377
|
+
/** `getSelectedCell()`: null without a selected cell, and while cell selection is off. */
|
|
378
|
+
getSelectedCell(): GridSelectedCell<TRow> | null;
|
|
379
|
+
/**
|
|
380
|
+
* Selects a cell (`rowIndex`: its view index, or -1 when unknown) or, with `null`, clears the selected cell. Emits
|
|
381
|
+
* `cellSelectionChange` when the selected cell changed. Never changes the row selection.
|
|
382
|
+
*/
|
|
383
|
+
setSelectedCell(next: {
|
|
384
|
+
key: GridRowKey;
|
|
385
|
+
field: string;
|
|
386
|
+
rowIndex: number;
|
|
387
|
+
} | null, source: GridCellSelectionSource, event: Event | null, defer?: boolean): boolean;
|
|
388
|
+
/** `selectCell()`: selects a displayed cell (row not filtered out, column not hidden). */
|
|
389
|
+
selectCellByKey(key: GridRowKey, field: string, scroll: boolean): boolean;
|
|
390
|
+
/** `clearCellSelection()`. */
|
|
391
|
+
clearCellSelection(): void;
|
|
392
|
+
private cellSelectionEvent;
|
|
393
|
+
/** Clears the selected cell when its row left the data or its column was removed (filters and hidden columns keep it). */
|
|
394
|
+
private reconcileSelectedCell;
|
|
395
|
+
/** Rows added while a filter is active, kept visible until the filter changes or the data is replaced. */
|
|
396
|
+
private readonly keptRows;
|
|
397
|
+
/** The array made by the last add or delete, so its echo through `[(data)]` isn't treated as new data. */
|
|
398
|
+
private crudData;
|
|
399
|
+
/** The open delete confirmation, if any. */
|
|
400
|
+
readonly deleteRequest: import("@angular/core").WritableSignal<DeleteRequest<TRow> | null>;
|
|
401
|
+
private readonly pathGetters;
|
|
402
|
+
private readonly pathSetters;
|
|
403
|
+
/** The primary-key field, when the primary key is a field rather than a function. */
|
|
404
|
+
readonly primaryKeyField: Signal<string | null>;
|
|
405
|
+
ngOnDestroy(): void;
|
|
406
|
+
/** `addRow()`: the object becomes the row (see the API documentation), then it is validated and added. */
|
|
407
|
+
addRow(values: Partial<TRow> | null | undefined, options: GridAddRowOptions | undefined, source: 'ui' | 'api'): GridCrudResult<TRow>;
|
|
408
|
+
/** Opens the inline add row: a draft row in row edit mode, added when the edit is committed. */
|
|
409
|
+
beginAddRow(options?: GridBeginAddRowOptions<TRow>): boolean;
|
|
410
|
+
/** `updateRow()`. */
|
|
411
|
+
updateRow(key: GridRowKey, changes: Readonly<Record<string, unknown>> | null | undefined): GridCrudResult<TRow>;
|
|
412
|
+
/** Deletes rows now, without confirmation. */
|
|
413
|
+
deleteRows(keys: readonly GridRowKey[], source: 'ui' | 'api' | 'keyboard'): GridCrudResult<TRow>;
|
|
414
|
+
/** Deletes rows after the configured confirmation (the built-in dialog or the `infiGridDeleteConfirm` template). */
|
|
415
|
+
requestDelete(keys: readonly GridRowKey[], source: 'ui' | 'api' | 'keyboard'): Promise<GridCrudResult<TRow>>;
|
|
416
|
+
/** Whether a cell gets an editor. Keys are read-only once a row is added; the add row uses `editableOnAdd`. */
|
|
417
|
+
isCellEditable(column: ResolvedColumn<TRow>, row: TRow, isNew?: boolean): boolean;
|
|
418
|
+
private isEditableOnAdd;
|
|
419
|
+
/**
|
|
420
|
+
* The object of a new row: the `editing.newRow` object with `values` applied, or `values` itself
|
|
421
|
+
* (a copy with `copy`); then column defaults fill the fields that are still undefined.
|
|
422
|
+
*/
|
|
423
|
+
private createRow;
|
|
424
|
+
/** Validates a new row and inserts it (copy-on-write). `session` is the add row being committed. */
|
|
425
|
+
private insertNewRow;
|
|
426
|
+
/**
|
|
427
|
+
* Validates and writes changes into a row, in place: `required` and column validators, the key must not
|
|
428
|
+
* change, `rowValidator` on a preview copy; then `rowUpdating` (cancelable), the writes, `cellValueChange`
|
|
429
|
+
* per field and `rowUpdated`. `session` is the edit session that produced the changes (closed before writing).
|
|
430
|
+
*/
|
|
431
|
+
private applyUpdate;
|
|
432
|
+
/** `required`, column validators and `editing.rowValidator` for a new row. */
|
|
433
|
+
private validateNewRow;
|
|
434
|
+
/** `required` and the column validator for a value (already converted to the column type). */
|
|
435
|
+
private checkValue;
|
|
436
|
+
private runRowValidator;
|
|
437
|
+
/** A new row needs a key that no row uses yet (with a primary key; without one, the row object is the key). */
|
|
438
|
+
private checkNewKey;
|
|
439
|
+
/** Rows of the given keys in the data or the pending adds (each key once), with their data positions (-1: pending). */
|
|
440
|
+
private findRows;
|
|
441
|
+
/** Stores the array made by an add or delete. The bound array is never changed. */
|
|
442
|
+
private commitData;
|
|
443
|
+
private emitCrudRefresh;
|
|
444
|
+
/** Scrolls a row into view; with `focus`, its first cell also gets the focus. */
|
|
445
|
+
private revealRow;
|
|
446
|
+
/** Errors of a refused commit, on the editors (messages for other fields go on the focused editor). */
|
|
447
|
+
private showEditErrors;
|
|
448
|
+
private readPath;
|
|
449
|
+
private pathSetter;
|
|
450
|
+
/** Pending adds, in the order they were made. */
|
|
451
|
+
readonly pendingAdds: import("@angular/core").WritableSignal<ReadonlyMap<GridRowKey, PendingAdd<TRow>>>;
|
|
452
|
+
/** Rows marked for deletion (shown struck through until saved). */
|
|
453
|
+
readonly pendingDeletes: import("@angular/core").WritableSignal<ReadonlyMap<GridRowKey, TRow>>;
|
|
454
|
+
/** Pending values of data rows, by key. Mutable: rows re-render through their version. */
|
|
455
|
+
private readonly pendingUpdates;
|
|
456
|
+
/** Data row → its copy with the pending values: what the grid shows, sorts, filters and sums. */
|
|
457
|
+
private readonly mergedRows;
|
|
458
|
+
/** Bumped once per change of the pending state (toolbar, `canUndo()`). */
|
|
459
|
+
readonly pendingVersion: import("@angular/core").WritableSignal<number>;
|
|
460
|
+
/** A save handler is running: changes are refused until it settles. */
|
|
461
|
+
readonly saving: import("@angular/core").WritableSignal<boolean>;
|
|
462
|
+
/** The last save failed (until the next change). */
|
|
463
|
+
readonly saveFailed: import("@angular/core").WritableSignal<boolean>;
|
|
464
|
+
private undoStack;
|
|
465
|
+
private redoStack;
|
|
466
|
+
/** Pending adds shown first (newest first, as if each was inserted at the top). */
|
|
467
|
+
private readonly pendingTop;
|
|
468
|
+
/** Pending adds shown last, in order. */
|
|
469
|
+
private readonly pendingBottom;
|
|
470
|
+
/** The row as displayed: in batch mode, a copy with its pending values. */
|
|
471
|
+
displayRow(row: TRow): TRow;
|
|
472
|
+
/** The batch state of a row, for rendering (null without changes). */
|
|
473
|
+
rowChange(row: TRow): RowChangeState | null;
|
|
474
|
+
private isPendingDelete;
|
|
475
|
+
hasPendingChanges(): boolean;
|
|
476
|
+
canUndo(): boolean;
|
|
477
|
+
canRedo(): boolean;
|
|
478
|
+
/** Undoes the last pending change. An open edit of a data row is discarded first. */
|
|
479
|
+
undo(): boolean;
|
|
480
|
+
redo(): boolean;
|
|
481
|
+
getPendingChanges(): GridChangeSet<TRow>;
|
|
482
|
+
/**
|
|
483
|
+
* Commits an open edit, runs the save handler (default `editing.saveHandler`) and applies the changes to the
|
|
484
|
+
* data when it succeeds. A handler that throws or rejects keeps everything pending. Never rejects.
|
|
485
|
+
*/
|
|
486
|
+
saveChanges(handler?: (changes: GridChangeSet<TRow>) => unknown): Promise<GridSaveResult<TRow>>;
|
|
487
|
+
/** Discards every pending change (and an open edit). Returns what was discarded. */
|
|
488
|
+
cancelChanges(): GridChangeSet<TRow>;
|
|
489
|
+
/** Batch mode: takes rows off the pending deletes (the action column's restore button). */
|
|
490
|
+
restoreRows(keys: readonly GridRowKey[]): boolean;
|
|
491
|
+
/**
|
|
492
|
+
* Called when the `[config]` input changed: a selection the new `selection.mode` can't hold is reduced, turning cell
|
|
493
|
+
* selection off forgets the selected cell (no event: the feature is off), and turning batch mode off discards the
|
|
494
|
+
* pending changes.
|
|
495
|
+
*/
|
|
496
|
+
configChanged(): void;
|
|
497
|
+
/** Records a validated new row as a pending add. */
|
|
498
|
+
private addPending;
|
|
499
|
+
/**
|
|
500
|
+
* Records validated changes: a pending add is changed in place (it is the grid's own object); a data row
|
|
501
|
+
* gets pending values and a display copy.
|
|
502
|
+
*/
|
|
503
|
+
private updatePending;
|
|
504
|
+
/** Marks rows as deleted; pending adds are dropped instead. */
|
|
505
|
+
private deletePending;
|
|
506
|
+
private setPendingAdds;
|
|
507
|
+
private setPendingDeletes;
|
|
508
|
+
/**
|
|
509
|
+
* Rows that were removed or marked deleted: their edit is cancelled and they are deselected. The selected cell only
|
|
510
|
+
* goes with rows that left the grid (a row marked deleted is still shown until the save).
|
|
511
|
+
*/
|
|
512
|
+
private forgetRows;
|
|
513
|
+
/** Stores pending values of a data row. A value equal to the data's drops that change. */
|
|
514
|
+
private setPendingValues;
|
|
515
|
+
/** Rebuilds the display copy of a row with pending values (or forgets the row when none are left). */
|
|
516
|
+
private rebuildMerged;
|
|
517
|
+
private pendingSnapshot;
|
|
518
|
+
/** Undo/redo of an update: puts back the pending values a row had. */
|
|
519
|
+
private restorePending;
|
|
520
|
+
private afterPendingWrite;
|
|
521
|
+
/** Writes the saved changes into the data: values in place, deletes and adds as a new array. */
|
|
522
|
+
private applyChanges;
|
|
523
|
+
/** Forgets every pending change and the undo history; every rendered row is drawn again. */
|
|
524
|
+
private clearPending;
|
|
525
|
+
/** After the data was replaced or refreshed, pending changes follow their rows by key (or go with them). */
|
|
526
|
+
private rebasePending;
|
|
527
|
+
/** Records an undoable step; a new change clears the redo history. */
|
|
528
|
+
private recordStep;
|
|
529
|
+
/** Undo/redo discard an open edit of a data row (an open add row stays). */
|
|
530
|
+
private discardRowEdit;
|
|
531
|
+
private emitPendingChange;
|
|
532
|
+
/** The data row with this key (never a pending add). */
|
|
533
|
+
private dataRowByKey;
|
|
534
|
+
/**
|
|
535
|
+
* Sets a column's width (clamped to min/max). `startWidth` is the width when a drag started, so every
|
|
536
|
+
* event of one drag reports the same `oldWidth`.
|
|
537
|
+
*/
|
|
538
|
+
setColumnWidth(field: string, width: number, finished?: boolean, source?: 'user' | 'api', startWidth?: number): void;
|
|
539
|
+
/** Restores the configured width of one column, or of every resized column. */
|
|
540
|
+
resetColumnWidth(field?: string): void;
|
|
541
|
+
setColumnVisible(field: string, visible: boolean): void;
|
|
542
|
+
columnWidth(field: string): number | undefined;
|
|
543
|
+
recalculateSummary(fields?: string | readonly string[]): void;
|
|
544
|
+
setLoading(loading: boolean): void;
|
|
545
|
+
private lastLoading;
|
|
546
|
+
/** Emits `loadingChange` once per real change of the effective loading state. */
|
|
547
|
+
private syncLoading;
|
|
548
|
+
setError(error: unknown): void;
|
|
549
|
+
/** Editable fields of a row, in display order (never the primary-key field). */
|
|
550
|
+
editableFields(row: TRow): string[];
|
|
551
|
+
/**
|
|
552
|
+
* Starts editing a cell (field given) or a whole row. In row mode (`editing.mode: 'row'`),
|
|
553
|
+
* starting on a cell edits the whole row with that cell focused.
|
|
554
|
+
*/
|
|
555
|
+
startEdit(rowIndex: number, field?: string): boolean;
|
|
556
|
+
/** Stores a draft value and re-validates it. */
|
|
557
|
+
setDraft(field: string, value: unknown): string | null;
|
|
558
|
+
/**
|
|
559
|
+
* Saves the current session: updates the row (`rowUpdating`/`rowUpdated`, source `'edit'`), or adds the
|
|
560
|
+
* inline add row. Returns false and keeps editing when validation fails or a handler cancels.
|
|
561
|
+
*/
|
|
562
|
+
commitEdit(): boolean;
|
|
563
|
+
/** Writes the add row's values into its draft and adds it. */
|
|
564
|
+
private commitNewRow;
|
|
565
|
+
cancelEdit(emit?: boolean): void;
|
|
566
|
+
/**
|
|
567
|
+
* Grid edit mode: every change is validated and saved immediately (as an update with source `'edit'`).
|
|
568
|
+
* `saved` is false when the value was refused or a `rowUpdating` handler cancelled.
|
|
569
|
+
*/
|
|
570
|
+
commitGridCell(row: TRow, rowIndex: number, field: string, value: unknown): {
|
|
571
|
+
error: string | null;
|
|
572
|
+
saved: boolean;
|
|
573
|
+
};
|
|
574
|
+
setGridEditMode(enabled: boolean): void;
|
|
575
|
+
getEditState(): GridEditState<TRow> | null;
|
|
576
|
+
private publicEditState;
|
|
577
|
+
/** Validates an editor value: a number for number columns, then `required` and the column validator. */
|
|
578
|
+
private validate;
|
|
579
|
+
/** Converts editor output back to the column type, keeping the shape of the original value. */
|
|
580
|
+
parseEditedValue(column: ResolvedColumn<TRow>, value: unknown, original: unknown): unknown;
|
|
581
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridStore<any>, never>;
|
|
582
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<GridStore<any>>;
|
|
583
|
+
}
|
|
584
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { OnDestroy } from '@angular/core';
|
|
2
|
+
import type { GridTemplate } from '../models/template.types';
|
|
3
|
+
import type { GridTooltipPlacement } from '../models/tooltip.types';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/** Text, or a template (TemplateRef or component) with its context. */
|
|
6
|
+
export type TooltipContent = string | {
|
|
7
|
+
readonly template: GridTemplate<any>;
|
|
8
|
+
readonly context: object;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The grid's single tooltip, in `document.body` so it is never clipped. Created on first use, reused for every
|
|
12
|
+
* cell and header, and removed with the grid. Templates are rendered on show (checked once: they aren't
|
|
13
|
+
* attached to the application, which would make showing a tooltip check the whole app) and destroyed on hide.
|
|
14
|
+
*/
|
|
15
|
+
export declare class GridTooltipService implements OnDestroy {
|
|
16
|
+
private readonly environmentInjector;
|
|
17
|
+
private readonly injector;
|
|
18
|
+
private readonly document;
|
|
19
|
+
/** The `<infi-grid>` element (for the theme); set by the grid component. */
|
|
20
|
+
host: HTMLElement | null;
|
|
21
|
+
readonly id: string;
|
|
22
|
+
private element;
|
|
23
|
+
private view;
|
|
24
|
+
private anchor;
|
|
25
|
+
/** True while the tooltip is shown. */
|
|
26
|
+
get visible(): boolean;
|
|
27
|
+
/** Shows `content` next to `anchor` (replacing what was shown). */
|
|
28
|
+
show(anchor: HTMLElement, content: TooltipContent, placement: GridTooltipPlacement): void;
|
|
29
|
+
hide(): void;
|
|
30
|
+
ngOnDestroy(): void;
|
|
31
|
+
private ensureElement;
|
|
32
|
+
private render;
|
|
33
|
+
/** Destroys rendered views and detaches the tooltip from its anchor. */
|
|
34
|
+
private clear;
|
|
35
|
+
private applyTheme;
|
|
36
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridTooltipService, never>;
|
|
37
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<GridTooltipService>;
|
|
38
|
+
}
|