@bit.rhplus/ui.grid-layout 0.0.5 → 0.0.6

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/useGridLayout.js CHANGED
@@ -19,7 +19,7 @@ import { debounce } from 'lodash';
19
19
  * @param {string} [config.filterName] - Název filtru (volitelné)
20
20
  * @param {boolean} [config.enabled=true] - Zapnout/vypnout layout management
21
21
  * @param {boolean} [config.autoSave=true] - Automatické ukládání při změnách
22
- * @param {number} [config.autoSaveDelay=2000] - Zpoždění auto-save v ms
22
+ * @param {number} [config.autoSaveDelay=500] - Zpoždění auto-save v ms
23
23
  * @param {Array} config.columnDefs - AG-Grid column definitions
24
24
  * @param {string} [config.accessToken] - Přístupový token
25
25
  * @param {boolean} [config.waitForSavedFields=false] - Skrýt columnDefs dokud nejsou načtena savedFields
@@ -35,7 +35,7 @@ export const useGridLayout = ({
35
35
  filterName,
36
36
  enabled = true,
37
37
  autoSave = true,
38
- autoSaveDelay = 2000,
38
+ autoSaveDelay = 500,
39
39
  columnDefs = [],
40
40
  accessToken,
41
41
  waitForSavedFields = false, // Nový prop pro odložené zobrazení columnDefs
@@ -61,6 +61,8 @@ export const useGridLayout = ({
61
61
  // Refs pro AG-Grid API
62
62
  const gridApiRef = useRef(null);
63
63
  const columnApiRef = useRef(null);
64
+ // Ref mapa pro ukládání aktuálních šířek sloupců (fieldId -> šířka)
65
+ const columnWidthRefsMap = useRef(new Map());
64
66
 
65
67
  // State
66
68
  const [isInitialized, setIsInitialized] = useState(false);
@@ -72,18 +74,8 @@ export const useGridLayout = ({
72
74
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
73
75
  const [isColumnEditorOpen, setIsColumnEditorOpen] = useState(false);
74
76
  const [lastKnownColumnState, setLastKnownColumnState] = useState(null);
75
- // Místo version counter použijeme stabilnější mechanismus pro tracking změn
76
- const [lastColumnDefsHash, setLastColumnDefsHash] = useState('');
77
+ const [columnWidthsVersion, setColumnWidthsVersion] = useState(0); // Pro trigger preTransformedColumnDefs
77
78
 
78
- // Utility funkce pro generování hash z columnDefs
79
- const generateColumnDefsHash = useCallback((colDefs) => {
80
- if (!Array.isArray(colDefs)) return '';
81
-
82
- // Vytvoříme hash z klíčových vlastností které ovlivňují rendering
83
- return colDefs.map(col =>
84
- `${col.field || col.colId}:${col.width || 'auto'}:${col.hide ? 'hidden' : 'visible'}:${col.headerName || ''}`
85
- ).join('|');
86
- }, []);
87
79
 
88
80
 
89
81
  // Grid Layout API hook
@@ -124,123 +116,6 @@ export const useGridLayout = ({
124
116
  }
125
117
  );
126
118
 
127
- // // Bezpečné aktualizování lastKnownColumnState při otevření editoru
128
- // useEffect(() => {
129
- // if (isColumnEditorOpen && columnApiRef.current && typeof columnApiRef.current.getColumnState === 'function') {
130
- // try {
131
- // const currentState = columnApiRef.current.getColumnState();
132
- // if (Array.isArray(currentState) && currentState.length > 0) {
133
- // // Aktualizujeme lastKnownColumnState po otevření editoru
134
- // const validColumnDefs = Array.isArray(columnDefs) ? columnDefs : [];
135
- // const formattedState = currentState.map((columnStateItem, index) => {
136
- // const colDef = validColumnDefs.find(cd => cd.field === columnStateItem.colId) || {};
137
- // const savedField = savedFields?.records?.find(sf => sf.fieldName === columnStateItem.colId);
138
-
139
- // return {
140
- // id: columnStateItem.colId,
141
- // field: columnStateItem.colId,
142
- // headerName: savedField?.headerName || colDef.headerName || columnStateItem.colId,
143
- // originalHeaderName: colDef.headerName || columnStateItem.colId,
144
- // width: columnStateItem.width || colDef.width || 100,
145
- // originalWidth: colDef.width || 100,
146
- // visible: !columnStateItem.hide,
147
- // order: index
148
- // };
149
- // });
150
-
151
- // setLastKnownColumnState(formattedState);
152
- // console.log('[GridLayout] Updated lastKnownColumnState after opening editor');
153
- // }
154
- // } catch (error) {
155
- // console.error('[GridLayout] Error updating column state after opening editor:', error);
156
- // }
157
- // }
158
- // }, [isColumnEditorOpen, columnDefs, savedFields, columnApiRef]);
159
-
160
- // MutationObserver pro sledování změn v DOM a okamžitou aktualizaci headerName
161
- // useEffect(() => {
162
- // if (!savedFields?.records || !isInitialized || !enabled) return;
163
-
164
- // // Reference na observer pro cleanup
165
- // let observer = null;
166
-
167
- // try {
168
- // console.log('[GridLayout] Setting up MutationObserver for header changes');
169
-
170
- // // Funkce pro aktualizaci headerName
171
- // const updateHeaderNames = () => {
172
- // try {
173
- // // Vytvoříme mapu fieldName -> headerName z API dat
174
- // const headerNameMap = new Map();
175
- // savedFields.records.forEach(field => {
176
- // if (field.fieldName && field.headerName) {
177
- // headerNameMap.set(field.fieldName, field.headerName);
178
- // }
179
- // });
180
-
181
- // // Najdeme všechny hlavičky sloupců v DOM
182
- // const headerCells = document.querySelectorAll('.ag-header-cell');
183
-
184
- // // Aktualizujeme texty hlaviček
185
- // headerCells.forEach(headerCell => {
186
- // try {
187
- // // Získáme ID sloupce z DOM atributů
188
- // const colId = headerCell.getAttribute('col-id');
189
- // if (colId && headerNameMap.has(colId)) {
190
- // // Najdeme element s textem hlavičky
191
- // const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
192
- // if (headerTextEl) {
193
- // const newHeaderName = headerNameMap.get(colId);
194
- // const currentText = headerTextEl.textContent;
195
- // if (currentText !== newHeaderName) {
196
- // console.log(`[GridLayout] MutationObserver update: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
197
- // headerTextEl.textContent = newHeaderName;
198
- // }
199
- // }
200
- // }
201
- // } catch (cellError) {
202
- // // Tiché selhání - nechceme, aby MutationObserver padal
203
- // }
204
- // });
205
- // } catch (error) {
206
- // // Tiché selhání - nechceme, aby MutationObserver padal
207
- // }
208
- // };
209
-
210
- // // Najdeme element hlavičky
211
- // const headerElement = document.querySelector('.ag-header');
212
- // if (headerElement) {
213
- // // Vytvoříme observer, který bude sledovat změny v hlavičce
214
- // observer = new MutationObserver((mutations) => {
215
- // // Detekovali jsme změnu v DOM hlavičky, aktualizujeme headerName
216
- // updateHeaderNames();
217
- // });
218
-
219
- // // Začneme sledovat změny v hlavičce
220
- // observer.observe(headerElement, {
221
- // childList: true, // sledujeme přidání/odebírání elementů
222
- // subtree: true, // sledujeme změny i v potomcích
223
- // characterData: true, // sledujeme změny textu
224
- // attributeFilter: ['col-id', 'class'] // sledujeme změny těchto atributů
225
- // });
226
-
227
- // console.log('[GridLayout] MutationObserver set up successfully');
228
- // } else {
229
- // console.log('[GridLayout] Header element not found for MutationObserver');
230
- // }
231
- // } catch (error) {
232
- // console.error('[GridLayout] Error setting up MutationObserver:', error);
233
- // }
234
-
235
- // // Cleanup - odpojit observer při unmount
236
- // return () => {
237
- // if (observer) {
238
- // observer.disconnect();
239
- // console.log('[GridLayout] MutationObserver disconnected');
240
- // }
241
- // };
242
- // }, [savedFields, isInitialized, enabled]);
243
-
244
119
  /**
245
120
  * Error handler
246
121
  */
@@ -263,45 +138,39 @@ export const useGridLayout = ({
263
138
  // Reference pro ukládání stavu sloupců bez state update v render cyklu
264
139
  const stableCurrentColumnsRef = useRef(null);
265
140
 
266
- // Aktualizujeme ref hodnoty
141
+ // Jednoduchá aktualizace ref hodnot - BEZ aktualizace columnDefs
267
142
  useEffect(() => {
268
- let updatedColumnDefs = columnDefs;
269
-
270
- // Pro columnDefs zachováváme aktualizované šířky pokud už existují
271
- if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current) && Array.isArray(columnDefs)) {
272
- // Vytvoříme mapu existujících šířek
273
- const existingWidthsMap = new Map();
274
- stableColumnDefsRef.current.forEach(colDef => {
275
- const fieldId = colDef.field || colDef.colId;
276
- if (fieldId && colDef.width) {
277
- existingWidthsMap.set(fieldId, colDef.width);
278
- }
279
- });
280
-
281
- // Aktualizujeme columnDefs s existujícími šířkami
282
- updatedColumnDefs = columnDefs.map(colDef => {
283
- const fieldId = colDef.field || colDef.colId;
284
- if (fieldId && existingWidthsMap.has(fieldId)) {
285
- return {
286
- ...colDef,
287
- width: existingWidthsMap.get(fieldId)
288
- };
289
- }
290
- return colDef;
291
- });
292
- }
293
-
294
- // Zkontrolujeme zda se columnDefs skutečně změnily pomocí hash
295
- const newHash = generateColumnDefsHash(updatedColumnDefs);
296
- if (newHash !== lastColumnDefsHash) {
297
- stableColumnDefsRef.current = updatedColumnDefs;
298
- setLastColumnDefsHash(newHash);
143
+ // Při změně columnDefs vyčistíme columnWidthRefsMap a přeneseme existující šířky
144
+ if (columnDefs !== stableColumnDefsRef.current) {
145
+ const newWidthMap = new Map();
146
+
147
+ // Zachováme šířky pro sloupce, které stále existují
148
+ if (Array.isArray(columnDefs)) {
149
+ columnDefs.forEach(colDef => {
150
+ const fieldId = colDef.field || colDef.colId;
151
+ if (fieldId) {
152
+ // Zkusíme najít existující šířku v ref map
153
+ const existingWidth = columnWidthRefsMap.current.get(fieldId);
154
+ if (existingWidth !== undefined) {
155
+ newWidthMap.set(fieldId, existingWidth);
156
+ } else if (colDef.width) {
157
+ // Použijeme šířku z nového columnDef
158
+ newWidthMap.set(fieldId, colDef.width);
159
+ }
160
+ }
161
+ });
162
+ }
163
+
164
+ columnWidthRefsMap.current = newWidthMap;
165
+ console.log('[GridLayout] Cleanup columnWidthRefsMap při změně columnDefs:', Object.fromEntries(newWidthMap));
166
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
299
167
  }
300
-
168
+
169
+ stableColumnDefsRef.current = columnDefs;
301
170
  stableGridLayoutApiRef.current = gridLayoutApi;
302
171
  stableOnLayoutSavedRef.current = onLayoutSaved;
303
172
  stableHandleErrorRef.current = handleError;
304
- });
173
+ }, [columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
305
174
 
306
175
  // Efekt pro bezpečnou aktualizaci lastKnownColumnState z ref
307
176
  // useEffect(() => {
@@ -317,8 +186,6 @@ export const useGridLayout = ({
317
186
  * Uloží současný stav sloupců do API
318
187
  */
319
188
  const saveCurrentLayout = useCallback(async () => {
320
-
321
-
322
189
  if (!enabled || !gridApiRef.current) {
323
190
  return;
324
191
  }
@@ -628,6 +495,16 @@ export const useGridLayout = ({
628
495
  );
629
496
 
630
497
  if (columnState && columnState.length > 0) {
498
+ // Při prvotním načítání inicializujeme ref mapu s API šířkami
499
+ if (!isInitialized) {
500
+ columnState.forEach(colState => {
501
+ if (colState.colId && colState.width) {
502
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
503
+ }
504
+ });
505
+ console.log('[GridLayout] Inicializace columnWidthRefsMap z API:', Object.fromEntries(columnWidthRefsMap.current));
506
+ }
507
+
631
508
  // Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
632
509
  // takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
633
510
  const applyFunction = () => {
@@ -637,32 +514,29 @@ export const useGridLayout = ({
637
514
  try {
638
515
  const applyOrderEnabled = !waitForSavedFields; // Při waitForSavedFields už je pořadí v columnDefs
639
516
 
640
- // Při prvotním načtení (isInitialized=false) používáme přímo columnState z API
641
- // Při následných aplikováních zachováváme aktuální šířky z gridu
642
- let adjustedColumnState = columnState;
643
-
644
- if (isInitialized) {
645
- // Pouze pokud už je grid inicializován, zachováváme současné šířky
646
- const currentColumnState = gridApiRef.current?.getColumnState?.() || [];
647
- const currentWidthMap = new Map();
648
- currentColumnState.forEach(colState => {
649
- if (colState.colId && colState.width) {
650
- currentWidthMap.set(colState.colId, colState.width);
651
- }
652
- });
517
+ // Upravíme columnState s aktuálními šířkami z ref map
518
+ // POUZE pokud ref mapa obsahuje hodnoty (tj. uživatel už manipuloval s šířkami)
519
+ // Při prvotním načítání z API zachováme API šířky
520
+ let adjustedColumnState = columnState.map(colState => {
521
+ // Zkontrolujeme, zda máme ref hodnotu pro tento sloupec
522
+ const refWidth = columnWidthRefsMap.current.get(colState.colId);
523
+ // Použijeme ref hodnotu POUZE pokud existuje A není to prvotní načítání
524
+ if (refWidth !== undefined && isInitialized) {
525
+ return {
526
+ ...colState,
527
+ width: refWidth
528
+ };
529
+ }
530
+ // Při prvotním načítání nebo pokud nemáme ref hodnotu, zachováme API šířku
531
+ return colState;
532
+ });
653
533
 
654
- // Upravíme columnState tak, aby zachoval aktuální šířky pokud existují
655
- adjustedColumnState = columnState.map(colState => {
656
- const currentWidth = currentWidthMap.get(colState.colId);
657
- if (currentWidth && currentWidth !== colState.width) {
658
- return {
659
- ...colState,
660
- width: currentWidth
661
- };
662
- }
663
- return colState;
664
- });
665
- }
534
+ console.log('[GridLayout] Aplikování column state s ref šířkami:', {
535
+ columnStateLength: adjustedColumnState?.length,
536
+ applyOrderEnabled,
537
+ firstColumnWidth: adjustedColumnState?.[0]?.width,
538
+ refWidthsCount: columnWidthRefsMap.current.size
539
+ });
666
540
 
667
541
  result = applyColumnStateApi.applyColumnState({
668
542
  state: adjustedColumnState,
@@ -675,6 +549,8 @@ export const useGridLayout = ({
675
549
  },
676
550
  });
677
551
 
552
+ console.log('[GridLayout] Column state aplikován úspěšně');
553
+
678
554
  // Explicitně aktualizujeme headerName pro každý sloupec, protože AG-Grid
679
555
  // nepodporuje nastavení headerName přes applyColumnState
680
556
  if (
@@ -740,8 +616,13 @@ export const useGridLayout = ({
740
616
  // Pro jistotu zkontrolujeme, zda byly změny aplikovány
741
617
  setTimeout(() => {
742
618
  try {
743
- const afterUpdateColDefs =
744
- gridApiRef.current.getColumnDefs();
619
+ const afterUpdateColDefs = gridApiRef.current.getColumnDefs();
620
+ const afterUpdateColumnState = gridApiRef.current.getColumnState?.() || [];
621
+
622
+ console.log('[GridLayout] Po aplikování - kontrola šířek:', {
623
+ columnCount: afterUpdateColumnState.length,
624
+ widths: afterUpdateColumnState.map(col => ({ field: col.colId, width: col.width }))
625
+ });
745
626
 
746
627
  // DOM operace dokončeny, můžeme ukončit loading
747
628
  setIsApplyingLayout(false);
@@ -909,42 +790,27 @@ export const useGridLayout = ({
909
790
 
910
791
  setHasUnsavedChanges(true);
911
792
 
912
- // Aktualizujeme šířky sloupců v columnDefs před uložením
793
+ // Okamžitě uložit aktuální šířky sloupců do ref map (podobně jako v handleColumnResized)
913
794
  try {
914
795
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
915
796
  const currentColumnState = gridApiRef.current.getColumnState();
916
797
 
917
798
  if (currentColumnState && Array.isArray(currentColumnState)) {
918
- // Aktualizujeme šířky v původních columnDefs
919
- const widthUpdatesMap = new Map();
799
+ // Uložit šířky do ref map pro každý sloupec
920
800
  currentColumnState.forEach(colState => {
921
801
  if (colState.colId && colState.width) {
922
- widthUpdatesMap.set(colState.colId, colState.width);
802
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
923
803
  }
924
804
  });
925
805
 
926
- // Aktualizujeme stableColumnDefsRef s novými šířkami
927
- if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current)) {
928
- const updatedColumnDefs = stableColumnDefsRef.current.map(colDef => {
929
- const fieldId = colDef.field || colDef.colId;
930
- if (fieldId && widthUpdatesMap.has(fieldId)) {
931
- return {
932
- ...colDef,
933
- width: widthUpdatesMap.get(fieldId)
934
- };
935
- }
936
- return colDef;
937
- });
938
- stableColumnDefsRef.current = updatedColumnDefs;
939
- // Hash se aktualizuje automaticky v hlavním useEffect
940
- }
806
+ console.log('[GridLayout] Updated columnWidthRefsMap in dragStopped:', Object.fromEntries(columnWidthRefsMap.current));
807
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
941
808
  }
942
809
  }
943
810
  } catch (error) {
944
- console.error('[GridLayout] Error updating columnDefs widths in handleDragStopped:', error);
811
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleDragStopped:', error);
945
812
  }
946
813
 
947
-
948
814
  // Pokud ještě není inicializované, přidáme akci do pending
949
815
  if (!isInitialized && autoSave) {
950
816
  setPendingActions((prev) => [
@@ -954,50 +820,66 @@ export const useGridLayout = ({
954
820
  return;
955
821
  }
956
822
 
957
- // Normální proces pokud je vše inicializované
958
823
  if (autoSave && debouncedSave) {
959
824
  debouncedSave();
960
- } else {
961
825
  }
962
826
  }, [enabled, isGridReady, isInitialized, autoSave, debouncedSave]);
963
827
 
828
+ // Handler pro PRŮBĚŽNÉ resize - ukládá šířky během resize operace
829
+ const handleColumnResizing = useCallback(() => {
830
+ if (!enabled || !isGridReady) return;
831
+
832
+ // Okamžitě uložit aktuální šířky sloupců do ref map BĚHEM resize operace
833
+ try {
834
+ if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
835
+ const currentColumnState = gridApiRef.current.getColumnState();
836
+
837
+ if (currentColumnState && Array.isArray(currentColumnState)) {
838
+ // Uložit šířky do ref map pro každý sloupec
839
+ currentColumnState.forEach(colState => {
840
+ if (colState.colId && colState.width) {
841
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
842
+ }
843
+ });
844
+
845
+ // Log pouze při výrazných změnách pro omezení logů
846
+ if (Math.random() < 0.1) { // 10% šance na log
847
+ console.log('[GridLayout] Updating columnWidthRefsMap during resize:', Object.fromEntries(columnWidthRefsMap.current));
848
+ }
849
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
850
+ }
851
+ }
852
+ } catch (error) {
853
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResizing:', error);
854
+ }
855
+
856
+ // NEPOUŽÍVÁME setHasUnsavedChanges zde - to až v handleColumnResized
857
+ }, [enabled, isGridReady]);
858
+
859
+ // Handler pro DOKONČENÍ resize - spouští auto-save
964
860
  const handleColumnResized = useCallback(() => {
965
861
  if (!enabled || !isGridReady) return;
966
862
  setHasUnsavedChanges(true);
967
863
 
968
- // Aktualizujeme šířky sloupců v columnDefs při resize
864
+ // Ještě jednou uložit aktuální šířky sloupců do ref map (pro jistotu)
969
865
  try {
970
866
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
971
867
  const currentColumnState = gridApiRef.current.getColumnState();
972
868
 
973
869
  if (currentColumnState && Array.isArray(currentColumnState)) {
974
- // Aktualizujeme šířky v původních columnDefs
975
- const widthUpdatesMap = new Map();
870
+ // Uložit šířky do ref map pro každý sloupec
976
871
  currentColumnState.forEach(colState => {
977
872
  if (colState.colId && colState.width) {
978
- widthUpdatesMap.set(colState.colId, colState.width);
873
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
979
874
  }
980
875
  });
981
876
 
982
- // Aktualizujeme stableColumnDefsRef s novými šířkami
983
- if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current)) {
984
- const updatedColumnDefs = stableColumnDefsRef.current.map(colDef => {
985
- const fieldId = colDef.field || colDef.colId;
986
- if (fieldId && widthUpdatesMap.has(fieldId)) {
987
- return {
988
- ...colDef,
989
- width: widthUpdatesMap.get(fieldId)
990
- };
991
- }
992
- return colDef;
993
- });
994
- stableColumnDefsRef.current = updatedColumnDefs;
995
- // Hash se aktualizuje automaticky v hlavním useEffect
996
- }
877
+ console.log('[GridLayout] Final columnWidthRefsMap after resize:', Object.fromEntries(columnWidthRefsMap.current));
878
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
997
879
  }
998
880
  }
999
881
  } catch (error) {
1000
- console.error('[GridLayout] Error updating columnDefs widths in handleColumnResized:', error);
882
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResized:', error);
1001
883
  }
1002
884
 
1003
885
  if (autoSave && isInitialized && debouncedSave) {
@@ -1048,166 +930,21 @@ export const useGridLayout = ({
1048
930
  */
1049
931
  useEffect(() => {
1050
932
  // Aplikujeme layout pokud:
1051
- // 1. Máme savedFields z API
1052
- // 2. Grid je ready (má API reference)
933
+ // 1. Máme savedFields z API (i když prázdné - první zobrazení modulu)
934
+ // 2. Grid je ready (má API references)
1053
935
  // 3. Ještě jsme neinicializovali layout
1054
- if (savedFields?.records && savedFields.records.length > 0 && gridApiRef.current && !isInitialized) {
1055
- applySavedLayout();
936
+ if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
937
+ if (savedFields.records.length > 0) {
938
+ applySavedLayout();
939
+ } else {
940
+ // Pro prázdné savedFields jen nastavíme inicializaci
941
+ setIsInitialized(true);
942
+ setIsGridReady(true);
943
+ }
1056
944
  }
1057
945
  }, [savedFields?.records, isInitialized, applySavedLayout]);
1058
946
 
1059
- /**
1060
- * Původní zakomentovaný effect pro aplikování layoutu když se načtou data
1061
- */
1062
- // useEffect(() => {
1063
- // if (savedFields?.records && columnApiRef.current && !isInitialized) {
1064
- // console.log('[GridLayout] Layout will be applied from effect');
1065
- // applySavedLayout();
1066
- // } else if (savedFields?.records && columnApiRef.current && isInitialized) {
1067
- // // Pokud je již inicializován, ale přišla nová data, aktualizujeme jen DOM (ne celý layout)
1068
- // console.log('[GridLayout] Already initialized, but received new data - updating headers directly');
1069
-
1070
- // // Počkáme moment, než se nová data zpracují, a pak aktualizujeme headerName
1071
- // setTimeout(() => {
1072
- // try {
1073
- // // Vytvoříme mapu fieldName -> headerName z API dat
1074
- // const headerNameMap = new Map();
1075
- // savedFields.records.forEach(field => {
1076
- // if (field.fieldName && field.headerName) {
1077
- // headerNameMap.set(field.fieldName, field.headerName);
1078
- // console.log(`[GridLayout] Update after reload: '${field.fieldName}' -> '${field.headerName}'`);
1079
- // }
1080
- // });
1081
-
1082
- // // Najdeme všechny hlavičky sloupců v DOM
1083
- // const headerCells = document.querySelectorAll('.ag-header-cell');
1084
- // console.log('[GridLayout] Found header cells after reload:', headerCells.length);
1085
-
1086
- // // Aktualizujeme texty hlaviček
1087
- // headerCells.forEach(headerCell => {
1088
- // try {
1089
- // // Získáme ID sloupce z DOM atributů
1090
- // const colId = headerCell.getAttribute('col-id');
1091
- // if (colId && headerNameMap.has(colId)) {
1092
- // // Najdeme element s textem hlavičky
1093
- // const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
1094
- // if (headerTextEl) {
1095
- // const newHeaderName = headerNameMap.get(colId);
1096
- // const currentText = headerTextEl.textContent;
1097
- // console.log(`[GridLayout] DOM update after reload: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
1098
- // headerTextEl.textContent = newHeaderName;
1099
- // }
1100
- // }
1101
- // } catch (cellError) {
1102
- // console.error('[GridLayout] Error updating header cell after reload:', cellError);
1103
- // }
1104
- // });
1105
-
1106
- // // Zkusíme vynutit překreslení hlavičky
1107
- // if (typeof gridApiRef.current.refreshHeader === 'function') {
1108
- // console.log('[GridLayout] Forcing header refresh after reload');
1109
- // gridApiRef.current.refreshHeader();
1110
- // }
1111
- // } catch (error) {
1112
- // console.error('[GridLayout] Error updating headers after reload:', error);
1113
- // }
1114
- // }, 200);
1115
- // }
1116
- // }, [savedFields, applySavedLayout, isInitialized, columnApiRef]);
1117
-
1118
- /**
1119
- * Alternativní metoda pro aktualizaci headerName po inicializaci gridu
1120
- */
1121
- // useEffect(() => {
1122
- // // Pokud již proběhla inicializace a máme uložená data z API
1123
- // if (isInitialized && savedFields?.records && gridApiRef.current) {
1124
- // console.log('[GridLayout] Attempting alternative header update after initialization');
1125
-
1126
- // // Zkusíme použít metodu columnDefHeaderNameChanged, pokud je dostupná
1127
- // try {
1128
- // if (typeof gridApiRef.current.columnDefHeaderNameChanged === 'function') {
1129
- // console.log('[GridLayout] Trying columnDefHeaderNameChanged method');
1130
-
1131
- // // Vytvoříme mapu fieldName -> headerName z API dat
1132
- // const headerNameMap = new Map();
1133
- // savedFields.records.forEach(field => {
1134
- // if (field.fieldName && field.headerName) {
1135
- // headerNameMap.set(field.fieldName, field.headerName);
1136
- // }
1137
- // });
1138
-
1139
- // // Získáme aktuální definice sloupců
1140
- // const currentColumnDefs = gridApiRef.current.getColumnDefs();
1141
- // if (currentColumnDefs && Array.isArray(currentColumnDefs)) {
1142
- // currentColumnDefs.forEach(colDef => {
1143
- // if (colDef.field && headerNameMap.has(colDef.field)) {
1144
- // const newHeaderName = headerNameMap.get(colDef.field);
1145
- // if (colDef.headerName !== newHeaderName) {
1146
- // console.log(`[GridLayout] Using columnDefHeaderNameChanged for '${colDef.field}': '${colDef.headerName}' -> '${newHeaderName}'`);
1147
- // colDef.headerName = newHeaderName;
1148
- // gridApiRef.current.columnDefHeaderNameChanged(colDef);
1149
- // }
1150
- // }
1151
- // });
1152
- // }
1153
- // }
1154
- // } catch (error) {
1155
- // console.error('[GridLayout] Error using columnDefHeaderNameChanged:', error);
1156
- // }
1157
-
1158
- // // Počkáme chvíli, aby se grid stihl plně vyrenderovat
1159
- // setTimeout(() => {
1160
- // try {
1161
- // // Získáme aktuální definice sloupců z gridu
1162
- // const currentColDefs = gridApiRef.current.getColumnDefs ? gridApiRef.current.getColumnDefs() : null;
1163
-
1164
- // if (currentColDefs && Array.isArray(currentColDefs)) {
1165
- // // Vytvoříme mapu fieldName -> headerName z API dat
1166
- // const headerNameMap = new Map();
1167
- // savedFields.records.forEach(field => {
1168
- // if (field.fieldName && field.headerName) {
1169
- // headerNameMap.set(field.fieldName, field.headerName);
1170
- // }
1171
- // });
1172
-
1173
- // // Zkontrolujeme, zda je třeba aktualizovat nějaké headery
1174
- // let needsUpdate = false;
1175
- // const updatedColDefs = currentColDefs.map(colDef => {
1176
- // const fieldName = colDef.field;
1177
- // if (fieldName && headerNameMap.has(fieldName)) {
1178
- // const newHeaderName = headerNameMap.get(fieldName);
1179
- // if (colDef.headerName !== newHeaderName) {
1180
- // needsUpdate = true;
1181
- // console.log(`[GridLayout] Alternative update: Column '${fieldName}' header from '${colDef.headerName}' to '${newHeaderName}'`);
1182
- // return {
1183
- // ...colDef,
1184
- // headerName: newHeaderName
1185
- // };
1186
- // }
1187
- // }
1188
- // return colDef;
1189
- // });
1190
-
1191
- // if (needsUpdate && typeof gridApiRef.current.setColumnDefs === 'function') {
1192
- // console.log('[GridLayout] Applying alternative column header update');
1193
- // gridApiRef.current.setColumnDefs(updatedColDefs);
1194
-
1195
- // // Zkusíme vynutit překreslení hlavičky
1196
- // setTimeout(() => {
1197
- // if (typeof gridApiRef.current.refreshHeader === 'function') {
1198
- // console.log('[GridLayout] Forcing header refresh');
1199
- // gridApiRef.current.refreshHeader();
1200
- // }
1201
- // }, 50);
1202
- // }
1203
- // }
1204
- // } catch (error) {
1205
- // console.error('[GridLayout] Error in alternative header update:', error);
1206
- // }
1207
- // }, 300);
1208
- // }
1209
- // }, [isInitialized, savedFields, gridApiRef]);
1210
-
947
+
1211
948
  /**
1212
949
  * Effect pro error handling
1213
950
  */
@@ -1589,7 +1326,7 @@ export const useGridLayout = ({
1589
1326
  // DŮLEŽITÉ: Toto useMemo nyní obsahuje i AgGridColumns transformaci pro eliminaci circular dependency
1590
1327
  const preTransformedColumnDefs = useMemo(() => {
1591
1328
  // Použijeme aktualizované columnDefs ze stableColumnDefsRef pokud existují
1592
- const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
1329
+ const columnDefsToUse = stableColumnDefsRef.current; // || columnDefs; //HLO
1593
1330
 
1594
1331
  let baseColumnDefs = columnDefsToUse;
1595
1332
 
@@ -1637,7 +1374,7 @@ export const useGridLayout = ({
1637
1374
  const fieldId = colDef.field || colDef.colId;
1638
1375
  const columnStateItem = columnStateMap.get(fieldId);
1639
1376
 
1640
- // Aplikujeme pouze headerName a hide z API (width se aplikuje v applySavedLayout)
1377
+ // Aplikujeme headerName, hide i width z API pro waitForSavedFields režim
1641
1378
  if (fieldId && (headerNameMap.has(fieldId) || columnStateItem)) {
1642
1379
  return {
1643
1380
  ...colDef,
@@ -1645,7 +1382,8 @@ export const useGridLayout = ({
1645
1382
  ...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
1646
1383
  // Aplikujeme hide hodnotu z columnState (z API show hodnoty)
1647
1384
  ...(columnStateItem && { hide: columnStateItem.hide }),
1648
- // Width se neaplikuje zde - aplikuje se až v applySavedLayout pro eliminaci konfliktu s resize
1385
+ // Aplikujeme také width pro konzistentní zobrazení
1386
+ ...(columnStateItem && columnStateItem.width && { width: columnStateItem.width }),
1649
1387
  };
1650
1388
  }
1651
1389
  return colDef;
@@ -1664,7 +1402,23 @@ export const useGridLayout = ({
1664
1402
  }
1665
1403
  }
1666
1404
 
1667
- return baseColumnDefs;
1405
+ // Aplikujeme ref šířky jako poslední krok POUZE pokud už byla provedena inicializace
1406
+ // Při prvotním načítání zachováváme API šířky (které jsou už v baseColumnDefs pro waitForSavedFields)
1407
+ const finalColumnDefs = baseColumnDefs.map(colDef => {
1408
+ const fieldId = colDef.field || colDef.colId;
1409
+ const refWidth = columnWidthRefsMap.current.get(fieldId);
1410
+
1411
+ // Použijeme ref šířku POUZE pokud už je grid inicializovaný (uživatel manipuloval s šířkami)
1412
+ if (refWidth !== undefined && isInitialized) {
1413
+ return {
1414
+ ...colDef,
1415
+ width: refWidth
1416
+ };
1417
+ }
1418
+ return colDef;
1419
+ });
1420
+
1421
+ return finalColumnDefs;
1668
1422
 
1669
1423
  // // Replikujeme AgGridColumns logiku pro všechny column definitions:
1670
1424
  // const processedColumns = baseColumnDefs?.map((column) => {
@@ -1687,62 +1441,9 @@ export const useGridLayout = ({
1687
1441
  // }) || [];
1688
1442
 
1689
1443
  // return processedColumns;
1690
- }, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, lastColumnDefsHash]);
1691
-
1692
- /**
1693
- * Handler pro změnu zobrazených dat - aktualizace headerName
1694
- */
1695
- const handleRowDataChanged = useCallback(
1696
- (params) => {
1697
- // if (!enabled || !savedFields?.records || !isInitialized) return;
1698
- // console.log('[GridLayout] Row data changed - ensuring header names stay updated');
1699
- // // Počkáme chvíli, až se vše vyrenderuje, a pak aktualizujeme headerName
1700
- // setTimeout(() => {
1701
- // try {
1702
- // // Vytvoříme mapu fieldName -> headerName z API dat
1703
- // const headerNameMap = new Map();
1704
- // savedFields.records.forEach(field => {
1705
- // if (field.fieldName && field.headerName) {
1706
- // headerNameMap.set(field.fieldName, field.headerName);
1707
- // }
1708
- // });
1709
- // // Najdeme všechny hlavičky sloupců v DOM
1710
- // const headerCells = document.querySelectorAll('.ag-header-cell');
1711
- // console.log('[GridLayout] Found header cells after data change:', headerCells.length);
1712
- // // Aktualizujeme texty hlaviček
1713
- // headerCells.forEach(headerCell => {
1714
- // try {
1715
- // // Získáme ID sloupce z DOM atributů
1716
- // const colId = headerCell.getAttribute('col-id');
1717
- // if (colId && headerNameMap.has(colId)) {
1718
- // // Najdeme element s textem hlavičky
1719
- // const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
1720
- // if (headerTextEl) {
1721
- // const newHeaderName = headerNameMap.get(colId);
1722
- // const currentText = headerTextEl.textContent;
1723
- // if (currentText !== newHeaderName) {
1724
- // console.log(`[GridLayout] Data change update: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
1725
- // headerTextEl.textContent = newHeaderName;
1726
- // }
1727
- // }
1728
- // }
1729
- // } catch (cellError) {
1730
- // console.error('[GridLayout] Error updating header cell after data change:', cellError);
1731
- // }
1732
- // });
1733
- // // Zkusíme vynutit překreslení hlavičky
1734
- // if (typeof gridApiRef.current.refreshHeader === 'function') {
1735
- // console.log('[GridLayout] Forcing header refresh after data change');
1736
- // gridApiRef.current.refreshHeader();
1737
- // }
1738
- // } catch (error) {
1739
- // console.error('[GridLayout] Error updating headers after data change:', error);
1740
- // }
1741
- // }, 100);
1742
- },
1743
- [enabled, savedFields, isInitialized]
1744
- );
1444
+ }, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
1745
1445
 
1446
+ console.log("rerender");
1746
1447
  return {
1747
1448
  // State
1748
1449
  isLoading: isLoading || isFieldsLoading,
@@ -1759,10 +1460,11 @@ export const useGridLayout = ({
1759
1460
  onGridReady: handleGridReady,
1760
1461
  onColumnMoved: handleColumnMoved,
1761
1462
  onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
1463
+ onColumnResizing: handleColumnResizing, // NOVÝ handler pro průběžné resize
1762
1464
  onColumnResized: handleColumnResized,
1763
1465
  onColumnVisible: handleColumnVisible,
1764
1466
  onColumnPinned: handleColumnPinned,
1765
- onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1467
+ // onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1766
1468
 
1767
1469
  // Manual actions
1768
1470
  saveLayout,