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

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,38 @@ 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
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
299
166
  }
300
-
167
+
168
+ stableColumnDefsRef.current = columnDefs;
301
169
  stableGridLayoutApiRef.current = gridLayoutApi;
302
170
  stableOnLayoutSavedRef.current = onLayoutSaved;
303
171
  stableHandleErrorRef.current = handleError;
304
- });
172
+ }, [columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
305
173
 
306
174
  // Efekt pro bezpečnou aktualizaci lastKnownColumnState z ref
307
175
  // useEffect(() => {
@@ -317,8 +185,6 @@ export const useGridLayout = ({
317
185
  * Uloží současný stav sloupců do API
318
186
  */
319
187
  const saveCurrentLayout = useCallback(async () => {
320
-
321
-
322
188
  if (!enabled || !gridApiRef.current) {
323
189
  return;
324
190
  }
@@ -628,6 +494,15 @@ export const useGridLayout = ({
628
494
  );
629
495
 
630
496
  if (columnState && columnState.length > 0) {
497
+ // Při prvotním načítání inicializujeme ref mapu s API šířkami
498
+ if (!isInitialized) {
499
+ columnState.forEach(colState => {
500
+ if (colState.colId && colState.width) {
501
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
502
+ }
503
+ });
504
+ }
505
+
631
506
  // Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
632
507
  // takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
633
508
  const applyFunction = () => {
@@ -637,33 +512,22 @@ export const useGridLayout = ({
637
512
  try {
638
513
  const applyOrderEnabled = !waitForSavedFields; // Při waitForSavedFields už je pořadí v columnDefs
639
514
 
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
- });
653
-
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
- }
666
-
515
+ // Upravíme columnState s aktuálními šířkami z ref map
516
+ // POUZE pokud ref mapa obsahuje hodnoty (tj. uživatel už manipuloval s šířkami)
517
+ // Při prvotním načítání z API zachováme API šířky
518
+ let adjustedColumnState = columnState.map(colState => {
519
+ // Zkontrolujeme, zda máme ref hodnotu pro tento sloupec
520
+ const refWidth = columnWidthRefsMap.current.get(colState.colId);
521
+ // Použijeme ref hodnotu POUZE pokud existuje A není to prvotní načítání
522
+ if (refWidth !== undefined && isInitialized) {
523
+ return {
524
+ ...colState,
525
+ width: refWidth
526
+ };
527
+ }
528
+ // Při prvotním načítání nebo pokud nemáme ref hodnotu, zachováme API šířku
529
+ return colState;
530
+ });
667
531
  result = applyColumnStateApi.applyColumnState({
668
532
  state: adjustedColumnState,
669
533
  applyOrder: applyOrderEnabled, // Pořadí jen když není waitForSavedFields
@@ -740,9 +604,9 @@ export const useGridLayout = ({
740
604
  // Pro jistotu zkontrolujeme, zda byly změny aplikovány
741
605
  setTimeout(() => {
742
606
  try {
743
- const afterUpdateColDefs =
744
- gridApiRef.current.getColumnDefs();
745
-
607
+ const afterUpdateColDefs = gridApiRef.current.getColumnDefs();
608
+ const afterUpdateColumnState = gridApiRef.current.getColumnState?.() || [];
609
+
746
610
  // DOM operace dokončeny, můžeme ukončit loading
747
611
  setIsApplyingLayout(false);
748
612
  } catch (checkError) {
@@ -909,42 +773,26 @@ export const useGridLayout = ({
909
773
 
910
774
  setHasUnsavedChanges(true);
911
775
 
912
- // Aktualizujeme šířky sloupců v columnDefs před uložením
776
+ // Okamžitě uložit aktuální šířky sloupců do ref map (podobně jako v handleColumnResized)
913
777
  try {
914
778
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
915
779
  const currentColumnState = gridApiRef.current.getColumnState();
916
780
 
917
781
  if (currentColumnState && Array.isArray(currentColumnState)) {
918
- // Aktualizujeme šířky v původních columnDefs
919
- const widthUpdatesMap = new Map();
782
+ // Uložit šířky do ref map pro každý sloupec
920
783
  currentColumnState.forEach(colState => {
921
784
  if (colState.colId && colState.width) {
922
- widthUpdatesMap.set(colState.colId, colState.width);
785
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
923
786
  }
924
787
  });
925
788
 
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
- }
789
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
941
790
  }
942
791
  }
943
792
  } catch (error) {
944
- console.error('[GridLayout] Error updating columnDefs widths in handleDragStopped:', error);
793
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleDragStopped:', error);
945
794
  }
946
795
 
947
-
948
796
  // Pokud ještě není inicializované, přidáme akci do pending
949
797
  if (!isInitialized && autoSave) {
950
798
  setPendingActions((prev) => [
@@ -954,50 +802,59 @@ export const useGridLayout = ({
954
802
  return;
955
803
  }
956
804
 
957
- // Normální proces pokud je vše inicializované
958
805
  if (autoSave && debouncedSave) {
959
806
  debouncedSave();
960
- } else {
961
807
  }
962
808
  }, [enabled, isGridReady, isInitialized, autoSave, debouncedSave]);
963
809
 
810
+ // Handler pro PRŮBĚŽNÉ resize - ukládá šířky během resize operace
811
+ const handleColumnResizing = useCallback(() => {
812
+ if (!enabled || !isGridReady) return;
813
+
814
+ // Okamžitě uložit aktuální šířky sloupců do ref map BĚHEM resize operace
815
+ try {
816
+ if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
817
+ const currentColumnState = gridApiRef.current.getColumnState();
818
+
819
+ if (currentColumnState && Array.isArray(currentColumnState)) {
820
+ // Uložit šířky do ref map pro každý sloupec
821
+ currentColumnState.forEach(colState => {
822
+ if (colState.colId && colState.width) {
823
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
824
+ }
825
+ });
826
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
827
+ }
828
+ }
829
+ } catch (error) {
830
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResizing:', error);
831
+ }
832
+
833
+ // NEPOUŽÍVÁME setHasUnsavedChanges zde - to až v handleColumnResized
834
+ }, [enabled, isGridReady]);
835
+
836
+ // Handler pro DOKONČENÍ resize - spouští auto-save
964
837
  const handleColumnResized = useCallback(() => {
965
838
  if (!enabled || !isGridReady) return;
966
839
  setHasUnsavedChanges(true);
967
840
 
968
- // Aktualizujeme šířky sloupců v columnDefs při resize
841
+ // Ještě jednou uložit aktuální šířky sloupců do ref map (pro jistotu)
969
842
  try {
970
843
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
971
844
  const currentColumnState = gridApiRef.current.getColumnState();
972
845
 
973
846
  if (currentColumnState && Array.isArray(currentColumnState)) {
974
- // Aktualizujeme šířky v původních columnDefs
975
- const widthUpdatesMap = new Map();
847
+ // Uložit šířky do ref map pro každý sloupec
976
848
  currentColumnState.forEach(colState => {
977
849
  if (colState.colId && colState.width) {
978
- widthUpdatesMap.set(colState.colId, colState.width);
850
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
979
851
  }
980
852
  });
981
-
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
- }
853
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
997
854
  }
998
855
  }
999
856
  } catch (error) {
1000
- console.error('[GridLayout] Error updating columnDefs widths in handleColumnResized:', error);
857
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResized:', error);
1001
858
  }
1002
859
 
1003
860
  if (autoSave && isInitialized && debouncedSave) {
@@ -1048,166 +905,21 @@ export const useGridLayout = ({
1048
905
  */
1049
906
  useEffect(() => {
1050
907
  // Aplikujeme layout pokud:
1051
- // 1. Máme savedFields z API
1052
- // 2. Grid je ready (má API reference)
908
+ // 1. Máme savedFields z API (i když prázdné - první zobrazení modulu)
909
+ // 2. Grid je ready (má API references)
1053
910
  // 3. Ještě jsme neinicializovali layout
1054
- if (savedFields?.records && savedFields.records.length > 0 && gridApiRef.current && !isInitialized) {
1055
- applySavedLayout();
911
+ if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
912
+ if (savedFields.records.length > 0) {
913
+ applySavedLayout();
914
+ } else {
915
+ // Pro prázdné savedFields jen nastavíme inicializaci
916
+ setIsInitialized(true);
917
+ setIsGridReady(true);
918
+ }
1056
919
  }
1057
920
  }, [savedFields?.records, isInitialized, applySavedLayout]);
1058
921
 
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
-
922
+
1211
923
  /**
1212
924
  * Effect pro error handling
1213
925
  */
@@ -1589,7 +1301,7 @@ export const useGridLayout = ({
1589
1301
  // DŮLEŽITÉ: Toto useMemo nyní obsahuje i AgGridColumns transformaci pro eliminaci circular dependency
1590
1302
  const preTransformedColumnDefs = useMemo(() => {
1591
1303
  // Použijeme aktualizované columnDefs ze stableColumnDefsRef pokud existují
1592
- const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
1304
+ const columnDefsToUse = stableColumnDefsRef.current; // || columnDefs; //HLO
1593
1305
 
1594
1306
  let baseColumnDefs = columnDefsToUse;
1595
1307
 
@@ -1637,7 +1349,7 @@ export const useGridLayout = ({
1637
1349
  const fieldId = colDef.field || colDef.colId;
1638
1350
  const columnStateItem = columnStateMap.get(fieldId);
1639
1351
 
1640
- // Aplikujeme pouze headerName a hide z API (width se aplikuje v applySavedLayout)
1352
+ // Aplikujeme headerName, hide i width z API pro waitForSavedFields režim
1641
1353
  if (fieldId && (headerNameMap.has(fieldId) || columnStateItem)) {
1642
1354
  return {
1643
1355
  ...colDef,
@@ -1645,7 +1357,8 @@ export const useGridLayout = ({
1645
1357
  ...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
1646
1358
  // Aplikujeme hide hodnotu z columnState (z API show hodnoty)
1647
1359
  ...(columnStateItem && { hide: columnStateItem.hide }),
1648
- // Width se neaplikuje zde - aplikuje se až v applySavedLayout pro eliminaci konfliktu s resize
1360
+ // Aplikujeme také width pro konzistentní zobrazení
1361
+ ...(columnStateItem && columnStateItem.width && { width: columnStateItem.width }),
1649
1362
  };
1650
1363
  }
1651
1364
  return colDef;
@@ -1664,7 +1377,23 @@ export const useGridLayout = ({
1664
1377
  }
1665
1378
  }
1666
1379
 
1667
- return baseColumnDefs;
1380
+ // Aplikujeme ref šířky jako poslední krok POUZE pokud už byla provedena inicializace
1381
+ // Při prvotním načítání zachováváme API šířky (které jsou už v baseColumnDefs pro waitForSavedFields)
1382
+ const finalColumnDefs = baseColumnDefs.map(colDef => {
1383
+ const fieldId = colDef.field || colDef.colId;
1384
+ const refWidth = columnWidthRefsMap.current.get(fieldId);
1385
+
1386
+ // Použijeme ref šířku POUZE pokud už je grid inicializovaný (uživatel manipuloval s šířkami)
1387
+ if (refWidth !== undefined && isInitialized) {
1388
+ return {
1389
+ ...colDef,
1390
+ width: refWidth
1391
+ };
1392
+ }
1393
+ return colDef;
1394
+ });
1395
+
1396
+ return finalColumnDefs;
1668
1397
 
1669
1398
  // // Replikujeme AgGridColumns logiku pro všechny column definitions:
1670
1399
  // const processedColumns = baseColumnDefs?.map((column) => {
@@ -1687,61 +1416,7 @@ export const useGridLayout = ({
1687
1416
  // }) || [];
1688
1417
 
1689
1418
  // 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
- );
1419
+ }, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
1745
1420
 
1746
1421
  return {
1747
1422
  // State
@@ -1759,10 +1434,11 @@ export const useGridLayout = ({
1759
1434
  onGridReady: handleGridReady,
1760
1435
  onColumnMoved: handleColumnMoved,
1761
1436
  onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
1437
+ onColumnResizing: handleColumnResizing, // NOVÝ handler pro průběžné resize
1762
1438
  onColumnResized: handleColumnResized,
1763
1439
  onColumnVisible: handleColumnVisible,
1764
1440
  onColumnPinned: handleColumnPinned,
1765
- onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1441
+ // onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1766
1442
 
1767
1443
  // Manual actions
1768
1444
  saveLayout,