@toolbox-web/grid-angular 0.10.0 → 0.11.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.
Files changed (26) hide show
  1. package/README.md +28 -22
  2. package/fesm2022/toolbox-web-grid-angular-features-export.mjs +123 -4
  3. package/fesm2022/toolbox-web-grid-angular-features-export.mjs.map +1 -1
  4. package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +123 -1
  5. package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
  6. package/fesm2022/toolbox-web-grid-angular-features-print.mjs +89 -1
  7. package/fesm2022/toolbox-web-grid-angular-features-print.mjs.map +1 -1
  8. package/fesm2022/toolbox-web-grid-angular-features-selection.mjs +133 -1
  9. package/fesm2022/toolbox-web-grid-angular-features-selection.mjs.map +1 -1
  10. package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs +106 -1
  11. package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs.map +1 -1
  12. package/fesm2022/toolbox-web-grid-angular.mjs +649 -64
  13. package/fesm2022/toolbox-web-grid-angular.mjs.map +1 -1
  14. package/package.json +1 -1
  15. package/types/toolbox-web-grid-angular-features-export.d.ts +113 -1
  16. package/types/toolbox-web-grid-angular-features-export.d.ts.map +1 -1
  17. package/types/toolbox-web-grid-angular-features-filtering.d.ts +120 -1
  18. package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
  19. package/types/toolbox-web-grid-angular-features-print.d.ts +91 -1
  20. package/types/toolbox-web-grid-angular-features-print.d.ts.map +1 -1
  21. package/types/toolbox-web-grid-angular-features-selection.d.ts +114 -1
  22. package/types/toolbox-web-grid-angular-features-selection.d.ts.map +1 -1
  23. package/types/toolbox-web-grid-angular-features-undo-redo.d.ts +107 -1
  24. package/types/toolbox-web-grid-angular-features-undo-redo.d.ts.map +1 -1
  25. package/types/toolbox-web-grid-angular.d.ts +383 -115
  26. package/types/toolbox-web-grid-angular.d.ts.map +1 -1
package/README.md CHANGED
@@ -434,14 +434,14 @@ Your components should implement one of these interfaces:
434
434
 
435
435
  ```typescript
436
436
  import { Component, input } from '@angular/core';
437
- import type { AngularCellRenderer, ColumnConfig } from '@toolbox-web/grid-angular';
437
+ import type { CellRenderer, ColumnConfig } from '@toolbox-web/grid-angular';
438
438
 
439
439
  @Component({
440
440
  selector: 'app-status-badge',
441
441
  template: `<span [class]="'badge badge--' + value()">{{ value() }}</span>`,
442
442
  standalone: true,
443
443
  })
444
- export class StatusBadgeComponent implements AngularCellRenderer<Employee, string> {
444
+ export class StatusBadgeComponent implements CellRenderer<Employee, string> {
445
445
  value = input.required<string>();
446
446
  row = input.required<Employee>();
447
447
  column = input<ColumnConfig>(); // Optional
@@ -452,7 +452,7 @@ export class StatusBadgeComponent implements AngularCellRenderer<Employee, strin
452
452
 
453
453
  ```typescript
454
454
  import { Component, input, output } from '@angular/core';
455
- import type { AngularCellEditor, ColumnConfig } from '@toolbox-web/grid-angular';
455
+ import type { CellEditor, ColumnConfig } from '@toolbox-web/grid-angular';
456
456
 
