@bit.rhplus/ag-grid 0.0.85 → 0.0.86
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/AgGridColumn.js +5 -5
- package/BulkEdit/useBulkCellEdit.js +37 -138
- package/dist/AgGridColumn.js +5 -5
- package/dist/AgGridColumn.js.map +1 -1
- package/dist/BulkEdit/useBulkCellEdit.js +36 -119
- package/dist/BulkEdit/useBulkCellEdit.js.map +1 -1
- package/dist/index.js +122 -104
- package/dist/index.js.map +1 -1
- package/index.jsx +162 -121
- package/package.json +5 -5
- /package/dist/{preview-1768848551266.js → preview-1768914354237.js} +0 -0
package/AgGridColumn.js
CHANGED
|
@@ -26,7 +26,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
26
26
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
27
27
|
column.cellRendererParams = {
|
|
28
28
|
...column.booleanRendererParams,
|
|
29
|
-
deferRender:
|
|
29
|
+
deferRender: false
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -35,7 +35,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
35
35
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
36
36
|
column.cellRendererParams = {
|
|
37
37
|
...column.iconRendererParams,
|
|
38
|
-
deferRender:
|
|
38
|
+
deferRender: false
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -44,7 +44,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
44
44
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
45
45
|
column.cellRendererParams = {
|
|
46
46
|
...column.imageRendererParams,
|
|
47
|
-
deferRender:
|
|
47
|
+
deferRender: false
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -53,7 +53,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
53
53
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
54
54
|
column.cellRendererParams = {
|
|
55
55
|
...column.stateRendererParams,
|
|
56
|
-
deferRender:
|
|
56
|
+
deferRender: false
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -62,7 +62,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
62
62
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
63
63
|
column.cellRendererParams = {
|
|
64
64
|
...column.buttonRendererParams,
|
|
65
|
-
deferRender:
|
|
65
|
+
deferRender: false
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import {
|
|
4
4
|
validateRangeEditable,
|
|
5
|
-
getLastCellPosition,
|
|
6
5
|
applyBulkChanges,
|
|
7
6
|
applyBulkChangesWithApi,
|
|
8
7
|
} from './utils';
|
|
@@ -48,6 +47,9 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
48
47
|
const debounceTimeoutRef = useRef(null);
|
|
49
48
|
const pendingEventRef = useRef(null);
|
|
50
49
|
|
|
50
|
+
// ✅ FIX #2: Ref pro pending floating button data (eliminuje intermediate state update)
|
|
51
|
+
const pendingFloatingButtonRef = useRef(null);
|
|
52
|
+
|
|
51
53
|
// ✅ OPTIMALIZACE: Cache pro pozice buněk - eliminuje opakované getBoundingClientRect
|
|
52
54
|
const positionCacheRef = useRef({ endRowIndex: null, colId: null, position: null });
|
|
53
55
|
|
|
@@ -85,19 +87,24 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
85
87
|
}, [buttonPosition, buttonOffset]);
|
|
86
88
|
|
|
87
89
|
/**
|
|
88
|
-
* Handler pro změnu range selection s
|
|
90
|
+
* Handler pro změnu range selection s konsolidovanou validací
|
|
91
|
+
* ✅ FIX #2: Lightweight validace ukládá pouze do ref, heavy validace provede jediný setFloatingButton
|
|
89
92
|
*/
|
|
90
93
|
const handleRangeChange = useCallback(
|
|
91
94
|
(event) => {
|
|
92
95
|
// Lightweight pre-checks - okamžitě bez debounce
|
|
93
96
|
if (!enabled) {
|
|
94
|
-
|
|
97
|
+
pendingFloatingButtonRef.current = null;
|
|
98
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ - způsobuje rerendery!
|
|
99
|
+
// Nechej to na debounced validaci
|
|
95
100
|
return;
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
const ranges = event.api.getCellRanges();
|
|
99
104
|
if (!ranges || ranges.length === 0) {
|
|
100
|
-
|
|
105
|
+
pendingFloatingButtonRef.current = null;
|
|
106
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ - způsobuje rerendery!
|
|
107
|
+
// Nechej to na debounced validaci
|
|
101
108
|
return;
|
|
102
109
|
}
|
|
103
110
|
|
|
@@ -175,14 +182,16 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
if (!targetCell) {
|
|
178
|
-
|
|
185
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ
|
|
186
|
+
pendingFloatingButtonRef.current = null;
|
|
179
187
|
return;
|
|
180
188
|
}
|
|
181
189
|
|
|
182
190
|
// Od buňky najdeme její .ag-center-cols-container (specifický pro tento grid)
|
|
183
191
|
const rowsContainer = targetCell.closest('.ag-center-cols-container');
|
|
184
192
|
if (!rowsContainer) {
|
|
185
|
-
|
|
193
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ
|
|
194
|
+
pendingFloatingButtonRef.current = null;
|
|
186
195
|
return;
|
|
187
196
|
}
|
|
188
197
|
|
|
@@ -202,17 +211,18 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
202
211
|
bottom: cellRect.bottom - containerRect.top
|
|
203
212
|
};
|
|
204
213
|
|
|
205
|
-
|
|
214
|
+
// ✅ FIX #2: Uložit pouze do ref, ne state (eliminuje rerender #1)
|
|
215
|
+
pendingFloatingButtonRef.current = {
|
|
206
216
|
visible: true,
|
|
207
217
|
position: calculateButtonPosition(cellPosition),
|
|
208
218
|
range,
|
|
209
219
|
column: column,
|
|
210
220
|
cellCount,
|
|
211
221
|
rowsContainer, // ✅ Předat container specifický pro tento grid
|
|
212
|
-
}
|
|
222
|
+
};
|
|
213
223
|
} else {
|
|
214
|
-
//
|
|
215
|
-
|
|
224
|
+
// Sloupec nemá bulk edit podporu
|
|
225
|
+
pendingFloatingButtonRef.current = null;
|
|
216
226
|
}
|
|
217
227
|
}
|
|
218
228
|
}
|
|
@@ -220,7 +230,7 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
220
230
|
// Uložit event pro debounced těžkou validaci (editable check)
|
|
221
231
|
pendingEventRef.current = event;
|
|
222
232
|
|
|
223
|
-
//
|
|
233
|
+
// ✅ FIX #2: Debounce zvýšen z 15ms na 50ms pro lepší UX a konsolidaci rerenderů
|
|
224
234
|
if (debounceTimeoutRef.current) {
|
|
225
235
|
clearTimeout(debounceTimeoutRef.current);
|
|
226
236
|
}
|
|
@@ -229,26 +239,35 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
229
239
|
if (pendingEventRef.current) {
|
|
230
240
|
executeRangeValidation(pendingEventRef.current);
|
|
231
241
|
}
|
|
232
|
-
},
|
|
242
|
+
}, 50);
|
|
233
243
|
},
|
|
234
244
|
[enabled, allowMultiColumn, minCells, calculateButtonPosition]
|
|
235
245
|
);
|
|
236
246
|
|
|
237
247
|
/**
|
|
238
248
|
* Těžké validace a výpočty v debounced callbacku
|
|
249
|
+
* ✅ FIX #2: Konsolidovaná validace - využívá lightweight data z ref + provede těžké kontroly
|
|
239
250
|
*/
|
|
240
251
|
const executeRangeValidation = useCallback(
|
|
241
252
|
(event) => {
|
|
242
253
|
const ranges = event.api.getCellRanges();
|
|
243
254
|
if (!ranges || ranges.length === 0) {
|
|
255
|
+
pendingFloatingButtonRef.current = null;
|
|
244
256
|
setFloatingButton({ visible: false });
|
|
245
257
|
return;
|
|
246
258
|
}
|
|
247
259
|
|
|
248
260
|
const range = ranges[0];
|
|
249
261
|
|
|
262
|
+
// ✅ FIX #2: Pokud lightweight validace neprošla, nemá smysl pokračovat
|
|
263
|
+
if (!pendingFloatingButtonRef.current) {
|
|
264
|
+
setFloatingButton({ visible: false });
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
250
268
|
// Kontrola single column
|
|
251
269
|
if (!allowMultiColumn && range.columns.length !== 1) {
|
|
270
|
+
pendingFloatingButtonRef.current = null;
|
|
252
271
|
setFloatingButton({ visible: false });
|
|
253
272
|
return;
|
|
254
273
|
}
|
|
@@ -259,141 +278,21 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
259
278
|
|
|
260
279
|
// Kontrola min počtu buněk
|
|
261
280
|
if (cellCount < minCells) {
|
|
281
|
+
pendingFloatingButtonRef.current = null;
|
|
262
282
|
setFloatingButton({ visible: false });
|
|
263
283
|
return;
|
|
264
284
|
}
|
|
265
285
|
|
|
266
|
-
//
|
|
286
|
+
// ✅ FIX #2: KLÍČOVÁ TĚŽKÁ VALIDACE - kontrola editovatelnosti buněk
|
|
267
287
|
if (!validateRangeEditable(range, event.api)) {
|
|
288
|
+
pendingFloatingButtonRef.current = null;
|
|
268
289
|
setFloatingButton({ visible: false });
|
|
269
290
|
return;
|
|
270
291
|
}
|
|
271
292
|
|
|
272
|
-
// ✅
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
let firstCell = null;
|
|
276
|
-
|
|
277
|
-
// Metoda 1: Použít getCellRendererInstances (nejspolehlivější)
|
|
278
|
-
try {
|
|
279
|
-
const cellRenderers = event.api.getCellRendererInstances({
|
|
280
|
-
rowNodes: [range.startRow],
|
|
281
|
-
columns: [column]
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
if (cellRenderers && cellRenderers.length > 0) {
|
|
285
|
-
firstCell = cellRenderers[0].eGui || cellRenderers[0].getGui?.();
|
|
286
|
-
}
|
|
287
|
-
} catch (e) {
|
|
288
|
-
// Tiché selhání, fallback
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Metoda 2: Fallback - najít aktivní grid container a pak hledat row (STEJNĚ jako v lightweight)
|
|
292
|
-
if (!firstCell) {
|
|
293
|
-
// Nejprve najdeme jakoukoliv viditelnou buňku z TOHOTO gridu
|
|
294
|
-
const allCellsWithColId = Array.from(document.querySelectorAll(`[col-id="${colId}"].ag-cell`));
|
|
295
|
-
const visibleCell = allCellsWithColId.find(cell => {
|
|
296
|
-
const rect = cell.getBoundingClientRect();
|
|
297
|
-
return rect.width > 0 && rect.height > 0;
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
if (visibleCell) {
|
|
301
|
-
// Od viditelné buňky najdeme její grid container
|
|
302
|
-
const activeGridContainer = visibleCell.closest('.ag-center-cols-container');
|
|
303
|
-
|
|
304
|
-
if (activeGridContainer) {
|
|
305
|
-
// V aktivním containeru hledáme row podle row-index
|
|
306
|
-
const rowId = range.startRow.id || range.startRow.data?.id;
|
|
307
|
-
const rowsInActiveGrid = Array.from(activeGridContainer.querySelectorAll('.ag-row'));
|
|
308
|
-
|
|
309
|
-
let targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-id') === rowId);
|
|
310
|
-
|
|
311
|
-
if (!targetRow) {
|
|
312
|
-
targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-index') === String(range.startRow.rowIndex));
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (targetRow) {
|
|
316
|
-
firstCell = targetRow.querySelector(`[col-id="${colId}"]`);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (!firstCell) {
|
|
323
|
-
setFloatingButton({ visible: false });
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// Od buňky najdeme její .ag-center-cols-container (specifický pro tento grid)
|
|
328
|
-
const rowsContainer = firstCell.closest('.ag-center-cols-container');
|
|
329
|
-
if (!rowsContainer) {
|
|
330
|
-
setFloatingButton({ visible: false });
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Těžký výpočet - najít POSLEDNÍ buňku v range (pro přesné umístění buttonu)
|
|
335
|
-
// Najdeme buňku na endRow pozici
|
|
336
|
-
const endRowIndex = Math.max(range.startRow.rowIndex, range.endRow.rowIndex);
|
|
337
|
-
let lastCell = null;
|
|
338
|
-
|
|
339
|
-
// Metoda 1: getCellRendererInstances pro endRow
|
|
340
|
-
try {
|
|
341
|
-
const cellRenderers = event.api.getCellRendererInstances({
|
|
342
|
-
rowNodes: [range.endRow],
|
|
343
|
-
columns: [column]
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
if (cellRenderers && cellRenderers.length > 0) {
|
|
347
|
-
lastCell = cellRenderers[0].eGui || cellRenderers[0].getGui?.();
|
|
348
|
-
}
|
|
349
|
-
} catch (e) {
|
|
350
|
-
// Fallback
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// Metoda 2: Fallback - hledat row v AKTIVNÍM containeru (použít rowsContainer který už máme!)
|
|
354
|
-
if (!lastCell) {
|
|
355
|
-
const rowId = range.endRow.id || range.endRow.data?.id;
|
|
356
|
-
const rowsInActiveGrid = Array.from(rowsContainer.querySelectorAll('.ag-row'));
|
|
357
|
-
|
|
358
|
-
let targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-id') === rowId);
|
|
359
|
-
|
|
360
|
-
if (!targetRow) {
|
|
361
|
-
targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-index') === String(endRowIndex));
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (targetRow) {
|
|
365
|
-
lastCell = targetRow.querySelector(`[col-id="${colId}"]`);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// Metoda 3: Fallback na firstCell pokud endRow buňku nenajdeme
|
|
370
|
-
if (!lastCell) {
|
|
371
|
-
lastCell = firstCell;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Spočítej pozici z lastCell
|
|
375
|
-
const cellRect = lastCell.getBoundingClientRect();
|
|
376
|
-
const containerRect = rowsContainer.getBoundingClientRect();
|
|
377
|
-
|
|
378
|
-
const cellPosition = {
|
|
379
|
-
x: cellRect.right - containerRect.left,
|
|
380
|
-
y: cellRect.bottom - containerRect.top,
|
|
381
|
-
width: cellRect.width,
|
|
382
|
-
height: cellRect.height,
|
|
383
|
-
top: cellRect.top - containerRect.top,
|
|
384
|
-
left: cellRect.left - containerRect.left,
|
|
385
|
-
right: cellRect.right - containerRect.left,
|
|
386
|
-
bottom: cellRect.bottom - containerRect.top
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
setFloatingButton({
|
|
390
|
-
visible: true,
|
|
391
|
-
position: calculateButtonPosition(cellPosition),
|
|
392
|
-
range,
|
|
393
|
-
column: range.columns[0],
|
|
394
|
-
cellCount,
|
|
395
|
-
rowsContainer, // ✅ Předat container specifický pro tento grid
|
|
396
|
-
});
|
|
293
|
+
// ✅ FIX #2: Všechny validace prošly - použij data z lightweight validace (pendingFloatingButtonRef)
|
|
294
|
+
// Jediný setFloatingButton call → eliminuje rerender #2
|
|
295
|
+
setFloatingButton(pendingFloatingButtonRef.current);
|
|
397
296
|
},
|
|
398
297
|
[minCells, allowMultiColumn, buttonPosition, buttonOffset, calculateButtonPosition, gridRef]
|
|
399
298
|
);
|
package/dist/AgGridColumn.js
CHANGED
|
@@ -17,7 +17,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
17
17
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
18
18
|
column.cellRendererParams = {
|
|
19
19
|
...column.booleanRendererParams,
|
|
20
|
-
deferRender:
|
|
20
|
+
deferRender: false
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
if (column.iconRenderer) {
|
|
@@ -25,7 +25,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
25
25
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
26
26
|
column.cellRendererParams = {
|
|
27
27
|
...column.iconRendererParams,
|
|
28
|
-
deferRender:
|
|
28
|
+
deferRender: false
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
if (column.imageRenderer) {
|
|
@@ -33,7 +33,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
33
33
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
34
34
|
column.cellRendererParams = {
|
|
35
35
|
...column.imageRendererParams,
|
|
36
|
-
deferRender:
|
|
36
|
+
deferRender: false
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
if (column.stateRenderer) {
|
|
@@ -41,7 +41,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
41
41
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
42
42
|
column.cellRendererParams = {
|
|
43
43
|
...column.stateRendererParams,
|
|
44
|
-
deferRender:
|
|
44
|
+
deferRender: false
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
if (column.buttonRenderer) {
|
|
@@ -49,7 +49,7 @@ export const AgGridColumn = (column, options) => {
|
|
|
49
49
|
// AG-Grid deferRender: odkládá rendering během scrollování pro lepší výkon
|
|
50
50
|
column.cellRendererParams = {
|
|
51
51
|
...column.buttonRendererParams,
|
|
52
|
-
deferRender:
|
|
52
|
+
deferRender: false
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
if (column.headerHtmlText) {
|
package/dist/AgGridColumn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgGridColumn.js","sourceRoot":"","sources":["../AgGridColumn.js"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,GAAG,MAAM,YAAY,CAAC;AAC7B,OAAO,GAAG,MAAM,YAAY,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE;IACjC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACpC,CAAC,CAAC;AAEF,sCAAsC;AACtC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IAE9C,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,CAAC,YAAY,GAAG,CAAC,IAAI,EAAE,EAAE,CAC7B,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;IACzE,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,MAAM,CAAC,YAAY,GAAG,iBAAiB,CAAC;QACxC,2EAA2E;QAC3E,MAAM,CAAC,kBAAkB,GAAG;YAC1B,GAAG,MAAM,CAAC,qBAAqB;YAC/B,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"AgGridColumn.js","sourceRoot":"","sources":["../AgGridColumn.js"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
3
|
-
import { validateRangeEditable,
|
|
3
|
+
import { validateRangeEditable, applyBulkChanges, applyBulkChangesWithApi, } from './utils';
|
|
4
4
|
import useData from '@bit.rhplus/data';
|
|
5
5
|
/**
|
|
6
6
|
* Hook pro bulk cell edit funkcionalitu v AG Grid
|
|
@@ -28,6 +28,8 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
28
28
|
const scrollListenerRef = useRef(null);
|
|
29
29
|
const debounceTimeoutRef = useRef(null);
|
|
30
30
|
const pendingEventRef = useRef(null);
|
|
31
|
+
// ✅ FIX #2: Ref pro pending floating button data (eliminuje intermediate state update)
|
|
32
|
+
const pendingFloatingButtonRef = useRef(null);
|
|
31
33
|
// ✅ OPTIMALIZACE: Cache pro pozice buněk - eliminuje opakované getBoundingClientRect
|
|
32
34
|
const positionCacheRef = useRef({ endRowIndex: null, colId: null, position: null });
|
|
33
35
|
/**
|
|
@@ -61,17 +63,22 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
61
63
|
return { x: buttonX, y: buttonY };
|
|
62
64
|
}, [buttonPosition, buttonOffset]);
|
|
63
65
|
/**
|
|
64
|
-
* Handler pro změnu range selection s
|
|
66
|
+
* Handler pro změnu range selection s konsolidovanou validací
|
|
67
|
+
* ✅ FIX #2: Lightweight validace ukládá pouze do ref, heavy validace provede jediný setFloatingButton
|
|
65
68
|
*/
|
|
66
69
|
const handleRangeChange = useCallback((event) => {
|
|
67
70
|
// Lightweight pre-checks - okamžitě bez debounce
|
|
68
71
|
if (!enabled) {
|
|
69
|
-
|
|
72
|
+
pendingFloatingButtonRef.current = null;
|
|
73
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ - způsobuje rerendery!
|
|
74
|
+
// Nechej to na debounced validaci
|
|
70
75
|
return;
|
|
71
76
|
}
|
|
72
77
|
const ranges = event.api.getCellRanges();
|
|
73
78
|
if (!ranges || ranges.length === 0) {
|
|
74
|
-
|
|
79
|
+
pendingFloatingButtonRef.current = null;
|
|
80
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ - způsobuje rerendery!
|
|
81
|
+
// Nechej to na debounced validaci
|
|
75
82
|
return;
|
|
76
83
|
}
|
|
77
84
|
const range = ranges[0];
|
|
@@ -135,13 +142,15 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
135
142
|
}
|
|
136
143
|
}
|
|
137
144
|
if (!targetCell) {
|
|
138
|
-
|
|
145
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ
|
|
146
|
+
pendingFloatingButtonRef.current = null;
|
|
139
147
|
return;
|
|
140
148
|
}
|
|
141
149
|
// Od buňky najdeme její .ag-center-cols-container (specifický pro tento grid)
|
|
142
150
|
const rowsContainer = targetCell.closest('.ag-center-cols-container');
|
|
143
151
|
if (!rowsContainer) {
|
|
144
|
-
|
|
152
|
+
// ✅ FIX #14: Nevolat setFloatingButton OKAMŽITĚ
|
|
153
|
+
pendingFloatingButtonRef.current = null;
|
|
145
154
|
return;
|
|
146
155
|
}
|
|
147
156
|
// ✅ OPTIMALIZACE: Vypočítat pozici z POSLEDNÍ buňky (stejně jako heavy validace)
|
|
@@ -158,24 +167,25 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
158
167
|
right: cellRect.right - containerRect.left,
|
|
159
168
|
bottom: cellRect.bottom - containerRect.top
|
|
160
169
|
};
|
|
161
|
-
|
|
170
|
+
// ✅ FIX #2: Uložit pouze do ref, ne state (eliminuje rerender #1)
|
|
171
|
+
pendingFloatingButtonRef.current = {
|
|
162
172
|
visible: true,
|
|
163
173
|
position: calculateButtonPosition(cellPosition),
|
|
164
174
|
range,
|
|
165
175
|
column: column,
|
|
166
176
|
cellCount,
|
|
167
177
|
rowsContainer, // ✅ Předat container specifický pro tento grid
|
|
168
|
-
}
|
|
178
|
+
};
|
|
169
179
|
}
|
|
170
180
|
else {
|
|
171
|
-
//
|
|
172
|
-
|
|
181
|
+
// Sloupec nemá bulk edit podporu
|
|
182
|
+
pendingFloatingButtonRef.current = null;
|
|
173
183
|
}
|
|
174
184
|
}
|
|
175
185
|
}
|
|
176
186
|
// Uložit event pro debounced těžkou validaci (editable check)
|
|
177
187
|
pendingEventRef.current = event;
|
|
178
|
-
//
|
|
188
|
+
// ✅ FIX #2: Debounce zvýšen z 15ms na 50ms pro lepší UX a konsolidaci rerenderů
|
|
179
189
|
if (debounceTimeoutRef.current) {
|
|
180
190
|
clearTimeout(debounceTimeoutRef.current);
|
|
181
191
|
}
|
|
@@ -183,20 +193,28 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
183
193
|
if (pendingEventRef.current) {
|
|
184
194
|
executeRangeValidation(pendingEventRef.current);
|
|
185
195
|
}
|
|
186
|
-
},
|
|
196
|
+
}, 50);
|
|
187
197
|
}, [enabled, allowMultiColumn, minCells, calculateButtonPosition]);
|
|
188
198
|
/**
|
|
189
199
|
* Těžké validace a výpočty v debounced callbacku
|
|
200
|
+
* ✅ FIX #2: Konsolidovaná validace - využívá lightweight data z ref + provede těžké kontroly
|
|
190
201
|
*/
|
|
191
202
|
const executeRangeValidation = useCallback((event) => {
|
|
192
203
|
const ranges = event.api.getCellRanges();
|
|
193
204
|
if (!ranges || ranges.length === 0) {
|
|
205
|
+
pendingFloatingButtonRef.current = null;
|
|
194
206
|
setFloatingButton({ visible: false });
|
|
195
207
|
return;
|
|
196
208
|
}
|
|
197
209
|
const range = ranges[0];
|
|
210
|
+
// ✅ FIX #2: Pokud lightweight validace neprošla, nemá smysl pokračovat
|
|
211
|
+
if (!pendingFloatingButtonRef.current) {
|
|
212
|
+
setFloatingButton({ visible: false });
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
198
215
|
// Kontrola single column
|
|
199
216
|
if (!allowMultiColumn && range.columns.length !== 1) {
|
|
217
|
+
pendingFloatingButtonRef.current = null;
|
|
200
218
|
setFloatingButton({ visible: false });
|
|
201
219
|
return;
|
|
202
220
|
}
|
|
@@ -204,120 +222,19 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
|
|
|
204
222
|
const cellCount = Math.abs(range.endRow.rowIndex - range.startRow.rowIndex) + 1;
|
|
205
223
|
// Kontrola min počtu buněk
|
|
206
224
|
if (cellCount < minCells) {
|
|
225
|
+
pendingFloatingButtonRef.current = null;
|
|
207
226
|
setFloatingButton({ visible: false });
|
|
208
227
|
return;
|
|
209
228
|
}
|
|
210
|
-
//
|
|
229
|
+
// ✅ FIX #2: KLÍČOVÁ TĚŽKÁ VALIDACE - kontrola editovatelnosti buněk
|
|
211
230
|
if (!validateRangeEditable(range, event.api)) {
|
|
231
|
+
pendingFloatingButtonRef.current = null;
|
|
212
232
|
setFloatingButton({ visible: false });
|
|
213
233
|
return;
|
|
214
234
|
}
|
|
215
|
-
// ✅
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
let firstCell = null;
|
|
219
|
-
// Metoda 1: Použít getCellRendererInstances (nejspolehlivější)
|
|
220
|
-
try {
|
|
221
|
-
const cellRenderers = event.api.getCellRendererInstances({
|
|
222
|
-
rowNodes: [range.startRow],
|
|
223
|
-
columns: [column]
|
|
224
|
-
});
|
|
225
|
-
if (cellRenderers && cellRenderers.length > 0) {
|
|
226
|
-
firstCell = cellRenderers[0].eGui || cellRenderers[0].getGui?.();
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
catch (e) {
|
|
230
|
-
// Tiché selhání, fallback
|
|
231
|
-
}
|
|
232
|
-
// Metoda 2: Fallback - najít aktivní grid container a pak hledat row (STEJNĚ jako v lightweight)
|
|
233
|
-
if (!firstCell) {
|
|
234
|
-
// Nejprve najdeme jakoukoliv viditelnou buňku z TOHOTO gridu
|
|
235
|
-
const allCellsWithColId = Array.from(document.querySelectorAll(`[col-id="${colId}"].ag-cell`));
|
|
236
|
-
const visibleCell = allCellsWithColId.find(cell => {
|
|
237
|
-
const rect = cell.getBoundingClientRect();
|
|
238
|
-
return rect.width > 0 && rect.height > 0;
|
|
239
|
-
});
|
|
240
|
-
if (visibleCell) {
|
|
241
|
-
// Od viditelné buňky najdeme její grid container
|
|
242
|
-
const activeGridContainer = visibleCell.closest('.ag-center-cols-container');
|
|
243
|
-
if (activeGridContainer) {
|
|
244
|
-
// V aktivním containeru hledáme row podle row-index
|
|
245
|
-
const rowId = range.startRow.id || range.startRow.data?.id;
|
|
246
|
-
const rowsInActiveGrid = Array.from(activeGridContainer.querySelectorAll('.ag-row'));
|
|
247
|
-
let targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-id') === rowId);
|
|
248
|
-
if (!targetRow) {
|
|
249
|
-
targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-index') === String(range.startRow.rowIndex));
|
|
250
|
-
}
|
|
251
|
-
if (targetRow) {
|
|
252
|
-
firstCell = targetRow.querySelector(`[col-id="${colId}"]`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
if (!firstCell) {
|
|
258
|
-
setFloatingButton({ visible: false });
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
// Od buňky najdeme její .ag-center-cols-container (specifický pro tento grid)
|
|
262
|
-
const rowsContainer = firstCell.closest('.ag-center-cols-container');
|
|
263
|
-
if (!rowsContainer) {
|
|
264
|
-
setFloatingButton({ visible: false });
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
// Těžký výpočet - najít POSLEDNÍ buňku v range (pro přesné umístění buttonu)
|
|
268
|
-
// Najdeme buňku na endRow pozici
|
|
269
|
-
const endRowIndex = Math.max(range.startRow.rowIndex, range.endRow.rowIndex);
|
|
270
|
-
let lastCell = null;
|
|
271
|
-
// Metoda 1: getCellRendererInstances pro endRow
|
|
272
|
-
try {
|
|
273
|
-
const cellRenderers = event.api.getCellRendererInstances({
|
|
274
|
-
rowNodes: [range.endRow],
|
|
275
|
-
columns: [column]
|
|
276
|
-
});
|
|
277
|
-
if (cellRenderers && cellRenderers.length > 0) {
|
|
278
|
-
lastCell = cellRenderers[0].eGui || cellRenderers[0].getGui?.();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
catch (e) {
|
|
282
|
-
// Fallback
|
|
283
|
-
}
|
|
284
|
-
// Metoda 2: Fallback - hledat row v AKTIVNÍM containeru (použít rowsContainer který už máme!)
|
|
285
|
-
if (!lastCell) {
|
|
286
|
-
const rowId = range.endRow.id || range.endRow.data?.id;
|
|
287
|
-
const rowsInActiveGrid = Array.from(rowsContainer.querySelectorAll('.ag-row'));
|
|
288
|
-
let targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-id') === rowId);
|
|
289
|
-
if (!targetRow) {
|
|
290
|
-
targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-index') === String(endRowIndex));
|
|
291
|
-
}
|
|
292
|
-
if (targetRow) {
|
|
293
|
-
lastCell = targetRow.querySelector(`[col-id="${colId}"]`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
// Metoda 3: Fallback na firstCell pokud endRow buňku nenajdeme
|
|
297
|
-
if (!lastCell) {
|
|
298
|
-
lastCell = firstCell;
|
|
299
|
-
}
|
|
300
|
-
// Spočítej pozici z lastCell
|
|
301
|
-
const cellRect = lastCell.getBoundingClientRect();
|
|
302
|
-
const containerRect = rowsContainer.getBoundingClientRect();
|
|
303
|
-
const cellPosition = {
|
|
304
|
-
x: cellRect.right - containerRect.left,
|
|
305
|
-
y: cellRect.bottom - containerRect.top,
|
|
306
|
-
width: cellRect.width,
|
|
307
|
-
height: cellRect.height,
|
|
308
|
-
top: cellRect.top - containerRect.top,
|
|
309
|
-
left: cellRect.left - containerRect.left,
|
|
310
|
-
right: cellRect.right - containerRect.left,
|
|
311
|
-
bottom: cellRect.bottom - containerRect.top
|
|
312
|
-
};
|
|
313
|
-
setFloatingButton({
|
|
314
|
-
visible: true,
|
|
315
|
-
position: calculateButtonPosition(cellPosition),
|
|
316
|
-
range,
|
|
317
|
-
column: range.columns[0],
|
|
318
|
-
cellCount,
|
|
319
|
-
rowsContainer, // ✅ Předat container specifický pro tento grid
|
|
320
|
-
});
|
|
235
|
+
// ✅ FIX #2: Všechny validace prošly - použij data z lightweight validace (pendingFloatingButtonRef)
|
|
236
|
+
// Jediný setFloatingButton call → eliminuje rerender #2
|
|
237
|
+
setFloatingButton(pendingFloatingButtonRef.current);
|
|
321
238
|
}, [minCells, allowMultiColumn, buttonPosition, buttonOffset, calculateButtonPosition, gridRef]);
|
|
322
239
|
/**
|
|
323
240
|
* Handler pro kliknutí na bulk edit button - otevře popover
|