@toolbox-web/grid-angular 0.19.2 → 0.19.3

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 (61) hide show
  1. package/fesm2022/toolbox-web-grid-angular-features-clipboard.mjs.map +1 -1
  2. package/fesm2022/toolbox-web-grid-angular-features-column-virtualization.mjs.map +1 -1
  3. package/fesm2022/toolbox-web-grid-angular-features-context-menu.mjs.map +1 -1
  4. package/fesm2022/toolbox-web-grid-angular-features-editing.mjs.map +1 -1
  5. package/fesm2022/toolbox-web-grid-angular-features-export.mjs +14 -3
  6. package/fesm2022/toolbox-web-grid-angular-features-export.mjs.map +1 -1
  7. package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +18 -3
  8. package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
  9. package/fesm2022/toolbox-web-grid-angular-features-grouping-columns.mjs.map +1 -1
  10. package/fesm2022/toolbox-web-grid-angular-features-grouping-rows.mjs.map +1 -1
  11. package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs.map +1 -1
  12. package/fesm2022/toolbox-web-grid-angular-features-multi-sort.mjs.map +1 -1
  13. package/fesm2022/toolbox-web-grid-angular-features-pinned-columns.mjs.map +1 -1
  14. package/fesm2022/toolbox-web-grid-angular-features-pinned-rows.mjs.map +1 -1
  15. package/fesm2022/toolbox-web-grid-angular-features-pivot.mjs.map +1 -1
  16. package/fesm2022/toolbox-web-grid-angular-features-print.mjs +14 -3
  17. package/fesm2022/toolbox-web-grid-angular-features-print.mjs.map +1 -1
  18. package/fesm2022/toolbox-web-grid-angular-features-reorder-columns.mjs.map +1 -1
  19. package/fesm2022/toolbox-web-grid-angular-features-reorder-rows.mjs.map +1 -1
  20. package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs.map +1 -1
  21. package/fesm2022/toolbox-web-grid-angular-features-selection.mjs +30 -5
  22. package/fesm2022/toolbox-web-grid-angular-features-selection.mjs.map +1 -1
  23. package/fesm2022/toolbox-web-grid-angular-features-server-side.mjs.map +1 -1
  24. package/fesm2022/toolbox-web-grid-angular-features-tooltip.mjs.map +1 -1
  25. package/fesm2022/toolbox-web-grid-angular-features-tree.mjs.map +1 -1
  26. package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs +30 -5
  27. package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs.map +1 -1
  28. package/fesm2022/toolbox-web-grid-angular-features-visibility.mjs.map +1 -1
  29. package/fesm2022/toolbox-web-grid-angular.mjs +5 -2
  30. package/fesm2022/toolbox-web-grid-angular.mjs.map +1 -1
  31. package/package.json +1 -1
  32. package/types/toolbox-web-grid-angular-features-clipboard.d.ts +1 -2
  33. package/types/toolbox-web-grid-angular-features-column-virtualization.d.ts +1 -2
  34. package/types/toolbox-web-grid-angular-features-context-menu.d.ts +1 -2
  35. package/types/toolbox-web-grid-angular-features-editing.d.ts +1 -2
  36. package/types/toolbox-web-grid-angular-features-export.d.ts +6 -1
  37. package/types/toolbox-web-grid-angular-features-export.d.ts.map +1 -1
  38. package/types/toolbox-web-grid-angular-features-filtering.d.ts +6 -1
  39. package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
  40. package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts +1 -2
  41. package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts +1 -2
  42. package/types/toolbox-web-grid-angular-features-master-detail.d.ts +1 -2
  43. package/types/toolbox-web-grid-angular-features-multi-sort.d.ts +1 -2
  44. package/types/toolbox-web-grid-angular-features-pinned-columns.d.ts +1 -2
  45. package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts +1 -2
  46. package/types/toolbox-web-grid-angular-features-pivot.d.ts +1 -2
  47. package/types/toolbox-web-grid-angular-features-print.d.ts +6 -1
  48. package/types/toolbox-web-grid-angular-features-print.d.ts.map +1 -1
  49. package/types/toolbox-web-grid-angular-features-reorder-columns.d.ts +1 -2
  50. package/types/toolbox-web-grid-angular-features-reorder-rows.d.ts +1 -2
  51. package/types/toolbox-web-grid-angular-features-responsive.d.ts +1 -2
  52. package/types/toolbox-web-grid-angular-features-selection.d.ts +6 -1
  53. package/types/toolbox-web-grid-angular-features-selection.d.ts.map +1 -1
  54. package/types/toolbox-web-grid-angular-features-server-side.d.ts +1 -2
  55. package/types/toolbox-web-grid-angular-features-tooltip.d.ts +1 -2
  56. package/types/toolbox-web-grid-angular-features-tree.d.ts +1 -2
  57. package/types/toolbox-web-grid-angular-features-undo-redo.d.ts +6 -1
  58. package/types/toolbox-web-grid-angular-features-undo-redo.d.ts.map +1 -1
  59. package/types/toolbox-web-grid-angular-features-visibility.d.ts +1 -2
  60. package/types/toolbox-web-grid-angular.d.ts +4 -1
  61. package/types/toolbox-web-grid-angular.d.ts.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-clipboard.mjs","sources":["../../../../libs/grid-angular/features/clipboard/src/index.ts","../../../../libs/grid-angular/features/clipboard/src/toolbox-web-grid-angular-features-clipboard.ts"],"sourcesContent":["/**\n * Clipboard feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `clipboard` input on Grid directive.\n * Requires selection feature to be enabled.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/selection';\n * import '@toolbox-web/grid-angular/features/clipboard';\n *\n * <tbw-grid [selection]=\"'range'\" [clipboard]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/clipboard';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;AAeG;;ACfH;;AAEG"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-clipboard.mjs","sources":["../../../../libs/grid-angular/features/clipboard/src/index.ts","../../../../libs/grid-angular/features/clipboard/src/toolbox-web-grid-angular-features-clipboard.ts"],"sourcesContent":["/**\n * Clipboard feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `clipboard` input on Grid directive.\n * Requires selection feature to be enabled.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/selection';\n * import '@toolbox-web/grid-angular/features/clipboard';\n *\n * <tbw-grid [selection]=\"'range'\" [clipboard]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/clipboard';\nexport type { _Augmentation as _ClipboardAugmentation } from '@toolbox-web/grid/features/clipboard';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;AAeG;;ACfH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-column-virtualization.mjs","sources":["../../../../libs/grid-angular/features/column-virtualization/src/index.ts","../../../../libs/grid-angular/features/column-virtualization/src/toolbox-web-grid-angular-features-column-virtualization.ts"],"sourcesContent":["/**\n * Column virtualization feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `columnVirtualization` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/column-virtualization';\n *\n * <tbw-grid [columnVirtualization]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/column-virtualization';\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-column-virtualization.mjs","sources":["../../../../libs/grid-angular/features/column-virtualization/src/index.ts","../../../../libs/grid-angular/features/column-virtualization/src/toolbox-web-grid-angular-features-column-virtualization.ts"],"sourcesContent":["/**\n * Column virtualization feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `columnVirtualization` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/column-virtualization';\n *\n * <tbw-grid [columnVirtualization]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/column-virtualization';\nexport type { _Augmentation as _ColumnVirtualizationAugmentation } from '@toolbox-web/grid/features/column-virtualization';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-context-menu.mjs","sources":["../../../../libs/grid-angular/features/context-menu/src/index.ts","../../../../libs/grid-angular/features/context-menu/src/toolbox-web-grid-angular-features-context-menu.ts"],"sourcesContent":["/**\n * Context menu feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `contextMenu` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/context-menu';\n *\n * <tbw-grid [contextMenu]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/context-menu';\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-context-menu.mjs","sources":["../../../../libs/grid-angular/features/context-menu/src/index.ts","../../../../libs/grid-angular/features/context-menu/src/toolbox-web-grid-angular-features-context-menu.ts"],"sourcesContent":["/**\n * Context menu feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `contextMenu` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/context-menu';\n *\n * <tbw-grid [contextMenu]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/context-menu';\nexport type { _Augmentation as _ContextMenuAugmentation } from '@toolbox-web/grid/features/context-menu';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -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';\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/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"}
@@ -63,8 +63,12 @@ import '@toolbox-web/grid/features/export';
63
63
  * }
64
64
  * }
65
65
  * ```
66
+ *
67
+ * @param selector - Optional CSS selector to target a specific grid element.
68
+ * Defaults to `'tbw-grid'` (first grid in the component). Use when the
69
+ * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.
66
70
  */