457
457
  @Component({
458
458
  selector: 'app-bonus-editor',
@@ -462,7 +462,7 @@ import type { AngularCellEditor, ColumnConfig } from '@toolbox-web/grid-angular'
462
462
  `,
463
463
  standalone: true,
464
464
  })
465
- export class BonusEditorComponent implements AngularCellEditor<Employee, number> {
465
+ export class BonusEditorComponent implements CellEditor<Employee, number> {
466
466
  value = input.required<number>();
467
467
  row = input.required<Employee>();
468
468
  column = input<ColumnConfig>(); // Optional
@@ -482,21 +482,21 @@ export class BonusEditorComponent implements AngularCellEditor<Employee, number>
482
482
 
483
483
  ### Using Components in Grid Config
484
484
 
485
- Use `AngularGridConfig` and `angularConfig` input for type-safe component references:
485
+ Use `GridConfig` with the `gridConfig` input for type-safe component references:
486
486
 
487
487
  ```typescript
488
488
  import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
489
- import { Grid, type AngularGridConfig } from '@toolbox-web/grid-angular';
489
+ import { Grid, type GridConfig } from '@toolbox-web/grid-angular';
490
490
  import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';
491
491
  import { StatusBadgeComponent, BonusEditorComponent } from './components';
492
492
 
493
493
  @Component({
494
494
  imports: [Grid],
495
495
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
496
- template: `<tbw-grid [angularConfig]="config" [rows]="employees" />`,
496
+ template: `<tbw-grid [gridConfig]="config" [rows]="employees" />`,
497
497
  })
498
498
  export class MyGridComponent {
499
- config: AngularGridConfig<Employee> = {
499
+ config: GridConfig<Employee> = {
500
500
  columns: [
501
501
  { field: 'name', header: 'Name' },
502
502
  { field: 'status', header: 'Status', renderer: StatusBadgeComponent },
@@ -507,14 +507,14 @@ export class MyGridComponent {
507
507
  }
508
508
  ```
509
509
 
510
- > **Note:** Use `[angularConfig]` instead of `[gridConfig]` when using component classes. The directive automatically processes the config and converts component classes to grid-compatible functions.
510
+ The `gridConfig` input accepts `GridConfig` (Angular-augmented) which allows both component classes and vanilla JS functions. When component classes are detected, the directive automatically converts them to grid-compatible renderer functions.
511
511
 
512
512
  ### Interfaces Reference
513
513
 
514
- | Interface | Required Inputs | Required Outputs | Description |
515
- | --------------------- | ------------------ | ------------------ | ------------------ |
516
- | `AngularCellRenderer` | `value()`, `row()` | - | Read-only renderer |
517
- | `AngularCellEditor` | `value()`, `row()` | `commit`, `cancel` | Editable cell |
514
+ | Interface | Required Inputs | Required Outputs | Description |
515
+ | -------------- | ------------------ | ------------------ | ------------------ |
516
+ | `CellRenderer` | `value()`, `row()` | - | Read-only renderer |
517
+ | `CellEditor` | `value()`, `row()` | `commit`, `cancel` | Editable cell |
518
518
 
519
519
  Both interfaces also support an optional `column()` input for accessing the column configuration.
520
520
 
@@ -855,10 +855,11 @@ if (context?.hasFormGroups) {
855
855
 
856
856
  ### Grid Directive Inputs
857
857
 
858
- | Input | Type | Description |
859
- | --------------- | ------------------------- | ------------------------------------------------------ |
860
- | `angularConfig` | `AngularGridConfig<TRow>` | Grid config with component class support (recommended) |
861
- | `customStyles` | `string` | Custom CSS styles to inject into the grid |
858
+ | Input | Type | Description |
859
+ | --------------- | ------------------ | ------------------------------------------------- |
860
+ | `gridConfig` | `GridConfig<TRow>` | Grid config with optional component class support |
861
+ | `angularConfig` | `GridConfig<TRow>` | **Deprecated** - use `gridConfig` instead |
862
+ | `customStyles` | `string` | Custom CSS styles to inject into the grid |
862
863
 
863
864
  ### Grid Directive Outputs
864
865
 
@@ -900,13 +901,18 @@ import type {
900
901
  // Events
901
902
  CellCommitEvent,
902
903
  RowCommitEvent,
903
- // Type-level defaults
904
- AngularTypeDefault,
905
- // Component-class column config
904
+ // Primary config exports - use these
905
+ GridConfig,
906
+ ColumnConfig,
907
+ CellRenderer,
908
+ CellEditor,
909
+ TypeDefault,
910
+ // Deprecated aliases
911
+ AngularGridConfig,
912
+ AngularColumnConfig,
906
913
  AngularCellRenderer,
907
914
  AngularCellEditor,
908
- AngularColumnConfig,
909
- AngularGridConfig,
915
+ AngularTypeDefault,
910
916
  // Reactive Forms
911
917
  FormArrayContext,
912
918
  } from '@toolbox-web/grid-angular';
@@ -1,17 +1,33 @@
1
- import { ExportPlugin } from '@toolbox-web/grid/plugins/export';
1
+ import { inject, ElementRef, signal } from '@angular/core';
2
2
  import { registerFeature } from '@toolbox-web/grid-angular';
3
+ import { ExportPlugin } from '@toolbox-web/grid/plugins/export';
3
4
 
4
5
  /**
5
6
  * Export feature for @toolbox-web/grid-angular
6
7
  *
7
- * Import this module to enable the `exportFeature` input on Grid directive.
8
+ * Import this module to enable the `export` input on Grid directive.
9
+ * Also exports `injectGridExport()` for programmatic export control.
8
10
  *
9
11
  * @example
10
12
  * ```typescript
11
13
  * import '@toolbox-web/grid-angular/features/export';
12
14
  *
13
- * <tbw-grid [exportFeature]="true" />
14
- * <tbw-grid [exportFeature]="{ filename: 'data.csv' }" />
15
+ * <tbw-grid [export]="true" />
16
+ * <tbw-grid [export]="{ fileName: 'data.csv' }" />
17
+ * ```
18
+ *
19
+ * @example Using injectGridExport
20
+ * ```typescript
21
+ * import { injectGridExport } from '@toolbox-web/grid-angular/features/export';
22
+ *
23
+ * @Component({...})
24
+ * export class MyComponent {
25
+ * private gridExport = injectGridExport();
26
+ *
27
+ * exportData() {
28
+ * this.gridExport.exportToCsv('employees.csv');
29
+ * }
30
+ * }
15
31
  * ```
16
32
  *
17
33
  * @packageDocumentation
@@ -22,8 +38,111 @@ registerFeature('export', (config) => {
22
38
  }
23
39
  return new ExportPlugin(config ?? undefined);
24
40
  });
41
+ /**
42
+ * Angular inject function for programmatic export control.
43
+ *
44
+ * Uses **lazy grid discovery** - the grid element is found when methods are called,
45
+ * not during initialization. This ensures it works reliably with:
46
+ * - Lazy-rendered tabs
47
+ * - Conditional rendering (*ngIf)
48
+ * - Dynamic component loading
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
53
+ * import { Grid } from '@toolbox-web/grid-angular';
54
+ * import '@toolbox-web/grid-angular/features/export';
55
+ * import { injectGridExport } from '@toolbox-web/grid-angular/features/export';
56
+ *
57
+ * @Component({
58
+ * selector: 'app-my-grid',
59
+ * imports: [Grid],
60
+ * schemas: [CUSTOM_ELEMENTS_SCHEMA],
61
+ * template: `
62
+ * <button (click)="handleExport()">Export CSV</button>
63
+ * <tbw-grid [rows]="rows" [export]="true"></tbw-grid>
64
+ * `
65
+ * })
66
+ * export class MyGridComponent {
67
+ * gridExport = injectGridExport();
68
+ *
69
+ * handleExport() {
70
+ * this.gridExport.exportToCsv('employees.csv');
71
+ * }
72
+ * }
73
+ * ```
74
+ */
75
+ function injectGridExport() {
76
+ const elementRef = inject(ElementRef);
77
+ const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
78
+ // Lazy discovery: cached grid reference
79
+ let cachedGrid = null;
80
+ let readyPromiseStarted = false;
81
+ /**
82
+ * Lazily find the grid element. Called on each method invocation.
83
+ * Caches the reference once found and triggers ready() check.
84
+ */
85
+ const getGrid = () => {
86
+ if (cachedGrid)
87
+ return cachedGrid;
88
+ const grid = elementRef.nativeElement.querySelector('tbw-grid');
89
+ if (grid) {
90
+ cachedGrid = grid;
91
+ // Start ready() check only once
92
+ if (!readyPromiseStarted) {
93
+ readyPromiseStarted = true;
94
+ grid.ready?.().then(() => isReady.set(true));
95
+ }
96
+ }
97
+ return grid;
98
+ };
99
+ const getPlugin = () => {
100
+ return getGrid()?.getPlugin(ExportPlugin);
101
+ };
102
+ return {
103
+ isReady: isReady.asReadonly(),
104
+ exportToCsv: (filename, params) => {
105
+ const plugin = getPlugin();
106
+ if (!plugin) {
107
+ console.warn(`[tbw-grid:export] ExportPlugin not found.\n\n` +
108
+ ` → Enable export on the grid:\n` +
109
+ ` <tbw-grid [export]="true" />`);
110
+ return;
111
+ }
112
+ plugin.exportCsv({ ...params, fileName: filename ?? params?.fileName ?? 'export.csv' });
113
+ },
114
+ exportToExcel: (filename, params) => {
115
+ const plugin = getPlugin();
116
+ if (!plugin) {
117
+ console.warn(`[tbw-grid:export] ExportPlugin not found.\n\n` +
118
+ ` → Enable export on the grid:\n` +
119
+ ` <tbw-grid [export]="true" />`);
120
+ return;
121
+ }
122
+ plugin.exportExcel({ ...params, fileName: filename ?? params?.fileName ?? 'export.xlsx' });
123
+ },
124
+ exportToJson: (filename, params) => {
125
+ const plugin = getPlugin();
126
+ if (!plugin) {
127
+ console.warn(`[tbw-grid:export] ExportPlugin not found.\n\n` +
128
+ ` → Enable export on the grid:\n` +
129
+ ` <tbw-grid [export]="true" />`);
130
+ return;
131
+ }
132
+ plugin.exportJson({ ...params, fileName: filename ?? params?.fileName ?? 'export.json' });
133
+ },
134
+ isExporting: () => {
135
+ return getPlugin()?.isExporting() ?? false;
136
+ },
137
+ getLastExport: () => {
138
+ return getPlugin()?.getLastExport() ?? null;
139
+ },
140
+ };
141
+ }
25
142
 
26
143
  /**
27
144
  * Generated bundle index. Do not edit.
28
145
  */
146
+
147
+ export { injectGridExport };
29
148
  //# 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 `exportFeature` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/export';\n *\n * <tbw-grid [exportFeature]=\"true\" />\n * <tbw-grid [exportFeature]=\"{ filename: 'data.csv' }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport { ExportPlugin } from '@toolbox-web/grid/plugins/export';\nimport { registerFeature } from '@toolbox-web/grid-angular';\n\nregisterFeature('export', (config) => {\n if (config === true) {\n return new ExportPlugin();\n }\n return new ExportPlugin(config ?? undefined);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;AAcG;AAKH,eAAe,CAAC,QAAQ,EAAE,CAAC,MAAM,KAAI;AACnC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,YAAY,EAAE;IAC3B;AACA,IAAA,OAAO,IAAI,YAAY,CAAC,MAAM,IAAI,SAAS,CAAC;AAC9C,CAAC,CAAC;;ACxBF;;AAEG"}
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 { ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeature } from '@toolbox-web/grid-angular';\nimport { ExportPlugin, type ExportFormat, type ExportParams } from '@toolbox-web/grid/plugins/export';\n\nregisterFeature('export', (config) => {\n if (config === true) {\n return new ExportPlugin();\n }\n return new ExportPlugin(config ?? undefined);\n});\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, CUSTOM_ELEMENTS_SCHEMA } 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 * schemas: [CUSTOM_ELEMENTS_SCHEMA],\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 */\nexport function injectGridExport(): ExportMethods {\n const elementRef = inject(ElementRef);\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('tbw-grid') 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(() => isReady.set(true));\n }\n }\n return grid;\n };\n\n const getPlugin = (): ExportPlugin | undefined => {\n return getGrid()?.getPlugin(ExportPlugin);\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":";;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;AAOH,eAAe,CAAC,QAAQ,EAAE,CAAC,MAAM,KAAI;AACnC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,YAAY,EAAE;IAC3B;AACA,IAAA,OAAO,IAAI,YAAY,CAAC,MAAM,IAAI,SAAS,CAAC;AAC9C,CAAC,CAAC;AA+CF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;SACa,gBAAgB,GAAA;AAC9B,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,mDAAC;;IAG7B,IAAI,UAAU,GAA2B,IAAI;IAC7C,IAAI,mBAAmB,GAAG,KAAK;AAE/B;;;AAGG;IACH,MAAM,OAAO,GAAG,MAA6B;AAC3C,QAAA,IAAI,UAAU;AAAE,YAAA,OAAO,UAAU;QAEjC,MAAM,IAAI,GAAG,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,CAA2B;QACzF,IAAI,IAAI,EAAE;YACR,UAAU,GAAG,IAAI;;YAEjB,IAAI,CAAC,mBAAmB,EAAE;gBACxB,mBAAmB,GAAG,IAAI;AAC1B,gBAAA,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9C;QACF;AACA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC;IAED,MAAM,SAAS,GAAG,MAA+B;AAC/C,QAAA,OAAO,OAAO,EAAE,EAAE,SAAS,CAAC,YAAY,CAAC;AAC3C,IAAA,CAAC;IAED,OAAO;AACL,QAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAE7B,QAAA,WAAW,EAAE,CAAC,QAAiB,EAAE,MAA8B,KAAI;AACjE,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,6CAAA,CAA+C;oBAC7C,CAAA,gCAAA,CAAkC;AAClC,oBAAA,CAAA,gCAAA,CAAkC,CACrC;gBACD;YACF;AACA,YAAA,MAAM,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,IAAI,MAAM,EAAE,QAAQ,IAAI,YAAY,EAAE,CAAC;QACzF,CAAC;AAED,QAAA,aAAa,EAAE,CAAC,QAAiB,EAAE,MAA8B,KAAI;AACnE,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,6CAAA,CAA+C;oBAC7C,CAAA,gCAAA,CAAkC;AAClC,oBAAA,CAAA,gCAAA,CAAkC,CACrC;gBACD;YACF;AACA,YAAA,MAAM,CAAC,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,IAAI,MAAM,EAAE,QAAQ,IAAI,aAAa,EAAE,CAAC;QAC5F,CAAC;AAED,QAAA,YAAY,EAAE,CAAC,QAAiB,EAAE,MAA8B,KAAI;AAClE,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,6CAAA,CAA+C;oBAC7C,CAAA,gCAAA,CAAkC;AAClC,oBAAA,CAAA,gCAAA,CAAkC,CACrC;gBACD;YACF;AACA,YAAA,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,IAAI,MAAM,EAAE,QAAQ,IAAI,aAAa,EAAE,CAAC;QAC3F,CAAC;QAED,WAAW,EAAE,MAAK;AAChB,YAAA,OAAO,SAAS,EAAE,EAAE,WAAW,EAAE,IAAI,KAAK;QAC5C,CAAC;QAED,aAAa,EAAE,MAAK;AAClB,YAAA,OAAO,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,IAAI;QAC7C,CAAC;KACF;AACH;;AC3MA;;AAEG;;;;"}
@@ -1,10 +1,12 @@
1
- import { FilteringPlugin } from '@toolbox-web/grid/plugins/filtering';
1
+ import { inject, ElementRef, signal } from '@angular/core';
2
2
  import { registerFeature } from '@toolbox-web/grid-angular';
3
+ import { FilteringPlugin } from '@toolbox-web/grid/plugins/filtering';
3
4
 
4
5
  /**
5
6
  * Filtering feature for @toolbox-web/grid-angular
6
7
  *
7
8
  * Import this module to enable the `filtering` input on Grid directive.
9
+ * Also exports `injectGridFiltering()` for programmatic filter control.
8
10
  *
9
11
  * @example
10
12
  * ```typescript
@@ -14,6 +16,20 @@ import { registerFeature } from '@toolbox-web/grid-angular';
14
16
  * <tbw-grid [filtering]="{ debounceMs: 200 }" />
15
17
  * ```
16
18
  *
19
+ * @example Using injectGridFiltering
20
+ * ```typescript
21
+ * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';
22
+ *
23
+ * @Component({...})
24
+ * export class MyComponent {
25
+ * private filtering = injectGridFiltering();
26
+ *
27
+ * filterByStatus(status: string) {
28
+ * this.filtering.setFilter('status', { operator: 'equals', value: status });
29
+ * }
30
+ * }
31
+ * ```
32
+ *
17
33
  * @packageDocumentation
18
34
  */
19
35
  registerFeature('filtering', (config) => {
@@ -22,8 +38,114 @@ registerFeature('filtering', (config) => {
22
38
  }
23
39
  return new FilteringPlugin(config ?? undefined);
24
40
  });
41
+ /**
42
+ * Angular inject function for programmatic filter control.
43
+ *
44
+ * Uses **lazy grid discovery** - the grid element is found when methods are called,
45
+ * not during initialization.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
50
+ * import { Grid } from '@toolbox-web/grid-angular';
51
+ * import '@toolbox-web/grid-angular/features/filtering';
52
+ * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';
53
+ *
54
+ * @Component({
55
+ * selector: 'app-my-grid',
56
+ * imports: [Grid],
57
+ * schemas: [CUSTOM_ELEMENTS_SCHEMA],
58
+ * template: `
59
+ * <input (input)="applyFilter($event)" placeholder="Filter by name..." />
60
+ * <span>{{ filtering.getFilteredRowCount() }} results</span>
61
+ * <button (click)="filtering.clearAllFilters()">Clear</button>
62
+ * <tbw-grid [rows]="rows" [filtering]="true"></tbw-grid>
63
+ * `
64
+ * })
65
+ * export class MyGridComponent {
66
+ * filtering = injectGridFiltering();
67
+ *
68
+ * applyFilter(event: Event) {
69
+ * const value = (event.target as HTMLInputElement).value;
70
+ * this.filtering.setFilter('name', value ? { operator: 'contains', value } : null);
71
+ * }
72
+ * }
73
+ * ```
74
+ */
75
+ function injectGridFiltering() {
76
+ const elementRef = inject(ElementRef);
77
+ const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
78
+ let cachedGrid = null;
79
+ let readyPromiseStarted = false;
80
+ const getGrid = () => {
81
+ if (cachedGrid)
82
+ return cachedGrid;
83
+ const grid = elementRef.nativeElement.querySelector('tbw-grid');
84
+ if (grid) {
85
+ cachedGrid = grid;
86
+ if (!readyPromiseStarted) {
87
+ readyPromiseStarted = true;
88
+ grid.ready?.().then(() => isReady.set(true));
89
+ }
90
+ }
91
+ return grid;
92
+ };
93
+ const getPlugin = () => {
94
+ return getGrid()?.getPlugin(FilteringPlugin);
95
+ };
96
+ return {
97
+ isReady: isReady.asReadonly(),
98
+ setFilter: (field, filter) => {
99
+ const plugin = getPlugin();
100
+ if (!plugin) {
101
+ console.warn(`[tbw-grid:filtering] FilteringPlugin not found.\n\n` +
102
+ ` → Enable filtering on the grid:\n` +
103
+ ` <tbw-grid [filtering]="true" />`);
104
+ return;
105
+ }
106
+ plugin.setFilter(field, filter);
107
+ },
108
+ getFilter: (field) => getPlugin()?.getFilter(field),
109
+ getFilters: () => getPlugin()?.getFilters() ?? [],
110
+ setFilterModel: (filters) => {
111
+ const plugin = getPlugin();
112
+ if (!plugin) {
113
+ console.warn(`[tbw-grid:filtering] FilteringPlugin not found.\n\n` +
114
+ ` → Enable filtering on the grid:\n` +
115
+ ` <tbw-grid [filtering]="true" />`);
116
+ return;
117
+ }
118
+ plugin.setFilterModel(filters);
119
+ },
120
+ clearAllFilters: () => {
121
+ const plugin = getPlugin();
122
+ if (!plugin) {
123
+ console.warn(`[tbw-grid:filtering] FilteringPlugin not found.\n\n` +
124
+ ` → Enable filtering on the grid:\n` +
125
+ ` <tbw-grid [filtering]="true" />`);
126
+ return;
127
+ }
128
+ plugin.clearAllFilters();
129
+ },
130
+ clearFieldFilter: (field) => {
131
+ const plugin = getPlugin();
132
+ if (!plugin) {
133
+ console.warn(`[tbw-grid:filtering] FilteringPlugin not found.\n\n` +
134
+ ` → Enable filtering on the grid:\n` +
135
+ ` <tbw-grid [filtering]="true" />`);
136
+ return;
137
+ }
138
+ plugin.clearFieldFilter(field);
139
+ },
140
+ isFieldFiltered: (field) => getPlugin()?.isFieldFiltered(field) ?? false,
141
+ getFilteredRowCount: () => getPlugin()?.getFilteredRowCount() ?? 0,
142
+ getUniqueValues: (field) => getPlugin()?.getUniqueValues(field) ?? [],
143
+ };
144
+ }
25
145
 
26
146
  /**
27
147
  * Generated bundle index. Do not edit.
28
148
  */
149
+
150
+ export { injectGridFiltering };
29
151
  //# 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 *\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 * @packageDocumentation\n */\n\nimport { FilteringPlugin } from '@toolbox-web/grid/plugins/filtering';\nimport { registerFeature } from '@toolbox-web/grid-angular';\n\nregisterFeature('filtering', (config) => {\n if (config === true) {\n return new FilteringPlugin();\n }\n return new FilteringPlugin(config ?? undefined);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;AAcG;AAKH,eAAe,CAAC,WAAW,EAAE,CAAC,MAAM,KAAI;AACtC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,eAAe,EAAE;IAC9B;AACA,IAAA,OAAO,IAAI,eAAe,CAAC,MAAM,IAAI,SAAS,CAAC;AACjD,CAAC,CAAC;;ACxBF;;AAEG"}
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 { ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeature } from '@toolbox-web/grid-angular';\nimport { FilteringPlugin, type FilterModel } from '@toolbox-web/grid/plugins/filtering';\n\nregisterFeature('filtering', (config) => {\n if (config === true) {\n return new FilteringPlugin();\n }\n return new FilteringPlugin(config ?? undefined);\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 */\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null) => 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 */\n setFilterModel: (filters: FilterModel[]) => void;\n\n /**\n * Clear all active filters.\n */\n clearAllFilters: () => void;\n\n /**\n * Clear filter for a specific field.\n */\n clearFieldFilter: (field: string) => 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 * 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, CUSTOM_ELEMENTS_SCHEMA } 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 * schemas: [CUSTOM_ELEMENTS_SCHEMA],\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 */\nexport function injectGridFiltering(): FilteringMethods {\n const elementRef = inject(ElementRef);\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('tbw-grid') as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => isReady.set(true));\n }\n }\n return grid;\n };\n\n const getPlugin = (): FilteringPlugin | undefined => {\n return getGrid()?.getPlugin(FilteringPlugin);\n };\n\n return {\n isReady: isReady.asReadonly(),\n\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null) => {\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);\n },\n\n getFilter: (field: string) => getPlugin()?.getFilter(field),\n\n getFilters: () => getPlugin()?.getFilters() ?? [],\n\n setFilterModel: (filters: FilterModel[]) => {\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);\n },\n\n clearAllFilters: () => {\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();\n },\n\n clearFieldFilter: (field: string) => {\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);\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}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,10 +1,12 @@
1
- import { PrintPlugin } from '@toolbox-web/grid/plugins/print';
1
+ import { inject, ElementRef, signal } from '@angular/core';
2
2
  import { registerFeature } from '@toolbox-web/grid-angular';
