@toolbox-web/grid-angular 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +28 -22
  2. package/fesm2022/toolbox-web-grid-angular-features-export.mjs +123 -4
  3. package/fesm2022/toolbox-web-grid-angular-features-export.mjs.map +1 -1
  4. package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +123 -1
  5. package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
  6. package/fesm2022/toolbox-web-grid-angular-features-print.mjs +89 -1
  7. package/fesm2022/toolbox-web-grid-angular-features-print.mjs.map +1 -1
  8. package/fesm2022/toolbox-web-grid-angular-features-selection.mjs +133 -1
  9. package/fesm2022/toolbox-web-grid-angular-features-selection.mjs.map +1 -1
  10. package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs +106 -1
  11. package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs.map +1 -1
  12. package/fesm2022/toolbox-web-grid-angular.mjs +757 -122
  13. package/fesm2022/toolbox-web-grid-angular.mjs.map +1 -1
  14. package/package.json +1 -1
  15. package/types/toolbox-web-grid-angular-features-export.d.ts +113 -1
  16. package/types/toolbox-web-grid-angular-features-export.d.ts.map +1 -1
  17. package/types/toolbox-web-grid-angular-features-filtering.d.ts +120 -1
  18. package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
  19. package/types/toolbox-web-grid-angular-features-print.d.ts +91 -1
  20. package/types/toolbox-web-grid-angular-features-print.d.ts.map +1 -1
  21. package/types/toolbox-web-grid-angular-features-selection.d.ts +114 -1
  22. package/types/toolbox-web-grid-angular-features-selection.d.ts.map +1 -1
  23. package/types/toolbox-web-grid-angular-features-undo-redo.d.ts +107 -1
  24. package/types/toolbox-web-grid-angular-features-undo-redo.d.ts.map +1 -1
  25. package/types/toolbox-web-grid-angular.d.ts +419 -91
  26. package/types/toolbox-web-grid-angular.d.ts.map +1 -1
@@ -1,10 +1,12 @@
1
- import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';
1
+ import { inject, ElementRef, signal } from '@angular/core';
2
2
  import { registerFeature } from '@toolbox-web/grid-angular';
3
+ import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';
3
4
 
4
5
  /**
5
6
  * Selection feature for @toolbox-web/grid-angular
6
7
  *
7
8
  * Import this module to enable the `selection` input on Grid directive.
9
+ * Also exports `injectGridSelection()` for programmatic selection control.
8
10
  *
9
11
  * @example
10
12
  * ```typescript
@@ -13,6 +15,24 @@ import { registerFeature } from '@toolbox-web/grid-angular';
13
15
  * <tbw-grid [selection]="'range'" />
14
16
  * ```
15
17
  *
18
+ * @example Using injectGridSelection
19
+ * ```typescript
20
+ * import { injectGridSelection } from '@toolbox-web/grid-angular/features/selection';
21
+ *
22
+ * @Component({...})
23
+ * export class MyComponent {
24
+ * private selection = injectGridSelection<Employee>();
25
+ *
26
+ * selectAll() {
27
+ * this.selection.selectAll();
28
+ * }
29
+ *
30
+ * getSelected() {
31
+ * return this.selection.getSelection();
32
+ * }
33
+ * }
34
+ * ```
35
+ *
16
36
  * @packageDocumentation
17
37
  */