67
- function injectGridExport() {
71
+ function injectGridExport(selector = 'tbw-grid') {
68
72
  const elementRef = inject(ElementRef);
69
73
  const destroyRef = inject(DestroyRef);
70
74
  const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : /* istanbul ignore next */ []));
@@ -78,13 +82,20 @@ function injectGridExport() {
78
82
  const getGrid = () => {
79
83
  if (cachedGrid)
80
84
  return cachedGrid;
81
- const grid = elementRef.nativeElement.querySelector('tbw-grid');
85
+ const grid = elementRef.nativeElement.querySelector(selector);
82
86
  if (grid) {
83
87
  cachedGrid = grid;
84
88
  // Start ready() check only once
85
89
  if (!readyPromiseStarted) {
86
90
  readyPromiseStarted = true;
87
- grid.ready?.().then(() => isReady.set(true));
91
+ grid.ready?.().then(() => {
92
+ if (grid.getPluginByName('export')) {
93
+ isReady.set(true);
94
+ }
95
+ else {
96
+ setTimeout(() => isReady.set(true), 0);
97
+ }
98
+ });
88
99
  }
89
100
  }
90
101
  return grid;
@@ -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';\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 */\nexport function injectGridExport(): 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('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()?.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/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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"}
@@ -63,8 +63,12 @@ import '@toolbox-web/grid/features/filtering';
63
63
  * }
64
64
  * }
