@bit.rhplus/ag-grid 0.0.48 → 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.
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable */
2
2
  import React, { useState, useRef, useEffect } from 'react';
3
+ import ReactDOM from 'react-dom';
3
4
  import { Button, Tooltip } from 'antd';
4
5
  import { EditOutlined } from '@ant-design/icons';
5
6
  import BulkEditPopover from './BulkEditPopover';
@@ -24,6 +25,7 @@ const BulkEditButton = ({
24
25
  range,
25
26
  column,
26
27
  cellCount,
28
+ rowsContainer, // ✅ Container specifický pro tento grid
27
29
  editPopover,
28
30
  onOpenPopover,
29
31
  onValueChange,
@@ -120,21 +122,33 @@ const BulkEditButton = ({
120
122
  cellCount === 1 ? 'buňku' : cellCount < 5 ? 'buňky' : 'buněk'
121
123
  } v "${fieldName}"`;
122
124
 
123
- return (
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)
137
+ const content = (
124
138
  <>
125
139
  {/* Floating Button */}
126
140
  <div
127
141
  ref={buttonRef}
128
142
  style={{
129
- position: 'fixed',
143
+ position: 'absolute',
130
144
  top: position?.y || 0,
131
145
  left: position?.x || 0,
132
146
  zIndex: 9999,
133
147
  pointerEvents: 'auto',
134
148
  }}
135
149
  >
136
- <Tooltip
137
- title={tooltipTitle}
150
+ <Tooltip
151
+ title={tooltipTitle}
138
152
  placement="top"
139
153
  getPopupContainer={() => document.body}
140
154
  zIndex={10001}
@@ -157,7 +171,7 @@ const BulkEditButton = ({
157
171
  <div
158
172
  ref={popoverRef}
159
173
  style={{
160
- position: 'fixed',
174
+ position: 'absolute',
161
175
  top: popoverPosition?.top ?? (position?.y || 0) + 35,
162
176
  left: popoverPosition?.left ?? (position?.x || 0),
163
177
  zIndex: 10000,
@@ -182,6 +196,10 @@ const BulkEditButton = ({
182
196
  )}
183
197
  </>
184
198
  );
199
+
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);
185
203
  };
186
204
 
187
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]
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
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;
146
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;
147
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,34 +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
- // Najít DOM element poslední buňky
102
+
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
- if (!rowElement) return null;
105
-
106
+ if (!rowElement) {
107
+ return null;
108
+ }
109
+
106
110
  const cellElement = rowElement.querySelector(`[col-id="${colId}"]`);
107
- if (!cellElement) return null;
108
-
109
- const rect = cellElement.getBoundingClientRect();
110
-
111
+ if (!cellElement) {
112
+ return null;
113
+ }
114
+
115
+ const cellRect = cellElement.getBoundingClientRect();
116
+
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
+ }
134
+
135
+ // Fallback: absolute pozice (window-relative) pokud container není dostupný
111
136
  return {
112
- x: rect.right,
113
- y: rect.bottom,
114
- width: rect.width,
115
- height: rect.height,
116
- top: rect.top,
117
- left: rect.left,
118
- right: rect.right,
119
- 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
120
145
  };
121
146
  } catch (error) {
147
+ // Tiché selhání - vrátit null
122
148
  return null;
123
149
  }
124
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;
@@ -24,4 +24,5 @@ declare function BulkEditButton({ visible, position, range, column, cellCount, e
24
24
  onValueChange: Function;
25
25
  onSubmit: Function;
26
26
  onCancel: Function;
27
- }): import("react/jsx-runtime").JSX.Element | null;
27
+ }): React.ReactPortal | null;
28
+ import React from 'react';
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /* eslint-disable */
3
3
  import React, { useState, useRef, useEffect } from 'react';
4
+ import ReactDOM from 'react-dom';
4
5
  import { Button, Tooltip } from 'antd';
5
6
  import { EditOutlined } from '@ant-design/icons';
6
7
  import BulkEditPopover from './BulkEditPopover';
@@ -18,7 +19,8 @@ import BulkEditPopover from './BulkEditPopover';
18
19
  * @param {Function} props.onSubmit - Handler pro submit
19
20
  * @param {Function} props.onCancel - Handler pro cancel
20
21
  */
21
- 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, }) => {
22
24
  const [popoverVisible, setPopoverVisible] = useState(false);
23
25
  const [popoverPosition, setPopoverPosition] = useState(null);
24
26
  const buttonRef = useRef(null);
@@ -92,8 +94,20 @@ const BulkEditButton = ({ visible, position, range, column, cellCount, editPopov
92
94
  }
93
95
  }, [popoverVisible]);
94
96
  const tooltipTitle = `Hromadně změnit ${cellCount} ${cellCount === 1 ? 'buňku' : cellCount < 5 ? 'buňky' : 'buněk'} v "${fieldName}"`;
95
- return (_jsxs(_Fragment, { children: [_jsx("div", { ref: buttonRef, style: {
96
- position: 'fixed',
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)
109
+ const content = (_jsxs(_Fragment, { children: [_jsx("div", { ref: buttonRef, style: {
110
+ position: 'absolute',
97
111
  top: position?.y || 0,
98
112
  left: position?.x || 0,
99
113
  zIndex: 9999,
@@ -101,7 +115,7 @@ const BulkEditButton = ({ visible, position, range, column, cellCount, editPopov
101
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: {
102
116
  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
103
117
  } }) }) }), popoverVisible && (_jsx("div", { ref: popoverRef, style: {
104
- position: 'fixed',
118
+ position: 'absolute',
105
119
  top: popoverPosition?.top ?? (position?.y || 0) + 35,
106
120
  left: popoverPosition?.left ?? (position?.x || 0),
107
121
  zIndex: 10000,
@@ -109,6 +123,9 @@ const BulkEditButton = ({ visible, position, range, column, cellCount, editPopov
109
123
  opacity: popoverPosition ? 1 : 0,
110
124
  transition: 'opacity 0.1s ease-in-out',
111
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 }) }))] }));
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);
112
129
  };
113
130
  export default BulkEditButton;
114
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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"}