18
38
  registerFeature('selection', (config) => {
@@ -23,8 +43,120 @@ registerFeature('selection', (config) => {
23
43
  // Full config object
24
44
  return new SelectionPlugin(config ?? undefined);
25
45
  });
46
+ /**
47
+ * Angular inject function for programmatic selection control.
48
+ *
49
+ * Uses **lazy grid discovery** - the grid element is found when methods are called,
50
+ * not during initialization. This ensures it works reliably with:
51
+ * - Lazy-rendered tabs
52
+ * - Conditional rendering (*ngIf)
53
+ * - Dynamic component loading
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
58
+ * import { Grid } from '@toolbox-web/grid-angular';
59
+ * import '@toolbox-web/grid-angular/features/selection';
60
+ * import { injectGridSelection } from '@toolbox-web/grid-angular/features/selection';
61
+ *
62
+ * @Component({
63
+ * selector: 'app-my-grid',
64
+ * imports: [Grid],
65
+ * schemas: [CUSTOM_ELEMENTS_SCHEMA],
66
+ * template: `
67
+ * <button (click)="handleSelectAll()">Select All</button>
68
+ * <tbw-grid [rows]="rows" [selection]="'range'"></tbw-grid>
69
+ * `
70
+ * })
71
+ * export class MyGridComponent {
72
+ * selection = injectGridSelection();
73
+ *
74
+ * handleSelectAll() {
75
+ * this.selection.selectAll();
76
+ * }
77
+ *
78
+ * getSelectedRows() {
79
+ * const selection = this.selection.getSelection();
80
+ * if (!selection) return [];
81
+ * // Derive rows from selection.ranges as needed
82
+ * }
83
+ * }
84
+ * ```
85
+ */
86
+ function injectGridSelection() {
87
+ const elementRef = inject(ElementRef);
88
+ const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
89
+ // Lazy discovery: cached grid reference
90
+ let cachedGrid = null;
91
+ let readyPromiseStarted = false;
92
+ /**
93
+ * Lazily find the grid element. Called on each method invocation.
94
+ * Caches the reference once found and triggers ready() check.
95
+ */
96
+ const getGrid = () => {
97
+ if (cachedGrid)
98
+ return cachedGrid;
99
+ const grid = elementRef.nativeElement.querySelector('tbw-grid');
100
+ if (grid) {
101
+ cachedGrid = grid;
102
+ // Start ready() check only once
103
+ if (!readyPromiseStarted) {
104
+ readyPromiseStarted = true;
105
+ grid.ready?.().then(() => isReady.set(true));
106
+ }
107
+ }
108
+ return grid;
109
+ };
110
+ const getPlugin = () => {
111
+ return getGrid()?.getPlugin(SelectionPlugin);
112
+ };
113
+ return {
114
+ isReady: isReady.asReadonly(),
115
+ selectAll: () => {
116
+ const plugin = getPlugin();
117
+ if (!plugin) {
118
+ console.warn(`[tbw-grid:selection] SelectionPlugin not found.\n\n` +
119
+ ` → Enable selection on the grid:\n` +
120
+ ` <tbw-grid [selection]="'range'" />`);
121
+ return;
122
+ }
123
+ const grid = getGrid();
124
+ // Cast to any to access protected config
125
+ const mode = plugin.config?.mode;
126
+ if (mode === 'row') {
127
+ const rowCount = grid?.rows?.length ?? 0;
128
+ const allIndices = new Set();
129
+ for (let i = 0; i < rowCount; i++)
130
+ allIndices.add(i);
131
+ plugin.selected = allIndices;
132
+ plugin.requestAfterRender?.();
133
+ }
134
+ else if (mode === 'range') {
135
+ const rowCount = grid?.rows?.length ?? 0;
136
+ const colCount = grid?._columns?.length ?? 0;
137
+ if (rowCount > 0 && colCount > 0) {
138
+ plugin.setRanges([{ from: { row: 0, col: 0 }, to: { row: rowCount - 1, col: colCount - 1 } }]);
139
+ }
140
+ }
141
+ },
142
+ clearSelection: () => {
143
+ getPlugin()?.clearSelection();
144
+ },
145
+ getSelection: () => {
146
+ return getPlugin()?.getSelection() ?? null;
147
+ },
148
+ isCellSelected: (row, col) => {
149
+ return getPlugin()?.isCellSelected(row, col) ?? false;
150
+ },
151
+ setRanges: (ranges) => {
152
+ getPlugin()?.setRanges(ranges);
153
+ },
154
+ };
155
+ }
26
156
 
27
157
  /**
28
158
  * Generated bundle index. Do not edit.
29
159
  */
160
+
161
+ export { injectGridSelection };
30
162
  //# sourceMappingURL=toolbox-web-grid-angular-features-selection.mjs.map
@@ -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 *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/selection';\n *\n * <tbw-grid [selection]=\"'range'\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';\nimport { registerFeature } from '@toolbox-web/grid-angular';\n\nregisterFeature('selection', (config) => {\n // Handle shorthand: 'cell', 'row', 'range'\n if (config === 'cell' || config === 'row' || config === 'range') {\n return new SelectionPlugin({ mode: config });\n }\n // Full config object\n return new SelectionPlugin(config ?? undefined);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;AAaG;AAKH,eAAe,CAAC,WAAW,EAAE,CAAC,MAAM,KAAI;;AAEtC,IAAA,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,OAAO,EAAE;QAC/D,OAAO,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC9C;;AAEA,IAAA,OAAO,IAAI,eAAe,CAAC,MAAM,IAAI,SAAS,CAAC;AACjD,CAAC,CAAC;;ACzBF;;AAEG"}
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 { ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeature } from '@toolbox-web/grid-angular';\nimport { SelectionPlugin, type CellRange, type SelectionResult } from '@toolbox-web/grid/plugins/selection';\n\nregisterFeature('selection', (config) => {\n // Handle shorthand: 'cell', 'row', 'range'\n if (config === 'cell' || config === 'row' || config === 'range') {\n return new SelectionPlugin({ mode: config });\n }\n // Full config object\n return new SelectionPlugin(config ?? undefined);\n});\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 {\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.\n * Use this to derive selected rows, indices, etc.\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 * 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, CUSTOM_ELEMENTS_SCHEMA } 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 * schemas: [CUSTOM_ELEMENTS_SCHEMA],\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 {\n const elementRef = inject(ElementRef);\n const isReady = signal(false);\n\n // Lazy discovery: cached grid reference\n let cachedGrid: DataGridElement<TRow> | 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<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 // 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()?.getPlugin(SelectionPlugin);\n };\n\n return {\n isReady: isReady.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,10 +1,12 @@
1
- import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';
1
+ import { inject, ElementRef, signal } from '@angular/core';
2
2
  import { registerFeature } from '@toolbox-web/grid-angular';
3
+ import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';
3
4
 
4
5
  /**
5
6
  * Undo/Redo feature for @toolbox-web/grid-angular
6
7
  *
7
8
  * Import this module to enable the `undoRedo` input on Grid directive.
9
+ * Also exports `injectGridUndoRedo()` for programmatic undo/redo control.
8
10
  * Requires editing feature to be enabled.
9
11
  *
10
12
  * @example
@@ -15,6 +17,19 @@ import { registerFeature } from '@toolbox-web/grid-angular';
15
17
  * <tbw-grid [editing]="'dblclick'" [undoRedo]="true" />
16
18
  * ```
17
19
  *
20
+ * @example Using injectGridUndoRedo
21
+ * ```typescript
22
+ * import { injectGridUndoRedo } from '@toolbox-web/grid-angular/features/undo-redo';
23
+ *
24
+ * @Component({...})
25
+ * export class MyComponent {
26
+ * private undoRedo = injectGridUndoRedo();
27
+ *
28
+ * undo() { this.undoRedo.undo(); }
29
+ * redo() { this.undoRedo.redo(); }
30
+ * }
31
+ * ```
32
+ *
18
33
  * @packageDocumentation
19
34
  */
20
35
  registerFeature('undoRedo', (config) => {
@@ -23,8 +38,98 @@ registerFeature('undoRedo', (config) => {
23
38
  }
24
39
  return new UndoRedoPlugin(config ?? undefined);
25
40
  });
41
+ /**
42
+ * Angular inject function for programmatic undo/redo control.
43
+ *
44
+ * Uses **lazy grid discovery** - the grid element is found when methods are called,
45
+ * not during initialization.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
50
+ * import { Grid } from '@toolbox-web/grid-angular';
51
+ * import '@toolbox-web/grid-angular/features/editing';
52
+ * import '@toolbox-web/grid-angular/features/undo-redo';
53
+ * import { injectGridUndoRedo } from '@toolbox-web/grid-angular/features/undo-redo';
54
+ *
55
+ * @Component({
56
+ * selector: 'app-my-grid',
57
+ * imports: [Grid],
58
+ * schemas: [CUSTOM_ELEMENTS_SCHEMA],
59
+ * template: `
60
+ * <button (click)="undoRedo.undo()" [disabled]="!undoRedo.canUndo()">Undo</button>
61
+ * <button (click)="undoRedo.redo()" [disabled]="!undoRedo.canRedo()">Redo</button>
62
+ * <tbw-grid [rows]="rows" [editing]="'dblclick'" [undoRedo]="true"></tbw-grid>
63
+ * `
64
+ * })
65
+ * export class MyGridComponent {
66
+ * undoRedo = injectGridUndoRedo();
67
+ * }
68
+ * ```
69
+ */
70
+ function injectGridUndoRedo() {
71
+ const elementRef = inject(ElementRef);
72
+ const isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
73
+ let cachedGrid = null;
74
+ let readyPromiseStarted = false;
75
+ const getGrid = () => {
76
+ if (cachedGrid)
77
+ return cachedGrid;
78
+ const grid = elementRef.nativeElement.querySelector('tbw-grid');
79
+ if (grid) {
80
+ cachedGrid = grid;
81
+ if (!readyPromiseStarted) {
82
+ readyPromiseStarted = true;
83
+ grid.ready?.().then(() => isReady.set(true));
84
+ }
85
+ }
86
+ return grid;
87
+ };
88
+ const getPlugin = () => {
89
+ return getGrid()?.getPlugin(UndoRedoPlugin);
90
+ };
91
+ return {
92
+ isReady: isReady.asReadonly(),
93
+ undo: () => {
94
+ const plugin = getPlugin();
95
+ if (!plugin) {
96
+ console.warn(`[tbw-grid:undoRedo] UndoRedoPlugin not found.\n\n` +
97
+ ` → Enable undo/redo on the grid:\n` +
98
+ ` <tbw-grid [editing]="'dblclick'" [undoRedo]="true" />`);
99
+ return null;
100
+ }
101
+ return plugin.undo();
102
+ },
103
+ redo: () => {
104
+ const plugin = getPlugin();
105
+ if (!plugin) {
106
+ console.warn(`[tbw-grid:undoRedo] UndoRedoPlugin not found.\n\n` +
107
+ ` → Enable undo/redo on the grid:\n` +
108
+ ` <tbw-grid [editing]="'dblclick'" [undoRedo]="true" />`);
109
+ return null;
110
+ }
111
+ return plugin.redo();
112
+ },
113
+ canUndo: () => getPlugin()?.canUndo() ?? false,
114
+ canRedo: () => getPlugin()?.canRedo() ?? false,
115
+ clearHistory: () => {
116
+ const plugin = getPlugin();
117
+ if (!plugin) {
118
+ console.warn(`[tbw-grid:undoRedo] UndoRedoPlugin not found.\n\n` +
119
+ ` → Enable undo/redo on the grid:\n` +
120
+ ` <tbw-grid [editing]="'dblclick'" [undoRedo]="true" />`);
121
+ return;
122
+ }
123
+ plugin.clearHistory();
124
+ },
125
+ getUndoStack: () => getPlugin()?.getUndoStack() ?? [],
126
+ getRedoStack: () => getPlugin()?.getRedoStack() ?? [],
127
+ };
128
+ }
26
129
 
27
130
  /**
28
131
  * Generated bundle index. Do not edit.
29
132
  */
133
+
134
+ export { injectGridUndoRedo };
30
135
  //# sourceMappingURL=toolbox-web-grid-angular-features-undo-redo.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-undo-redo.mjs","sources":["../../../../libs/grid-angular/features/undo-redo/src/index.ts","../../../../libs/grid-angular/features/undo-redo/src/toolbox-web-grid-angular-features-undo-redo.ts"],"sourcesContent":["/**\n * Undo/Redo feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `undoRedo` input on Grid directive.\n * Requires editing feature to be enabled.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/editing';\n * import '@toolbox-web/grid-angular/features/undo-redo';\n *\n * <tbw-grid [editing]=\"'dblclick'\" [undoRedo]=\"true\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';\nimport { registerFeature } from '@toolbox-web/grid-angular';\n\nregisterFeature('undoRedo', (config) => {\n if (config === true) {\n return new UndoRedoPlugin();\n }\n return new UndoRedoPlugin(config ?? undefined);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;AAeG;AAKH,eAAe,CAAC,UAAU,EAAE,CAAC,MAAM,KAAI;AACrC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,cAAc,EAAE;IAC7B;AACA,IAAA,OAAO,IAAI,cAAc,CAAC,MAAM,IAAI,SAAS,CAAC;AAChD,CAAC,CAAC;;ACzBF;;AAEG"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-undo-redo.mjs","sources":["../../../../libs/grid-angular/features/undo-redo/src/index.ts","../../../../libs/grid-angular/features/undo-redo/src/toolbox-web-grid-angular-features-undo-redo.ts"],"sourcesContent":["/**\n * Undo/Redo feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `undoRedo` input on Grid directive.\n * Also exports `injectGridUndoRedo()` for programmatic undo/redo control.\n * Requires editing feature to be enabled.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/editing';\n * import '@toolbox-web/grid-angular/features/undo-redo';\n *\n * <tbw-grid [editing]=\"'dblclick'\" [undoRedo]=\"true\" />\n * ```\n *\n * @example Using injectGridUndoRedo\n * ```typescript\n * import { injectGridUndoRedo } from '@toolbox-web/grid-angular/features/undo-redo';\n *\n * @Component({...})\n * export class MyComponent {\n * private undoRedo = injectGridUndoRedo();\n *\n * undo() { this.undoRedo.undo(); }\n * redo() { this.undoRedo.redo(); }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { ElementRef, inject, signal, type Signal } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeature } from '@toolbox-web/grid-angular';\nimport { UndoRedoPlugin, type EditAction } from '@toolbox-web/grid/plugins/undo-redo';\n\nregisterFeature('undoRedo', (config) => {\n if (config === true) {\n return new UndoRedoPlugin();\n }\n return new UndoRedoPlugin(config ?? undefined);\n});\n\n/**\n * Undo/Redo methods returned from injectGridUndoRedo.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n */\nexport interface UndoRedoMethods {\n /**\n * Undo the last edit action.\n * @returns The undone action, or null if nothing to undo\n */\n undo: () => EditAction | null;\n\n /**\n * Redo the last undone action.\n * @returns The redone action, or null if nothing to redo\n */\n redo: () => EditAction | null;\n\n /**\n * Check if there are any actions that can be undone.\n */\n canUndo: () => boolean;\n\n /**\n * Check if there are any actions that can be redone.\n */\n canRedo: () => boolean;\n\n /**\n * Clear all undo/redo history.\n */\n clearHistory: () => void;\n\n /**\n * Get a copy of the current undo stack.\n */\n getUndoStack: () => EditAction[];\n\n /**\n * Get a copy of the current redo stack.\n */\n getRedoStack: () => EditAction[];\n\n /**\n * Signal indicating if grid is ready.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic undo/redo control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization.\n *\n * @example\n * ```typescript\n * import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/editing';\n * import '@toolbox-web/grid-angular/features/undo-redo';\n * import { injectGridUndoRedo } from '@toolbox-web/grid-angular/features/undo-redo';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * schemas: [CUSTOM_ELEMENTS_SCHEMA],\n * template: `\n * <button (click)=\"undoRedo.undo()\" [disabled]=\"!undoRedo.canUndo()\">Undo</button>\n * <button (click)=\"undoRedo.redo()\" [disabled]=\"!undoRedo.canRedo()\">Redo</button>\n * <tbw-grid [rows]=\"rows\" [editing]=\"'dblclick'\" [undoRedo]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * undoRedo = injectGridUndoRedo();\n * }\n * ```\n */\nexport function injectGridUndoRedo(): UndoRedoMethods {\n const elementRef = inject(ElementRef);\n const isReady = signal(false);\n\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector('tbw-grid') as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => isReady.set(true));\n }\n }\n return grid;\n };\n\n const getPlugin = (): UndoRedoPlugin | undefined => {\n return getGrid()?.getPlugin(UndoRedoPlugin);\n };\n\n return {\n isReady: isReady.asReadonly(),\n\n undo: () => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:undoRedo] UndoRedoPlugin not found.\\n\\n` +\n ` → Enable undo/redo on the grid:\\n` +\n ` <tbw-grid [editing]=\"'dblclick'\" [undoRedo]=\"true\" />`,\n );\n return null;\n }\n return plugin.undo();\n },\n\n redo: () => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:undoRedo] UndoRedoPlugin not found.\\n\\n` +\n ` → Enable undo/redo on the grid:\\n` +\n ` <tbw-grid [editing]=\"'dblclick'\" [undoRedo]=\"true\" />`,\n );\n return null;\n }\n return plugin.redo();\n },\n\n canUndo: () => getPlugin()?.canUndo() ?? false,\n\n canRedo: () => getPlugin()?.canRedo() ?? false,\n\n clearHistory: () => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:undoRedo] UndoRedoPlugin not found.\\n\\n` +\n ` → Enable undo/redo on the grid:\\n` +\n ` <tbw-grid [editing]=\"'dblclick'\" [undoRedo]=\"true\" />`,\n );\n return;\n }\n plugin.clearHistory();\n },\n\n getUndoStack: () => getPlugin()?.getUndoStack() ?? [],\n\n getRedoStack: () => getPlugin()?.getRedoStack() ?? [],\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;AAOH,eAAe,CAAC,UAAU,EAAE,CAAC,MAAM,KAAI;AACrC,IAAA,IAAI,MAAM,KAAK,IAAI,EAAE;QACnB,OAAO,IAAI,cAAc,EAAE;IAC7B;AACA,IAAA,OAAO,IAAI,cAAc,CAAC,MAAM,IAAI,SAAS,CAAC;AAChD,CAAC,CAAC;AAmDF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;SACa,kBAAkB,GAAA;AAChC,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,mDAAC;IAE7B,IAAI,UAAU,GAA2B,IAAI;IAC7C,IAAI,mBAAmB,GAAG,KAAK;IAE/B,MAAM,OAAO,GAAG,MAA6B;AAC3C,QAAA,IAAI,UAAU;AAAE,YAAA,OAAO,UAAU;QAEjC,MAAM,IAAI,GAAG,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,CAA2B;QACzF,IAAI,IAAI,EAAE;YACR,UAAU,GAAG,IAAI;YACjB,IAAI,CAAC,mBAAmB,EAAE;gBACxB,mBAAmB,GAAG,IAAI;AAC1B,gBAAA,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9C;QACF;AACA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC;IAED,MAAM,SAAS,GAAG,MAAiC;AACjD,QAAA,OAAO,OAAO,EAAE,EAAE,SAAS,CAAC,cAAc,CAAC;AAC7C,IAAA,CAAC;IAED,OAAO;AACL,QAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAE7B,IAAI,EAAE,MAAK;AACT,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,iDAAA,CAAmD;oBACjD,CAAA,mCAAA,CAAqC;AACrC,oBAAA,CAAA,yDAAA,CAA2D,CAC9D;AACD,gBAAA,OAAO,IAAI;YACb;AACA,YAAA,OAAO,MAAM,CAAC,IAAI,EAAE;QACtB,CAAC;QAED,IAAI,EAAE,MAAK;AACT,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,iDAAA,CAAmD;oBACjD,CAAA,mCAAA,CAAqC;AACrC,oBAAA,CAAA,yDAAA,CAA2D,CAC9D;AACD,gBAAA,OAAO,IAAI;YACb;AACA,YAAA,OAAO,MAAM,CAAC,IAAI,EAAE;QACtB,CAAC;QAED,OAAO,EAAE,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,KAAK;QAE9C,OAAO,EAAE,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,KAAK;QAE9C,YAAY,EAAE,MAAK;AACjB,YAAA,MAAM,MAAM,GAAG,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,CAAC,IAAI,CACV,CAAA,iDAAA,CAAmD;oBACjD,CAAA,mCAAA,CAAqC;AACrC,oBAAA,CAAA,yDAAA,CAA2D,CAC9D;gBACD;YACF;YACA,MAAM,CAAC,YAAY,EAAE;QACvB,CAAC;QAED,YAAY,EAAE,MAAM,SAAS,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;QAErD,YAAY,EAAE,MAAM,SAAS,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACtD;AACH;;ACpMA;;AAEG;;;;"}