65
65
  * ```
66
+ *
67
+ * @param selector - Optional CSS selector to target a specific grid element.
68
+ * Defaults to `'tbw-grid'` (first grid in the component). Use when the
69
+ * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.
66
70
  */
67
- function injectGridFiltering() {
71
+ function injectGridFiltering(selector = 'tbw-grid') {
68
72
  const elementRef = inject(ElementRef);
69
73
  const destroyRef = inject(DestroyRef);
70
74
  const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : /* istanbul ignore next */ []));
@@ -73,12 +77,23 @@ function injectGridFiltering() {
73
77
  const getGrid = () => {
74
78
  if (cachedGrid)
75
79
  return cachedGrid;
76
- const grid = elementRef.nativeElement.querySelector('tbw-grid');
80
+ const grid = elementRef.nativeElement.querySelector(selector);
77
81
  if (grid) {
78
82
  cachedGrid = grid;
79
83
  if (!readyPromiseStarted) {
80
84
  readyPromiseStarted = true;
81
- grid.ready?.().then(() => isReady.set(true));
85
+ grid.ready?.().then(() => {
86
+ // If the plugin is already attached, signal readiness immediately.
87
+ // Otherwise, Angular's Grid directive may not have applied gridConfig
88
+ // yet (it uses effect + queueMicrotask). Defer to let pending
89
+ // microtasks flush before signaling readiness.
90
+ if (grid.getPluginByName('filtering')) {
91
+ isReady.set(true);
92
+ }
93
+ else {
94
+ setTimeout(() => isReady.set(true), 0);
95
+ }
96
+ });
82
97
  }
83
98
  }
84
99
  return grid;
@@ -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';\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 */\nexport function injectGridFiltering(): 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('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()?.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/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 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-grouping-columns.mjs","sources":["../../../../libs/grid-angular/features/grouping-columns/src/index.ts","../../../../libs/grid-angular/features/grouping-columns/src/toolbox-web-grid-angular-features-grouping-columns.ts"],"sourcesContent":["/**\n * Column grouping feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `groupingColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/grouping-columns';\n *\n * <tbw-grid [groupingColumns]=\"{ columnGroups: [...] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/grouping-columns';\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-grouping-columns.mjs","sources":["../../../../libs/grid-angular/features/grouping-columns/src/index.ts","../../../../libs/grid-angular/features/grouping-columns/src/toolbox-web-grid-angular-features-grouping-columns.ts"],"sourcesContent":["/**\n * Column grouping feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `groupingColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/grouping-columns';\n *\n * <tbw-grid [groupingColumns]=\"{ columnGroups: [...] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/grouping-columns';\nexport type { _Augmentation as _GroupingColumnsAugmentation } from '@toolbox-web/grid/features/grouping-columns';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-grouping-rows.mjs","sources":["../../../../libs/grid-angular/features/grouping-rows/src/index.ts","../../../../libs/grid-angular/features/grouping-rows/src/toolbox-web-grid-angular-features-grouping-rows.ts"],"sourcesContent":["/**\n * Row grouping feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `groupingRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/grouping-rows';\n *\n * <tbw-grid [groupingRows]=\"{ groupBy: ['department'] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/grouping-rows';\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-grouping-rows.mjs","sources":["../../../../libs/grid-angular/features/grouping-rows/src/index.ts","../../../../libs/grid-angular/features/grouping-rows/src/toolbox-web-grid-angular-features-grouping-rows.ts"],"sourcesContent":["/**\n * Row grouping feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `groupingRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/grouping-rows';\n *\n * <tbw-grid [groupingRows]=\"{ groupBy: ['department'] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/grouping-rows';\nexport type { _Augmentation as _GroupingRowsAugmentation } from '@toolbox-web/grid/features/grouping-rows';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-master-detail.mjs","sources":["../../../../libs/grid-angular/features/master-detail/src/index.ts","../../../../libs/grid-angular/features/master-detail/src/toolbox-web-grid-angular-features-master-detail.ts"],"sourcesContent":["/**\n * Master-detail feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `masterDetail` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/master-detail';\n *\n * <tbw-grid [masterDetail]=\"{ detailRenderer: myRenderer }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/master-detail';\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-master-detail.mjs","sources":["../../../../libs/grid-angular/features/master-detail/src/index.ts","../../../../libs/grid-angular/features/master-detail/src/toolbox-web-grid-angular-features-master-detail.ts"],"sourcesContent":["/**\n * Master-detail feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `masterDetail` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/master-detail';\n *\n * <tbw-grid [masterDetail]=\"{ detailRenderer: myRenderer }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/master-detail';\nexport type { _Augmentation as _MasterDetailAugmentation } from '@toolbox-web/grid/features/master-detail';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-multi-sort.mjs","sources":["../../../../libs/grid-angular/features/multi-sort/src/index.ts","../../../../libs/grid-angular/features/multi-sort/src/toolbox-web-grid-angular-features-multi-sort.ts"],"sourcesContent":["/**\n * Multi-sort feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `multiSort` input on Grid directive.\n * Multi-sort allows sorting by multiple columns simultaneously.\n *\n * For basic single-column sorting, columns with `sortable: true` work without this plugin.\n * Use `[sortable]=\"false\"` on the grid to disable all sorting.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/multi-sort';\n *\n * <tbw-grid [multiSort]=\"true\" />\n * <tbw-grid [multiSort]=\"'single'\" />\n * <tbw-grid [multiSort]=\"{ maxSortColumns: 3 }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/multi-sort';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;;;;;AAmBG;;ACnBH;;AAEG"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-multi-sort.mjs","sources":["../../../../libs/grid-angular/features/multi-sort/src/index.ts","../../../../libs/grid-angular/features/multi-sort/src/toolbox-web-grid-angular-features-multi-sort.ts"],"sourcesContent":["/**\n * Multi-sort feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `multiSort` input on Grid directive.\n * Multi-sort allows sorting by multiple columns simultaneously.\n *\n * For basic single-column sorting, columns with `sortable: true` work without this plugin.\n * Use `[sortable]=\"false\"` on the grid to disable all sorting.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/multi-sort';\n *\n * <tbw-grid [multiSort]=\"true\" />\n * <tbw-grid [multiSort]=\"'single'\" />\n * <tbw-grid [multiSort]=\"{ maxSortColumns: 3 }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/multi-sort';\nexport type { _Augmentation as _MultiSortAugmentation } from '@toolbox-web/grid/features/multi-sort';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;;;;;AAmBG;;ACnBH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-pinned-columns.mjs","sources":["../../../../libs/grid-angular/features/pinned-columns/src/index.ts","../../../../libs/grid-angular/features/pinned-columns/src/toolbox-web-grid-angular-features-pinned-columns.ts"],"sourcesContent":["/**\n * Pinned columns feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pinnedColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pinned-columns';\n *\n * <tbw-grid [pinnedColumns]=\"true\" [columns]=\"[\n * { field: 'id', pinned: 'left' },\n * { field: 'name' }\n * ]\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/pinned-columns';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;;AAgBG;;AChBH;;AAEG"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-pinned-columns.mjs","sources":["../../../../libs/grid-angular/features/pinned-columns/src/index.ts","../../../../libs/grid-angular/features/pinned-columns/src/toolbox-web-grid-angular-features-pinned-columns.ts"],"sourcesContent":["/**\n * Pinned columns feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pinnedColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pinned-columns';\n *\n * <tbw-grid [pinnedColumns]=\"true\" [columns]=\"[\n * { field: 'id', pinned: 'left' },\n * { field: 'name' }\n * ]\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/pinned-columns';\nexport type { _Augmentation as _PinnedColumnsAugmentation } from '@toolbox-web/grid/features/pinned-columns';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;;AAgBG;;AChBH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-pinned-rows.mjs","sources":["../../../../libs/grid-angular/features/pinned-rows/src/index.ts","../../../../libs/grid-angular/features/pinned-rows/src/toolbox-web-grid-angular-features-pinned-rows.ts"],"sourcesContent":["/**\n * Pinned rows feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pinnedRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pinned-rows';\n *\n * <tbw-grid [pinnedRows]=\"{ bottom: [{ type: 'aggregation' }] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/pinned-rows';\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-pinned-rows.mjs","sources":["../../../../libs/grid-angular/features/pinned-rows/src/index.ts","../../../../libs/grid-angular/features/pinned-rows/src/toolbox-web-grid-angular-features-pinned-rows.ts"],"sourcesContent":["/**\n * Pinned rows feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pinnedRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pinned-rows';\n *\n * <tbw-grid [pinnedRows]=\"{ bottom: [{ type: 'aggregation' }] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/pinned-rows';\nexport type { _Augmentation as _PinnedRowsAugmentation } from '@toolbox-web/grid/features/pinned-rows';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-pivot.mjs","sources":["../../../../libs/grid-angular/features/pivot/src/index.ts","../../../../libs/grid-angular/features/pivot/src/toolbox-web-grid-angular-features-pivot.ts"],"sourcesContent":["/**\n * Pivot feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pivot` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pivot';\n *\n * <tbw-grid [pivot]=\"{ rowFields: ['category'], valueField: 'sales' }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/pivot';\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-pivot.mjs","sources":["../../../../libs/grid-angular/features/pivot/src/index.ts","../../../../libs/grid-angular/features/pivot/src/toolbox-web-grid-angular-features-pivot.ts"],"sourcesContent":["/**\n * Pivot feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pivot` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pivot';\n *\n * <tbw-grid [pivot]=\"{ rowFields: ['category'], valueField: 'sales' }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/pivot';\nexport type { _Augmentation as _PivotAugmentation } from '@toolbox-web/grid/features/pivot';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -62,8 +62,12 @@ import '@toolbox-web/grid/features/print';
62
62
  * }
63
63
  * }
64
64
  * ```
65
+ *
66
+ * @param selector - Optional CSS selector to target a specific grid element.
67
+ * Defaults to `'tbw-grid'` (first grid in the component). Use when the
68
+ * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.
65
69
  */
