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
package/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AfterViewInit, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
+
import type { GridEditorOptions, GridSelectOption } from '../models/column.types';
|
|
3
|
+
import type { GridEditContext } from '../models/template.types';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Built-in editors: text, number, dropdown (select), checkbox and date picker.
|
|
7
|
+
* In a normal edit session values are drafts until committed; in grid edit mode (`live`)
|
|
8
|
+
* each change is saved immediately.
|
|
9
|
+
*/
|
|
10
|
+
export declare class GridCellEditorComponent implements OnChanges, AfterViewInit {
|
|
11
|
+
context: GridEditContext;
|
|
12
|
+
/** Grid edit mode: save on every change instead of keeping a draft. */
|
|
13
|
+
live: boolean;
|
|
14
|
+
/** The data row (`context.row` can be a copy showing pending values in batch mode). */
|
|
15
|
+
source: unknown;
|
|
16
|
+
private inputRef?;
|
|
17
|
+
private readonly store;
|
|
18
|
+
private readonly zone;
|
|
19
|
+
private readonly host;
|
|
20
|
+
opts: GridEditorOptions;
|
|
21
|
+
options: readonly GridSelectOption[];
|
|
22
|
+
error: string | null;
|
|
23
|
+
private boundRow;
|
|
24
|
+
private boundField;
|
|
25
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
26
|
+
ngAfterViewInit(): void;
|
|
27
|
+
/** Puts the current value into the native control (not bound, so typing never loses the caret). */
|
|
28
|
+
private writeValue;
|
|
29
|
+
onText(event: Event): void;
|
|
30
|
+
onChange(event: Event): void;
|
|
31
|
+
onCheckbox(event: Event): void;
|
|
32
|
+
onSelect(event: Event): void;
|
|
33
|
+
onKeydown(event: KeyboardEvent): void;
|
|
34
|
+
onBlur(): void;
|
|
35
|
+
private syncDraftFromInput;
|
|
36
|
+
private setDraft;
|
|
37
|
+
private save;
|
|
38
|
+
/** Tab / Shift+Tab: save and edit the next editable cell (wrapping to the next row). */
|
|
39
|
+
private moveToNextEditable;
|
|
40
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridCellEditorComponent, never>;
|
|
41
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GridCellEditorComponent, "infi-grid-cell-editor", never, { "context": { "alias": "context"; "required": true; }; "live": { "alias": "live"; "required": false; }; "source": { "alias": "source"; "required": false; }; }, {}, never, never, true, never>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ResolvedColumn } from '../models/column.types';
|
|
2
|
+
import type { GridText } from '../models/config.types';
|
|
3
|
+
import { type ColumnFilterModel } from '../models/filter.types';
|
|
4
|
+
import type { SortDirection } from '../models/sort.types';
|
|
5
|
+
import { type ValueListItem, type ValueListResult } from '../core/filter-engine';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
interface ConditionDraft {
|
|
8
|
+
operator: string;
|
|
9
|
+
value: string;
|
|
10
|
+
valueTo: string;
|
|
11
|
+
}
|
|
12
|
+
export interface FilterPopupSetup {
|
|
13
|
+
column: ResolvedColumn;
|
|
14
|
+
text: GridText;
|
|
15
|
+
model: ColumnFilterModel | null;
|
|
16
|
+
showSortButtons: boolean;
|
|
17
|
+
sortDirection: SortDirection | null;
|
|
18
|
+
loadValues: () => ValueListResult;
|
|
19
|
+
apply: (model: ColumnFilterModel | null) => void;
|
|
20
|
+
cancel: () => void;
|
|
21
|
+
sort: (direction: SortDirection) => void;
|
|
22
|
+
/** Some column is filtered (offers "Clear all filters"). */
|
|
23
|
+
anyFiltered: boolean;
|
|
24
|
+
clearAll: () => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Excel-style filter popup: Clear filter, sort buttons, 1 to 5 typed conditions (AND/OR), a searchable checkbox
|
|
28
|
+
* list of values (virtualized, so 100k distinct values stay fast), and Clear all filters / Cancel / Apply.
|
|
29
|
+
* Nothing is applied before Apply; Cancel and Escape close without applying.
|
|
30
|
+
*/
|
|
31
|
+
export declare class GridFilterPopupComponent {
|
|
32
|
+
private readonly host;
|
|
33
|
+
readonly uid: number;
|
|
34
|
+
readonly itemHeight = 28;
|
|
35
|
+
setup: FilterPopupSetup;
|
|
36
|
+
column: ResolvedColumn;
|
|
37
|
+
text: GridText;
|
|
38
|
+
title: string;
|
|
39
|
+
operators: readonly string[];
|
|
40
|
+
inputType: string;
|
|
41
|
+
showConditions: boolean;
|
|
42
|
+
showValueList: boolean;
|
|
43
|
+
showSortButtons: boolean;
|
|
44
|
+
sortDirection: SortDirection | null;
|
|
45
|
+
private maxConditions;
|
|
46
|
+
readonly conditions: import("@angular/core").WritableSignal<ConditionDraft[]>;
|
|
47
|
+
readonly logic: import("@angular/core").WritableSignal<"and" | "or">;
|
|
48
|
+
readonly search: import("@angular/core").WritableSignal<string>;
|
|
49
|
+
readonly items: import("@angular/core").WritableSignal<ValueListItem[]>;
|
|
50
|
+
readonly truncated: import("@angular/core").WritableSignal<boolean>;
|
|
51
|
+
private readonly selected;
|
|
52
|
+
private readonly selectionVersion;
|
|
53
|
+
private readonly listScroll;
|
|
54
|
+
readonly filteredItems: import("@angular/core").Signal<ValueListItem[]>;
|
|
55
|
+
readonly listHeight: import("@angular/core").Signal<number>;
|
|
56
|
+
readonly visibleItems: import("@angular/core").Signal<{
|
|
57
|
+
item: ValueListItem;
|
|
58
|
+
index: number;
|
|
59
|
+
}[]>;
|
|
60
|
+
readonly allState: import("@angular/core").Signal<"all" | "none" | "some">;
|
|
61
|
+
readonly canApply: import("@angular/core").Signal<boolean>;
|
|
62
|
+
/** Another condition can be added: below the maximum, and the last one is complete. */
|
|
63
|
+
readonly canAddCondition: import("@angular/core").Signal<boolean>;
|
|
64
|
+
readonly truncatedText: import("@angular/core").Signal<string>;
|
|
65
|
+
/** Called once by the popup service before the first render. */
|
|
66
|
+
init(setup: FilterPopupSetup): void;
|
|
67
|
+
focusFirst(): void;
|
|
68
|
+
operatorLabel(op: string): string;
|
|
69
|
+
inputCount(op: string): number;
|
|
70
|
+
setOperator(index: number, event: Event): void;
|
|
71
|
+
setConditionValue(index: number, key: 'value' | 'valueTo', event: Event): void;
|
|
72
|
+
private updateCondition;
|
|
73
|
+
addCondition(): void;
|
|
74
|
+
removeCondition(index: number): void;
|
|
75
|
+
/** A new condition row: the column's default operator, when it takes a value (booleans pick one). */
|
|
76
|
+
private emptyCondition;
|
|
77
|
+
private isComplete;
|
|
78
|
+
onSearch(event: Event): void;
|
|
79
|
+
onListScroll(event: Event): void;
|
|
80
|
+
isSelected(item: ValueListItem): boolean;
|
|
81
|
+
toggle(item: ValueListItem, event: Event): void;
|
|
82
|
+
toggleAll(event: Event): void;
|
|
83
|
+
onKeydown(event: KeyboardEvent): void;
|
|
84
|
+
clear(): void;
|
|
85
|
+
apply(): void;
|
|
86
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridFilterPopupComponent, never>;
|
|
87
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GridFilterPopupComponent, "infi-grid-filter-popup", never, {}, {}, never, never, true, never>;
|
|
88
|
+
}
|
|
89
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AfterViewChecked, OnChanges, OnDestroy } from '@angular/core';
|
|
2
|
+
import type { GridText } from '../models/config.types';
|
|
3
|
+
import { type FilterModel } from '../models/filter.types';
|
|
4
|
+
import { type LayoutColumn } from '../state/grid-store';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
interface FilterCellView {
|
|
7
|
+
key: string | null;
|
|
8
|
+
ariaCol: number | null;
|
|
9
|
+
left: number;
|
|
10
|
+
width: number;
|
|
11
|
+
cls: string;
|
|
12
|
+
/** Booleans use a select instead of the input. */
|
|
13
|
+
boolean: boolean;
|
|
14
|
+
inputType: string;
|
|
15
|
+
text: string;
|
|
16
|
+
booleanValue: string;
|
|
17
|
+
/** The applied first condition takes two values (`between`): edited in the popup only. */
|
|
18
|
+
locked: boolean;
|
|
19
|
+
/** The operator takes no value (`empty`): the input is disabled. */
|
|
20
|
+
noInput: boolean;
|
|
21
|
+
symbol: string;
|
|
22
|
+
operatorLabel: string;
|
|
23
|
+
inputLabel: string;
|
|
24
|
+
active: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The filter row (`filtering.mode: 'row' | 'both'`, shown while a displayed column is filterable, see
|
|
28
|
+
* `GridStore.filterRowHeight`): one cell per column under the header, with an operator button, a typed input
|
|
29
|
+
* (a select for booleans) and a clear button. It edits the first condition of the column's filter and keeps
|
|
30
|
+
* the rest (more conditions, the value list), so the popup shows the same filter.
|
|
31
|
+
*
|
|
32
|
+
* Cells are pooled like header cells: horizontal scrolling rebinds them. Typed text is kept per field, so a
|
|
33
|
+
* recycled input never loses it; an input whose column scrolls away is applied and blurred first.
|
|
34
|
+
*/
|
|
35
|
+
export declare class GridFilterRowComponent implements OnChanges, AfterViewChecked, OnDestroy {
|
|
36
|
+
columns: readonly LayoutColumn[];
|
|
37
|
+
columnPool: number;
|
|
38
|
+
filterModel: FilterModel;
|
|
39
|
+
nonce: number;
|
|
40
|
+
leading: number;
|
|
41
|
+
trailing: number;
|
|
42
|
+
private readonly store;
|
|
43
|
+
/** Where the pinned regions are placed with syncScroll, or null (sticky): see `GridStore.pinPlacement`. */
|
|
44
|
+
protected get pins(): {
|
|
45
|
+
start: number;
|
|
46
|
+
end: number;
|
|
47
|
+
} | null;
|
|
48
|
+
private readonly zone;
|
|
49
|
+
private readonly cdr;
|
|
50
|
+
private readonly host;
|
|
51
|
+
private readonly document;
|
|
52
|
+
cells: FilterCellView[];
|
|
53
|
+
text: GridText;
|
|
54
|
+
/** Typed text not applied yet, by field (survives recycling). */
|
|
55
|
+
private readonly drafts;
|
|
56
|
+
/** Operator chosen in the menu, by field (until the filter changes elsewhere). */
|
|
57
|
+
private readonly operators;
|
|
58
|
+
private readonly timers;
|
|
59
|
+
/** Fields this row applied, so their next model change isn't taken as a change from elsewhere. */
|
|
60
|
+
private readonly ownChanges;
|
|
61
|
+
private previousModel;
|
|
62
|
+
/** Field each input slot was last written for (the input values are written by hand, see `ngAfterViewChecked`). */
|
|
63
|
+
private readonly boundFields;
|
|
64
|
+
private menu;
|
|
65
|
+
ngOnChanges(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Writes the inputs' values by hand: a value binding only writes when the bound value changes, so a reused
|
|
68
|
+
* input could keep text typed for another column. An input is written when its slot shows another column,
|
|
69
|
+
* or when it isn't focused and shows something else (the filter changed elsewhere).
|
|
70
|
+
*/
|
|
71
|
+
ngAfterViewChecked(): void;
|
|
72
|
+
ngOnDestroy(): void;
|
|
73
|
+
/** A filter changed elsewhere (popup, API): the row shows it, unless that column is being typed into. */
|
|
74
|
+
private syncWithModel;
|
|
75
|
+
private buildCell;
|
|
76
|
+
/** The operator of a column's cell: chosen in the menu, else the applied one, else the column default. */
|
|
77
|
+
private operatorOf;
|
|
78
|
+
/** Operators offered by the row: the column's, without two-value ones (those are in the popup). */
|
|
79
|
+
private rowOperators;
|
|
80
|
+
private inputCount;
|
|
81
|
+
private operatorLabel;
|
|
82
|
+
onInput(event: Event, cell: FilterCellView): void;
|
|
83
|
+
onBoolean(event: Event, cell: FilterCellView): void;
|
|
84
|
+
onKeydown(event: KeyboardEvent, cell: FilterCellView): void;
|
|
85
|
+
clear(cell: FilterCellView): void;
|
|
86
|
+
/** Applies a field's typed text after `filtering.rowDebounce`. */
|
|
87
|
+
private schedule;
|
|
88
|
+
private cancelTimer;
|
|
89
|
+
/** Applies a field's typed text now. */
|
|
90
|
+
private flush;
|
|
91
|
+
private parse;
|
|
92
|
+
/** Sets (or removes) the first condition of a column's filter, keeping its other conditions and value list. */
|
|
93
|
+
private writeFirst;
|
|
94
|
+
private refresh;
|
|
95
|
+
/** Tab / Shift+Tab: the next or previous column's filter, in column order (scrolling it into view). */
|
|
96
|
+
private moveFocus;
|
|
97
|
+
openMenu(event: MouseEvent, cell: FilterCellView): void;
|
|
98
|
+
/** An operator was picked: applied at once when it needs no value or a value is there. */
|
|
99
|
+
private choose;
|
|
100
|
+
private applyTheme;
|
|
101
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridFilterRowComponent, never>;
|
|
102
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GridFilterRowComponent, "div[infi-grid-filter-row]", never, { "columns": { "alias": "columns"; "required": false; }; "columnPool": { "alias": "columnPool"; "required": false; }; "filterModel": { "alias": "filterModel"; "required": false; }; "nonce": { "alias": "nonce"; "required": false; }; "leading": { "alias": "leading"; "required": false; }; "trailing": { "alias": "trailing"; "required": false; }; }, {}, never, never, true, never>;
|
|
103
|
+
}
|
|
104
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { EventEmitter, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
|
2
|
+
import type { GridApi } from '../models/api.types';
|
|
3
|
+
import type { ColumnConfig } from '../models/column.types';
|
|
4
|
+
import type { GridConfig } from '../models/config.types';
|
|
5
|
+
import type { GridChangeSet, GridPendingChangeEvent, GridRowAddedEvent, GridRowAddingEvent, GridRowDeletedEvent, GridRowDeletingEvent, GridRowUpdatedEvent, GridRowUpdatingEvent, GridSaveFailedEvent } from '../models/crud.types';
|
|
6
|
+
import type { GridDataRefreshEvent, GridLoadingChangeEvent } from '../models/data.types';
|
|
7
|
+
import type { GridCellSelectionChangeEvent, GridRowSelectionEvent, GridSelectionChangeEvent, GridSelectionClearedEvent, GridSelectionClickEvent } from '../models/selection.types';
|
|
8
|
+
import type { GridCellEvent, GridCellValueChangeEvent, GridColumnResizeEvent, GridEditEvent, GridErrorEvent, GridFilterChangeEvent, GridHeaderClickEvent, GridReadyEvent, GridRowEvent, GridSortChangeEvent, GridViewportChangeEvent } from '../models/events.types';
|
|
9
|
+
import type { GridDeleteConfirmContext, GridEmptyContext, GridErrorContext, GridLoadingContext, GridTemplate } from '../models/template.types';
|
|
10
|
+
import { GridStore } from '../state/grid-store';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
interface OverlayState<C> {
|
|
13
|
+
template: GridTemplate<C> | null;
|
|
14
|
+
context: C;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Every Grid API method is also available on the component instance, so a parent can call
|
|
18
|
+
* `@ViewChild(InfiGridComponent) grid; grid.selectRowByKey(1)` as well as `grid.api.selectRowByKey(1)`.
|
|
19
|
+
*/
|
|
20
|
+
export interface InfiGridComponent<TRow = any> extends GridApi<TRow> {
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* `<infi-grid>`: virtualized data grid with Excel-style filtering, multi-sort, editing,
|
|
24
|
+
* summaries and templates.
|
|
25
|
+
*
|
|
26
|
+
* ```html
|
|
27
|
+
* <infi-grid [data]="rows" [columns]="columns" [config]="config" (gridReady)="api = $event.api" />
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class InfiGridComponent<TRow = any> implements OnInit, OnChanges {
|
|
31
|
+
/** The rows to show. */
|
|
32
|
+
readonly data: import("@angular/core").InputSignal<readonly TRow[] | null | undefined>;
|
|
33
|
+
/** Column definitions. */
|
|
34
|
+
readonly columns: import("@angular/core").InputSignal<readonly ColumnConfig<TRow, any>[] | null | undefined>;
|
|
35
|
+
/** Grid configuration and feature flags. */
|
|
36
|
+
readonly config: import("@angular/core").InputSignal<GridConfig<TRow> | null | undefined>;
|
|
37
|
+
/** Shows the loading state. */
|
|
38
|
+
readonly loading: import("@angular/core").InputSignal<boolean>;
|
|
39
|
+
/** Shows the error state when set (any value: string, Error, HTTP error…). */
|
|
40
|
+
readonly error: import("@angular/core").InputSignal<unknown>;
|
|
41
|
+
readonly gridReady: EventEmitter<GridReadyEvent<TRow>>;
|
|
42
|
+
readonly sortChange: EventEmitter<GridSortChangeEvent>;
|
|
43
|
+
readonly filterChange: EventEmitter<GridFilterChangeEvent>;
|
|
44
|
+
readonly cellValueChange: EventEmitter<GridCellValueChangeEvent<TRow>>;
|
|
45
|
+
readonly editStart: EventEmitter<GridEditEvent<TRow>>;
|
|
46
|
+
readonly editCommit: EventEmitter<GridEditEvent<TRow>>;
|
|
47
|
+
readonly editCancel: EventEmitter<GridEditEvent<TRow>>;
|
|
48
|
+
readonly cellClick: EventEmitter<GridCellEvent<TRow>>;
|
|
49
|
+
readonly cellDoubleClick: EventEmitter<GridCellEvent<TRow>>;
|
|
50
|
+
readonly rowClick: EventEmitter<GridRowEvent<TRow>>;
|
|
51
|
+
readonly rowDoubleClick: EventEmitter<GridRowEvent<TRow>>;
|
|
52
|
+
/** A click on a header's label or filter button (before sorting / opening the filter; cancelable). */
|
|
53
|
+
readonly headerClick: EventEmitter<GridHeaderClickEvent<TRow>>;
|
|
54
|
+
/** Right click on a cell (`events.preventContextMenu` suppresses the browser menu). */
|
|
55
|
+
readonly cellContextMenu: EventEmitter<GridCellEvent<TRow>>;
|
|
56
|
+
/** The pointer entered a cell (identified by row key and field; not fired while scrolling). */
|
|
57
|
+
readonly cellMouseEnter: EventEmitter<GridCellEvent<TRow>>;
|
|
58
|
+
/** The pointer left a cell. */
|
|
59
|
+
readonly cellMouseLeave: EventEmitter<GridCellEvent<TRow>>;
|
|
60
|
+
readonly columnResize: EventEmitter<GridColumnResizeEvent<TRow>>;
|
|
61
|
+
/** Emits while scrolling (only computed when you listen to it). */
|
|
62
|
+
readonly viewportChange: EventEmitter<GridViewportChangeEvent>;
|
|
63
|
+
/** Errors the grid caught (the grid never logs to the console). */
|
|
64
|
+
readonly gridError: EventEmitter<GridErrorEvent>;
|
|
65
|
+
/** The effective loading state changed (from `[loading]` or `setLoading()`). */
|
|
66
|
+
readonly loadingChange: EventEmitter<GridLoadingChangeEvent>;
|
|
67
|
+
/** The data was replaced or refreshed and the grid state was reconciled with it. */
|
|
68
|
+
readonly dataRefresh: EventEmitter<GridDataRefreshEvent>;
|
|
69
|
+
/** The selection changed (once per operation, with the added/removed rows and the old/new selection). */
|
|
70
|
+
readonly selectionChange: EventEmitter<GridSelectionChangeEvent<TRow>>;
|
|
71
|
+
/** Rows were selected by one operation. */
|
|
72
|
+
readonly rowSelected: EventEmitter<GridRowSelectionEvent<TRow>>;
|
|
73
|
+
/** Rows were deselected by one operation. */
|
|
74
|
+
readonly rowDeselected: EventEmitter<GridRowSelectionEvent<TRow>>;
|
|
75
|
+
/** The selection became empty. */
|
|
76
|
+
readonly selectionCleared: EventEmitter<GridSelectionClearedEvent<TRow>>;
|
|
77
|
+
/** A click (or key) is about to change the selection; set `cancel` to prevent it. */
|
|
78
|
+
readonly selectionClick: EventEmitter<GridSelectionClickEvent<TRow>>;
|
|
79
|
+
/** The selected cell changed (`cellSelection.enabled`): click, keyboard, API, or its row or column went away. */
|
|
80
|
+
readonly cellSelectionChange: EventEmitter<GridCellSelectionChangeEvent<TRow>>;
|
|
81
|
+
/** A row is about to be added (after validation); set `cancel` to prevent it. */
|
|
82
|
+
readonly rowAdding: EventEmitter<GridRowAddingEvent<TRow>>;
|
|
83
|
+
/** A row was added (inline add row or `addRow()`). */
|
|
84
|
+
readonly rowAdded: EventEmitter<GridRowAddedEvent<TRow>>;
|
|
85
|
+
/** A row is about to change (inline edit or `updateRow()`); set `cancel` to prevent it. */
|
|
86
|
+
readonly rowUpdating: EventEmitter<GridRowUpdatingEvent<TRow>>;
|
|
87
|
+
/** A row changed, with its old values, new values and a copy of the old row. */
|
|
88
|
+
readonly rowUpdated: EventEmitter<GridRowUpdatedEvent<TRow>>;
|
|
89
|
+
/** Rows are about to be deleted (after the confirmation); set `cancel` to prevent it. */
|
|
90
|
+
readonly rowDeleting: EventEmitter<GridRowDeletingEvent<TRow>>;
|
|
91
|
+
/** Rows were deleted (once per operation). */
|
|
92
|
+
readonly rowDeleted: EventEmitter<GridRowDeletedEvent<TRow>>;
|
|
93
|
+
/**
|
|
94
|
+
* The new data array after an add or delete (the bound array is never changed). Bind `[(data)]="rows"`
|
|
95
|
+
* to keep your array in sync.
|
|
96
|
+
*/
|
|
97
|
+
readonly dataChange: EventEmitter<readonly TRow[]>;
|
|
98
|
+
/** Batch mode: the pending changes were saved (and applied to the data). */
|
|
99
|
+
readonly changesSaved: EventEmitter<GridChangeSet<TRow>>;
|
|
100
|
+
/** Batch mode: the pending changes were discarded. */
|
|
101
|
+
readonly changesCancelled: EventEmitter<GridChangeSet<TRow>>;
|
|
102
|
+
/** Batch mode: the save handler threw or rejected; the changes are still pending. */
|
|
103
|
+
readonly changesSaveFailed: EventEmitter<GridSaveFailedEvent<TRow>>;
|
|
104
|
+
/** Batch mode: the pending changes or the undo history changed. */
|
|
105
|
+
readonly pendingChange: EventEmitter<GridPendingChangeEvent>;
|
|
106
|
+
private readonly cellTemplates;
|
|
107
|
+
private readonly editTemplates;
|
|
108
|
+
private readonly headerTemplates;
|
|
109
|
+
private readonly summaryTemplates;
|
|
110
|
+
private readonly loadingTemplates;
|
|
111
|
+
private readonly emptyTemplates;
|
|
112
|
+
private readonly errorTemplates;
|
|
113
|
+
private readonly deleteConfirmTemplates;
|
|
114
|
+
private readonly cellTooltipTemplates;
|
|
115
|
+
private readonly headerTooltipTemplates;
|
|
116
|
+
protected readonly store: GridStore<TRow>;
|
|
117
|
+
private readonly zone;
|
|
118
|
+
private readonly popup;
|
|
119
|
+
/** Grid reference / API. Also emitted by `(gridReady)`. */
|
|
120
|
+
readonly api: GridApi<TRow>;
|
|
121
|
+
private readonly registry;
|
|
122
|
+
protected readonly hostClass: import("@angular/core").Signal<string>;
|
|
123
|
+
/** The header plus the filter row (when there is one): overlays start below it. */
|
|
124
|
+
protected readonly headerBlockHeight: import("@angular/core").Signal<number>;
|
|
125
|
+
protected readonly overlayBottom: import("@angular/core").Signal<number>;
|
|
126
|
+
protected readonly blockWhileLoading: import("@angular/core").Signal<boolean>;
|
|
127
|
+
protected readonly errorOverlay: import("@angular/core").Signal<OverlayState<GridErrorContext<TRow>> | null>;
|
|
128
|
+
protected readonly emptyOverlay: import("@angular/core").Signal<OverlayState<GridEmptyContext<TRow>> | null>;
|
|
129
|
+
protected readonly loadingOverlay: import("@angular/core").Signal<OverlayState<GridLoadingContext<TRow>> | null>;
|
|
130
|
+
/** The batch toolbar: shown in batch mode while there are changes, undo steps, a save or a failed save. */
|
|
131
|
+
protected readonly batchBar: import("@angular/core").Signal<{
|
|
132
|
+
text: import("infi-grid").GridText;
|
|
133
|
+
saving: boolean;
|
|
134
|
+
failed: boolean;
|
|
135
|
+
hasChanges: boolean;
|
|
136
|
+
canUndo: boolean;
|
|
137
|
+
canRedo: boolean;
|
|
138
|
+
message: string;
|
|
139
|
+
} | null>;
|
|
140
|
+
protected readonly deleteConfirm: import("@angular/core").Signal<OverlayState<GridDeleteConfirmContext<TRow>> | null>;
|
|
141
|
+
/** Focuses the dialog's confirm button (or the template's first control) when it opens. */
|
|
142
|
+
private set confirmOverlay(value);
|
|
143
|
+
private closeConfirm;
|
|
144
|
+
/** Keeps the focus inside the confirmation (Tab cycles); Escape cancels. */
|
|
145
|
+
protected onConfirmKeydown(event: KeyboardEvent, context: GridDeleteConfirmContext<TRow>): void;
|
|
146
|
+
private focusable;
|
|
147
|
+
constructor();
|
|
148
|
+
ngOnInit(): void;
|
|
149
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
150
|
+
/** Forwards store events to the outputs, always inside Angular's zone. */
|
|
151
|
+
private wireEvents;
|
|
152
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<InfiGridComponent<any>, never>;
|
|
153
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<InfiGridComponent<any>, "infi-grid", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; }, { "gridReady": "gridReady"; "sortChange": "sortChange"; "filterChange": "filterChange"; "cellValueChange": "cellValueChange"; "editStart": "editStart"; "editCommit": "editCommit"; "editCancel": "editCancel"; "cellClick": "cellClick"; "cellDoubleClick": "cellDoubleClick"; "rowClick": "rowClick"; "rowDoubleClick": "rowDoubleClick"; "headerClick": "headerClick"; "cellContextMenu": "cellContextMenu"; "cellMouseEnter": "cellMouseEnter"; "cellMouseLeave": "cellMouseLeave"; "columnResize": "columnResize"; "viewportChange": "viewportChange"; "gridError": "gridError"; "loadingChange": "loadingChange"; "dataRefresh": "dataRefresh"; "selectionChange": "selectionChange"; "rowSelected": "rowSelected"; "rowDeselected": "rowDeselected"; "selectionCleared": "selectionCleared"; "selectionClick": "selectionClick"; "cellSelectionChange": "cellSelectionChange"; "rowAdding": "rowAdding"; "rowAdded": "rowAdded"; "rowUpdating": "rowUpdating"; "rowUpdated": "rowUpdated"; "rowDeleting": "rowDeleting"; "rowDeleted": "rowDeleted"; "dataChange": "dataChange"; "changesSaved": "changesSaved"; "changesCancelled": "changesCancelled"; "changesSaveFailed": "changesSaveFailed"; "pendingChange": "pendingChange"; }, ["cellTemplates", "editTemplates", "headerTemplates", "summaryTemplates", "loadingTemplates", "emptyTemplates", "errorTemplates", "deleteConfirmTemplates", "cellTooltipTemplates", "headerTooltipTemplates"], never, true, never>;
|
|
154
|
+
}
|
|
155
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { OnChanges } from '@angular/core';
|
|
2
|
+
import type { GridStyleValue, ResolvedColumn } from '../models/column.types';
|
|
3
|
+
import type { FilterModel } from '../models/filter.types';
|
|
4
|
+
import type { SortModelItem } from '../models/sort.types';
|
|
5
|
+
import type { GridHeaderContext, GridTemplate } from '../models/template.types';
|
|
6
|
+
import { type LayoutColumn } from '../state/grid-store';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
interface HeaderView {
|
|
9
|
+
key: string | null;
|
|
10
|
+
col: ResolvedColumn | null;
|
|
11
|
+
header: string;
|
|
12
|
+
/** Native `title` (only when the grid's tooltips are off). */
|
|
13
|
+
title: string | null;
|
|
14
|
+
ariaCol: number | null;
|
|
15
|
+
left: number;
|
|
16
|
+
width: number;
|
|
17
|
+
cls: string;
|
|
18
|
+
style: GridStyleValue | null;
|
|
19
|
+
sortable: boolean;
|
|
20
|
+
ariaSort: 'ascending' | 'descending' | 'none' | null;
|
|
21
|
+
sortIndexText: string;
|
|
22
|
+
sortIconCls: string;
|
|
23
|
+
filterBtnCls: string;
|
|
24
|
+
filterLabel: string | null;
|
|
25
|
+
filterActive: boolean;
|
|
26
|
+
resizeCls: string;
|
|
27
|
+
template: GridTemplate<GridHeaderContext> | null;
|
|
28
|
+
context: GridHeaderContext | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The single header row: labels/templates, sort icon with sort order, filter button, resize handle.
|
|
32
|
+
* Header cells use the same slot pool as body cells and toggle icons with CSS classes,
|
|
33
|
+
* so horizontal scrolling never creates or destroys views.
|
|
34
|
+
*/
|
|
35
|
+
export declare class GridHeaderRowComponent implements OnChanges {
|
|
36
|
+
columns: readonly LayoutColumn[];
|
|
37
|
+
columnPool: number;
|
|
38
|
+
templatePool: number;
|
|
39
|
+
sortModel: readonly SortModelItem[];
|
|
40
|
+
filterModel: FilterModel;
|
|
41
|
+
openFilterField: string | null;
|
|
42
|
+
nonce: number;
|
|
43
|
+
/** Width of the pinned checkbox cell (0: no checkbox column). */
|
|
44
|
+
leading: number;
|
|
45
|
+
/** Show the select-all checkbox. */
|
|
46
|
+
selectAll: boolean;
|
|
47
|
+
selectionState: 'none' | 'some' | 'all';
|
|
48
|
+
/** Width of the pinned action column (0: none). */
|
|
49
|
+
trailing: number;
|
|
50
|
+
private readonly store;
|
|
51
|
+
/** Where the pinned regions are placed with syncScroll, or null (sticky): see `GridStore.pinPlacement`. */
|
|
52
|
+
protected get pins(): {
|
|
53
|
+
start: number;
|
|
54
|
+
end: number;
|
|
55
|
+
} | null;
|
|
56
|
+
private readonly zone;
|
|
57
|
+
headers: HeaderView[];
|
|
58
|
+
templateHeaders: HeaderView[];
|
|
59
|
+
selectAllLabel: string;
|
|
60
|
+
text: import("infi-grid").GridText;
|
|
61
|
+
showAdd: boolean;
|
|
62
|
+
actionsAriaCol: number;
|
|
63
|
+
private resizing;
|
|
64
|
+
private ariaColOffset;
|
|
65
|
+
ngOnChanges(): void;
|
|
66
|
+
private buildHeader;
|
|
67
|
+
/** Emits `(headerClick)`; returns true when a handler cancelled the built-in reaction. */
|
|
68
|
+
private emitHeaderClick;
|
|
69
|
+
onHeaderClick(event: MouseEvent, h: HeaderView): void;
|
|
70
|
+
onSelectAll(event: MouseEvent): void;
|
|
71
|
+
onFilterClick(event: MouseEvent, h: HeaderView): void;
|
|
72
|
+
onResizeStart(event: PointerEvent, h: HeaderView): void;
|
|
73
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridHeaderRowComponent, never>;
|
|
74
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GridHeaderRowComponent, "div[infi-grid-header-row]", never, { "columns": { "alias": "columns"; "required": false; }; "columnPool": { "alias": "columnPool"; "required": false; }; "templatePool": { "alias": "templatePool"; "required": false; }; "sortModel": { "alias": "sortModel"; "required": false; }; "filterModel": { "alias": "filterModel"; "required": false; }; "openFilterField": { "alias": "openFilterField"; "required": false; }; "nonce": { "alias": "nonce"; "required": false; }; "leading": { "alias": "leading"; "required": false; }; "selectAll": { "alias": "selectAll"; "required": false; }; "selectionState": { "alias": "selectionState"; "required": false; }; "trailing": { "alias": "trailing"; "required": false; }; }, {}, never, never, true, never>;
|
|
75
|
+
}
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
+
import type { GridClassValue, GridStyleValue } from '../models/column.types';
|
|
3
|
+
import type { GridCellContext, GridEditContext, GridTemplate } from '../models/template.types';
|
|
4
|
+
import { type EditSession, type LayoutColumn } from '../state/grid-store';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/** `text` cells (also booleans and empty slots) are a single element with `textContent`. */
|
|
7
|
+
type CellKind = 'text' | 'template' | 'editor';
|
|
8
|
+
interface CellView {
|
|
9
|
+
key: string | null;
|
|
10
|
+
ariaCol: number | null;
|
|
11
|
+
/** `aria-selected` with cell selection (`'true'` on the selected cell), else null (no attribute). */
|
|
12
|
+
ariaSelected: 'true' | 'false' | null;
|
|
13
|
+
left: number;
|
|
14
|
+
width: number;
|
|
15
|
+
cls: string;
|
|
16
|
+
style: GridStyleValue | null;
|
|
17
|
+
kind: CellKind;
|
|
18
|
+
text: string;
|
|
19
|
+
template: GridTemplate<any> | null;
|
|
20
|
+
context: GridCellContext | GridEditContext | null;
|
|
21
|
+
}
|
|
22
|
+
export declare function classList(value: GridClassValue): string;
|
|
23
|
+
/**
|
|
24
|
+
* One grid row. OnPush with plain `@Input`s: it re-renders only when its row, row version,
|
|
25
|
+
* columns, edit state or focus (with cell selection: the selected cell) change, so updating one cell re-renders one row.
|
|
26
|
+
*
|
|
27
|
+
* Cells live in fixed pools of slots: plain cells in `cells` (column `i` → slot `i % columnPool`)
|
|
28
|
+
* and template cells in `templateCells` (template column `t` → slot `t % templatePool`; with `templateKey`s, a column
|
|
29
|
+
* takes a slot that last showed a column with the same key, see `assignTemplateSlots`).
|
|
30
|
+
* Scrolling in any direction therefore rebinds existing elements and template views instead of
|
|
31
|
+
* creating new ones — creating views would make Angular check the whole application.
|
|
32
|
+
* Editors (only on rows being edited) are rendered separately in `editorCells`.
|
|
33
|
+
*/
|
|
34
|
+
export declare class GridRowComponent<TRow = any> implements OnChanges {
|
|
35
|
+
row: TRow | null;
|
|
36
|
+
rowIndex: number;
|
|
37
|
+
dataIndex: number;
|
|
38
|
+
columns: readonly LayoutColumn<TRow>[];
|
|
39
|
+
/** Number of plain-cell slots (≥ columns.length). */
|
|
40
|
+
columnPool: number;
|
|
41
|
+
/** Number of template-cell slots (≥ template columns in `columns`). */
|
|
42
|
+
templatePool: number;
|
|
43
|
+
/** Changes when this row's data was edited. */
|
|
44
|
+
version: number;
|
|
45
|
+
/** Changes when every row must rebuild. */
|
|
46
|
+
nonce: number;
|
|
47
|
+
edit: EditSession<TRow> | null;
|
|
48
|
+
gridEditMode: boolean;
|
|
49
|
+
focusField: string | null;
|
|
50
|
+
/** Selection state (drawn by the checkbox; the row class is set by the viewport). */
|
|
51
|
+
selected: boolean;
|
|
52
|
+
selectable: boolean;
|
|
53
|
+
/** Width of the pinned checkbox cell (0: no checkbox column). */
|
|
54
|
+
leading: number;
|
|
55
|
+
/** Width of the pinned action column (0: none). */
|
|
56
|
+
trailing: number;
|
|
57
|
+
/** The inline add row (its row is a draft that isn't in the data yet). */
|
|
58
|
+
addRow: boolean;
|
|
59
|
+
private readonly store;
|
|
60
|
+
/** Where the pinned regions are placed with syncScroll, or null (sticky): see `GridStore.pinPlacement`. */
|
|
61
|
+
protected get pins(): {
|
|
62
|
+
start: number;
|
|
63
|
+
end: number;
|
|
64
|
+
} | null;
|
|
65
|
+
cells: CellView[];
|
|
66
|
+
templateCells: CellView[];
|
|
67
|
+
editorCells: CellView[];
|
|
68
|
+
hostClass: string;
|
|
69
|
+
hostStyle: GridStyleValue | null;
|
|
70
|
+
selectLabel: string;
|
|
71
|
+
/** Classes of the action buttons (hidden ones get `is-hidden`). */
|
|
72
|
+
actions: {
|
|
73
|
+
edit: string;
|
|
74
|
+
delete: string;
|
|
75
|
+
save: string;
|
|
76
|
+
cancel: string;
|
|
77
|
+
restore: string;
|
|
78
|
+
};
|
|
79
|
+
canEdit: boolean;
|
|
80
|
+
actionsAriaCol: number;
|
|
81
|
+
text: import("infi-grid").GridText;
|
|
82
|
+
private errorReported;
|
|
83
|
+
/** What each template slot last showed (a kept, hidden view still shows it): field, template and `templateKey`. */
|
|
84
|
+
private slotFields;
|
|
85
|
+
private slotTemplates;
|
|
86
|
+
private slotKeys;
|
|
87
|
+
private ariaColOffset;
|
|
88
|
+
/** Cell selection: the focused cell is the selected cell. */
|
|
89
|
+
private cellSelection;
|
|
90
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
91
|
+
/**
|
|
92
|
+
* Template slots when columns have `templateKey`s: a column keeps the slot it already has; otherwise it takes a
|
|
93
|
+
* free slot that last showed a column with the same template and key (its view only updates), then a slot never
|
|
94
|
+
* used, then any free slot (its view re-renders). The viewport sizes the pool for the most columns of each key that
|
|
95
|
+
* can be in view, so once the slots have met their keys, scrolling sideways only updates cells.
|
|
96
|
+
*/
|
|
97
|
+
private assignTemplateSlots;
|
|
98
|
+
/** Which action buttons show: edit/delete normally, save/cancel while editing, restore on deleted rows (batch). */
|
|
99
|
+
private buildActions;
|
|
100
|
+
private buildCell;
|
|
101
|
+
private editContext;
|
|
102
|
+
private safe;
|
|
103
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridRowComponent<any>, never>;
|
|
104
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GridRowComponent<any>, "div[infi-grid-row]", never, { "row": { "alias": "row"; "required": false; }; "rowIndex": { "alias": "rowIndex"; "required": false; }; "dataIndex": { "alias": "dataIndex"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "columnPool": { "alias": "columnPool"; "required": false; }; "templatePool": { "alias": "templatePool"; "required": false; }; "version": { "alias": "version"; "required": false; }; "nonce": { "alias": "nonce"; "required": false; }; "edit": { "alias": "edit"; "required": false; }; "gridEditMode": { "alias": "gridEditMode"; "required": false; }; "focusField": { "alias": "focusField"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; "leading": { "alias": "leading"; "required": false; }; "trailing": { "alias": "trailing"; "required": false; }; "addRow": { "alias": "addRow"; "required": false; }; }, {}, never, never, true, never>;
|
|
105
|
+
}
|
|
106
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { OnChanges } from '@angular/core';
|
|
2
|
+
import type { GridSummaryResult } from '../models/summary.types';
|
|
3
|
+
import type { GridSummaryCellContext, GridTemplate } from '../models/template.types';
|
|
4
|
+
import { type LayoutColumn } from '../state/grid-store';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
interface SummaryCellView {
|
|
7
|
+
key: string | null;
|
|
8
|
+
ariaCol: number | null;
|
|
9
|
+
left: number;
|
|
10
|
+
width: number;
|
|
11
|
+
cls: string;
|
|
12
|
+
label: string;
|
|
13
|
+
value: string;
|
|
14
|
+
title: string | null;
|
|
15
|
+
template: GridTemplate<GridSummaryCellContext> | null;
|
|
16
|
+
context: GridSummaryCellContext | null;
|
|
17
|
+
}
|
|
18
|
+
/** Summary row cells (label + value, or a summary template), pooled like body cells. */
|
|
19
|
+
export declare class GridSummaryRowComponent implements OnChanges {
|
|
20
|
+
columns: readonly LayoutColumn[];
|
|
21
|
+
columnPool: number;
|
|
22
|
+
templatePool: number;
|
|
23
|
+
results: Readonly<Record<string, GridSummaryResult>>;
|
|
24
|
+
/** Width of the pinned checkbox cell (0: no checkbox column). */
|
|
25
|
+
leading: number;
|
|
26
|
+
/** Width of the pinned action column (0: none). */
|
|
27
|
+
trailing: number;
|
|
28
|
+
private readonly store;
|
|
29
|
+
/** Where the pinned regions are placed with syncScroll, or null (sticky): see `GridStore.pinPlacement`. */
|
|
30
|
+
protected get pins(): {
|
|
31
|
+
start: number;
|
|
32
|
+
end: number;
|
|
33
|
+
} | null;
|
|
34
|
+
cells: SummaryCellView[];
|
|
35
|
+
templateCells: SummaryCellView[];
|
|
36
|
+
ngOnChanges(): void;
|
|
37
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GridSummaryRowComponent, never>;
|
|
38
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GridSummaryRowComponent, "div[infi-grid-summary-row]", never, { "columns": { "alias": "columns"; "required": false; }; "columnPool": { "alias": "columnPool"; "required": false; }; "templatePool": { "alias": "templatePool"; "required": false; }; "results": { "alias": "results"; "required": false; }; "leading": { "alias": "leading"; "required": false; }; "trailing": { "alias": "trailing"; "required": false; }; }, {}, never, never, true, never>;
|
|
39
|
+
}
|
|
40
|
+
export {};
|