@toolbox-web/grid-angular 1.3.1 → 1.4.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/README.md +146 -54
- package/fesm2022/toolbox-web-grid-angular-features-clipboard.mjs +58 -0
- package/fesm2022/toolbox-web-grid-angular-features-clipboard.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-column-virtualization.mjs +37 -0
- package/fesm2022/toolbox-web-grid-angular-features-column-virtualization.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-context-menu.mjs +51 -0
- package/fesm2022/toolbox-web-grid-angular-features-context-menu.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-editing.mjs +115 -1
- package/fesm2022/toolbox-web-grid-angular-features-editing.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-export.mjs +55 -2
- package/fesm2022/toolbox-web-grid-angular-features-export.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +159 -5
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-grouping-columns.mjs +83 -0
- package/fesm2022/toolbox-web-grid-angular-features-grouping-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-grouping-rows.mjs +82 -0
- package/fesm2022/toolbox-web-grid-angular-features-grouping-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs +109 -2
- package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-multi-sort.mjs +38 -0
- package/fesm2022/toolbox-web-grid-angular-features-multi-sort.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pinned-columns.mjs +37 -0
- package/fesm2022/toolbox-web-grid-angular-features-pinned-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pinned-rows.mjs +103 -0
- package/fesm2022/toolbox-web-grid-angular-features-pinned-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pivot.mjs +36 -0
- package/fesm2022/toolbox-web-grid-angular-features-pivot.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-print.mjs +58 -2
- package/fesm2022/toolbox-web-grid-angular-features-print.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-reorder-columns.mjs +52 -0
- package/fesm2022/toolbox-web-grid-angular-features-reorder-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-reorder-rows.mjs +41 -0
- package/fesm2022/toolbox-web-grid-angular-features-reorder-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs +105 -2
- package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-row-drag-drop.mjs +77 -0
- package/fesm2022/toolbox-web-grid-angular-features-row-drag-drop.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-selection.mjs +52 -2
- package/fesm2022/toolbox-web-grid-angular-features-selection.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-server-side.mjs +36 -0
- package/fesm2022/toolbox-web-grid-angular-features-server-side.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-tooltip.mjs +36 -0
- package/fesm2022/toolbox-web-grid-angular-features-tooltip.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-tree.mjs +53 -0
- package/fesm2022/toolbox-web-grid-angular-features-tree.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs +57 -2
- package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-visibility.mjs +53 -0
- package/fesm2022/toolbox-web-grid-angular-features-visibility.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular.mjs +1225 -728
- package/fesm2022/toolbox-web-grid-angular.mjs.map +1 -1
- package/package.json +1 -1
- package/types/toolbox-web-grid-angular-features-clipboard.d.ts +23 -0
- package/types/toolbox-web-grid-angular-features-clipboard.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-column-virtualization.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-column-virtualization.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-context-menu.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-context-menu.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-editing.d.ts +32 -0
- package/types/toolbox-web-grid-angular-features-editing.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-export.d.ts +21 -3
- package/types/toolbox-web-grid-angular-features-export.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-filtering.d.ts +67 -6
- package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts +25 -0
- package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-master-detail.d.ts +23 -0
- package/types/toolbox-web-grid-angular-features-master-detail.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-multi-sort.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-multi-sort.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pinned-columns.d.ts +18 -0
- package/types/toolbox-web-grid-angular-features-pinned-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pivot.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-pivot.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-print.d.ts +22 -3
- package/types/toolbox-web-grid-angular-features-print.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-reorder-columns.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-reorder-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-reorder-rows.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-reorder-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-responsive.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-responsive.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-row-drag-drop.d.ts +27 -0
- package/types/toolbox-web-grid-angular-features-row-drag-drop.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-selection.d.ts +21 -3
- package/types/toolbox-web-grid-angular-features-selection.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-server-side.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-server-side.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-tooltip.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-tooltip.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-tree.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-tree.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-undo-redo.d.ts +22 -3
- package/types/toolbox-web-grid-angular-features-undo-redo.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-visibility.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-visibility.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular.d.ts +858 -128
- package/types/toolbox-web-grid-angular.d.ts.map +1 -1
|
@@ -1,9 +1,111 @@
|
|
|
1
|
+
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerEditorMountHook, makeFlushFocusedInput } from '@toolbox-web/grid-angular';
|
|
2
|
+
export { BaseGridEditor, BaseGridEditorCVA, BaseOverlayEditor, GridColumnEditor, GridFormArray, GridLazyForm, TbwEditor, getFormArrayContext, getLazyFormContext } from '@toolbox-web/grid-angular';
|
|
1
3
|
import '@toolbox-web/grid/features/editing';
|
|
4
|
+
import * as i0 from '@angular/core';
|
|
5
|
+
import { inject, ElementRef, input, output, Directive } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `GridEditingDirective` — owns `[editing]` and the editing-specific
|
|
9
|
+
* outputs on `<tbw-grid>`. The shared outputs `cellChange` and `dataChange`
|
|
10
|
+
* stay on `Grid` because they are emitted by multiple sources, not just
|
|
11
|
+
* the editing plugin. See `GridFilteringDirective` for full rationale.
|
|
12
|
+
*
|
|
13
|
+
* Output type compatibility note: this directive uses the Angular adapter
|
|
14
|
+
* wrapper types `CellCommitEvent` / `RowCommitEvent` (re-exported from the
|
|
15
|
+
* package barrel) to stay binary-compatible with apps migrating from the
|
|
16
|
+
* deprecated bindings on `Grid`.
|
|
17
|
+
*
|
|
18
|
+
* @category Directive
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Owns the binding(s) `[editing], [cellCommit], [cellCancel], [rowCommit], [changedRowsReset], [editOpen], [beforeEditClose], [editClose], [dirtyChange]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.
|
|
22
|
+
*
|
|
23
|
+
* @category Directive
|
|
24
|
+
*/
|
|
25
|
+
class GridEditingDirective {
|
|
26
|
+
elementRef = inject((ElementRef));
|
|
27
|
+
editing = input(...(ngDevMode ? [undefined, { debugName: "editing" }] : /* istanbul ignore next */ []));
|
|
28
|
+
cellCommit = output();
|
|
29
|
+
cellCancel = output();
|
|
30
|
+
rowCommit = output();
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
changedRowsReset = output();
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
editOpen = output();
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
beforeEditClose = output();
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
editClose = output();
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
+
dirtyChange = output();
|
|
41
|
+
listeners = new Map();
|
|
42
|
+
static EVENTS = [
|
|
43
|
+
'cell-commit',
|
|
44
|
+
'cell-cancel',
|
|
45
|
+
'row-commit',
|
|
46
|
+
'changed-rows-reset',
|
|
47
|
+
'edit-open',
|
|
48
|
+
'before-edit-close',
|
|
49
|
+
'edit-close',
|
|
50
|
+
'dirty-change',
|
|
51
|
+
];
|
|
52
|
+
constructor() {
|
|
53
|
+
const grid = this.elementRef.nativeElement;
|
|
54
|
+
registerFeatureClaim(grid, 'editing', () => this.editing());
|
|
55
|
+
for (const ev of GridEditingDirective.EVENTS)
|
|
56
|
+
claimEvent(grid, ev);
|
|
57
|
+
}
|
|
58
|
+
ngOnInit() {
|
|
59
|
+
const grid = this.elementRef.nativeElement;
|
|
60
|
+
const wire = (name, out) => {
|
|
61
|
+
const l = (e) => out.emit(e.detail);
|
|
62
|
+
grid.addEventListener(name, l);
|
|
63
|
+
this.listeners.set(name, l);
|
|
64
|
+
};
|
|
65
|
+
wire('cell-commit', this.cellCommit);
|
|
66
|
+
wire('cell-cancel', this.cellCancel);
|
|
67
|
+
wire('row-commit', this.rowCommit);
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
wire('changed-rows-reset', this.changedRowsReset);
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
+
wire('edit-open', this.editOpen);
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
wire('before-edit-close', this.beforeEditClose);
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
+
wire('edit-close', this.editClose);
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
+
wire('dirty-change', this.dirtyChange);
|
|
78
|
+
}
|
|
79
|
+
ngOnDestroy() {
|
|
80
|
+
const grid = this.elementRef.nativeElement;
|
|
81
|
+
for (const [name, l] of this.listeners)
|
|
82
|
+
grid.removeEventListener(name, l);
|
|
83
|
+
this.listeners.clear();
|
|
84
|
+
unregisterFeatureClaim(grid, 'editing');
|
|
85
|
+
for (const ev of GridEditingDirective.EVENTS)
|
|
86
|
+
unclaimEvent(grid, ev);
|
|
87
|
+
}
|
|
88
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridEditingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
89
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: GridEditingDirective, isStandalone: true, selector: "tbw-grid[editing], tbw-grid[cellCommit], tbw-grid[cellCancel], tbw-grid[rowCommit], tbw-grid[changedRowsReset], tbw-grid[editOpen], tbw-grid[beforeEditClose], tbw-grid[editClose], tbw-grid[dirtyChange]", inputs: { editing: { classPropertyName: "editing", publicName: "editing", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellCommit: "cellCommit", cellCancel: "cellCancel", rowCommit: "rowCommit", changedRowsReset: "changedRowsReset", editOpen: "editOpen", beforeEditClose: "beforeEditClose", editClose: "editClose", dirtyChange: "dirtyChange" }, ngImport: i0 });
|
|
90
|
+
}
|
|
91
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridEditingDirective, decorators: [{
|
|
92
|
+
type: Directive,
|
|
93
|
+
args: [{
|
|
94
|
+
selector: 'tbw-grid[editing], tbw-grid[cellCommit], tbw-grid[cellCancel], tbw-grid[rowCommit], tbw-grid[changedRowsReset], tbw-grid[editOpen], tbw-grid[beforeEditClose], tbw-grid[editClose], tbw-grid[dirtyChange]',
|
|
95
|
+
standalone: true,
|
|
96
|
+
}]
|
|
97
|
+
}], ctorParameters: () => [], propDecorators: { editing: [{ type: i0.Input, args: [{ isSignal: true, alias: "editing", required: false }] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], cellCancel: [{ type: i0.Output, args: ["cellCancel"] }], rowCommit: [{ type: i0.Output, args: ["rowCommit"] }], changedRowsReset: [{ type: i0.Output, args: ["changedRowsReset"] }], editOpen: [{ type: i0.Output, args: ["editOpen"] }], beforeEditClose: [{ type: i0.Output, args: ["beforeEditClose"] }], editClose: [{ type: i0.Output, args: ["editClose"] }], dirtyChange: [{ type: i0.Output, args: ["dirtyChange"] }] } });
|
|
2
98
|
|
|
3
99
|
/**
|
|
4
100
|
* Editing feature for @toolbox-web/grid-angular
|
|
5
101
|
*
|
|
6
|
-
* Import this module to enable the `editing` input on Grid directive
|
|
102
|
+
* Import this module to enable the `editing` input on Grid directive AND to
|
|
103
|
+
* install the `before-edit-close` blur bridge that flushes pending input from
|
|
104
|
+
* Angular editors that commit on `(blur)` before the cell DOM is torn down by
|
|
105
|
+
* Tab / programmatic row exit.
|
|
106
|
+
*
|
|
107
|
+
* Without this import, Angular `(blur)`-committing editors silently lose
|
|
108
|
+
* pending input on programmatic row exit.
|
|
7
109
|
*
|
|
8
110
|
* @example
|
|
9
111
|
* ```typescript
|
|
@@ -14,8 +116,20 @@ import '@toolbox-web/grid/features/editing';
|
|
|
14
116
|
*
|
|
15
117
|
* @packageDocumentation
|
|
16
118
|
*/
|
|
119
|
+
// Bridge the editing plugin's `before-edit-close` event to a synchronous
|
|
120
|
+
// `.blur()` on the focused input/textarea/select inside the editor host.
|
|
121
|
+
// Angular editors that commit on `(blur)` rely on the focused control firing
|
|
122
|
+
// blur naturally, but Tab / programmatic row exit rebuilds the cell DOM
|
|
123
|
+
// synchronously without giving the focused control a chance to blur first.
|
|
124
|
+
registerEditorMountHook(({ container, gridEl }) => {
|
|
125
|
+
const flush = makeFlushFocusedInput(container);
|
|
126
|
+
gridEl.addEventListener('before-edit-close', flush);
|
|
127
|
+
return () => gridEl.removeEventListener('before-edit-close', flush);
|
|
128
|
+
});
|
|
17
129
|
|
|
18
130
|
/**
|
|
19
131
|
* Generated bundle index. Do not edit.
|
|
20
132
|
*/
|
|
133
|
+
|
|
134
|
+
export { GridEditingDirective };
|
|
21
135
|
//# sourceMappingURL=toolbox-web-grid-angular-features-editing.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-editing.mjs","sources":["../../../../libs/grid-angular/features/editing/src/index.ts","../../../../libs/grid-angular/features/editing/src/toolbox-web-grid-angular-features-editing.ts"],"sourcesContent":["/**\n * Editing feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `editing` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/editing';\n *\n * <tbw-grid [editing]=\"'dblclick'\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/editing';\nexport type { _Augmentation as _EditingAugmentation } from '@toolbox-web/grid/features/editing';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-editing.mjs","sources":["../../../../libs/grid-angular/features/editing/src/grid-editing.directive.ts","../../../../libs/grid-angular/features/editing/src/index.ts","../../../../libs/grid-angular/features/editing/src/toolbox-web-grid-angular-features-editing.ts"],"sourcesContent":["/**\n * `GridEditingDirective` — owns `[editing]` and the editing-specific\n * outputs on `<tbw-grid>`. The shared outputs `cellChange` and `dataChange`\n * stay on `Grid` because they are emitted by multiple sources, not just\n * the editing plugin. See `GridFilteringDirective` for full rationale.\n *\n * Output type compatibility note: this directive uses the Angular adapter\n * wrapper types `CellCommitEvent` / `RowCommitEvent` (re-exported from the\n * package barrel) to stay binary-compatible with apps migrating from the\n * deprecated bindings on `Grid`.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport {\n type CellCommitEvent,\n claimEvent,\n registerFeatureClaim,\n type RowCommitEvent,\n unclaimEvent,\n unregisterFeatureClaim,\n} from '@toolbox-web/grid-angular';\nimport type {\n BeforeEditCloseDetail,\n CellCancelDetail,\n ChangedRowsResetDetail,\n DirtyChangeDetail,\n EditCloseDetail,\n EditingConfig,\n EditOpenDetail,\n} from '@toolbox-web/grid/plugins/editing';\n\n/**\n * Owns the binding(s) `[editing], [cellCommit], [cellCancel], [rowCommit], [changedRowsReset], [editOpen], [beforeEditClose], [editClose], [dirtyChange]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector:\n 'tbw-grid[editing], tbw-grid[cellCommit], tbw-grid[cellCancel], tbw-grid[rowCommit], tbw-grid[changedRowsReset], tbw-grid[editOpen], tbw-grid[beforeEditClose], tbw-grid[editClose], tbw-grid[dirtyChange]',\n standalone: true,\n})\nexport class GridEditingDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly editing = input<boolean | 'click' | 'dblclick' | 'manual' | EditingConfig>();\n readonly cellCommit = output<CellCommitEvent>();\n readonly cellCancel = output<CellCancelDetail>();\n readonly rowCommit = output<RowCommitEvent>();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly changedRowsReset = output<ChangedRowsResetDetail<any>>();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly editOpen = output<EditOpenDetail<any>>();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly beforeEditClose = output<BeforeEditCloseDetail<any>>();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly editClose = output<EditCloseDetail<any>>();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly dirtyChange = output<DirtyChangeDetail<any>>();\n\n private readonly listeners = new Map<string, (e: Event) => void>();\n private static readonly EVENTS = [\n 'cell-commit',\n 'cell-cancel',\n 'row-commit',\n 'changed-rows-reset',\n 'edit-open',\n 'before-edit-close',\n 'edit-close',\n 'dirty-change',\n ] as const;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'editing', () => this.editing());\n for (const ev of GridEditingDirective.EVENTS) claimEvent(grid, ev);\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n const wire = <T>(name: string, out: { emit: (v: T) => void }): void => {\n const l = (e: Event): void => out.emit((e as CustomEvent<T>).detail);\n grid.addEventListener(name, l);\n this.listeners.set(name, l);\n };\n wire<CellCommitEvent>('cell-commit', this.cellCommit);\n wire<CellCancelDetail>('cell-cancel', this.cellCancel);\n wire<RowCommitEvent>('row-commit', this.rowCommit);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n wire<ChangedRowsResetDetail<any>>('changed-rows-reset', this.changedRowsReset);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n wire<EditOpenDetail<any>>('edit-open', this.editOpen);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n wire<BeforeEditCloseDetail<any>>('before-edit-close', this.beforeEditClose);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n wire<EditCloseDetail<any>>('edit-close', this.editClose);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n wire<DirtyChangeDetail<any>>('dirty-change', this.dirtyChange);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n for (const [name, l] of this.listeners) grid.removeEventListener(name, l);\n this.listeners.clear();\n unregisterFeatureClaim(grid, 'editing');\n for (const ev of GridEditingDirective.EVENTS) unclaimEvent(grid, ev);\n }\n}\n","/**\n * Editing feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `editing` input on Grid directive AND to\n * install the `before-edit-close` blur bridge that flushes pending input from\n * Angular editors that commit on `(blur)` before the cell DOM is torn down by\n * Tab / programmatic row exit.\n *\n * Without this import, Angular `(blur)`-committing editors silently lose\n * pending input on programmatic row exit.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/editing';\n *\n * <tbw-grid [editing]=\"'dblclick'\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport { makeFlushFocusedInput, registerEditorMountHook } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/editing';\nexport { GridEditingDirective } from './grid-editing.directive';\nexport type { _Augmentation as _EditingAugmentation } from '@toolbox-web/grid/features/editing';\n\n// ---------------------------------------------------------------------------\n// Re-exports from `@toolbox-web/grid-angular` (main entry).\n//\n// These symbols still physically live in the main `@toolbox-web/grid-angular`\n// package today, but they are editing-specific and are re-exported here so\n// consumers can import them from the feature entry that owns the runtime\n// behaviour. The same symbols are marked `@deprecated` on the main entry.\n//\n// In v2.0.0 the source files will physically move into this secondary entry\n// and the deprecated re-exports on the main entry will be removed. Searching\n// for `@deprecated` in `libs/grid-angular/src/` enumerates everything that\n// needs to move at that point.\n// ---------------------------------------------------------------------------\nexport {\n BaseGridEditor,\n BaseGridEditorCVA,\n BaseOverlayEditor,\n getFormArrayContext,\n getLazyFormContext,\n GridColumnEditor,\n GridFormArray,\n GridLazyForm,\n TbwEditor,\n} from '@toolbox-web/grid-angular';\nexport type {\n FormArrayContext,\n GridEditorContext,\n LazyFormFactory,\n OverlayPosition,\n RowFormChangeEvent,\n StructuralEditorContext,\n} from '@toolbox-web/grid-angular';\n\n// Bridge the editing plugin's `before-edit-close` event to a synchronous\n// `.blur()` on the focused input/textarea/select inside the editor host.\n// Angular editors that commit on `(blur)` rely on the focused control firing\n// blur naturally, but Tab / programmatic row exit rebuilds the cell DOM\n// synchronously without giving the focused control a chance to blur first.\nregisterEditorMountHook(({ container, gridEl }) => {\n const flush = makeFlushFocusedInput(container);\n gridEl.addEventListener('before-edit-close', flush);\n return () => gridEl.removeEventListener('before-edit-close', flush);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,58 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, input, output, Directive, DestroyRef, signal, afterNextRender } from '@angular/core';
|
|
2
3
|
import '@toolbox-web/grid/features/export';
|
|
4
|
+
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent } from '@toolbox-web/grid-angular';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `GridExportDirective` — owns the `export` input (template alias of
|
|
8
|
+
* `exportFeature`) and `(exportComplete)` on `<tbw-grid>`. See
|
|
9
|
+
* `GridFilteringDirective` for the full rationale.
|
|
10
|
+
*
|
|
11
|
+
* The TypeScript field is `exportFeature` (with `alias: 'export'`) because
|
|
12
|
+
* `export` is a reserved keyword. Templates use `[export]` / `(exportComplete)`
|
|
13
|
+
* exactly as before.
|
|
14
|
+
*
|
|
15
|
+
* @category Directive
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Owns the binding(s) `[export], [exportComplete]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.
|
|
19
|
+
*
|
|
20
|
+
* @category Directive
|
|
21
|
+
*/
|
|
22
|
+
class GridExportDirective {
|
|
23
|
+
elementRef = inject((ElementRef));
|
|
24
|
+
exportFeature = input(undefined, { ...(ngDevMode ? { debugName: "exportFeature" } : /* istanbul ignore next */ {}), alias: 'export' });
|
|
25
|
+
exportComplete = output();
|
|
26
|
+
listener;
|
|
27
|
+
constructor() {
|
|
28
|
+
const grid = this.elementRef.nativeElement;
|
|
29
|
+
registerFeatureClaim(grid, 'export', () => this.exportFeature());
|
|
30
|
+
claimEvent(grid, 'export-complete');
|
|
31
|
+
}
|
|
32
|
+
ngOnInit() {
|
|
33
|
+
const grid = this.elementRef.nativeElement;
|
|
34
|
+
this.listener = (e) => this.exportComplete.emit(e.detail);
|
|
35
|
+
grid.addEventListener('export-complete', this.listener);
|
|
36
|
+
}
|
|
37
|
+
ngOnDestroy() {
|
|
38
|
+
const grid = this.elementRef.nativeElement;
|
|
39
|
+
if (this.listener) {
|
|
40
|
+
grid.removeEventListener('export-complete', this.listener);
|
|
41
|
+
this.listener = undefined;
|
|
42
|
+
}
|
|
43
|
+
unregisterFeatureClaim(grid, 'export');
|
|
44
|
+
unclaimEvent(grid, 'export-complete');
|
|
45
|
+
}
|
|
46
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridExportDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
47
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: GridExportDirective, isStandalone: true, selector: "tbw-grid[export], tbw-grid[exportComplete]", inputs: { exportFeature: { classPropertyName: "exportFeature", publicName: "export", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { exportComplete: "exportComplete" }, ngImport: i0 });
|
|
48
|
+
}
|
|
49
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridExportDirective, decorators: [{
|
|
50
|
+
type: Directive,
|
|
51
|
+
args: [{
|
|
52
|
+
selector: 'tbw-grid[export], tbw-grid[exportComplete]',
|
|
53
|
+
standalone: true,
|
|
54
|
+
}]
|
|
55
|
+
}], ctorParameters: () => [], propDecorators: { exportFeature: [{ type: i0.Input, args: [{ isSignal: true, alias: "export", required: false }] }], exportComplete: [{ type: i0.Output, args: ["exportComplete"] }] } });
|
|
3
56
|
|
|
4
57
|
/**
|
|
5
58
|
* Export feature for @toolbox-web/grid-angular
|
|
@@ -162,5 +215,5 @@ function injectGridExport(selector = 'tbw-grid') {
|
|
|
162
215
|
* Generated bundle index. Do not edit.
|
|
163
216
|
*/
|
|
164
217
|
|
|
165
|
-
export { injectGridExport };
|
|
218
|
+
export { GridExportDirective, injectGridExport };
|
|
166
219
|
//# sourceMappingURL=toolbox-web-grid-angular-features-export.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-export.mjs","sources":["../../../../libs/grid-angular/features/export/src/index.ts","../../../../libs/grid-angular/features/export/src/toolbox-web-grid-angular-features-export.ts"],"sourcesContent":["/**\n * Export feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `export` input on Grid directive.\n * Also exports `injectGridExport()` for programmatic export control.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/export';\n *\n * <tbw-grid [export]=\"true\" />\n * <tbw-grid [export]=\"{ fileName: 'data.csv' }\" />\n * ```\n *\n * @example Using injectGridExport\n * ```typescript\n * import { injectGridExport } from '@toolbox-web/grid-angular/features/export';\n *\n * @Component({...})\n * export class MyComponent {\n * private gridExport = injectGridExport();\n *\n * exportData() {\n * this.gridExport.exportToCsv('employees.csv');\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport '@toolbox-web/grid/features/export';\nimport { ExportPlugin, type ExportFormat, type ExportParams } from '@toolbox-web/grid/plugins/export';\nexport type { _Augmentation as _ExportAugmentation } from '@toolbox-web/grid/features/export';\n\n/**\n * Export methods returned from injectGridExport.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n * This ensures it works with lazy-rendered tabs, conditional rendering, etc.\n */\nexport interface ExportMethods {\n /**\n * Export grid data to CSV file.\n * @param filename - Optional filename (defaults to 'export.csv')\n * @param params - Optional export parameters\n */\n exportToCsv: (filename?: string, params?: Partial<ExportParams>) => void;\n\n /**\n * Export grid data to Excel file (XML Spreadsheet format).\n * @param filename - Optional filename (defaults to 'export.xlsx')\n * @param params - Optional export parameters\n */\n exportToExcel: (filename?: string, params?: Partial<ExportParams>) => void;\n\n /**\n * Export grid data to JSON file.\n * @param filename - Optional filename (defaults to 'export.json')\n * @param params - Optional export parameters\n */\n exportToJson: (filename?: string, params?: Partial<ExportParams>) => void;\n\n /**\n * Check if an export is currently in progress.\n */\n isExporting: () => boolean;\n\n /**\n * Get information about the last export.\n */\n getLastExport: () => { format: ExportFormat; timestamp: Date } | null;\n\n /**\n * Signal indicating if grid is ready.\n * The grid is discovered lazily, so this updates when first method call succeeds.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic export control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization. This ensures it works reliably with:\n * - Lazy-rendered tabs\n * - Conditional rendering (*ngIf)\n * - Dynamic component loading\n *\n * @example\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/export';\n * import { injectGridExport } from '@toolbox-web/grid-angular/features/export';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <button (click)=\"handleExport()\">Export CSV</button>\n * <tbw-grid [rows]=\"rows\" [export]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * gridExport = injectGridExport();\n *\n * handleExport() {\n * this.gridExport.exportToCsv('employees.csv');\n * }\n * }\n * ```\n *\n * @param selector - Optional CSS selector to target a specific grid element.\n * Defaults to `'tbw-grid'` (first grid in the component). Use when the\n * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.\n */\nexport function injectGridExport(selector = 'tbw-grid'): ExportMethods {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n // Lazy discovery: cached grid reference\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n /**\n * Lazily find the grid element. Called on each method invocation.\n * Caches the reference once found and triggers ready() check.\n */\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n // Start ready() check only once\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n if (grid.getPluginByName('export')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): ExportPlugin | undefined => {\n return getGrid()?.getPluginByName('export') as ExportPlugin | undefined;\n };\n\n // Eagerly discover the grid after the first render so isReady updates\n // without requiring a programmatic method call. Falls back to a\n // MutationObserver for lazy-rendered tabs, *ngIf, @defer, etc.\n afterNextRender(() => {\n if (getGrid()) return;\n\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n if (getGrid()) observer.disconnect();\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n\n exportToCsv: (filename?: string, params?: Partial<ExportParams>) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:export] ExportPlugin not found.\\n\\n` +\n ` → Enable export on the grid:\\n` +\n ` <tbw-grid [export]=\"true\" />`,\n );\n return;\n }\n plugin.exportCsv({ ...params, fileName: filename ?? params?.fileName ?? 'export.csv' });\n },\n\n exportToExcel: (filename?: string, params?: Partial<ExportParams>) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:export] ExportPlugin not found.\\n\\n` +\n ` → Enable export on the grid:\\n` +\n ` <tbw-grid [export]=\"true\" />`,\n );\n return;\n }\n plugin.exportExcel({ ...params, fileName: filename ?? params?.fileName ?? 'export.xlsx' });\n },\n\n exportToJson: (filename?: string, params?: Partial<ExportParams>) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:export] ExportPlugin not found.\\n\\n` +\n ` → Enable export on the grid:\\n` +\n ` <tbw-grid [export]=\"true\" />`,\n );\n return;\n }\n plugin.exportJson({ ...params, fileName: filename ?? params?.fileName ?? 'export.json' });\n },\n\n isExporting: () => {\n return getPlugin()?.isExporting() ?? false;\n },\n\n getLastExport: () => {\n return getPlugin()?.getLastExport() ?? null;\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-export.mjs","sources":["../../../../libs/grid-angular/features/export/src/grid-export.directive.ts","../../../../libs/grid-angular/features/export/src/index.ts","../../../../libs/grid-angular/features/export/src/toolbox-web-grid-angular-features-export.ts"],"sourcesContent":["/**\n * `GridExportDirective` — owns the `export` input (template alias of\n * `exportFeature`) and `(exportComplete)` on `<tbw-grid>`. See\n * `GridFilteringDirective` for the full rationale.\n *\n * The TypeScript field is `exportFeature` (with `alias: 'export'`) because\n * `export` is a reserved keyword. Templates use `[export]` / `(exportComplete)`\n * exactly as before.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { ExportCompleteDetail, ExportConfig } from '@toolbox-web/grid/plugins/export';\n\n/**\n * Owns the binding(s) `[export], [exportComplete]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[export], tbw-grid[exportComplete]',\n standalone: true,\n})\nexport class GridExportDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly exportFeature = input<boolean | ExportConfig>(undefined, { alias: 'export' });\n readonly exportComplete = output<ExportCompleteDetail>();\n\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'export', () => this.exportFeature());\n claimEvent(grid, 'export-complete');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event): void => this.exportComplete.emit((e as CustomEvent<ExportCompleteDetail>).detail);\n grid.addEventListener('export-complete', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('export-complete', this.listener);\n this.listener = undefined;\n }\n unregisterFeatureClaim(grid, 'export');\n unclaimEvent(grid, 'export-complete');\n }\n}\n","/**\n * Export feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `export` input on Grid directive.\n * Also exports `injectGridExport()` for programmatic export control.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/export';\n *\n * <tbw-grid [export]=\"true\" />\n * <tbw-grid [export]=\"{ fileName: 'data.csv' }\" />\n * ```\n *\n * @example Using injectGridExport\n * ```typescript\n * import { injectGridExport } from '@toolbox-web/grid-angular/features/export';\n *\n * @Component({...})\n * export class MyComponent {\n * private gridExport = injectGridExport();\n *\n * exportData() {\n * this.gridExport.exportToCsv('employees.csv');\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport '@toolbox-web/grid/features/export';\nimport { ExportPlugin, type ExportFormat, type ExportParams } from '@toolbox-web/grid/plugins/export';\nexport { GridExportDirective } from './grid-export.directive';\nexport type { _Augmentation as _ExportAugmentation } from '@toolbox-web/grid/features/export';\n\n/**\n * Export methods returned from injectGridExport.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n * This ensures it works with lazy-rendered tabs, conditional rendering, etc.\n */\nexport interface ExportMethods {\n /**\n * Export grid data to CSV file.\n * @param filename - Optional filename (defaults to 'export.csv')\n * @param params - Optional export parameters\n */\n exportToCsv: (filename?: string, params?: Partial<ExportParams>) => void;\n\n /**\n * Export grid data to Excel file (XML Spreadsheet format).\n * @param filename - Optional filename (defaults to 'export.xlsx')\n * @param params - Optional export parameters\n */\n exportToExcel: (filename?: string, params?: Partial<ExportParams>) => void;\n\n /**\n * Export grid data to JSON file.\n * @param filename - Optional filename (defaults to 'export.json')\n * @param params - Optional export parameters\n */\n exportToJson: (filename?: string, params?: Partial<ExportParams>) => void;\n\n /**\n * Check if an export is currently in progress.\n */\n isExporting: () => boolean;\n\n /**\n * Get information about the last export.\n */\n getLastExport: () => { format: ExportFormat; timestamp: Date } | null;\n\n /**\n * Signal indicating if grid is ready.\n * The grid is discovered lazily, so this updates when first method call succeeds.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic export control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization. This ensures it works reliably with:\n * - Lazy-rendered tabs\n * - Conditional rendering (*ngIf)\n * - Dynamic component loading\n *\n * @example\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/export';\n * import { injectGridExport } from '@toolbox-web/grid-angular/features/export';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <button (click)=\"handleExport()\">Export CSV</button>\n * <tbw-grid [rows]=\"rows\" [export]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * gridExport = injectGridExport();\n *\n * handleExport() {\n * this.gridExport.exportToCsv('employees.csv');\n * }\n * }\n * ```\n *\n * @param selector - Optional CSS selector to target a specific grid element.\n * Defaults to `'tbw-grid'` (first grid in the component). Use when the\n * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.\n */\nexport function injectGridExport(selector = 'tbw-grid'): ExportMethods {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n // Lazy discovery: cached grid reference\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n /**\n * Lazily find the grid element. Called on each method invocation.\n * Caches the reference once found and triggers ready() check.\n */\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n // Start ready() check only once\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n if (grid.getPluginByName('export')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): ExportPlugin | undefined => {\n return getGrid()?.getPluginByName('export') as ExportPlugin | undefined;\n };\n\n // Eagerly discover the grid after the first render so isReady updates\n // without requiring a programmatic method call. Falls back to a\n // MutationObserver for lazy-rendered tabs, *ngIf, @defer, etc.\n afterNextRender(() => {\n if (getGrid()) return;\n\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n if (getGrid()) observer.disconnect();\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n\n exportToCsv: (filename?: string, params?: Partial<ExportParams>) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:export] ExportPlugin not found.\\n\\n` +\n ` → Enable export on the grid:\\n` +\n ` <tbw-grid [export]=\"true\" />`,\n );\n return;\n }\n plugin.exportCsv({ ...params, fileName: filename ?? params?.fileName ?? 'export.csv' });\n },\n\n exportToExcel: (filename?: string, params?: Partial<ExportParams>) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:export] ExportPlugin not found.\\n\\n` +\n ` → Enable export on the grid:\\n` +\n ` <tbw-grid [export]=\"true\" />`,\n );\n return;\n }\n plugin.exportExcel({ ...params, fileName: filename ?? params?.fileName ?? 'export.xlsx' });\n },\n\n exportToJson: (filename?: string, params?: Partial<ExportParams>) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:export] ExportPlugin not found.\\n\\n` +\n ` → Enable export on the grid:\\n` +\n ` <tbw-grid [export]=\"true\" />`,\n );\n return;\n }\n plugin.exportJson({ ...params, fileName: filename ?? params?.fileName ?? 'export.json' });\n },\n\n isExporting: () => {\n return getPlugin()?.isExporting() ?? false;\n },\n\n getLastExport: () => {\n return getPlugin()?.getLastExport() ?? null;\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,155 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, input, output, Directive, DestroyRef, signal, afterNextRender } from '@angular/core';
|
|
3
|
+
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerFilterPanelTypeDefaultBridge } from '@toolbox-web/grid-angular';
|
|
4
|
+
export { BaseFilterPanel } from '@toolbox-web/grid-angular';
|
|
2
5
|
import '@toolbox-web/grid/features/filtering';
|
|
3
6
|
|
|
7
|
+
/**
|
|
8
|
+
* `GridFilteringDirective` — attribute-selector directive that owns the
|
|
9
|
+
* `filtering` input and the `filterChange` output on `<tbw-grid>`.
|
|
10
|
+
*
|
|
11
|
+
* ## Why this exists
|
|
12
|
+
*
|
|
13
|
+
* Historically these bindings lived on the central `Grid` directive in
|
|
14
|
+
* `@toolbox-web/grid-angular`. That meant the typed surface for the
|
|
15
|
+
* filtering plugin shipped in the core bundle of every consumer, even those
|
|
16
|
+
* that never imported the filtering feature. Moving them here lets the
|
|
17
|
+
* surface tree-shake away with the rest of the feature when it is not
|
|
18
|
+
* imported, matching the philosophy of the React / Vue adapters and the
|
|
19
|
+
* web-component core (where unloaded plugins simply don't exist on the
|
|
20
|
+
* element).
|
|
21
|
+
*
|
|
22
|
+
* ## Usage
|
|
23
|
+
*
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { Component } from '@angular/core';
|
|
26
|
+
* import { Grid } from '@toolbox-web/grid-angular';
|
|
27
|
+
* import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';
|
|
28
|
+
*
|
|
29
|
+
* @Component({
|
|
30
|
+
* selector: 'app-grid',
|
|
31
|
+
* imports: [Grid, GridFilteringDirective],
|
|
32
|
+
* template: `
|
|
33
|
+
* <tbw-grid [rows]="rows" [filtering]="true" (filterChange)="onFilter($event)" />
|
|
34
|
+
* `,
|
|
35
|
+
* })
|
|
36
|
+
* export class AppGridComponent {}
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* ## Backward compatibility (v1.x)
|
|
40
|
+
*
|
|
41
|
+
* The matching `filtering` input and `filterChange` output also still exist
|
|
42
|
+
* on `Grid` (marked `@deprecated`) so existing apps that bind them without
|
|
43
|
+
* importing `GridFilteringDirective` continue to work — those will be
|
|
44
|
+
* removed in v2.0.0. When both this directive and the deprecated bindings
|
|
45
|
+
* are present, the directive wins via the per-grid claims registry in
|
|
46
|
+
* `internal/feature-claims.ts`: `Grid` consults the registry and skips its
|
|
47
|
+
* own plugin creation + event wiring for any claimed feature.
|
|
48
|
+
*
|
|
49
|
+
* @category Directive
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Owns the `[filtering]` input and `(filterChange)` output on `<tbw-grid>`.
|
|
53
|
+
*
|
|
54
|
+
* Selector matches when *either* binding is present so users can pick the
|
|
55
|
+
* style that suits their template — both go through the same claim and the
|
|
56
|
+
* same wiring.
|
|
57
|
+
* @category Directive
|
|
58
|
+
*/
|
|
59
|
+
class GridFilteringDirective {
|
|
60
|
+
elementRef = inject((ElementRef));
|
|
61
|
+
/**
|
|
62
|
+
* Enable column filtering. Identical semantics to the deprecated input on
|
|
63
|
+
* `Grid` — this directive owns the binding when both are present.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```html
|
|
67
|
+
* <tbw-grid [filtering]="true" />
|
|
68
|
+
* <tbw-grid [filtering]="{ debounceMs: 200 }" />
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
filtering = input(...(ngDevMode ? [undefined, { debugName: "filtering" }] : /* istanbul ignore next */ []));
|
|
73
|
+
/**
|
|
74
|
+
* Emitted when filter values change.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```html
|
|
78
|
+
* <tbw-grid (filterChange)="onFilterChange($event)" />
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
filterChange = output();
|
|
82
|
+
// Listener kept so we can detach in `ngOnDestroy`.
|
|
83
|
+
listener;
|
|
84
|
+
constructor() {
|
|
85
|
+
const grid = this.elementRef.nativeElement;
|
|
86
|
+
// Tell `Grid` we own this feature's input. Reading `this.filtering()`
|
|
87
|
+
// inside the getter establishes a reactive dependency in `Grid`'s
|
|
88
|
+
// `createFeaturePlugins` effect — when our input changes, that effect
|
|
89
|
+
// re-runs and the plugin config is updated.
|
|
90
|
+
registerFeatureClaim(grid, 'filtering', () => this.filtering());
|
|
91
|
+
// Tell `Grid` we own the matching event so it doesn't double-emit on
|
|
92
|
+
// its own deprecated `filterChange` output.
|
|
93
|
+
claimEvent(grid, 'filter-change');
|
|
94
|
+
}
|
|
95
|
+
ngOnInit() {
|
|
96
|
+
const grid = this.elementRef.nativeElement;
|
|
97
|
+
this.listener = (e) => {
|
|
98
|
+
this.filterChange.emit(e.detail);
|
|
99
|
+
};
|
|
100
|
+
grid.addEventListener('filter-change', this.listener);
|
|
101
|
+
}
|
|
102
|
+
ngOnDestroy() {
|
|
103
|
+
const grid = this.elementRef.nativeElement;
|
|
104
|
+
if (this.listener) {
|
|
105
|
+
grid.removeEventListener('filter-change', this.listener);
|
|
106
|
+
this.listener = undefined;
|
|
107
|
+
}
|
|
108
|
+
// Drop the claims so that, if the directive is removed via *ngIf but
|
|
109
|
+
// the host `<tbw-grid>` survives, `Grid`'s deprecated bindings take
|
|
110
|
+
// back over without leaving stale ownership behind.
|
|
111
|
+
unregisterFeatureClaim(grid, 'filtering');
|
|
112
|
+
unclaimEvent(grid, 'filter-change');
|
|
113
|
+
}
|
|
114
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridFilteringDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
115
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: GridFilteringDirective, isStandalone: true, selector: "tbw-grid[filtering], tbw-grid[filterChange]", inputs: { filtering: { classPropertyName: "filtering", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterChange: "filterChange" }, ngImport: i0 });
|
|
116
|
+
}
|
|
117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridFilteringDirective, decorators: [{
|
|
118
|
+
type: Directive,
|
|
119
|
+
args: [{
|
|
120
|
+
selector: 'tbw-grid[filtering], tbw-grid[filterChange]',
|
|
121
|
+
standalone: true,
|
|
122
|
+
}]
|
|
123
|
+
}], ctorParameters: () => [], propDecorators: { filtering: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtering", required: false }] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }] } });
|
|
124
|
+
|
|
4
125
|
/**
|
|
5
126
|
* Filtering feature for @toolbox-web/grid-angular
|
|
6
127
|
*
|
|
7
|
-
*
|
|
8
|
-
* Also exports `injectGridFiltering()` for programmatic filter control.
|
|
128
|
+
* Two ways to use:
|
|
9
129
|
*
|
|
10
|
-
*
|
|
130
|
+
* 1. **Recommended (tree-shakeable surface):** add `GridFilteringDirective`
|
|
131
|
+
* to your component's `imports`. The directive owns the `[filtering]`
|
|
132
|
+
* input and `(filterChange)` output, so the typed surface tree-shakes
|
|
133
|
+
* away when the feature is not imported.
|
|
134
|
+
* 2. **Legacy (non-breaking, deprecated):** side-effect import the feature
|
|
135
|
+
* entry; the matching `[filtering]` / `(filterChange)` bindings on the
|
|
136
|
+
* central `Grid` directive will work as in v1.x. These bindings on `Grid`
|
|
137
|
+
* are marked `@deprecated` and will be removed in v2.0.0.
|
|
138
|
+
*
|
|
139
|
+
* Either way `injectGridFiltering()` is available for programmatic control.
|
|
140
|
+
*
|
|
141
|
+
* @example Recommended (directive-owned binding)
|
|
142
|
+
* ```typescript
|
|
143
|
+
* import { Grid } from '@toolbox-web/grid-angular';
|
|
144
|
+
* import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';
|
|
145
|
+
*
|
|
146
|
+
* @Component({
|
|
147
|
+
* imports: [Grid, GridFilteringDirective],
|
|
148
|
+
* template: `<tbw-grid [filtering]="true" (filterChange)="onChange($event)" />`,
|
|
149
|
+
* })
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @example Legacy (deprecated; works without importing the directive)
|
|
11
153
|
* ```typescript
|
|
12
154
|
* import '@toolbox-web/grid-angular/features/filtering';
|
|
13
155
|
*
|
|
@@ -31,6 +173,18 @@ import '@toolbox-web/grid/features/filtering';
|
|
|
31
173
|
*
|
|
32
174
|
* @packageDocumentation
|
|
33
175
|
*/
|
|
176
|
+
// Bridge any Angular component classes used as `filterPanelRenderer` (in
|
|
177
|
+
// `gridConfig.typeDefaults` or via `provideGridTypeDefaults`) to the
|
|
178
|
+
// `(container, params) => void` form required by FilteringPlugin. Without
|
|
179
|
+
// this import, component-class filterPanelRenderers are silently dropped \u2014
|
|
180
|
+
// the same precondition as the FilteringPlugin itself (TBW031).
|
|
181
|
+
registerFilterPanelTypeDefaultBridge((rendererValue, adapter) => {
|
|
182
|
+
const componentClass = rendererValue;
|
|
183
|
+
const mount = adapter.mountComponentRenderer(componentClass, (params) => ({ params }));
|
|
184
|
+
return (container, params) => {
|
|
185
|
+
container.appendChild(mount(params).hostElement);
|
|
186
|
+
};
|
|
187
|
+
});
|
|
34
188
|
/**
|
|
35
189
|
* Angular inject function for programmatic filter control.
|
|
36
190
|
*
|
|
@@ -181,5 +335,5 @@ function injectGridFiltering(selector = 'tbw-grid') {
|
|
|
181
335
|
* Generated bundle index. Do not edit.
|
|
182
336
|
*/
|
|
183
337
|
|
|
184
|
-
export { injectGridFiltering };
|
|
338
|
+
export { GridFilteringDirective, injectGridFiltering };
|
|
185
339
|
//# sourceMappingURL=toolbox-web-grid-angular-features-filtering.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-filtering.mjs","sources":["../../../../libs/grid-angular/features/filtering/src/index.ts","../../../../libs/grid-angular/features/filtering/src/toolbox-web-grid-angular-features-filtering.ts"],"sourcesContent":["/**\n * Filtering feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `filtering` input on Grid directive.\n * Also exports `injectGridFiltering()` for programmatic filter control.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/filtering';\n *\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n *\n * @example Using injectGridFiltering\n * ```typescript\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({...})\n * export class MyComponent {\n * private filtering = injectGridFiltering();\n *\n * filterByStatus(status: string) {\n * this.filtering.setFilter('status', { operator: 'equals', value: status });\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport '@toolbox-web/grid/features/filtering';\nimport { FilteringPlugin, type BlankMode, type FilterModel } from '@toolbox-web/grid/plugins/filtering';\nexport type { _Augmentation as _FilteringAugmentation } from '@toolbox-web/grid/features/filtering';\n\n/**\n * Filtering methods returned from injectGridFiltering.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n */\nexport interface FilteringMethods {\n /**\n * Set a filter on a specific field.\n * @param field - The field name to filter\n * @param filter - Filter configuration, or null to remove\n * @param options - `{ silent: true }` applies the filter without emitting `filter-change`\n */\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => void;\n\n /**\n * Get the current filter for a field.\n */\n getFilter: (field: string) => FilterModel | undefined;\n\n /**\n * Get all active filters.\n */\n getFilters: () => FilterModel[];\n\n /**\n * Set all filters at once (replaces existing).\n * @param options - `{ silent: true }` applies filters without emitting `filter-change`\n */\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => void;\n\n /**\n * Clear all active filters.\n * @param options - `{ silent: true }` clears filters without emitting `filter-change`\n */\n clearAllFilters: (options?: { silent?: boolean }) => void;\n\n /**\n * Clear filter for a specific field.\n * @param options - `{ silent: true }` clears filter without emitting `filter-change`\n */\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => void;\n\n /**\n * Check if a field has an active filter.\n */\n isFieldFiltered: (field: string) => boolean;\n\n /**\n * Get the count of rows after filtering.\n */\n getFilteredRowCount: () => number;\n\n /**\n * Get unique values for a field (for building filter dropdowns).\n */\n getUniqueValues: (field: string) => unknown[];\n\n /**\n * Get set filters whose values no longer match any rows in the current data.\n */\n getStaleFilters: () => FilterModel[];\n\n /**\n * Get the current blank mode for a field.\n */\n getBlankMode: (field: string) => BlankMode;\n\n /**\n * Toggle blank filter mode for a field.\n */\n toggleBlankFilter: (field: string, mode: BlankMode) => void;\n\n /**\n * Signal indicating if grid is ready.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic filter control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization.\n *\n * @example\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/filtering';\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <input (input)=\"applyFilter($event)\" placeholder=\"Filter by name...\" />\n * <span>{{ filtering.getFilteredRowCount() }} results</span>\n * <button (click)=\"filtering.clearAllFilters()\">Clear</button>\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * filtering = injectGridFiltering();\n *\n * applyFilter(event: Event) {\n * const value = (event.target as HTMLInputElement).value;\n * this.filtering.setFilter('name', value ? { operator: 'contains', value } : null);\n * }\n * }\n * ```\n *\n * @param selector - Optional CSS selector to target a specific grid element.\n * Defaults to `'tbw-grid'` (first grid in the component). Use when the\n * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.\n */\nexport function injectGridFiltering(selector = 'tbw-grid'): FilteringMethods {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n // If the plugin is already attached, signal readiness immediately.\n // Otherwise, Angular's Grid directive may not have applied gridConfig\n // yet (it uses effect + queueMicrotask). Defer to let pending\n // microtasks flush before signaling readiness.\n if (grid.getPluginByName('filtering')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): FilteringPlugin | undefined => {\n return getGrid()?.getPluginByName('filtering') as FilteringPlugin | undefined;\n };\n\n // Eagerly discover the grid after the first render so isReady updates\n // without requiring a programmatic method call. Falls back to a\n // MutationObserver for lazy-rendered tabs, *ngIf, @defer, etc.\n afterNextRender(() => {\n if (getGrid()) return;\n\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n if (getGrid()) observer.disconnect();\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilter(field, filter, options);\n },\n\n getFilter: (field: string) => getPlugin()?.getFilter(field),\n\n getFilters: () => getPlugin()?.getFilters() ?? [],\n\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilterModel(filters, options);\n },\n\n clearAllFilters: (options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearAllFilters(options);\n },\n\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearFieldFilter(field, options);\n },\n\n isFieldFiltered: (field: string) => getPlugin()?.isFieldFiltered(field) ?? false,\n\n getFilteredRowCount: () => getPlugin()?.getFilteredRowCount() ?? 0,\n\n getUniqueValues: (field: string) => getPlugin()?.getUniqueValues(field) ?? [],\n\n getStaleFilters: () => getPlugin()?.getStaleFilters() ?? [],\n\n getBlankMode: (field: string) => getPlugin()?.getBlankMode(field) ?? 'all',\n\n toggleBlankFilter: (field: string, mode: BlankMode) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.toggleBlankFilter(field, mode);\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-filtering.mjs","sources":["../../../../libs/grid-angular/features/filtering/src/grid-filtering.directive.ts","../../../../libs/grid-angular/features/filtering/src/index.ts","../../../../libs/grid-angular/features/filtering/src/toolbox-web-grid-angular-features-filtering.ts"],"sourcesContent":["/**\n * `GridFilteringDirective` — attribute-selector directive that owns the\n * `filtering` input and the `filterChange` output on `<tbw-grid>`.\n *\n * ## Why this exists\n *\n * Historically these bindings lived on the central `Grid` directive in\n * `@toolbox-web/grid-angular`. That meant the typed surface for the\n * filtering plugin shipped in the core bundle of every consumer, even those\n * that never imported the filtering feature. Moving them here lets the\n * surface tree-shake away with the rest of the feature when it is not\n * imported, matching the philosophy of the React / Vue adapters and the\n * web-component core (where unloaded plugins simply don't exist on the\n * element).\n *\n * ## Usage\n *\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-grid',\n * imports: [Grid, GridFilteringDirective],\n * template: `\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\" (filterChange)=\"onFilter($event)\" />\n * `,\n * })\n * export class AppGridComponent {}\n * ```\n *\n * ## Backward compatibility (v1.x)\n *\n * The matching `filtering` input and `filterChange` output also still exist\n * on `Grid` (marked `@deprecated`) so existing apps that bind them without\n * importing `GridFilteringDirective` continue to work — those will be\n * removed in v2.0.0. When both this directive and the deprecated bindings\n * are present, the directive wins via the per-grid claims registry in\n * `internal/feature-claims.ts`: `Grid` consults the registry and skips its\n * own plugin creation + event wiring for any claimed feature.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { FilterChangeDetail, FilterConfig } from '@toolbox-web/grid/plugins/filtering';\n\n/**\n * Owns the `[filtering]` input and `(filterChange)` output on `<tbw-grid>`.\n *\n * Selector matches when *either* binding is present so users can pick the\n * style that suits their template — both go through the same claim and the\n * same wiring.\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[filtering], tbw-grid[filterChange]',\n standalone: true,\n})\nexport class GridFilteringDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n /**\n * Enable column filtering. Identical semantics to the deprecated input on\n * `Grid` — this directive owns the binding when both are present.\n *\n * @example\n * ```html\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly filtering = input<boolean | FilterConfig<any>>();\n\n /**\n * Emitted when filter values change.\n *\n * @example\n * ```html\n * <tbw-grid (filterChange)=\"onFilterChange($event)\" />\n * ```\n */\n readonly filterChange = output<FilterChangeDetail>();\n\n // Listener kept so we can detach in `ngOnDestroy`.\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n // Tell `Grid` we own this feature's input. Reading `this.filtering()`\n // inside the getter establishes a reactive dependency in `Grid`'s\n // `createFeaturePlugins` effect — when our input changes, that effect\n // re-runs and the plugin config is updated.\n registerFeatureClaim(grid, 'filtering', () => this.filtering());\n // Tell `Grid` we own the matching event so it doesn't double-emit on\n // its own deprecated `filterChange` output.\n claimEvent(grid, 'filter-change');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event) => {\n this.filterChange.emit((e as CustomEvent<FilterChangeDetail>).detail);\n };\n grid.addEventListener('filter-change', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('filter-change', this.listener);\n this.listener = undefined;\n }\n // Drop the claims so that, if the directive is removed via *ngIf but\n // the host `<tbw-grid>` survives, `Grid`'s deprecated bindings take\n // back over without leaving stale ownership behind.\n unregisterFeatureClaim(grid, 'filtering');\n unclaimEvent(grid, 'filter-change');\n }\n}\n","/**\n * Filtering feature for @toolbox-web/grid-angular\n *\n * Two ways to use:\n *\n * 1. **Recommended (tree-shakeable surface):** add `GridFilteringDirective`\n * to your component's `imports`. The directive owns the `[filtering]`\n * input and `(filterChange)` output, so the typed surface tree-shakes\n * away when the feature is not imported.\n * 2. **Legacy (non-breaking, deprecated):** side-effect import the feature\n * entry; the matching `[filtering]` / `(filterChange)` bindings on the\n * central `Grid` directive will work as in v1.x. These bindings on `Grid`\n * are marked `@deprecated` and will be removed in v2.0.0.\n *\n * Either way `injectGridFiltering()` is available for programmatic control.\n *\n * @example Recommended (directive-owned binding)\n * ```typescript\n * import { Grid } from '@toolbox-web/grid-angular';\n * import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * imports: [Grid, GridFilteringDirective],\n * template: `<tbw-grid [filtering]=\"true\" (filterChange)=\"onChange($event)\" />`,\n * })\n * ```\n *\n * @example Legacy (deprecated; works without importing the directive)\n * ```typescript\n * import '@toolbox-web/grid-angular/features/filtering';\n *\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n *\n * @example Using injectGridFiltering\n * ```typescript\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({...})\n * export class MyComponent {\n * private filtering = injectGridFiltering();\n *\n * filterByStatus(status: string) {\n * this.filtering.setFilter('status', { operator: 'equals', value: status });\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFilterPanelTypeDefaultBridge, type GridAdapter } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/filtering';\nimport {\n FilteringPlugin,\n type BlankMode,\n type FilterModel,\n type FilterPanelParams,\n} from '@toolbox-web/grid/plugins/filtering';\nexport type { _Augmentation as _FilteringAugmentation } from '@toolbox-web/grid/features/filtering';\n\n// Attribute-selector directive that owns the `[filtering]` input and\n// `(filterChange)` output on `<tbw-grid>`. Add to your component's `imports`\n// alongside `Grid` to opt into the feature directly via the binding. The\n// matching deprecated bindings on `Grid` remain as a v1.x compatibility\n// shim and will be removed in v2.0.0.\nexport { GridFilteringDirective } from './grid-filtering.directive';\n\n// ---------------------------------------------------------------------------\n// Re-exports from `@toolbox-web/grid-angular` (main entry).\n//\n// `BaseFilterPanel` is filtering-specific (implements `FilterPanel` from the\n// filtering plugin). It still physically lives in the main entry today, but\n// is re-exported here so consumers can import it from the feature entry that\n// owns the runtime behaviour. The same symbol is `@deprecated` on the main\n// entry; in v2.0.0 the source will physically move into this secondary entry\n// and the deprecated re-export on the main entry will be removed.\n// ---------------------------------------------------------------------------\nexport { BaseFilterPanel } from '@toolbox-web/grid-angular';\n\n// Bridge any Angular component classes used as `filterPanelRenderer` (in\n// `gridConfig.typeDefaults` or via `provideGridTypeDefaults`) to the\n// `(container, params) => void` form required by FilteringPlugin. Without\n// this import, component-class filterPanelRenderers are silently dropped \\u2014\n// the same precondition as the FilteringPlugin itself (TBW031).\nregisterFilterPanelTypeDefaultBridge((rendererValue: unknown, adapter: GridAdapter) => {\n const componentClass = rendererValue as Type<unknown>;\n const mount = adapter.mountComponentRenderer<FilterPanelParams>(componentClass, (params) => ({ params }));\n return (container: HTMLElement, params: FilterPanelParams) => {\n container.appendChild(mount(params).hostElement);\n };\n});\n\n/**\n * Filtering methods returned from injectGridFiltering.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n */\nexport interface FilteringMethods {\n /**\n * Set a filter on a specific field.\n * @param field - The field name to filter\n * @param filter - Filter configuration, or null to remove\n * @param options - `{ silent: true }` applies the filter without emitting `filter-change`\n */\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => void;\n\n /**\n * Get the current filter for a field.\n */\n getFilter: (field: string) => FilterModel | undefined;\n\n /**\n * Get all active filters.\n */\n getFilters: () => FilterModel[];\n\n /**\n * Set all filters at once (replaces existing).\n * @param options - `{ silent: true }` applies filters without emitting `filter-change`\n */\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => void;\n\n /**\n * Clear all active filters.\n * @param options - `{ silent: true }` clears filters without emitting `filter-change`\n */\n clearAllFilters: (options?: { silent?: boolean }) => void;\n\n /**\n * Clear filter for a specific field.\n * @param options - `{ silent: true }` clears filter without emitting `filter-change`\n */\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => void;\n\n /**\n * Check if a field has an active filter.\n */\n isFieldFiltered: (field: string) => boolean;\n\n /**\n * Get the count of rows after filtering.\n */\n getFilteredRowCount: () => number;\n\n /**\n * Get unique values for a field (for building filter dropdowns).\n */\n getUniqueValues: (field: string) => unknown[];\n\n /**\n * Get set filters whose values no longer match any rows in the current data.\n */\n getStaleFilters: () => FilterModel[];\n\n /**\n * Get the current blank mode for a field.\n */\n getBlankMode: (field: string) => BlankMode;\n\n /**\n * Toggle blank filter mode for a field.\n */\n toggleBlankFilter: (field: string, mode: BlankMode) => void;\n\n /**\n * Signal indicating if grid is ready.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic filter control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization.\n *\n * @example\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/filtering';\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <input (input)=\"applyFilter($event)\" placeholder=\"Filter by name...\" />\n * <span>{{ filtering.getFilteredRowCount() }} results</span>\n * <button (click)=\"filtering.clearAllFilters()\">Clear</button>\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * filtering = injectGridFiltering();\n *\n * applyFilter(event: Event) {\n * const value = (event.target as HTMLInputElement).value;\n * this.filtering.setFilter('name', value ? { operator: 'contains', value } : null);\n * }\n * }\n * ```\n *\n * @param selector - Optional CSS selector to target a specific grid element.\n * Defaults to `'tbw-grid'` (first grid in the component). Use when the\n * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.\n */\nexport function injectGridFiltering(selector = 'tbw-grid'): FilteringMethods {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n // If the plugin is already attached, signal readiness immediately.\n // Otherwise, Angular's Grid directive may not have applied gridConfig\n // yet (it uses effect + queueMicrotask). Defer to let pending\n // microtasks flush before signaling readiness.\n if (grid.getPluginByName('filtering')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): FilteringPlugin | undefined => {\n return getGrid()?.getPluginByName('filtering') as FilteringPlugin | undefined;\n };\n\n // Eagerly discover the grid after the first render so isReady updates\n // without requiring a programmatic method call. Falls back to a\n // MutationObserver for lazy-rendered tabs, *ngIf, @defer, etc.\n afterNextRender(() => {\n if (getGrid()) return;\n\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n if (getGrid()) observer.disconnect();\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilter(field, filter, options);\n },\n\n getFilter: (field: string) => getPlugin()?.getFilter(field),\n\n getFilters: () => getPlugin()?.getFilters() ?? [],\n\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilterModel(filters, options);\n },\n\n clearAllFilters: (options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearAllFilters(options);\n },\n\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearFieldFilter(field, options);\n },\n\n isFieldFiltered: (field: string) => getPlugin()?.isFieldFiltered(field) ?? false,\n\n getFilteredRowCount: () => getPlugin()?.getFilteredRowCount() ?? 0,\n\n getUniqueValues: (field: string) => getPlugin()?.getUniqueValues(field) ?? [],\n\n getStaleFilters: () => getPlugin()?.getStaleFilters() ?? [],\n\n getBlankMode: (field: string) => getPlugin()?.getBlankMode(field) ?? 'all',\n\n toggleBlankFilter: (field: string, mode: BlankMode) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.toggleBlankFilter(field, mode);\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|