@bit.rhplus/ag-grid 0.0.49 → 0.0.50

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.
@@ -25,6 +25,7 @@ const BulkEditButton = ({
25
25
  range,
26
26
  column,
27
27
  cellCount,
28
+ rowsContainer, // ✅ Container specifický pro tento grid
28
29
  editPopover,
29
30
  onOpenPopover,
30
31
  onValueChange,
@@ -121,15 +122,25 @@ const BulkEditButton = ({
121
122
  cellCount === 1 ? 'buňku' : cellCount < 5 ? 'buňky' : 'buněk'
122
123
  } v "${fieldName}"`;
123
124
 
124
- // Renderujeme pomocí React Portal přímo do document.body
125
- // Tím se vyhneme problému s position: relative v GlowingEdge wrapperu
125
+ /**
126
+ * OPTIMALIZACE: Použít container specifický pro tento grid (předaný jako prop)
127
+ * Toto zajistí, že button se renderuje do správného gridu i když je v DOM více gridů
128
+ * → Funguje správně při přepínání mezi moduly (každý modul má svůj vlastní container)
129
+ */
130
+ const portalContainer = React.useMemo(() => {
131
+ if (!visible || !rowsContainer) return document.body;
132
+ return rowsContainer;
133
+ }, [visible, rowsContainer]);
134
+
135
+ // Renderujeme pomocí React Portal do ag-center-cols-container
136
+ // Button se automaticky scrolluje s gridem (součástí transformed containeru)
126
137
  const content = (
127
138
  <>
128
139
  {/* Floating Button */}
129
140
  <div
130
141
  ref={buttonRef}
131
142
  style={{
132
- position: 'fixed',
143
+ position: 'absolute',
133
144
  top: position?.y || 0,
134
145
  left: position?.x || 0,
135
146
  zIndex: 9999,
@@ -160,7 +171,7 @@ const BulkEditButton = ({
160
171
  <div
161
172
  ref={popoverRef}
162
173
  style={{
163
- position: 'fixed',
174
+ position: 'absolute',
164
175
  top: popoverPosition?.top ?? (position?.y || 0) + 35,
165
176
  left: popoverPosition?.left ?? (position?.x || 0),
166
177
  zIndex: 10000,
@@ -186,9 +197,9 @@ const BulkEditButton = ({
186
197
  </>
187
198
  );
188
199
 
189
- // Použijeme React Portal pro rendering přímo do document.body
190
- // Tím se vyhneme position: relative contextu z GlowingEdge
191
- return ReactDOM.createPortal(content, document.body);
200
+ // OPTIMALIZACE: React Portal do ag-center-cols-container
201
+ // portalContainer se aktualizuje při každém zobrazení funguje i po route change
202
+ return ReactDOM.createPortal(content, portalContainer);
192
203
  };
193
204
 
194
205
  export default BulkEditButton;
@@ -34,6 +34,7 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
34
34
  range: null,
35
35
  column: null,
36
36
  cellCount: 0,
37
+ rowsContainer: null, // ✅ Container specifický pro tento grid
37
38
  });
38
39
 
39
40
  const [editPopover, setEditPopover] = useState({
@@ -47,20 +48,16 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
47
48
  const debounceTimeoutRef = useRef(null);
48
49
  const pendingEventRef = useRef(null);
49
50
 
51
+ // ✅ OPTIMALIZACE: Cache pro pozice buněk - eliminuje opakované getBoundingClientRect
52
+ const positionCacheRef = useRef({ endRowIndex: null, colId: null, position: null });
53
+
50
54
  /**
51
- * Helper funkce pro výpočet pozice buttonu s viewport-aware positioning
55
+ * Helper funkce pro výpočet pozice buttonu (relativní k rows container)
56
+ * ✅ OPTIMALIZACE: Žádné viewport adjustments - button je position: absolute v containeru
52
57
  */
53
58
  const calculateButtonPosition = useCallback((cellPosition) => {
54
- const BUTTON_SIZE = 32;
55
- const POPOVER_WIDTH = 30;
56
- const POPOVER_HEIGHT = 30;
57
- const VIEWPORT_MARGIN = 10;
58
-
59
- const viewportWidth = window.innerWidth;
60
- const viewportHeight = window.innerHeight;
61
-
59
+ // Jednoduše použij pozici z cellPosition + offset podle buttonPosition
62
60
  let buttonX, buttonY;
63
- let adjustedPosition = buttonPosition;
64
61
 
65
62
  switch (buttonPosition) {
66
63
  case 'bottom-right':
@@ -68,39 +65,22 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
68
65
  buttonY = cellPosition.bottom + buttonOffset.y;
69
66
  break;
70
67
  case 'bottom-left':
71
- buttonX = cellPosition.left - buttonOffset.x;
68
+ buttonX = cellPosition.left - buttonOffset.x - 32; // 32 = button size
72
69
  buttonY = cellPosition.bottom + buttonOffset.y;
73
70
  break;
74
71
  case 'top-right':
75
72
  buttonX = cellPosition.right + buttonOffset.x;
76
- buttonY = cellPosition.top - buttonOffset.y;
73
+ buttonY = cellPosition.top - buttonOffset.y - 32;
77
74
  break;
78
75
  case 'top-left':
79
- buttonX = cellPosition.left - buttonOffset.x;
80
- buttonY = cellPosition.top - buttonOffset.y;
76
+ buttonX = cellPosition.left - buttonOffset.x - 32;
77
+ buttonY = cellPosition.top - buttonOffset.y - 32;
81
78
  break;
82
79
  default:
83
80
  buttonX = cellPosition.right + buttonOffset.x;
84
81
  buttonY = cellPosition.bottom + buttonOffset.y;
85
82
  }
86
83
 
87
- const buttonRight = buttonX + BUTTON_SIZE;
88
- const popoverRight = buttonX + POPOVER_WIDTH;
89
- const popoverBottom = buttonY + BUTTON_SIZE + POPOVER_HEIGHT;
90
-
91
- if (popoverRight > viewportWidth - VIEWPORT_MARGIN) {
92
- buttonX = cellPosition.left - buttonOffset.x - BUTTON_SIZE;
93
- buttonX = Math.max(VIEWPORT_MARGIN, buttonX);
94
- }
95
-
96
- if (popoverBottom > viewportHeight - VIEWPORT_MARGIN) {
97
- buttonY = cellPosition.top - buttonOffset.y - BUTTON_SIZE;
98
- buttonY = Math.max(VIEWPORT_MARGIN, buttonY);
99
- }
100
-
101
- buttonX = Math.max(VIEWPORT_MARGIN, Math.min(buttonX, viewportWidth - BUTTON_SIZE - VIEWPORT_MARGIN));
102
- buttonY = Math.max(VIEWPORT_MARGIN, Math.min(buttonY, viewportHeight - BUTTON_SIZE - VIEWPORT_MARGIN));
103
-
104
84
  return { x: buttonX, y: buttonY };
105
85
  }, [buttonPosition, buttonOffset]);
106
86
 
@@ -126,25 +106,110 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
126
106
  // ✨ OKAŽITÁ lightweight validace - zobraz button HNED
127
107
  if (allowMultiColumn || range.columns.length === 1) {
128
108
  const cellCount = Math.abs(range.endRow.rowIndex - range.startRow.rowIndex) + 1;
129
-
109
+
130
110
  if (cellCount >= minCells) {
131
111
  // Kontrola zda má sloupec bulkEditApi (rychlá kontrola)
132
112
  const column = range.columns[0];
133
113
  const colDef = column?.getColDef();
134
114
  const hasBulkEditApi = colDef?.bulkEditApi || colDef?.bulkEditPopover;
135
-
115
+
136
116
  // Zobraz button jen pokud má bulkEditApi nebo bulkEditPopover
137
117
  if (hasBulkEditApi) {
138
- const cellPosition = getLastCellPosition(range, event.api);
139
- if (cellPosition) {
140
- setFloatingButton({
141
- visible: true,
142
- position: calculateButtonPosition(cellPosition),
143
- range,
144
- column: column,
145
- cellCount,
118
+ const endRowIndex = Math.max(range.startRow.rowIndex, range.endRow.rowIndex);
119
+ const colId = column.getColId();
120
+
121
+ // ✅ KLÍČOVÉ ŘEŠENÍ: Najít container relativně od OZNAČENÉ BUŇKY
122
+ // Když jsou v DOM více gridů (shared/master), querySelector najde první
123
+ // Ale my potřebujeme container od AKTUÁLNĚ AKTIVNÍHO gridu
124
+
125
+ // ✅ KLÍČOVÉ ŘEŠENÍ: Najít POSLEDNÍ buňku v range (endRow) pro správné umístění
126
+ // API ví přesně, která buňka patří do kterého gridu (řeší multi-grid problém!)
127
+ // DŮLEŽITÉ: Používáme endRow (ne startRow), aby pozice byla stejná jako v heavy validaci
128
+ const endRowForCalc = Math.max(range.startRow.rowIndex, range.endRow.rowIndex) === range.startRow.rowIndex ? range.startRow : range.endRow;
129
+ let targetCell = null;
130
+
131
+ // Metoda 1: Použít getCellRendererInstances (nejspolehlivější)
132
+ try {
133
+ const cellRenderers = event.api.getCellRendererInstances({
134
+ rowNodes: [endRowForCalc],
135
+ columns: [column]
146
136
  });
137
+
138
+ if (cellRenderers && cellRenderers.length > 0) {
139
+ targetCell = cellRenderers[0].eGui || cellRenderers[0].getGui?.();
140
+ }
141
+ } catch (e) {
142
+ // Tiché selhání, fallback
147
143
  }
144
+
145
+ // Metoda 2: Fallback - najít aktivní grid container a pak hledat row
146
+ if (!targetCell) {
147
+ // Nejprve najdeme jakoukoliv viditelnou buňku z TOHOTO gridu
148
+ const allCellsWithColId = Array.from(document.querySelectorAll(`[col-id="${colId}"].ag-cell`));
149
+ const visibleCell = allCellsWithColId.find(cell => {
150
+ const rect = cell.getBoundingClientRect();
151
+ return rect.width > 0 && rect.height > 0;
152
+ });
153
+
154
+ if (visibleCell) {
155
+ // Od viditelné buňky najdeme její grid container
156
+ const activeGridContainer = visibleCell.closest('.ag-center-cols-container');
157
+
158
+ if (activeGridContainer) {
159
+ // V aktivním containeru hledáme row podle row-index
160
+ const rowId = endRowForCalc.id || endRowForCalc.data?.id;
161
+ const endRowIndex = Math.max(range.startRow.rowIndex, range.endRow.rowIndex);
162
+ const rowsInActiveGrid = Array.from(activeGridContainer.querySelectorAll('.ag-row'));
163
+
164
+ let targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-id') === rowId);
165
+
166
+ if (!targetRow) {
167
+ targetRow = rowsInActiveGrid.find(row => row.getAttribute('row-index') === String(endRowIndex));
168
+ }
169
+
170
+ if (targetRow) {
171
+ targetCell = targetRow.querySelector(`[col-id="${colId}"]`);
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ if (!targetCell) {
178
+ setFloatingButton({ visible: false });
179
+ return;
180
+ }
181
+
182
+ // Od buňky najdeme její .ag-center-cols-container (specifický pro tento grid)
183
+ const rowsContainer = targetCell.closest('.ag-center-cols-container');
184
+ if (!rowsContainer) {
185
+ setFloatingButton({ visible: false });
186
+ return;
187
+ }
188
+
189
+ // ✅ OPTIMALIZACE: Vypočítat pozici z POSLEDNÍ buňky (stejně jako heavy validace)
190
+ // Tím eliminujeme přeblikávání mezi firstCell a lastCell
191
+ const cellRect = targetCell.getBoundingClientRect();
192
+ const containerRect = rowsContainer.getBoundingClientRect();
193
+
194
+ const cellPosition = {
195
+ x: cellRect.right - containerRect.left,
196
+ y: cellRect.bottom - containerRect.top,
197
+ width: cellRect.width,
198
+ height: cellRect.height,
199
+ top: cellRect.top - containerRect.top,
200
+ left: cellRect.left - containerRect.left,
201
+ right: cellRect.right - containerRect.left,
202
+ bottom: cellRect.bottom - containerRect.top
203
+ };
204
+
205
+ setFloatingButton({
206
+ visible: true,
207
+ position: calculateButtonPosition(cellPosition),
208
+ range,
209
+ column: column,
210
+ cellCount,
211
+ rowsContainer, // ✅ Předat container specifický pro tento grid
212
+ });
148
213
  } else {
149
214
  // Skryj button pokud sloupec nemá bulk edit podporu
150
215
  setFloatingButton({ visible: false });
@@ -164,7 +229,7 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
164
229
  if (pendingEventRef.current) {
165
230
  executeRangeValidation(pendingEventRef.current);
166
231
  }
167
- }, 50);
232
+ }, 15);
168
233
  },
169
234
  [enabled, allowMultiColumn, minCells, calculateButtonPosition]
170
235
  );
@@ -204,22 +269,133 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
204
269
  return;
205
270
  }
206
271
 
207
- // Těžký výpočet - pozice buňky
208
- const cellPosition = getLastCellPosition(range, event.api);
209
- if (!cellPosition) {
272
+ // KLÍČOVÉ ŘEŠENÍ: Použít AG-Grid API k získání cell elementu (STEJNĚ jako v lightweight validaci)
273
+ const column = range.columns[0];
274
+ const colId = column.getColId();
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) {
210
330
  setFloatingButton({ visible: false });
211
331
  return;
212
332
  }
213
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
+
214
389
  setFloatingButton({
215
390
  visible: true,
216
391
  position: calculateButtonPosition(cellPosition),
217
392
  range,
218
393
  column: range.columns[0],
219
394
  cellCount,
395
+ rowsContainer, // ✅ Předat container specifický pro tento grid
220
396
  });
221
397
  },
222
- [minCells, allowMultiColumn, buttonPosition, buttonOffset]
398
+ [minCells, allowMultiColumn, buttonPosition, buttonOffset, calculateButtonPosition, gridRef]
223
399
  );
224
400
 
225
401
  /**
@@ -352,21 +528,21 @@ export const useBulkCellEdit = (gridRef, options = {}) => {
352
528
  useEffect(() => {
353
529
  if (!enabled || !gridRef.current) return;
354
530
 
355
- const gridElement = gridRef.current.api?.gridBodyCtrl?.eBodyViewport;
356
- if (!gridElement) return;
531
+ const gridViewport = gridRef.current.api?.gridBodyCtrl?.eBodyViewport;
532
+ if (!gridViewport) return;
357
533
 
358
534
  const handleScroll = () => {
359
- if (floatingButton.visible) {
360
- setFloatingButton({ visible: false });
361
- }
535
+ // ✅ OPTIMALIZACE: Button se nyní scrolluje automaticky s gridem (position: absolute v viewport)
536
+ // Není potřeba skrývat button ani invalidovat cache - button zůstává přilepený k buňce
537
+ // Cache zůstává validní, protože relativní pozice se nemění při scrollu
362
538
  };
363
539
 
364
540
  scrollListenerRef.current = handleScroll;
365
- gridElement.addEventListener('scroll', handleScroll);
541
+ gridViewport.addEventListener('scroll', handleScroll);
366
542
 
367
543
  return () => {
368
- if (gridElement && scrollListenerRef.current) {
369
- gridElement.removeEventListener('scroll', scrollListenerRef.current);
544
+ if (gridViewport && scrollListenerRef.current) {
545
+ gridViewport.removeEventListener('scroll', scrollListenerRef.current);
370
546
  }
371
547
  };
372
548
  }, [enabled, gridRef, floatingButton.visible]);
package/BulkEdit/utils.js CHANGED
@@ -91,58 +91,60 @@ export const validateRangeEditable = (range, gridApi) => {
91
91
  * Získá pozici poslední buňky v range pro umístění floating buttonu
92
92
  * @param {Object} range - AG Grid cell range
93
93
  * @param {Object} gridApi - AG Grid API
94
- * @returns {Object} - {x, y, width, height} pozice
94
+ * @param {HTMLElement} rowsContainer - AG Grid rows container (.ag-center-cols-container)
95
+ * @returns {Object} - {x, y, width, height} pozice RELATIVNÍ k rows container
95
96
  */
96
- export const getLastCellPosition = (range, gridApi) => {
97
+ export const getLastCellPosition = (range, gridApi, rowsContainer) => {
97
98
  try {
98
99
  const endRowIndex = Math.max(range.startRow.rowIndex, range.endRow.rowIndex);
99
100
  const column = range.columns[0];
100
101
  const colId = column.getColId();
101
102
 
102
- // Najít DOM element poslední buňky
103
+ // OPTIMALIZACE: querySelector je sice pomalejší, ale díky cache v useBulkCellEdit
104
+ // se volá pouze při změně pozice (cache hit = 0ms overhead)
103
105
  const rowElement = document.querySelector(`[row-index="${endRowIndex}"]`);
104
106
  if (!rowElement) {
105
- console.warn('🔍 BulkEdit: Row element not found', { endRowIndex });
106
107
  return null;
107
108
  }
108
109
 
109
110
  const cellElement = rowElement.querySelector(`[col-id="${colId}"]`);
110
111
  if (!cellElement) {
111
- console.warn('🔍 BulkEdit: Cell element not found', { colId });
112
112
  return null;
113
113
  }
114
114
 
115
- const rect = cellElement.getBoundingClientRect();
115
+ const cellRect = cellElement.getBoundingClientRect();
116
116
 
117
- console.log('🔍 BulkEdit: Cell position detected', {
118
- endRowIndex,
119
- colId,
120
- rect: {
121
- top: rect.top,
122
- left: rect.left,
123
- right: rect.right,
124
- bottom: rect.bottom,
125
- width: rect.width,
126
- height: rect.height
127
- },
128
- returnedPosition: {
129
- x: rect.right,
130
- y: rect.bottom
131
- }
132
- });
117
+ // ✅ OPTIMALIZACE: Výpočet pozice RELATIVNÍ k rows container
118
+ // Button je position: absolute uvnitř .ag-center-cols-container
119
+ // Tento container má transform: translateY() při scrollu → button scrolluje automaticky
120
+ if (rowsContainer) {
121
+ const containerRect = rowsContainer.getBoundingClientRect();
122
+
123
+ return {
124
+ x: cellRect.right - containerRect.left,
125
+ y: cellRect.bottom - containerRect.top,
126
+ width: cellRect.width,
127
+ height: cellRect.height,
128
+ top: cellRect.top - containerRect.top,
129
+ left: cellRect.left - containerRect.left,
130
+ right: cellRect.right - containerRect.left,
131
+ bottom: cellRect.bottom - containerRect.top
132
+ };
133
+ }
133
134
 
135
+ // Fallback: absolute pozice (window-relative) pokud container není dostupný
134
136
  return {
135
- x: rect.right,
136
- y: rect.bottom,
137
- width: rect.width,
138
- height: rect.height,
139
- top: rect.top,
140
- left: rect.left,
141
- right: rect.right,
142
- bottom: rect.bottom
137
+ x: cellRect.right,
138
+ y: cellRect.bottom,
139
+ width: cellRect.width,
140
+ height: cellRect.height,
141
+ top: cellRect.top,
142
+ left: cellRect.left,
143
+ right: cellRect.right,
144
+ bottom: cellRect.bottom
143
145
  };
144
146
  } catch (error) {
145
- console.error('🔍 BulkEdit: Error in getLastCellPosition', error);
147
+ // Tiché selhání - vrátit null
146
148
  return null;
147
149
  }
148
150
  };
@@ -13,7 +13,7 @@ export default BulkEditButton;
13
13
  * @param {Function} props.onSubmit - Handler pro submit
14
14
  * @param {Function} props.onCancel - Handler pro cancel
15
15
  */
16
- declare function BulkEditButton({ visible, position, range, column, cellCount, editPopover, onOpenPopover, onValueChange, onSubmit, onCancel, }: {
16
+ declare function BulkEditButton({ visible, position, range, column, cellCount, rowsContainer, editPopover, onOpenPopover, onValueChange, onSubmit, onCancel, }: {
17
17
  visible: boolean;
18
18
  position: Object;
19
19
  range: Object;
@@ -19,7 +19,8 @@ import BulkEditPopover from './BulkEditPopover';
19
19
  * @param {Function} props.onSubmit - Handler pro submit
20
20
  * @param {Function} props.onCancel - Handler pro cancel
21
21
  */
22
- const BulkEditButton = ({ visible, position, range, column, cellCount, editPopover, onOpenPopover, onValueChange, onSubmit, onCancel, }) => {
22
+ const BulkEditButton = ({ visible, position, range, column, cellCount, rowsContainer, // Container specifický pro tento grid
23
+ editPopover, onOpenPopover, onValueChange, onSubmit, onCancel, }) => {
23
24
  const [popoverVisible, setPopoverVisible] = useState(false);
24
25
  const [popoverPosition, setPopoverPosition] = useState(null);
25
26
  const buttonRef = useRef(null);
@@ -93,10 +94,20 @@ const BulkEditButton = ({ visible, position, range, column, cellCount, editPopov
93
94
  }
94
95
  }, [popoverVisible]);
95
96
  const tooltipTitle = `Hromadně změnit ${cellCount} ${cellCount === 1 ? 'buňku' : cellCount < 5 ? 'buňky' : 'buněk'} v "${fieldName}"`;
96
- // Renderujeme pomocí React Portal přímo do document.body
97
- // Tím se vyhneme problému s position: relative v GlowingEdge wrapperu
97
+ /**
98
+ * OPTIMALIZACE: Použít container specifický pro tento grid (předaný jako prop)
99
+ * Toto zajistí, že button se renderuje do správného gridu i když je v DOM více gridů
100
+ * → Funguje správně při přepínání mezi moduly (každý modul má svůj vlastní container)
101
+ */
102
+ const portalContainer = React.useMemo(() => {
103
+ if (!visible || !rowsContainer)
104
+ return document.body;
105
+ return rowsContainer;
106
+ }, [visible, rowsContainer]);
107
+ // Renderujeme pomocí React Portal do ag-center-cols-container
108
+ // Button se automaticky scrolluje s gridem (součástí transformed containeru)
98
109
  const content = (_jsxs(_Fragment, { children: [_jsx("div", { ref: buttonRef, style: {
99
- position: 'fixed',
110
+ position: 'absolute',
100
111
  top: position?.y || 0,
101
112
  left: position?.x || 0,
102
113
  zIndex: 9999,
@@ -104,7 +115,7 @@ const BulkEditButton = ({ visible, position, range, column, cellCount, editPopov
104
115
  }, children: _jsx(Tooltip, { title: tooltipTitle, placement: "top", getPopupContainer: () => document.body, zIndex: 10001, children: _jsx(Button, { type: "primary", shape: "circle", icon: _jsx(EditOutlined, {}), size: "small", onClick: handleButtonClick, style: {
105
116
  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
106
117
  } }) }) }), popoverVisible && (_jsx("div", { ref: popoverRef, style: {
107
- position: 'fixed',
118
+ position: 'absolute',
108
119
  top: popoverPosition?.top ?? (position?.y || 0) + 35,
109
120
  left: popoverPosition?.left ?? (position?.x || 0),
110
121
  zIndex: 10000,
@@ -112,9 +123,9 @@ const BulkEditButton = ({ visible, position, range, column, cellCount, editPopov
112
123
  opacity: popoverPosition ? 1 : 0,
113
124
  transition: 'opacity 0.1s ease-in-out',
114
125
  }, children: _jsx(BulkEditPopover, { visible: editPopover.visible, value: editPopover.value, loading: editPopover.loading, error: editPopover.error, column: column, range: range, cellCount: cellCount, onValueChange: onValueChange, onSubmit: onSubmit, onCancel: onCancel }) }))] }));
115
- // Použijeme React Portal pro rendering přímo do document.body
116
- // Tím se vyhneme position: relative contextu z GlowingEdge
117
- return ReactDOM.createPortal(content, document.body);
126
+ // OPTIMALIZACE: React Portal do ag-center-cols-container
127
+ // portalContainer se aktualizuje při každém zobrazení funguje i po route change
128
+ return ReactDOM.createPortal(content, portalContainer);
118
129
  };
119
130
  export default BulkEditButton;
120
131
  //# sourceMappingURL=BulkEditButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BulkEditButton.js","sourceRoot":"","sources":["../../BulkEdit/BulkEditButton.jsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BulkEditButton.js","sourceRoot":"","sources":["../../BulkEdit/BulkEditButton.jsx"],"names":[],"mappings":"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"}