@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.
- package/README.md +28 -22
- package/fesm2022/toolbox-web-grid-angular-features-export.mjs +123 -4
- package/fesm2022/toolbox-web-grid-angular-features-export.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +123 -1
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-print.mjs +89 -1
- package/fesm2022/toolbox-web-grid-angular-features-print.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-selection.mjs +133 -1
- package/fesm2022/toolbox-web-grid-angular-features-selection.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs +106 -1
- package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular.mjs +757 -122
- package/fesm2022/toolbox-web-grid-angular.mjs.map +1 -1
- package/package.json +1 -1
- package/types/toolbox-web-grid-angular-features-export.d.ts +113 -1
- package/types/toolbox-web-grid-angular-features-export.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-filtering.d.ts +120 -1
- package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-print.d.ts +91 -1
- package/types/toolbox-web-grid-angular-features-print.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-selection.d.ts +114 -1
- package/types/toolbox-web-grid-angular-features-selection.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-undo-redo.d.ts +107 -1
- package/types/toolbox-web-grid-angular-features-undo-redo.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular.d.ts +419 -91
- package/types/toolbox-web-grid-angular.d.ts.map +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
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 {
|
|
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 * @
|
|
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;;;;"}
|