@onehat/ui 0.4.80 → 0.4.82
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/package.json +1 -1
- package/src/Components/Container/Container.js +4 -4
- package/src/Components/Form/Field/Combo/Combo.js +5 -2
- package/src/Components/Form/Field/Combo/MeterTypesCombo.js +1 -0
- package/src/Components/Form/Field/Date.js +1 -1
- package/src/Components/Form/Field/Select/PageSizeSelect.js +6 -1
- package/src/Components/Form/Field/Select/Select.js +14 -38
- package/src/Components/Form/Field/Tag/Tag.js +215 -13
- package/src/Components/Form/Field/Tag/ValueBox.js +20 -1
- package/src/Components/Form/Form.js +25 -13
- package/src/Components/Grid/Grid.js +312 -106
- package/src/Components/Grid/GridHeaderRow.js +42 -22
- package/src/Components/Grid/GridRow.js +13 -6
- package/src/Components/Grid/RowHandle.js +16 -4
- package/src/Components/Hoc/withData.js +7 -0
- package/src/Components/Hoc/withEditor.js +19 -4
- package/src/Components/Hoc/withPresetButtons.js +1 -1
- package/src/Components/Hoc/withSideEditor.js +1 -1
- package/src/Components/Icons/Join.js +10 -0
- package/src/Components/Layout/AsyncOperation.js +62 -14
- package/src/Components/Layout/CenterBox.js +1 -1
- package/src/Components/Screens/Manager.js +1 -1
- package/src/Components/Toolbar/PaginationToolbar.js +3 -1
- package/src/Components/Toolbar/Toolbar.js +10 -6
- package/src/Components/Tree/TreeNode.js +38 -9
- package/src/Components/Viewer/Viewer.js +10 -2
- package/src/Constants/Progress.js +2 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useRef, useMemo, useCallback, } from 'react';
|
|
1
|
+
import { useState, useEffect, useRef, useMemo, useCallback, createRef, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
4
|
FlatList,
|
|
@@ -16,6 +16,9 @@ import {
|
|
|
16
16
|
SELECTION_MODE_SINGLE,
|
|
17
17
|
SELECTION_MODE_MULTI,
|
|
18
18
|
} from '../../Constants/Selection.js';
|
|
19
|
+
import {
|
|
20
|
+
EDITOR_TYPE__SIDE,
|
|
21
|
+
} from '../../Constants/Editor.js';
|
|
19
22
|
import {
|
|
20
23
|
EDIT,
|
|
21
24
|
VIEW,
|
|
@@ -104,9 +107,10 @@ const
|
|
|
104
107
|
SINGLE_CLICK = 1,
|
|
105
108
|
DOUBLE_CLICK = 2,
|
|
106
109
|
TRIPLE_CLICK = 3,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
PHASES__INITIAL = 'initial',
|
|
111
|
+
PHASES__MEASURING = 'measuring',
|
|
112
|
+
PHASES__OPTIMIZED = 'optimized',
|
|
113
|
+
DEBUG = false;
|
|
110
114
|
|
|
111
115
|
function GridComponent(props) {
|
|
112
116
|
const {
|
|
@@ -145,6 +149,7 @@ function GridComponent(props) {
|
|
|
145
149
|
canColumnsSort = true,
|
|
146
150
|
canColumnsReorder = true,
|
|
147
151
|
canColumnsResize = true,
|
|
152
|
+
areCellsScrollable = true,
|
|
148
153
|
allowToggleSelection = false, // i.e. single click with no shift key toggles the selection of the item clicked on
|
|
149
154
|
disableBottomToolbar = false,
|
|
150
155
|
disablePagination = false,
|
|
@@ -205,6 +210,8 @@ function GridComponent(props) {
|
|
|
205
210
|
onContextMenu,
|
|
206
211
|
isAdding,
|
|
207
212
|
isEditorViewOnly,
|
|
213
|
+
getIsEditorShown,
|
|
214
|
+
editorType,
|
|
208
215
|
|
|
209
216
|
// withData
|
|
210
217
|
Repository,
|
|
@@ -255,20 +262,42 @@ function GridComponent(props) {
|
|
|
255
262
|
return !isSerializable(columnsConfig); // (runs only once, when the component is first created)
|
|
256
263
|
}),
|
|
257
264
|
forceUpdate = useForceUpdate(),
|
|
265
|
+
isAddingRaw = useRef(),
|
|
266
|
+
measurementPhaseRaw = useRef(PHASES__INITIAL),
|
|
267
|
+
measuredRowHeightRaw = useRef(null),
|
|
258
268
|
containerRef = useRef(),
|
|
259
269
|
gridRef = useRef(),
|
|
260
270
|
gridContainerRef = useRef(),
|
|
261
|
-
isAddingRef = useRef(),
|
|
262
271
|
expandedRowsRef = useRef({}),
|
|
263
272
|
cachedDragElements = useRef(),
|
|
264
273
|
dragSelectionRef = useRef([]),
|
|
265
274
|
previousSelectorId = useRef(),
|
|
275
|
+
headerRowRef = useRef(null),
|
|
276
|
+
topToolbarRef = useRef(null),
|
|
277
|
+
measuredRowsRef = useRef([]),
|
|
278
|
+
footerToolbarRef = useRef(null),
|
|
279
|
+
rowRefs = useRef([]),
|
|
266
280
|
[isInited, setIsInited] = useState(false),
|
|
267
281
|
[isReady, setIsReady] = useState(false),
|
|
268
282
|
[isLoading, setIsLoading] = useState(false),
|
|
269
283
|
[localColumnsConfig, setLocalColumnsConfigRaw] = useState([]),
|
|
270
284
|
[isReorderMode, setIsReorderMode] = useState(false),
|
|
271
285
|
showRowHandle = showSelectHandle || areRowsDragSource || (canRowsReorder && isReorderMode),
|
|
286
|
+
[lastMeasuredContainerHeight, setLastMeasuredContainerHeight] = useState(0),
|
|
287
|
+
getMeasurementPhase = () => {
|
|
288
|
+
return measurementPhaseRaw.current;
|
|
289
|
+
},
|
|
290
|
+
setMeasurementPhase = (phase) => {
|
|
291
|
+
measurementPhaseRaw.current = phase;
|
|
292
|
+
forceUpdate();
|
|
293
|
+
},
|
|
294
|
+
getMeasuredRowHeight = () => {
|
|
295
|
+
return measuredRowHeightRaw.current;
|
|
296
|
+
},
|
|
297
|
+
setMeasuredRowHeight = (height) => {
|
|
298
|
+
measuredRowHeightRaw.current = height;
|
|
299
|
+
forceUpdate();
|
|
300
|
+
},
|
|
272
301
|
getIsExpanded = (index) => {
|
|
273
302
|
return !!expandedRowsRef.current[index];
|
|
274
303
|
},
|
|
@@ -639,14 +668,20 @@ function GridComponent(props) {
|
|
|
639
668
|
|
|
640
669
|
}
|
|
641
670
|
|
|
642
|
-
//
|
|
671
|
+
// assign ref for row height measurement during measurement phase
|
|
643
672
|
let rowRef = null;
|
|
644
|
-
if (autoAdjustPageSizeToHeight &&
|
|
645
|
-
!isHeaderRow && index >= 1
|
|
673
|
+
if (autoAdjustPageSizeToHeight && getMeasurementPhase() === PHASES__MEASURING &&
|
|
674
|
+
!isHeaderRow && index >= 1) { // Sample all data rows (index 1+)
|
|
646
675
|
const refIndex = index - 1; // Convert to 0-based index
|
|
647
|
-
|
|
648
|
-
if
|
|
649
|
-
|
|
676
|
+
|
|
677
|
+
// Create ref if it doesn't exist
|
|
678
|
+
if (!rowRefs.current[refIndex]) {
|
|
679
|
+
rowRefs.current[refIndex] = createRef();
|
|
680
|
+
}
|
|
681
|
+
rowRef = rowRefs.current[refIndex];
|
|
682
|
+
|
|
683
|
+
if (rowRef && !measuredRowsRef.current.includes(rowRef)) {
|
|
684
|
+
measuredRowsRef.current.push(rowRef);
|
|
650
685
|
}
|
|
651
686
|
}
|
|
652
687
|
|
|
@@ -661,6 +696,7 @@ function GridComponent(props) {
|
|
|
661
696
|
isRowHoverable={isRowHoverable}
|
|
662
697
|
isSelected={isSelected}
|
|
663
698
|
isHovered={hovered}
|
|
699
|
+
areCellsScrollable={areCellsScrollable}
|
|
664
700
|
showHovers={showHovers}
|
|
665
701
|
showRowHandle={showRowHandle}
|
|
666
702
|
rowCanSelect={rowCanSelect}
|
|
@@ -858,25 +894,17 @@ function GridComponent(props) {
|
|
|
858
894
|
marker.remove();
|
|
859
895
|
cachedDragElements.current = null;
|
|
860
896
|
},
|
|
861
|
-
// Refs for measuring actual row heights
|
|
862
|
-
headerRowRef = useRef(null),
|
|
863
|
-
paginationToolbarRef = useRef(null),
|
|
864
|
-
sampleRowsRef = useRef([]),
|
|
865
|
-
|
|
866
|
-
// Pre-create refs for first 5 rows for measurement
|
|
867
|
-
rowRefs = [useRef(null), useRef(null), useRef(null), useRef(null), useRef(null)],
|
|
868
|
-
|
|
869
|
-
// State for tracking measurement phases
|
|
870
|
-
[measurementPhase, setMeasurementPhase] = useState(PHASES_INITIAL), //
|
|
871
|
-
[lastMeasuredContainerHeight, setLastMeasuredContainerHeight] = useState(0),
|
|
872
|
-
[measuredRowHeight, setMeasuredRowHeight] = useState(null),
|
|
873
897
|
calculatePageSize = (containerHeight, useActualMeasurements = false) => {
|
|
898
|
+
if (DEBUG) {
|
|
899
|
+
console.log(`${getMeasurementPhase()}, calculatePageSize A containerHeight=${containerHeight}, useActualMeasurements=${useActualMeasurements}, measuredRowHeight=${getMeasuredRowHeight()}`);
|
|
900
|
+
}
|
|
874
901
|
// Phase 1: Initial calculation using estimated heights
|
|
875
|
-
if (!useActualMeasurements ||
|
|
902
|
+
if (!useActualMeasurements || getMeasurementPhase() === PHASES__INITIAL) {
|
|
876
903
|
const
|
|
877
|
-
|
|
904
|
+
headerRowHeight = showHeaders ? 50 : 0,
|
|
905
|
+
topToolbarHeight = topToolbar ? 50 : 0, // Estimate top toolbar height
|
|
878
906
|
footerHeight = !disablePagination ? 50 : 0,
|
|
879
|
-
availableHeight = containerHeight -
|
|
907
|
+
availableHeight = containerHeight - topToolbarHeight - headerRowHeight - footerHeight,
|
|
880
908
|
maxClassNormal = styles.GRID_ROW_MAX_HEIGHT_NORMAL, // e.g. max-h-[40px]
|
|
881
909
|
rowNormalHeight = parseInt(maxClassNormal.match(/\d+/)[0]);
|
|
882
910
|
|
|
@@ -886,111 +914,248 @@ function GridComponent(props) {
|
|
|
886
914
|
if (pageSize < 1) {
|
|
887
915
|
pageSize = 1;
|
|
888
916
|
}
|
|
917
|
+
if (DEBUG) {
|
|
918
|
+
console.log(`${getMeasurementPhase()}, calculatePageSize B using ESTIMATED heights, pageSize=${pageSize}`);
|
|
919
|
+
}
|
|
889
920
|
return pageSize;
|
|
890
921
|
}
|
|
891
922
|
|
|
892
923
|
// Phase 3: Optimized calculation using actual measurements
|
|
893
|
-
if (useActualMeasurements &&
|
|
894
|
-
let
|
|
895
|
-
|
|
896
|
-
|
|
924
|
+
if (useActualMeasurements && getMeasurementPhase() === PHASES__OPTIMIZED && getMeasuredRowHeight()) {
|
|
925
|
+
let actualTopToolbarHeight = 0,
|
|
926
|
+
actualHeaderHeight = 0,
|
|
927
|
+
actualFooterHeight = 0,
|
|
928
|
+
actualRowHeight = getMeasuredRowHeight();
|
|
897
929
|
|
|
898
|
-
|
|
930
|
+
if (topToolbar && topToolbarRef.current) {
|
|
931
|
+
actualTopToolbarHeight = topToolbarRef.current.offsetHeight || topToolbarRef.current.clientHeight || 50;
|
|
932
|
+
}
|
|
899
933
|
if (showHeaders && headerRowRef.current) {
|
|
900
934
|
actualHeaderHeight = headerRowRef.current.offsetHeight || headerRowRef.current.clientHeight || 50;
|
|
901
935
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
if (!disablePagination && paginationToolbarRef.current) {
|
|
905
|
-
actualFooterHeight = paginationToolbarRef.current.offsetHeight || paginationToolbarRef.current.clientHeight || 50;
|
|
936
|
+
if (!disablePagination && footerToolbarRef.current) {
|
|
937
|
+
actualFooterHeight = footerToolbarRef.current.offsetHeight || footerToolbarRef.current.clientHeight || 50;
|
|
906
938
|
}
|
|
907
939
|
|
|
908
|
-
const availableHeight = containerHeight - actualHeaderHeight - actualFooterHeight;
|
|
940
|
+
const availableHeight = containerHeight - actualTopToolbarHeight - actualHeaderHeight - actualFooterHeight;
|
|
909
941
|
let pageSize = Math.floor(availableHeight / actualRowHeight);
|
|
910
942
|
|
|
911
943
|
if (pageSize < 1) {
|
|
912
944
|
pageSize = 1;
|
|
913
945
|
}
|
|
946
|
+
if (DEBUG) {
|
|
947
|
+
console.log(`${getMeasurementPhase()}, calculatePageSize C using ACTUAL heights, pageSize=${pageSize}`);
|
|
948
|
+
}
|
|
914
949
|
return pageSize;
|
|
915
950
|
}
|
|
916
951
|
|
|
917
952
|
// Fallback to Phase 1 logic
|
|
953
|
+
if (DEBUG) {
|
|
954
|
+
console.log(`${getMeasurementPhase()}, calculatePageSize D fallback to ESTIMATED heights by calling calculatePageSize(${containerHeight}, false)`);
|
|
955
|
+
}
|
|
918
956
|
return calculatePageSize(containerHeight, false);
|
|
919
957
|
},
|
|
920
958
|
measureActualRowHeights = () => {
|
|
921
|
-
if (
|
|
922
|
-
return;
|
|
959
|
+
if (!gridContainerRef.current) {
|
|
960
|
+
return null;
|
|
923
961
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
962
|
+
if (DEBUG) {
|
|
963
|
+
console.log(`${getMeasurementPhase()}, measureActualRowHeights A`);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
const measuredRows = measuredRowsRef.current.filter(ref => ref && ref.current);
|
|
967
|
+
if (measuredRows.length === 0) {
|
|
968
|
+
if (DEBUG) {
|
|
969
|
+
console.log(`${getMeasurementPhase()}, measureActualRowHeights B no rows to measure`);
|
|
970
|
+
}
|
|
971
|
+
return null;
|
|
929
972
|
}
|
|
930
973
|
|
|
931
974
|
let totalHeight = 0;
|
|
932
975
|
let measuredCount = 0;
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
if (
|
|
938
|
-
|
|
939
|
-
|
|
976
|
+
|
|
977
|
+
if (CURRENT_MODE === UI_MODE_WEB) {
|
|
978
|
+
// Web: Use DOM measurement APIs
|
|
979
|
+
_.each(measuredRows, (rowRef) => {
|
|
980
|
+
if (rowRef.current) {
|
|
981
|
+
const height = rowRef.current.offsetHeight || rowRef.current.clientHeight;
|
|
982
|
+
if (height > 0) {
|
|
983
|
+
totalHeight += height;
|
|
984
|
+
measuredCount++;
|
|
985
|
+
}
|
|
940
986
|
}
|
|
941
|
-
}
|
|
942
|
-
})
|
|
987
|
+
});
|
|
988
|
+
} else if (CURRENT_MODE === UI_MODE_NATIVE) {
|
|
989
|
+
// React Native: Use measure API with promises
|
|
990
|
+
return new Promise((resolve) => {
|
|
991
|
+
let completed = 0;
|
|
992
|
+
const measurements = [];
|
|
993
|
+
|
|
994
|
+
_.each(measuredRows, (rowRef) => {
|
|
995
|
+
if (rowRef.current && rowRef.current.measure) {
|
|
996
|
+
rowRef.current.measure((x, y, width, height) => {
|
|
997
|
+
if (height > 0) {
|
|
998
|
+
measurements.push(height);
|
|
999
|
+
}
|
|
1000
|
+
completed++;
|
|
1001
|
+
|
|
1002
|
+
if (completed === measuredRows.length) {
|
|
1003
|
+
if (measurements.length > 0) {
|
|
1004
|
+
const averageHeight = measurements.reduce((sum, h) => sum + h, 0) / measurements.length;
|
|
1005
|
+
if (DEBUG) {
|
|
1006
|
+
console.log(`[Grid] Measured actual row height: ${averageHeight}px from ${measurements.length} measured rows`);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// Clear measured refs for next measurement cycle
|
|
1010
|
+
measuredRowsRef.current = [];
|
|
1011
|
+
|
|
1012
|
+
resolve(averageHeight);
|
|
1013
|
+
} else {
|
|
1014
|
+
resolve(null);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
} else {
|
|
1019
|
+
completed++;
|
|
1020
|
+
if (completed === measuredRows.length && measurements.length === 0) {
|
|
1021
|
+
resolve(null);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
// Timeout fallback
|
|
1027
|
+
setTimeout(() => {
|
|
1028
|
+
if (measurements.length > 0) {
|
|
1029
|
+
const averageHeight = measurements.reduce((sum, h) => sum + h, 0) / measurements.length;
|
|
1030
|
+
if (DEBUG) {
|
|
1031
|
+
log(`[Grid] Measured actual row height (timeout): ${averageHeight}px from ${measurements.length} measured rows`);
|
|
1032
|
+
}
|
|
1033
|
+
measuredRowsRef.current = [];
|
|
1034
|
+
resolve(averageHeight);
|
|
1035
|
+
} else {
|
|
1036
|
+
resolve(null);
|
|
1037
|
+
}
|
|
1038
|
+
}, 200);
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
943
1041
|
|
|
944
1042
|
if (measuredCount > 0) {
|
|
945
1043
|
const averageHeight = totalHeight / measuredCount;
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1044
|
+
|
|
1045
|
+
if (DEBUG) {
|
|
1046
|
+
console.log(`${getMeasurementPhase()}, measureActualRowHeights C averageHeight=${averageHeight}, measuredCount=${measuredCount}`);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
// Clear measured refs for next measurement cycle
|
|
1050
|
+
measuredRowsRef.current = [];
|
|
949
1051
|
|
|
950
|
-
|
|
951
|
-
|
|
1052
|
+
return averageHeight;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
if (DEBUG) {
|
|
1056
|
+
console.log(`${getMeasurementPhase()}, measureActualRowHeights D measuredCount=0`);
|
|
1057
|
+
}
|
|
1058
|
+
return null;
|
|
1059
|
+
},
|
|
1060
|
+
applyMeasuredRowHeight = (averageHeight) => {
|
|
1061
|
+
if (DEBUG) {
|
|
1062
|
+
console.log(`${getMeasurementPhase()}, applyMeasuredRowHeight A averageHeight=${averageHeight}, lastMeasuredContainerHeight=${lastMeasuredContainerHeight}, setMeasurementPhase(${PHASES__OPTIMIZED})`);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// Always transition to optimized phase, even if measurement failed
|
|
1066
|
+
setMeasurementPhase(PHASES__OPTIMIZED);
|
|
1067
|
+
|
|
1068
|
+
if (averageHeight) {
|
|
1069
|
+
setMeasuredRowHeight(averageHeight);
|
|
952
1070
|
|
|
953
1071
|
// Recalculate pageSize with actual measurements
|
|
954
1072
|
if (lastMeasuredContainerHeight > 0) {
|
|
1073
|
+
if (DEBUG) {
|
|
1074
|
+
console.log(`${getMeasurementPhase()}, applyMeasuredRowHeight B call calculatePageSize(${lastMeasuredContainerHeight}, true)`);
|
|
1075
|
+
}
|
|
955
1076
|
const newPageSize = calculatePageSize(lastMeasuredContainerHeight, true);
|
|
956
|
-
console.log(`[Grid] Optimized pageSize: ${newPageSize} (was ${Repository.pageSize})`);
|
|
957
1077
|
if (newPageSize !== Repository.pageSize) {
|
|
1078
|
+
if (DEBUG) {
|
|
1079
|
+
console.log(`${getMeasurementPhase()}, applyMeasuredRowHeight B Repository.setPageSize(${newPageSize})`);
|
|
1080
|
+
}
|
|
958
1081
|
Repository.setPageSize(newPageSize);
|
|
959
1082
|
}
|
|
960
1083
|
}
|
|
1084
|
+
} else {
|
|
1085
|
+
if (DEBUG) {
|
|
1086
|
+
console.log(`[Grid] Row height measurement failed or unavailable - using estimated pageSize`);
|
|
1087
|
+
}
|
|
1088
|
+
// Keep the current estimated pageSize, just hide the loading overlay
|
|
961
1089
|
}
|
|
962
1090
|
},
|
|
963
1091
|
adjustPageSizeToHeight = (e) => {
|
|
964
|
-
if (CURRENT_MODE !== UI_MODE_WEB) { // TODO: Remove this conditional, and don't even do the double render for RN
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
1092
|
if (!Repository || Repository.isDestroyed) { // This method gets delayed, so it's possible for Repository to have been destroyed. Check for this
|
|
968
1093
|
return;
|
|
969
1094
|
}
|
|
1095
|
+
if (DEBUG) {
|
|
1096
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight A`);
|
|
1097
|
+
}
|
|
970
1098
|
|
|
971
1099
|
let doAdjustment = autoAdjustPageSizeToHeight;
|
|
972
1100
|
if (!_.isNil(UiGlobals.autoAdjustPageSizeToHeight) && !UiGlobals.autoAdjustPageSizeToHeight) {
|
|
973
1101
|
// allow global override to prevent this auto adjustment
|
|
974
1102
|
doAdjustment = false;
|
|
975
1103
|
}
|
|
976
|
-
if (
|
|
977
|
-
|
|
978
|
-
|
|
1104
|
+
if (DEBUG) {
|
|
1105
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight A2 doAdjustment=${doAdjustment}, autoAdjustPageSizeToHeight=${autoAdjustPageSizeToHeight}, UiGlobals.autoAdjustPageSizeToHeight=${UiGlobals.autoAdjustPageSizeToHeight}`);
|
|
1106
|
+
}
|
|
1107
|
+
const containerHeight = e.nativeEvent.layout.height;
|
|
1108
|
+
if (DEBUG) {
|
|
1109
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight A3 containerHeight=${containerHeight}`);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Only proceed if height changed significantly
|
|
1113
|
+
const
|
|
1114
|
+
heightChanged = Math.abs(containerHeight - lastMeasuredContainerHeight) > 5, // 5px tolerance
|
|
1115
|
+
isFirstMeasurement = lastMeasuredContainerHeight === 0;
|
|
1116
|
+
if (containerHeight > 0 && (isFirstMeasurement || heightChanged)) {
|
|
1117
|
+
if (editorType === EDITOR_TYPE__SIDE && getIsEditorShown()) {
|
|
1118
|
+
// When side editor is shown, skip adjustment to avoid layout thrashing
|
|
1119
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight A4 height changed significantly, but side editor is shown, skipping remeasurement`);
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
if (DEBUG) {
|
|
1123
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight A4 height changed significantly, proceeding with remeasurement`);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
if (doAdjustment) {
|
|
979
1127
|
setLastMeasuredContainerHeight(containerHeight);
|
|
980
1128
|
|
|
981
1129
|
// Phase 1: Initial calculation with buffer
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1130
|
+
if (DEBUG) {
|
|
1131
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight B call calculatePageSize(${containerHeight}, false)`);
|
|
1132
|
+
}
|
|
1133
|
+
const
|
|
1134
|
+
useActualMeasurements = (getMeasurementPhase() === PHASES__OPTIMIZED && getMeasuredRowHeight()),
|
|
1135
|
+
pageSize = calculatePageSize(containerHeight, useActualMeasurements);
|
|
1136
|
+
if (DEBUG) {
|
|
1137
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight C containerHeight=${containerHeight}, pageSize=${pageSize}, currentPageSize=${Repository.pageSize}`);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
985
1140
|
if (pageSize !== Repository.pageSize) {
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
// Trigger Phase 2: Enable measurement mode after render
|
|
989
|
-
if (measurementPhase === PHASES_INITIAL) {
|
|
990
|
-
setMeasurementPhase(PHASES_MEASURING);
|
|
1141
|
+
if (DEBUG) {
|
|
1142
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight D Repository.setPageSize(${pageSize})`);
|
|
991
1143
|
}
|
|
1144
|
+
Repository.setPageSize(pageSize);
|
|
992
1145
|
}
|
|
993
1146
|
}
|
|
1147
|
+
|
|
1148
|
+
// Trigger Phase 2: Enable measurement mode after render
|
|
1149
|
+
if (getMeasurementPhase() === PHASES__INITIAL) {
|
|
1150
|
+
if (DEBUG) {
|
|
1151
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight E setMeasurementPhase(${PHASES__MEASURING})`);
|
|
1152
|
+
}
|
|
1153
|
+
setMeasurementPhase(PHASES__MEASURING);
|
|
1154
|
+
}
|
|
1155
|
+
} else {
|
|
1156
|
+
if (DEBUG) {
|
|
1157
|
+
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight A5 height unchanged, skipping remeasurement`);
|
|
1158
|
+
}
|
|
994
1159
|
}
|
|
995
1160
|
},
|
|
996
1161
|
debouncedAdjustPageSizeToHeight = useCallback(_.debounce(adjustPageSizeToHeight, 200), []),
|
|
@@ -1130,22 +1295,24 @@ function GridComponent(props) {
|
|
|
1130
1295
|
|
|
1131
1296
|
useEffect(() => {
|
|
1132
1297
|
if (!isInited) {
|
|
1133
|
-
// first call
|
|
1298
|
+
// first call, Repository.pauseEvents, while we render placeholder so we get container dimensions
|
|
1134
1299
|
if (Repository) {
|
|
1135
1300
|
if (Repository.isRemote) {
|
|
1136
1301
|
Repository.isAutoLoad = false;
|
|
1137
1302
|
}
|
|
1303
|
+
if (DEBUG) {
|
|
1304
|
+
console.log(`${getMeasurementPhase()}, useEffect 1 - first call, Repository.pauseEvents, while we render placeholder to get container dimensions`);
|
|
1305
|
+
}
|
|
1138
1306
|
Repository.pauseEvents();
|
|
1139
1307
|
}
|
|
1140
|
-
if (onRender) {
|
|
1141
|
-
onRender(self)
|
|
1142
|
-
}
|
|
1143
1308
|
return () => {};
|
|
1144
1309
|
}
|
|
1145
1310
|
|
|
1146
1311
|
(async () => {
|
|
1147
|
-
|
|
1148
|
-
|
|
1312
|
+
if (DEBUG) {
|
|
1313
|
+
console.log(`${getMeasurementPhase()}, useEffect 1 - second call, do other necessary column setup`);
|
|
1314
|
+
}
|
|
1315
|
+
// second call, do other necessary column setup
|
|
1149
1316
|
let columnsConfigVariable = columnsConfig,
|
|
1150
1317
|
localColumnsConfig = [],
|
|
1151
1318
|
savedLocalColumnsConfig,
|
|
@@ -1231,6 +1398,9 @@ function GridComponent(props) {
|
|
|
1231
1398
|
|
|
1232
1399
|
setLocalColumnsConfig(localColumnsConfig);
|
|
1233
1400
|
|
|
1401
|
+
if (onRender) {
|
|
1402
|
+
onRender(self)
|
|
1403
|
+
}
|
|
1234
1404
|
setIsReady(true);
|
|
1235
1405
|
})();
|
|
1236
1406
|
|
|
@@ -1243,23 +1413,12 @@ function GridComponent(props) {
|
|
|
1243
1413
|
setTrue = () => setIsLoading(true),
|
|
1244
1414
|
setFalse = () => setIsLoading(false),
|
|
1245
1415
|
onChangeFilters = () => {
|
|
1416
|
+
if (DEBUG) {
|
|
1417
|
+
console.log('onChangeFilters, reload and re-measure');
|
|
1418
|
+
}
|
|
1246
1419
|
if (!Repository.isAutoLoad) {
|
|
1247
1420
|
Repository.reload();
|
|
1248
1421
|
}
|
|
1249
|
-
|
|
1250
|
-
// Reset measurement phase and recalculate pageSize if auto-adjust is enabled
|
|
1251
|
-
if (autoAdjustPageSizeToHeight && lastMeasuredContainerHeight > 0) {
|
|
1252
|
-
console.log(`[Grid] Filters changed - resetting pageSize measurement`);
|
|
1253
|
-
setMeasurementPhase(PHASES_INITIAL);
|
|
1254
|
-
setMeasuredRowHeight(null);
|
|
1255
|
-
sampleRowsRef.current = [];
|
|
1256
|
-
|
|
1257
|
-
// Recalculate pageSize with fresh measurements
|
|
1258
|
-
const pageSize = calculatePageSize(lastMeasuredContainerHeight, false);
|
|
1259
|
-
if (pageSize !== Repository.pageSize) {
|
|
1260
|
-
Repository.setPageSize(pageSize);
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
1422
|
},
|
|
1264
1423
|
onChangeSorters = () => {
|
|
1265
1424
|
if (!Repository.isAutoLoad) {
|
|
@@ -1283,9 +1442,16 @@ function GridComponent(props) {
|
|
|
1283
1442
|
Repository.on('changePage', onChangePage);
|
|
1284
1443
|
|
|
1285
1444
|
applySelectorSelected();
|
|
1445
|
+
|
|
1446
|
+
if (DEBUG) {
|
|
1447
|
+
console.log(`${getMeasurementPhase()}, useEffect 1 - Repository.resumeEvents()`);
|
|
1448
|
+
}
|
|
1286
1449
|
Repository.resumeEvents();
|
|
1287
1450
|
|
|
1288
1451
|
if (((Repository.isRemote && !Repository.isLoaded && !Repository.isLoading) || forceLoadOnRender) && !disableLoadOnRender) { // default remote repositories to load on render, optionally force or disable load on render
|
|
1452
|
+
if (DEBUG) {
|
|
1453
|
+
console.log(`${getMeasurementPhase()}, useEffect 1 - Repository.load()`);
|
|
1454
|
+
}
|
|
1289
1455
|
Repository.load();
|
|
1290
1456
|
}
|
|
1291
1457
|
|
|
@@ -1307,27 +1473,47 @@ function GridComponent(props) {
|
|
|
1307
1473
|
return () => {};
|
|
1308
1474
|
}
|
|
1309
1475
|
|
|
1476
|
+
if (DEBUG) {
|
|
1477
|
+
console.log(`useEffect 2 - applySelectorSelected()`);
|
|
1478
|
+
}
|
|
1310
1479
|
applySelectorSelected();
|
|
1311
1480
|
|
|
1312
1481
|
}, [selectorId, selectorSelected]);
|
|
1313
1482
|
|
|
1314
1483
|
// Effect to trigger row height measurement after render
|
|
1315
1484
|
useEffect(() => {
|
|
1316
|
-
if (
|
|
1317
|
-
// Small delay to ensure
|
|
1318
|
-
const timer = setTimeout(() => {
|
|
1319
|
-
|
|
1320
|
-
|
|
1485
|
+
if (getMeasurementPhase() === PHASES__MEASURING) {
|
|
1486
|
+
// Small delay to ensure elements are fully rendered
|
|
1487
|
+
const timer = setTimeout(async () => {
|
|
1488
|
+
try {
|
|
1489
|
+
if (DEBUG) {
|
|
1490
|
+
console.log(`${getMeasurementPhase()}, useEffect 3 call measureActualRowHeights()`);
|
|
1491
|
+
}
|
|
1492
|
+
const averageHeight = await measureActualRowHeights();
|
|
1493
|
+
if (DEBUG) {
|
|
1494
|
+
console.log(`${getMeasurementPhase()}, useEffect 3 averageHeight=${averageHeight}, call applyMeasuredRowHeight()`);
|
|
1495
|
+
}
|
|
1496
|
+
applyMeasuredRowHeight(averageHeight);
|
|
1497
|
+
} catch (error) {
|
|
1498
|
+
if (DEBUG) {
|
|
1499
|
+
console.warn('useEffect 3 - error', error);
|
|
1500
|
+
}
|
|
1501
|
+
// Fallback: use default height estimation
|
|
1502
|
+
applyMeasuredRowHeight(null);
|
|
1503
|
+
}
|
|
1504
|
+
}, 1000);
|
|
1321
1505
|
return () => clearTimeout(timer);
|
|
1322
1506
|
}
|
|
1323
|
-
}, [
|
|
1507
|
+
}, [getMeasurementPhase(), data]);
|
|
1324
1508
|
|
|
1325
|
-
// Effect to reset measurement state when autoAdjustPageSizeToHeight changes
|
|
1326
1509
|
useEffect(() => {
|
|
1327
|
-
if (autoAdjustPageSizeToHeight) {
|
|
1328
|
-
|
|
1510
|
+
if (autoAdjustPageSizeToHeight && getMeasurementPhase() !== PHASES__INITIAL) {
|
|
1511
|
+
if (DEBUG) {
|
|
1512
|
+
console.log(`${getMeasurementPhase()}, useEffect 4 setMeasurementPhase(${PHASES__INITIAL})`);
|
|
1513
|
+
}
|
|
1514
|
+
setMeasurementPhase(PHASES__INITIAL);
|
|
1329
1515
|
setMeasuredRowHeight(null);
|
|
1330
|
-
|
|
1516
|
+
measuredRowsRef.current = [];
|
|
1331
1517
|
}
|
|
1332
1518
|
}, [autoAdjustPageSizeToHeight]);
|
|
1333
1519
|
|
|
@@ -1340,7 +1526,7 @@ function GridComponent(props) {
|
|
|
1340
1526
|
self.gridRef = gridRef;
|
|
1341
1527
|
}
|
|
1342
1528
|
|
|
1343
|
-
|
|
1529
|
+
isAddingRaw.current = isAdding;
|
|
1344
1530
|
|
|
1345
1531
|
const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [Repository?.hash, additionalToolbarButtons, isReorderMode]);
|
|
1346
1532
|
|
|
@@ -1348,7 +1534,13 @@ function GridComponent(props) {
|
|
|
1348
1534
|
// first time through, render a placeholder so we can get container dimensions
|
|
1349
1535
|
return <VStackNative
|
|
1350
1536
|
onLayout={(e) => {
|
|
1537
|
+
if (DEBUG) {
|
|
1538
|
+
console.log(`${getMeasurementPhase()}, placeholder onLayout, call adjustPageSizeToHeight()`);
|
|
1539
|
+
}
|
|
1351
1540
|
adjustPageSizeToHeight(e);
|
|
1541
|
+
if (DEBUG) {
|
|
1542
|
+
console.log(`${getMeasurementPhase()}, placeholder onLayout, call setIsInited(true)`);
|
|
1543
|
+
}
|
|
1352
1544
|
setIsInited(true);
|
|
1353
1545
|
}}
|
|
1354
1546
|
className="w-full flex-1"
|
|
@@ -1383,7 +1575,7 @@ function GridComponent(props) {
|
|
|
1383
1575
|
showMoreOnly = true;
|
|
1384
1576
|
}
|
|
1385
1577
|
listFooterComponent = <PaginationToolbar
|
|
1386
|
-
ref={
|
|
1578
|
+
ref={footerToolbarRef}
|
|
1387
1579
|
Repository={Repository}
|
|
1388
1580
|
self={self}
|
|
1389
1581
|
toolbarItems={footerToolbarItemComponents}
|
|
@@ -1392,7 +1584,9 @@ function GridComponent(props) {
|
|
|
1392
1584
|
{..._paginationToolbarProps}
|
|
1393
1585
|
/>;
|
|
1394
1586
|
} else if (footerToolbarItemComponents.length) {
|
|
1395
|
-
listFooterComponent = <Toolbar
|
|
1587
|
+
listFooterComponent = <Toolbar
|
|
1588
|
+
ref={footerToolbarRef}
|
|
1589
|
+
>
|
|
1396
1590
|
<ReloadButton Repository={Repository} self={self} />
|
|
1397
1591
|
{footerToolbarItemComponents}
|
|
1398
1592
|
</Toolbar>;
|
|
@@ -1490,7 +1684,10 @@ function GridComponent(props) {
|
|
|
1490
1684
|
className={className}
|
|
1491
1685
|
style={style}
|
|
1492
1686
|
>
|
|
1493
|
-
{topToolbar
|
|
1687
|
+
{topToolbar &&
|
|
1688
|
+
<VStack ref={topToolbarRef}>
|
|
1689
|
+
{topToolbar}
|
|
1690
|
+
</VStack>}
|
|
1494
1691
|
|
|
1495
1692
|
<VStack
|
|
1496
1693
|
ref={gridContainerRef}
|
|
@@ -1505,10 +1702,19 @@ function GridComponent(props) {
|
|
|
1505
1702
|
// 'h-full',
|
|
1506
1703
|
'flex-1',
|
|
1507
1704
|
'min-h-[40px]',
|
|
1705
|
+
'relative', // Enable positioning for overlay
|
|
1508
1706
|
gridContainerBorderClassName,
|
|
1509
1707
|
)}
|
|
1510
1708
|
>
|
|
1511
1709
|
{grid}
|
|
1710
|
+
{/* Loading overlay during measurement phases to prevent visual flashing */}
|
|
1711
|
+
{autoAdjustPageSizeToHeight &&
|
|
1712
|
+
(getMeasurementPhase() === PHASES__INITIAL || getMeasurementPhase() === PHASES__MEASURING) &&
|
|
1713
|
+
entities?.length > 0 && (
|
|
1714
|
+
<VStack className="absolute inset-0 z-10 bg-white">
|
|
1715
|
+
<Loading isScreen={true} />
|
|
1716
|
+
</VStack>
|
|
1717
|
+
)}
|
|
1512
1718
|
</VStack>
|
|
1513
1719
|
|
|
1514
1720
|
{listFooterComponent}
|