3
+ import { PrintPlugin } from '@toolbox-web/grid/plugins/print';
3
4
 
4
5
  /**
5
6
  * Print feature for @toolbox-web/grid-angular
6
7
  *
7
8
  * Import this module to enable the `print` input on Grid directive.
9
+ * Also exports `injectGridPrint()` for programmatic print control.
8
10
  *
9
11
  * @example
10
12
  * ```typescript
@@ -13,6 +15,20 @@ import { registerFeature } from '@toolbox-web/grid-angular';
13
15
  * <tbw-grid [print]="true" />
14
16
  * ```
15
17
  *
18
+ * @example Using injectGridPrint
19
+ * ```typescript
20
+ * import { injectGridPrint } from '@toolbox-web/grid-angular/features/print';
21
+ *
22
+ * @Component({...})
23
+ * export class MyComponent {
24
+ * private gridPrint = injectGridPrint();
25
+ *
26
+ * printReport() {
27
+ * this.gridPrint.print({ title: 'My Report' });
28
+ * }
29
+ * }
30
+ * ```
31
+ *
16
32
  * @packageDocumentation
17
33
  */
18
34
  registerFeature('print', (config) => {
@@ -21,8 +37,80 @@ registerFeature('print', (config) => {
21
37
  }
22
38
  return new PrintPlugin(config ?? undefined);
23
39
  });
40
+ /**
41
+ * Angular inject function for programmatic print control.
42
+ *
43
+ * Uses **lazy grid discovery** - the grid element is found when methods are called,
44
+ * not during initialization.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
49
+ * import { Grid } from '@toolbox-web/grid-angular';
50
+ * import '@toolbox-web/grid-angular/features/print';
51
+ * import { injectGridPrint } from '@toolbox-web/grid-angular/features/print';
52
+ *
53
+ * @Component({
54
+ * selector: 'app-my-grid',
55
+ * imports: [Grid],
56
+ * schemas: [CUSTOM_ELEMENTS_SCHEMA],
57
+ * template: `
58
+ * <button (click)="handlePrint()" [disabled]="gridPrint.isPrinting()">
59
+ * {{ gridPrint.isPrinting() ? 'Printing...' : 'Print' }}
60
+ * </button>
61
+ * <tbw-grid [rows]="rows" [print]="true"></tbw-grid>
62
+ * `
63
+ * })
64
+ * export class MyGridComponent {
65
+ * gridPrint = injectGridPrint();
66
+ *
67
+ * async handlePrint() {
68
+ * await this.gridPrint.print({ title: 'Employee Report', isolate: true });
69
+ * console.log('Print dialog closed');
70
+ * }
71
+ * }
72
+ * ```
73
+ */
74
+ function injectGridPrint() {
75
+ const elementRef = inject(ElementRef);
76
+ const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
77
+ let cachedGrid = null;
78
+ let readyPromiseStarted = false;
79
+ const getGrid = () => {
80
+ if (cachedGrid)
81
+ return cachedGrid;
82
+ const grid = elementRef.nativeElement.querySelector('tbw-grid');
83
+ if (grid) {
84
+ cachedGrid = grid;
85
+ if (!readyPromiseStarted) {
86
+ readyPromiseStarted = true;
87
+ grid.ready?.().then(() => isReady.set(true));
88
+ }
89
+ }
90
+ return grid;
91
+ };
92
+ const getPlugin = () => {
93
+ return getGrid()?.getPlugin(PrintPlugin);
94
+ };
95
+ return {
96
+ isReady: isReady.asReadonly(),
97
+ print: async (params) => {
98
+ const plugin = getPlugin();
99
+ if (!plugin) {
100
+ console.warn(`[tbw-grid:print] PrintPlugin not found.\n\n` +
101
+ ` → Enable print on the grid:\n` +
102
+ ` <tbw-grid [print]="true" />`);
103
+ return;
104
+ }
105
+ await plugin.print(params);
106
+ },
107
+ isPrinting: () => getPlugin()?.isPrinting() ?? false,
108
+ };
109
+ }
24
110
 
25
111
  /**
26
112
  * Generated bundle index. Do not edit.
27
113
  */
114
+
115
+ export { injectGridPrint };
28
116
  //# sourceMappingURL=toolbox-web-grid-angular-features-print.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-print.mjs","sources":["../../../../libs/grid-angular/features/print/src/index.ts","../../../../libs/grid-angular/features/print/src/toolbox-web-grid-angular-features-print.ts"],"sourcesContent":["/**\n * Print feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `print` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/print';\n *\n * <tbw-grid [print]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport { PrintPlugin } from '@toolbox-web/grid/plugins/print';\nimport { registerFeature } from '@toolbox-web/grid-angular';\n\nregisterFeature('print', (config) => {\n if (config === true) {\n return new PrintPlugin();\n }\n return new PrintPlugin(config ?? undefined);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;AAaG;AAKH,eAAe,CAAC,OAAO,EAAE,CAAC,MAAM,KAAI;AAClC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,WAAW,EAAE;IAC1B;AACA,IAAA,OAAO,IAAI,WAAW,CAAC,MAAM,IAAI,SAAS,CAAC;AAC7C,CAAC,CAAC;;ACvBF;;AAEG"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-print.mjs","sources":["../../../../libs/grid-angular/features/print/src/index.ts","../../../../libs/grid-angular/features/print/src/toolbox-web-grid-angular-features-print.ts"],"sourcesContent":["/**\n * Print feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `print` input on Grid directive.\n * Also exports `injectGridPrint()` for programmatic print control.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/print';\n *\n * <tbw-grid [print]=\"true\" />\n * ```\n *\n * @example Using injectGridPrint\n * ```typescript\n * import { injectGridPrint } from '@toolbox-web/grid-angular/features/print';\n *\n * @Component({...})\n * export class MyComponent {\n * private gridPrint = injectGridPrint();\n *\n * printReport() {\n * this.gridPrint.print({ title: 'My Report' });\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeature } from '@toolbox-web/grid-angular';\nimport { PrintPlugin, type PrintParams } from '@toolbox-web/grid/plugins/print';\n\nregisterFeature('print', (config) => {\n if (config === true) {\n return new PrintPlugin();\n }\n return new PrintPlugin(config ?? undefined);\n});\n\n/**\n * Print methods returned from injectGridPrint.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n */\nexport interface PrintMethods {\n /**\n * Print the grid.\n * Opens browser print dialog after preparing the grid for printing.\n * @param params - Optional print parameters\n */\n print: (params?: PrintParams) => Promise<void>;\n\n /**\n * Check if a print operation is currently in progress.\n */\n isPrinting: () => boolean;\n\n /**\n * Signal indicating if grid is ready.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic print 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, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/print';\n * import { injectGridPrint } from '@toolbox-web/grid-angular/features/print';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * schemas: [CUSTOM_ELEMENTS_SCHEMA],\n * template: `\n * <button (click)=\"handlePrint()\" [disabled]=\"gridPrint.isPrinting()\">\n * {{ gridPrint.isPrinting() ? 'Printing...' : 'Print' }}\n * </button>\n * <tbw-grid [rows]=\"rows\" [print]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * gridPrint = injectGridPrint();\n *\n * async handlePrint() {\n * await this.gridPrint.print({ title: 'Employee Report', isolate: true });\n * console.log('Print dialog closed');\n * }\n * }\n * ```\n */\nexport function injectGridPrint(): PrintMethods {\n const elementRef = inject(ElementRef);\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('tbw-grid') as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => isReady.set(true));\n }\n }\n return grid;\n };\n\n const getPlugin = (): PrintPlugin | undefined => {\n return getGrid()?.getPlugin(PrintPlugin);\n };\n\n return {\n isReady: isReady.asReadonly(),\n\n print: async (params?: PrintParams) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:print] PrintPlugin not found.\\n\\n` +\n ` → Enable print on the grid:\\n` +\n ` <tbw-grid [print]=\"true\" />`,\n );\n return;\n }\n await plugin.print(params);\n },\n\n isPrinting: () => getPlugin()?.isPrinting() ?? false,\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AAOH,eAAe,CAAC,OAAO,EAAE,CAAC,MAAM,KAAI;AAClC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,WAAW,EAAE;IAC1B;AACA,IAAA,OAAO,IAAI,WAAW,CAAC,MAAM,IAAI,SAAS,CAAC;AAC7C,CAAC,CAAC;AA0BF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;SACa,eAAe,GAAA;AAC7B,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,mDAAC;IAE7B,IAAI,UAAU,GAA2B,IAAI;IAC7C,IAAI,mBAAmB,GAAG,KAAK;IAE/B,MAAM,OAAO,GAAG,MAA6B;AAC3C,QAAA,IAAI,UAAU;AAAE,YAAA,OAAO,UAAU;QAEjC,MAAM,IAAI,GAAG,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,CAA2B;QACzF,IAAI,IAAI,EAAE;YACR,UAAU,GAAG,IAAI;YACjB,IAAI,CAAC,mBAAmB,EAAE;gBACxB,mBAAmB,GAAG,IAAI;AAC1B,gBAAA,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9C;QACF;AACA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC;IAED,MAAM,SAAS,GAAG,MAA8B;AAC9C,QAAA,OAAO,OAAO,EAAE,EAAE,SAAS,CAAC,WAAW,CAAC;AAC1C,IAAA,CAAC;IAED,OAAO;AACL,QAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAE7B,QAAA,KAAK,EAAE,OAAO,MAAoB,KAAI;AACpC,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,2CAAA,CAA6C;oBAC3C,CAAA,+BAAA,CAAiC;AACjC,oBAAA,CAAA,+BAAA,CAAiC,CACpC;gBACD;YACF;AACA,YAAA,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAC5B,CAAC;QAED,UAAU,EAAE,MAAM,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,KAAK;KACrD;AACH;;AC/IA;;AAEG;;;;"}