66
- function injectGridPrint() {
70
+ function injectGridPrint(selector = 'tbw-grid') {
67
71
  const elementRef = inject(ElementRef);
68
72
  const destroyRef = inject(DestroyRef);
69
73
  const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : /* istanbul ignore next */ []));
@@ -72,12 +76,19 @@ function injectGridPrint() {
72
76
  const getGrid = () => {
73
77
  if (cachedGrid)
74
78
  return cachedGrid;
75
- const grid = elementRef.nativeElement.querySelector('tbw-grid');
79
+ const grid = elementRef.nativeElement.querySelector(selector);
76
80
  if (grid) {
77
81
  cachedGrid = grid;
78
82
  if (!readyPromiseStarted) {
79
83
  readyPromiseStarted = true;
80
- grid.ready?.().then(() => isReady.set(true));
84
+ grid.ready?.().then(() => {
85
+ if (grid.getPluginByName('print')) {
86
+ isReady.set(true);
87
+ }
88
+ else {
89
+ setTimeout(() => isReady.set(true), 0);
90
+ }
91
+ });
81
92
  }
82
93
  }
83
94
  return grid;
@@ -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 * 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 { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport '@toolbox-web/grid/features/print';\nimport { PrintPlugin, type PrintParams } from '@toolbox-web/grid/plugins/print';\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 } 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 * 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 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('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()?.getPluginByName('print');\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 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;AA+BH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;SACa,eAAe,GAAA;AAC7B,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,8EAAC;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,eAAe,CAAC,OAAO,CAAC;AAC5C,IAAA,CAAC;;;;IAKD,eAAe,CAAC,MAAK;AACnB,QAAA,IAAI,OAAO,EAAE;YAAE;AAEf,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,aAA4B;AACpD,QAAA,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAK;AACzC,YAAA,IAAI,OAAO,EAAE;gBAAE,QAAQ,CAAC,UAAU,EAAE;AACtC,QAAA,CAAC,CAAC;AACF,QAAA,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAE1D,UAAU,CAAC,SAAS,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;AACnD,IAAA,CAAC,CAAC;IAEF,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;;ACvJA;;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 { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport '@toolbox-web/grid/features/print';\nimport { PrintPlugin, type PrintParams } from '@toolbox-web/grid/plugins/print';\nexport type { _Augmentation as _PrintAugmentation } from '@toolbox-web/grid/features/print';\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 } 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 * 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 *\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 injectGridPrint(selector = 'tbw-grid'): PrintMethods {\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 (grid.getPluginByName('print')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): PrintPlugin | undefined => {\n return getGrid()?.getPluginByName('print');\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 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;AAgCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCG;AACG,SAAU,eAAe,CAAC,QAAQ,GAAG,UAAU,EAAA;AACnD,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,8EAAC;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,QAAQ,CAA2B;QACvF,IAAI,IAAI,EAAE;YACR,UAAU,GAAG,IAAI;YACjB,IAAI,CAAC,mBAAmB,EAAE;gBACxB,mBAAmB,GAAG,IAAI;gBAC1B,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAK;AACvB,oBAAA,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE;AACjC,wBAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;oBACnB;yBAAO;AACL,wBAAA,UAAU,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACxC;AACF,gBAAA,CAAC,CAAC;YACJ;QACF;AACA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC;IAED,MAAM,SAAS,GAAG,MAA8B;AAC9C,QAAA,OAAO,OAAO,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC;AAC5C,IAAA,CAAC;;;;IAKD,eAAe,CAAC,MAAK;AACnB,QAAA,IAAI,OAAO,EAAE;YAAE;AAEf,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,aAA4B;AACpD,QAAA,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAK;AACzC,YAAA,IAAI,OAAO,EAAE;gBAAE,QAAQ,CAAC,UAAU,EAAE;AACtC,QAAA,CAAC,CAAC;AACF,QAAA,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAE1D,UAAU,CAAC,SAAS,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;AACnD,IAAA,CAAC,CAAC;IAEF,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;;AClKA;;AAEG;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-reorder-columns.mjs","sources":["../../../../libs/grid-angular/features/reorder-columns/src/index.ts","../../../../libs/grid-angular/features/reorder-columns/src/toolbox-web-grid-angular-features-reorder-columns.ts"],"sourcesContent":["/**\n * Column reorder feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `reorderColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/reorder-columns';\n *\n * <tbw-grid [reorderColumns]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/reorder-columns';\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-reorder-columns.mjs","sources":["../../../../libs/grid-angular/features/reorder-columns/src/index.ts","../../../../libs/grid-angular/features/reorder-columns/src/toolbox-web-grid-angular-features-reorder-columns.ts"],"sourcesContent":["/**\n * Column reorder feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `reorderColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/reorder-columns';\n *\n * <tbw-grid [reorderColumns]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/reorder-columns';\nexport type { _Augmentation as _ReorderColumnsAugmentation } from '@toolbox-web/grid/features/reorder-columns';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-reorder-rows.mjs","sources":["../../../../libs/grid-angular/features/reorder-rows/src/index.ts","../../../../libs/grid-angular/features/reorder-rows/src/toolbox-web-grid-angular-features-reorder-rows.ts"],"sourcesContent":["/**\n * Row reorder feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `reorderRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/reorder-rows';\n *\n * <tbw-grid [reorderRows]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/reorder-rows';\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-reorder-rows.mjs","sources":["../../../../libs/grid-angular/features/reorder-rows/src/index.ts","../../../../libs/grid-angular/features/reorder-rows/src/toolbox-web-grid-angular-features-reorder-rows.ts"],"sourcesContent":["/**\n * Row reorder feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `reorderRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/reorder-rows';\n *\n * <tbw-grid [reorderRows]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/reorder-rows';\nexport type { _Augmentation as _ReorderRowsAugmentation } from '@toolbox-web/grid/features/reorder-rows';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-responsive.mjs","sources":["../../../../libs/grid-angular/features/responsive/src/index.ts","../../../../libs/grid-angular/features/responsive/src/toolbox-web-grid-angular-features-responsive.ts"],"sourcesContent":["/**\n * Responsive feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `responsive` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/responsive';\n *\n * <tbw-grid [responsive]=\"{ breakpoint: 768 }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/responsive';\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-responsive.mjs","sources":["../../../../libs/grid-angular/features/responsive/src/index.ts","../../../../libs/grid-angular/features/responsive/src/toolbox-web-grid-angular-features-responsive.ts"],"sourcesContent":["/**\n * Responsive feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `responsive` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/responsive';\n *\n * <tbw-grid [responsive]=\"{ breakpoint: 768 }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/responsive';\nexport type { _Augmentation as _ResponsiveAugmentation } from '@toolbox-web/grid/features/responsive';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -72,8 +72,12 @@ import '@toolbox-web/grid/features/selection';
72
72
  * }
73
73
  * }
74
74
  * ```
75
+ *
76
+ * @param selector - Optional CSS selector to target a specific grid element.
77
+ * Defaults to `'tbw-grid'` (first grid in the component). Use when the
78
+ * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.
75
79
  */
76
- function injectGridSelection() {
80
+ function injectGridSelection(selector = 'tbw-grid') {
77
81
  const elementRef = inject(ElementRef);
78
82
  const destroyRef = inject(DestroyRef);
79
83
  const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : /* istanbul ignore next */ []));
@@ -117,14 +121,21 @@ function injectGridSelection() {
117
121
  const getGrid = () => {
118
122
  if (cachedGrid)
119
123
  return cachedGrid;
120
- const grid = elementRef.nativeElement.querySelector('tbw-grid');
124
+ const grid = elementRef.nativeElement.querySelector(selector);
121
125
  if (grid) {
122
126
  cachedGrid = grid;
123
127
  attachListener(grid);
124
128
  // Start ready() check only once
125
129
  if (!readyPromiseStarted) {
126
130
  readyPromiseStarted = true;
127
- grid.ready?.().then(() => isReady.set(true));
131
+ grid.ready?.().then(() => {
132
+ if (grid.getPluginByName('selection')) {
133
+ isReady.set(true);
134
+ }
135
+ else {
136
+ setTimeout(() => isReady.set(true), 0);
137
+ }
138
+ });
128
139
  }
129
140
  }
130
141
  return grid;
@@ -152,7 +163,14 @@ function injectGridSelection() {
152
163
  afterNextRender(() => {
153
164
  const grid = getGrid();
154
165
  if (grid) {
155
- grid.ready?.().then(syncSignals);
166
+ grid.ready?.().then(() => {
167
+ if (grid.getPluginByName('selection')) {
168
+ syncSignals();
169
+ }
170
+ else {
171
+ setTimeout(syncSignals, 0);
172
+ }
173
+ });
156
174
  return;
157
175
  }
158
176
  // Grid not in DOM yet — watch for it to appear.
@@ -161,7 +179,14 @@ function injectGridSelection() {
161
179
  const discovered = getGrid();
162
180
  if (discovered) {
163
181
  observer.disconnect();
164
- discovered.ready?.().then(syncSignals);
182
+ discovered.ready?.().then(() => {
183
+ if (discovered.getPluginByName('selection')) {
184
+ syncSignals();
185
+ }
186
+ else {
187
+ setTimeout(syncSignals, 0);
188
+ }
189
+ });
165
190
  }
166
191
  });
167
192
  observer.observe(host, { childList: true, subtree: true });
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-selection.mjs","sources":["../../../../libs/grid-angular/features/selection/src/index.ts","../../../../libs/grid-angular/features/selection/src/toolbox-web-grid-angular-features-selection.ts"],"sourcesContent":["/**\n * Selection feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `selection` input on Grid directive.\n * Also exports `injectGridSelection()` for programmatic selection control.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/selection';\n *\n * <tbw-grid [selection]=\"'range'\" />\n * ```\n *\n * @example Using injectGridSelection\n * ```typescript\n * import { injectGridSelection } from '@toolbox-web/grid-angular/features/selection';\n *\n * @Component({...})\n * export class MyComponent {\n * private selection = injectGridSelection<Employee>();\n *\n * selectAll() {\n * this.selection.selectAll();\n * }\n *\n * getSelected() {\n * return this.selection.getSelection();\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/selection';\nimport {\n SelectionPlugin,\n type CellRange,\n type SelectionChangeDetail,\n type SelectionResult,\n} from '@toolbox-web/grid/plugins/selection';\n\n/**\n * Selection methods returned from injectGridSelection.\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 SelectionMethods<TRow = unknown> {\n /**\n * Select all rows (row mode) or all cells (range mode).\n */\n selectAll: () => void;\n\n /**\n * Clear all selection.\n */\n clearSelection: () => void;\n\n /**\n * Get the current selection state (imperative, point-in-time snapshot).\n * For reactive selection state, use the `selection` signal instead.\n */\n getSelection: () => SelectionResult | null;\n\n /**\n * Check if a specific cell is selected.\n */\n isCellSelected: (row: number, col: number) => boolean;\n\n /**\n * Set selection ranges programmatically.\n */\n setRanges: (ranges: CellRange[]) => void;\n\n /**\n * Reactive selection state. Updates automatically whenever the selection changes.\n * Null when no SelectionPlugin is active or no selection has been made yet.\n *\n * @example\n * ```typescript\n * readonly selection = injectGridSelection();\n *\n * // In template:\n * // {{ selection.selection()?.ranges?.length ?? 0 }} cells selected\n *\n * // In computed:\n * readonly hasSelection = computed(() => (this.selection.selection()?.ranges?.length ?? 0) > 0);\n * ```\n */\n selection: Signal<SelectionResult | null>;\n\n /**\n * Reactive selected row indices (sorted ascending). Updates automatically.\n * Convenience signal for row-mode selection — returns `[]` in cell/range modes\n * or when nothing is selected.\n *\n * **Prefer `selectedRows`** for getting actual row objects — it handles\n * index-to-object resolution correctly regardless of sorting/filtering.\n *\n * @example\n * ```typescript\n * readonly selection = injectGridSelection();\n *\n * // In template:\n * // {{ selection.selectedRowIndices().length }} rows selected\n * ```\n */\n selectedRowIndices: Signal<number[]>;\n\n /**\n * Reactive selected row objects. Updates automatically whenever the selection changes.\n * Works in all selection modes (row, cell, range) — returns the actual row objects\n * from the grid's processed (sorted/filtered) rows.\n *\n * This is the recommended way to get selected rows. Unlike manual index mapping,\n * it correctly resolves rows even when the grid is sorted or filtered.\n *\n * @example\n * ```typescript\n * readonly selection = injectGridSelection<Employee>();\n *\n * // In template:\n * // {{ selection.selectedRows().length }} rows selected\n *\n * // In computed:\n * readonly hasSelection = computed(() => this.selection.selectedRows().length > 0);\n * ```\n */\n selectedRows: Signal<TRow[]>;\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 selection 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/selection';\n * import { injectGridSelection } from '@toolbox-web/grid-angular/features/selection';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <button (click)=\"handleSelectAll()\">Select All</button>\n * <tbw-grid [rows]=\"rows\" [selection]=\"'range'\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * selection = injectGridSelection();\n *\n * handleSelectAll() {\n * this.selection.selectAll();\n * }\n *\n * getSelectedRows() {\n * const selection = this.selection.getSelection();\n * if (!selection) return [];\n * // Derive rows from selection.ranges as needed\n * }\n * }\n * ```\n */\nexport function injectGridSelection<TRow = unknown>(): SelectionMethods<TRow> {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n // Reactive selection state\n const selectionSignal = signal<SelectionResult | null>(null);\n const selectedRowIndicesSignal = signal<number[]>([]);\n const selectedRowsSignal = signal<TRow[]>([]);\n\n // Lazy discovery: cached grid reference\n let cachedGrid: DataGridElement<TRow> | null = null;\n let readyPromiseStarted = false;\n let listenerAttached = false;\n\n /**\n * Handle selection-change events from the grid.\n * Updates both reactive signals.\n */\n const onSelectionChange = (detail: SelectionChangeDetail): void => {\n const plugin = getPlugin();\n if (plugin) {\n selectionSignal.set(plugin.getSelection());\n selectedRowIndicesSignal.set(detail.mode === 'row' ? plugin.getSelectedRowIndices() : []);\n selectedRowsSignal.set(plugin.getSelectedRows<TRow>());\n }\n };\n\n /**\n * Attach the selection-change event listener to the grid element.\n * Called once when the grid is first discovered.\n */\n const attachListener = (grid: DataGridElement<TRow>): void => {\n if (listenerAttached) return;\n listenerAttached = true;\n\n const unsub = grid.on('selection-change', onSelectionChange);\n\n destroyRef.onDestroy(() => {\n unsub();\n });\n };\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<TRow> | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector('tbw-grid') as DataGridElement<TRow> | null;\n if (grid) {\n cachedGrid = grid;\n attachListener(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 = (): SelectionPlugin | undefined => {\n return getGrid()?.getPluginByName('selection') as SelectionPlugin | undefined;\n };\n\n /**\n * Sync reactive signals with the current plugin state.\n * Called once when the grid is first discovered and ready.\n */\n const syncSignals = (): void => {\n const plugin = getPlugin();\n if (plugin) {\n selectionSignal.set(plugin.getSelection());\n const mode = (plugin as any).config?.mode;\n selectedRowIndicesSignal.set(mode === 'row' ? plugin.getSelectedRowIndices() : []);\n selectedRowsSignal.set(plugin.getSelectedRows<TRow>());\n }\n };\n\n // Discover the grid after the first render so the selection-change\n // listener is attached without requiring a programmatic method call.\n // Uses a MutationObserver as fallback for lazy-rendered tabs, *ngIf,\n // @defer, etc. where the grid may not be in the DOM on first render.\n afterNextRender(() => {\n const grid = getGrid();\n if (grid) {\n grid.ready?.().then(syncSignals);\n return;\n }\n\n // Grid not in DOM yet — watch for it to appear.\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n const discovered = getGrid();\n if (discovered) {\n observer.disconnect();\n discovered.ready?.().then(syncSignals);\n }\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n selection: selectionSignal.asReadonly(),\n selectedRowIndices: selectedRowIndicesSignal.asReadonly(),\n selectedRows: selectedRowsSignal.asReadonly(),\n\n selectAll: () => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:selection] SelectionPlugin not found.\\n\\n` +\n ` → Enable selection on the grid:\\n` +\n ` <tbw-grid [selection]=\"'range'\" />`,\n );\n return;\n }\n const grid = getGrid();\n // Cast to any to access protected config\n const mode = (plugin as any).config?.mode;\n\n if (mode === 'row') {\n const rowCount = grid?.rows?.length ?? 0;\n const allIndices = new Set<number>();\n for (let i = 0; i < rowCount; i++) allIndices.add(i);\n (plugin as any).selected = allIndices;\n (plugin as any).requestAfterRender?.();\n } else if (mode === 'range') {\n const rowCount = grid?.rows?.length ?? 0;\n const colCount = (grid as any)?._columns?.length ?? 0;\n if (rowCount > 0 && colCount > 0) {\n plugin.setRanges([{ from: { row: 0, col: 0 }, to: { row: rowCount - 1, col: colCount - 1 } }]);\n }\n }\n },\n\n clearSelection: () => {\n getPlugin()?.clearSelection();\n },\n\n getSelection: () => {\n return getPlugin()?.getSelection() ?? null;\n },\n\n isCellSelected: (row: number, col: number) => {\n return getPlugin()?.isCellSelected(row, col) ?? false;\n },\n\n setRanges: (ranges: CellRange[]) => {\n getPlugin()?.setRanges(ranges);\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-selection.mjs","sources":["../../../../libs/grid-angular/features/selection/src/index.ts","../../../../libs/grid-angular/features/selection/src/toolbox-web-grid-angular-features-selection.ts"],"sourcesContent":["/**\n * Selection feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `selection` input on Grid directive.\n * Also exports `injectGridSelection()` for programmatic selection control.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/selection';\n *\n * <tbw-grid [selection]=\"'range'\" />\n * ```\n *\n * @example Using injectGridSelection\n * ```typescript\n * import { injectGridSelection } from '@toolbox-web/grid-angular/features/selection';\n *\n * @Component({...})\n * export class MyComponent {\n * private selection = injectGridSelection<Employee>();\n *\n * selectAll() {\n * this.selection.selectAll();\n * }\n *\n * getSelected() {\n * return this.selection.getSelection();\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/selection';\nimport {\n SelectionPlugin,\n type CellRange,\n type SelectionChangeDetail,\n type SelectionResult,\n} from '@toolbox-web/grid/plugins/selection';\nexport type { _Augmentation as _SelectionAugmentation } from '@toolbox-web/grid/features/selection';\n\n/**\n * Selection methods returned from injectGridSelection.\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 SelectionMethods<TRow = unknown> {\n /**\n * Select all rows (row mode) or all cells (range mode).\n */\n selectAll: () => void;\n\n /**\n * Clear all selection.\n */\n clearSelection: () => void;\n\n /**\n * Get the current selection state (imperative, point-in-time snapshot).\n * For reactive selection state, use the `selection` signal instead.\n */\n getSelection: () => SelectionResult | null;\n\n /**\n * Check if a specific cell is selected.\n */\n isCellSelected: (row: number, col: number) => boolean;\n\n /**\n * Set selection ranges programmatically.\n */\n setRanges: (ranges: CellRange[]) => void;\n\n /**\n * Reactive selection state. Updates automatically whenever the selection changes.\n * Null when no SelectionPlugin is active or no selection has been made yet.\n *\n * @example\n * ```typescript\n * readonly selection = injectGridSelection();\n *\n * // In template:\n * // {{ selection.selection()?.ranges?.length ?? 0 }} cells selected\n *\n * // In computed:\n * readonly hasSelection = computed(() => (this.selection.selection()?.ranges?.length ?? 0) > 0);\n * ```\n */\n selection: Signal<SelectionResult | null>;\n\n /**\n * Reactive selected row indices (sorted ascending). Updates automatically.\n * Convenience signal for row-mode selection — returns `[]` in cell/range modes\n * or when nothing is selected.\n *\n * **Prefer `selectedRows`** for getting actual row objects — it handles\n * index-to-object resolution correctly regardless of sorting/filtering.\n *\n * @example\n * ```typescript\n * readonly selection = injectGridSelection();\n *\n * // In template:\n * // {{ selection.selectedRowIndices().length }} rows selected\n * ```\n */\n selectedRowIndices: Signal<number[]>;\n\n /**\n * Reactive selected row objects. Updates automatically whenever the selection changes.\n * Works in all selection modes (row, cell, range) — returns the actual row objects\n * from the grid's processed (sorted/filtered) rows.\n *\n * This is the recommended way to get selected rows. Unlike manual index mapping,\n * it correctly resolves rows even when the grid is sorted or filtered.\n *\n * @example\n * ```typescript\n * readonly selection = injectGridSelection<Employee>();\n *\n * // In template:\n * // {{ selection.selectedRows().length }} rows selected\n *\n * // In computed:\n * readonly hasSelection = computed(() => this.selection.selectedRows().length > 0);\n * ```\n */\n selectedRows: Signal<TRow[]>;\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 selection 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/selection';\n * import { injectGridSelection } from '@toolbox-web/grid-angular/features/selection';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <button (click)=\"handleSelectAll()\">Select All</button>\n * <tbw-grid [rows]=\"rows\" [selection]=\"'range'\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * selection = injectGridSelection();\n *\n * handleSelectAll() {\n * this.selection.selectAll();\n * }\n *\n * getSelectedRows() {\n * const selection = this.selection.getSelection();\n * if (!selection) return [];\n * // Derive rows from selection.ranges as needed\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 injectGridSelection<TRow = unknown>(selector = 'tbw-grid'): SelectionMethods<TRow> {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n // Reactive selection state\n const selectionSignal = signal<SelectionResult | null>(null);\n const selectedRowIndicesSignal = signal<number[]>([]);\n const selectedRowsSignal = signal<TRow[]>([]);\n\n // Lazy discovery: cached grid reference\n let cachedGrid: DataGridElement<TRow> | null = null;\n let readyPromiseStarted = false;\n let listenerAttached = false;\n\n /**\n * Handle selection-change events from the grid.\n * Updates both reactive signals.\n */\n const onSelectionChange = (detail: SelectionChangeDetail): void => {\n const plugin = getPlugin();\n if (plugin) {\n selectionSignal.set(plugin.getSelection());\n selectedRowIndicesSignal.set(detail.mode === 'row' ? plugin.getSelectedRowIndices() : []);\n selectedRowsSignal.set(plugin.getSelectedRows<TRow>());\n }\n };\n\n /**\n * Attach the selection-change event listener to the grid element.\n * Called once when the grid is first discovered.\n */\n const attachListener = (grid: DataGridElement<TRow>): void => {\n if (listenerAttached) return;\n listenerAttached = true;\n\n const unsub = grid.on('selection-change', onSelectionChange);\n\n destroyRef.onDestroy(() => {\n unsub();\n });\n };\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<TRow> | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement<TRow> | null;\n if (grid) {\n cachedGrid = grid;\n attachListener(grid);\n // Start ready() check only once\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n if (grid.getPluginByName('selection')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): SelectionPlugin | undefined => {\n return getGrid()?.getPluginByName('selection') as SelectionPlugin | undefined;\n };\n\n /**\n * Sync reactive signals with the current plugin state.\n * Called once when the grid is first discovered and ready.\n */\n const syncSignals = (): void => {\n const plugin = getPlugin();\n if (plugin) {\n selectionSignal.set(plugin.getSelection());\n const mode = (plugin as any).config?.mode;\n selectedRowIndicesSignal.set(mode === 'row' ? plugin.getSelectedRowIndices() : []);\n selectedRowsSignal.set(plugin.getSelectedRows<TRow>());\n }\n };\n\n // Discover the grid after the first render so the selection-change\n // listener is attached without requiring a programmatic method call.\n // Uses a MutationObserver as fallback for lazy-rendered tabs, *ngIf,\n // @defer, etc. where the grid may not be in the DOM on first render.\n afterNextRender(() => {\n const grid = getGrid();\n if (grid) {\n grid.ready?.().then(() => {\n if (grid.getPluginByName('selection')) {\n syncSignals();\n } else {\n setTimeout(syncSignals, 0);\n }\n });\n return;\n }\n\n // Grid not in DOM yet — watch for it to appear.\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n const discovered = getGrid();\n if (discovered) {\n observer.disconnect();\n discovered.ready?.().then(() => {\n if (discovered.getPluginByName('selection')) {\n syncSignals();\n } else {\n setTimeout(syncSignals, 0);\n }\n });\n }\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n selection: selectionSignal.asReadonly(),\n selectedRowIndices: selectedRowIndicesSignal.asReadonly(),\n selectedRows: selectedRowsSignal.asReadonly(),\n\n selectAll: () => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:selection] SelectionPlugin not found.\\n\\n` +\n ` → Enable selection on the grid:\\n` +\n ` <tbw-grid [selection]=\"'range'\" />`,\n );\n return;\n }\n const grid = getGrid();\n // Cast to any to access protected config\n const mode = (plugin as any).config?.mode;\n\n if (mode === 'row') {\n const rowCount = grid?.rows?.length ?? 0;\n const allIndices = new Set<number>();\n for (let i = 0; i < rowCount; i++) allIndices.add(i);\n (plugin as any).selected = allIndices;\n (plugin as any).requestAfterRender?.();\n } else if (mode === 'range') {\n const rowCount = grid?.rows?.length ?? 0;\n const colCount = (grid as any)?._columns?.length ?? 0;\n if (rowCount > 0 && colCount > 0) {\n plugin.setRanges([{ from: { row: 0, col: 0 }, to: { row: rowCount - 1, col: colCount - 1 } }]);\n }\n }\n },\n\n clearSelection: () => {\n getPlugin()?.clearSelection();\n },\n\n getSelection: () => {\n return getPlugin()?.getSelection() ?? null;\n },\n\n isCellSelected: (row: number, col: number) => {\n return getPlugin()?.isCellSelected(row, col) ?? false;\n },\n\n setRanges: (ranges: CellRange[]) => {\n getPlugin()?.setRanges(ranges);\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-server-side.mjs","sources":["../../../../libs/grid-angular/features/server-side/src/index.ts","../../../../libs/grid-angular/features/server-side/src/toolbox-web-grid-angular-features-server-side.ts"],"sourcesContent":["/**\n * Server-side feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `serverSide` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/server-side';\n *\n * <tbw-grid [serverSide]=\"{ dataSource: fetchDataFn }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/server-side';\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-server-side.mjs","sources":["../../../../libs/grid-angular/features/server-side/src/index.ts","../../../../libs/grid-angular/features/server-side/src/toolbox-web-grid-angular-features-server-side.ts"],"sourcesContent":["/**\n * Server-side feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `serverSide` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/server-side';\n *\n * <tbw-grid [serverSide]=\"{ dataSource: fetchDataFn }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/server-side';\nexport type { _Augmentation as _ServerSideAugmentation } from '@toolbox-web/grid/features/server-side';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-tooltip.mjs","sources":["../../../../libs/grid-angular/features/tooltip/src/index.ts","../../../../libs/grid-angular/features/tooltip/src/toolbox-web-grid-angular-features-tooltip.ts"],"sourcesContent":["/**\n * Tooltip feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `tooltip` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/tooltip';\n *\n * <tbw-grid [tooltip]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/tooltip';\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-tooltip.mjs","sources":["../../../../libs/grid-angular/features/tooltip/src/index.ts","../../../../libs/grid-angular/features/tooltip/src/toolbox-web-grid-angular-features-tooltip.ts"],"sourcesContent":["/**\n * Tooltip feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `tooltip` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/tooltip';\n *\n * <tbw-grid [tooltip]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/tooltip';\nexport type { _Augmentation as _TooltipAugmentation } from '@toolbox-web/grid/features/tooltip';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-tree.mjs","sources":["../../../../libs/grid-angular/features/tree/src/index.ts","../../../../libs/grid-angular/features/tree/src/toolbox-web-grid-angular-features-tree.ts"],"sourcesContent":["/**\n * Tree feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `tree` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/tree';\n *\n * <tbw-grid [tree]=\"{ childrenField: 'children' }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/tree';\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-tree.mjs","sources":["../../../../libs/grid-angular/features/tree/src/index.ts","../../../../libs/grid-angular/features/tree/src/toolbox-web-grid-angular-features-tree.ts"],"sourcesContent":["/**\n * Tree feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `tree` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/tree';\n *\n * <tbw-grid [tree]=\"{ childrenField: 'children' }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport '@toolbox-web/grid/features/tree';\nexport type { _Augmentation as _TreeAugmentation } from '@toolbox-web/grid/features/tree';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;AAaG;;ACbH;;AAEG"}