@noraent/nora-datagrid 0.0.43 → 0.0.45
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/lib/cjs/buildPackage.json +2 -1
- package/lib/cjs/common/constants/utils.d.ts +15 -0
- package/lib/cjs/common/constants/utils.js +40 -0
- package/lib/cjs/components/TwoDimensionalVirtualizedList.js +54 -13
- package/lib/cjs/components/virtualized/_styled/index.js +1 -1
- package/lib/esm/buildPackage.json +2 -1
- package/lib/esm/common/constants/utils.d.ts +15 -0
- package/lib/esm/common/constants/utils.js +40 -0
- package/lib/esm/components/TwoDimensionalVirtualizedList.js +54 -13
- package/lib/esm/components/virtualized/_styled/index.js +1 -1
- package/package.json +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noraent/nora-datagrid",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.45",
|
|
4
4
|
"module": "./lib/esm/index.js",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"@emotion/react": "^11.13.3",
|
|
29
29
|
"@emotion/styled": "^11.13.0",
|
|
30
30
|
"@noraent/nora-datagrid": "file:",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
31
32
|
"react": "^18.3.1",
|
|
32
33
|
"react-dom": "^18.3.1",
|
|
33
34
|
"rimraf": "^6.0.1",
|
|
@@ -6,4 +6,19 @@ import React from "react";
|
|
|
6
6
|
* @param deps
|
|
7
7
|
*/
|
|
8
8
|
declare function useUpdateEffect(callback: React.EffectCallback, deps: React.DependencyList): void;
|
|
9
|
+
/**
|
|
10
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
11
|
+
* 깊은 비교를 통해 종속성 배열의 변경을 감지하는 커스텀 훅
|
|
12
|
+
* @param callback 실행할 효과 함수
|
|
13
|
+
* @param dependencies 종속성 배열
|
|
14
|
+
*/
|
|
15
|
+
export declare function useDeepCompareEffect<T>(callback: () => void | (() => void), dependencies: T[]): void;
|
|
16
|
+
/**
|
|
17
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
18
|
+
* 깊은 비교와 팩토리 함수를 사용하는 메모이제이션 훅
|
|
19
|
+
* @param factory 계산을 수행하는 팩토리 함수
|
|
20
|
+
* @param deps 의존성 배열
|
|
21
|
+
* @returns 메모이제이션된 계산 결과
|
|
22
|
+
*/
|
|
23
|
+
export declare function useDeepCompareMemo<T>(factory: () => T, deps: any[]): T;
|
|
9
24
|
export default useUpdateEffect;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import _ from "lodash";
|
|
2
3
|
/**
|
|
3
4
|
* 첫 마운트시 실행 되지 않습니다.
|
|
4
5
|
* 업데이트시 실행하고 싶다면 사용해주세요.
|
|
@@ -17,4 +18,43 @@ function useUpdateEffect(callback, deps) {
|
|
|
17
18
|
}
|
|
18
19
|
}, deps);
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
23
|
+
* 깊은 비교를 통해 종속성 배열의 변경을 감지하는 커스텀 훅
|
|
24
|
+
* @param callback 실행할 효과 함수
|
|
25
|
+
* @param dependencies 종속성 배열
|
|
26
|
+
*/
|
|
27
|
+
export function useDeepCompareEffect(callback, dependencies) {
|
|
28
|
+
const previousDependenciesRef = React.useRef();
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
const isSame = _.isEqual(previousDependenciesRef.current, dependencies);
|
|
31
|
+
if (!isSame) {
|
|
32
|
+
previousDependenciesRef.current = _.cloneDeep(dependencies);
|
|
33
|
+
return callback();
|
|
34
|
+
}
|
|
35
|
+
}, [callback, JSON.stringify(dependencies)]);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
39
|
+
* 깊은 비교와 팩토리 함수를 사용하는 메모이제이션 훅
|
|
40
|
+
* @param factory 계산을 수행하는 팩토리 함수
|
|
41
|
+
* @param deps 의존성 배열
|
|
42
|
+
* @returns 메모이제이션된 계산 결과
|
|
43
|
+
*/
|
|
44
|
+
export function useDeepCompareMemo(factory, deps) {
|
|
45
|
+
// 의존성 배열을 위한 ref
|
|
46
|
+
const depsRef = React.useRef();
|
|
47
|
+
// 현재 값을 저장하기 위한 ref
|
|
48
|
+
const valueRef = React.useRef();
|
|
49
|
+
// 의존성의 깊은 비교 수행
|
|
50
|
+
const depsChanged = !_.isEqual(depsRef.current, deps);
|
|
51
|
+
// 의존성이 변경되었을 때만 값 재계산
|
|
52
|
+
if (depsChanged || valueRef.current === undefined) {
|
|
53
|
+
valueRef.current = factory();
|
|
54
|
+
depsRef.current = _.cloneDeep(deps);
|
|
55
|
+
}
|
|
56
|
+
// deps 배열의 얕은 비교를 위한 문자열화
|
|
57
|
+
// 이는 React의 렌더링 시스템과 함께 작동하기 위함
|
|
58
|
+
return React.useMemo(() => valueRef.current, [JSON.stringify(deps)]);
|
|
59
|
+
}
|
|
20
60
|
export default useUpdateEffect;
|
|
@@ -12,6 +12,7 @@ import CellMode from "./cell/CellMode";
|
|
|
12
12
|
import ImeComponent from "./ime/IMEComponent";
|
|
13
13
|
import NoDataComponent from "./body/NoDataComponent";
|
|
14
14
|
import { useAddApi } from "../hooks/useGridInitialization";
|
|
15
|
+
import { useDeepCompareMemo } from "../common/constants/utils";
|
|
15
16
|
const initialWindowWidth = 800;
|
|
16
17
|
export const initialWindowHeight = 500;
|
|
17
18
|
const overscanTopRow = 4;
|
|
@@ -76,8 +77,19 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
76
77
|
const { __randomDataSourceKey } = useSelector((store) => ({
|
|
77
78
|
__randomDataSourceKey: store.__randomDataSourceKey,
|
|
78
79
|
}));
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
// useDeepCompareEffect(() => {
|
|
81
|
+
// console.log("변경됨", dataSource);
|
|
82
|
+
// }, [dataSource]);
|
|
83
|
+
// const totalHeight = useMemo(
|
|
84
|
+
// () => dataSource.reduce((sum, item) => sum + item.height!, 0),
|
|
85
|
+
// [
|
|
86
|
+
// // dataSource,
|
|
87
|
+
// __randomDataSourceKey,
|
|
88
|
+
// ]
|
|
89
|
+
// );
|
|
90
|
+
const totalHeight = useDeepCompareMemo(() => dataSource.reduce((sum, item) => sum + item.height, 0), [dataSource]);
|
|
91
|
+
const totalWidth = useDeepCompareMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
|
|
92
|
+
// const totalWidth = useMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
|
|
81
93
|
const binarySearchIndex = useCallback((items, target) => {
|
|
82
94
|
let low = 0;
|
|
83
95
|
let high = items.length - 1;
|
|
@@ -95,14 +107,31 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
95
107
|
}
|
|
96
108
|
return Math.max(0, low - 1);
|
|
97
109
|
}, []);
|
|
98
|
-
const cumulativeHeights = useMemo(() => {
|
|
110
|
+
// const cumulativeHeights = useMemo(() => {
|
|
111
|
+
// const heights = [0];
|
|
112
|
+
// for (let i = 0; i < dataSource.length; i++) {
|
|
113
|
+
// heights.push(heights[i] + dataSource[i].height!);
|
|
114
|
+
// }
|
|
115
|
+
// return heights;
|
|
116
|
+
// }, [
|
|
117
|
+
// // dataSource,
|
|
118
|
+
// __randomDataSourceKey,
|
|
119
|
+
// ]);
|
|
120
|
+
const cumulativeHeights = useDeepCompareMemo(() => {
|
|
99
121
|
const heights = [0];
|
|
100
122
|
for (let i = 0; i < dataSource.length; i++) {
|
|
101
123
|
heights.push(heights[i] + dataSource[i].height);
|
|
102
124
|
}
|
|
103
125
|
return heights;
|
|
104
|
-
}, [dataSource
|
|
105
|
-
const cumulativeWidths = useMemo(() => {
|
|
126
|
+
}, [dataSource]);
|
|
127
|
+
// const cumulativeWidths = useMemo(() => {
|
|
128
|
+
// const widths = [0];
|
|
129
|
+
// for (let i = 0; i < columns.length || 0; i++) {
|
|
130
|
+
// widths.push(widths[i] + Number(columns[i].width));
|
|
131
|
+
// }
|
|
132
|
+
// return widths;
|
|
133
|
+
// }, [columns]);
|
|
134
|
+
const cumulativeWidths = useDeepCompareMemo(() => {
|
|
106
135
|
const widths = [0];
|
|
107
136
|
for (let i = 0; i < columns.length || 0; i++) {
|
|
108
137
|
widths.push(widths[i] + Number(columns[i].width));
|
|
@@ -118,9 +147,16 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
118
147
|
}
|
|
119
148
|
end = Math.min(end + overscanBottomRow, dataSource.length);
|
|
120
149
|
return { start, end };
|
|
121
|
-
}, [
|
|
150
|
+
}, [
|
|
151
|
+
JSON.stringify(dataSource),
|
|
152
|
+
scrollTop,
|
|
153
|
+
cumulativeHeights,
|
|
154
|
+
windowSize.height,
|
|
155
|
+
binarySearchIndex,
|
|
156
|
+
// __randomDataSourceKey,
|
|
157
|
+
]);
|
|
122
158
|
const { start, end } = getItemRange();
|
|
123
|
-
const visibleItems =
|
|
159
|
+
const visibleItems = useDeepCompareMemo(() => {
|
|
124
160
|
const result = [];
|
|
125
161
|
const rowIndex = gridRef.current.getCellFocus()[0];
|
|
126
162
|
// 포함 안되어있으면 추가
|
|
@@ -136,10 +172,15 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
136
172
|
result.push(dataSource[rowIndex - 1]); // fixedIndex가 범위에 포함되지 않으면 첫 번째에 추가
|
|
137
173
|
}
|
|
138
174
|
return result;
|
|
139
|
-
}, [
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
175
|
+
}, [
|
|
176
|
+
// __randomDataSourceKey,
|
|
177
|
+
dataSource,
|
|
178
|
+
start,
|
|
179
|
+
end,
|
|
180
|
+
]);
|
|
181
|
+
const startColumnIndex = useDeepCompareMemo(() => Math.max(0, binarySearchIndex(cumulativeWidths, scrollLeft) - overscanColumn), [cumulativeWidths, scrollLeft, binarySearchIndex, overscanColumn]);
|
|
182
|
+
const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
|
|
183
|
+
const offsetLeft = useDeepCompareMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
|
|
143
184
|
const domRef = React.useRef(null);
|
|
144
185
|
const updateScroll = useCallback((newScrollTop, newScrollLeft) => {
|
|
145
186
|
newScrollTop !== undefined && setScrollTop(newScrollTop);
|
|
@@ -181,7 +222,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
181
222
|
}
|
|
182
223
|
return items.length - 1;
|
|
183
224
|
}, [windowSize.width]);
|
|
184
|
-
const columnEndIndex =
|
|
225
|
+
const columnEndIndex = useDeepCompareMemo(() => binarySearchColumnIndex(cumulativeWidths, startColumnIndex, scrollLeft), [cumulativeWidths, startColumnIndex, scrollLeft, windowSize.width]);
|
|
185
226
|
const isSyncingRef = useRef(false);
|
|
186
227
|
const handleScrollController = useCallback((e) => {
|
|
187
228
|
if (isSyncingRef.current)
|
|
@@ -251,7 +292,7 @@ const VirtualListItem = React.memo(({ item, startColumnIndex, cumulativeWidths,
|
|
|
251
292
|
return { start, end };
|
|
252
293
|
}, [startColumnIndex, cumulativeWidths, windowSize, columnEndIndex]);
|
|
253
294
|
const { start, end } = getItemRange();
|
|
254
|
-
const visibleColumns =
|
|
295
|
+
const visibleColumns = useDeepCompareMemo(() => columns.slice(start, end + 1), [start, end, columns]);
|
|
255
296
|
const cellStyle = useMemo(() => ({ height: `${item.height}px` }), [item.height]);
|
|
256
297
|
return (_jsx(TableRow, { "aria-rowindex": item.__ariaRowindex, style: cellStyle, className: classes.TableClasses.body.row.root, children: visibleColumns.map((column) => (_jsx(VirtualItem, { column: column, row: row, rowIndex: item.__dataRowindex, isFocus: isColIndex === column.__ariaColindex, editStatus: isColIndex === column.__ariaColindex ? editStatus : undefined }, column.__uuid))) }, item.id));
|
|
257
298
|
});
|
|
@@ -14,7 +14,7 @@ export const TableBody = styled("div")(({ lineHeight = defaultProps.height }) =>
|
|
|
14
14
|
},
|
|
15
15
|
}));
|
|
16
16
|
export const TableCell = styled("div")(() => ({
|
|
17
|
-
padding: "
|
|
17
|
+
padding: "1px 10px",
|
|
18
18
|
overflow: "hidden",
|
|
19
19
|
textOverflow: "ellipsis",
|
|
20
20
|
whiteSpace: "nowrap",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noraent/nora-datagrid",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.45",
|
|
4
4
|
"module": "./lib/esm/index.js",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"@emotion/react": "^11.13.3",
|
|
29
29
|
"@emotion/styled": "^11.13.0",
|
|
30
30
|
"@noraent/nora-datagrid": "file:",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
31
32
|
"react": "^18.3.1",
|
|
32
33
|
"react-dom": "^18.3.1",
|
|
33
34
|
"rimraf": "^6.0.1",
|
|
@@ -6,4 +6,19 @@ import React from "react";
|
|
|
6
6
|
* @param deps
|
|
7
7
|
*/
|
|
8
8
|
declare function useUpdateEffect(callback: React.EffectCallback, deps: React.DependencyList): void;
|
|
9
|
+
/**
|
|
10
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
11
|
+
* 깊은 비교를 통해 종속성 배열의 변경을 감지하는 커스텀 훅
|
|
12
|
+
* @param callback 실행할 효과 함수
|
|
13
|
+
* @param dependencies 종속성 배열
|
|
14
|
+
*/
|
|
15
|
+
export declare function useDeepCompareEffect<T>(callback: () => void | (() => void), dependencies: T[]): void;
|
|
16
|
+
/**
|
|
17
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
18
|
+
* 깊은 비교와 팩토리 함수를 사용하는 메모이제이션 훅
|
|
19
|
+
* @param factory 계산을 수행하는 팩토리 함수
|
|
20
|
+
* @param deps 의존성 배열
|
|
21
|
+
* @returns 메모이제이션된 계산 결과
|
|
22
|
+
*/
|
|
23
|
+
export declare function useDeepCompareMemo<T>(factory: () => T, deps: any[]): T;
|
|
9
24
|
export default useUpdateEffect;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import _ from "lodash";
|
|
2
3
|
/**
|
|
3
4
|
* 첫 마운트시 실행 되지 않습니다.
|
|
4
5
|
* 업데이트시 실행하고 싶다면 사용해주세요.
|
|
@@ -17,4 +18,43 @@ function useUpdateEffect(callback, deps) {
|
|
|
17
18
|
}
|
|
18
19
|
}, deps);
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
23
|
+
* 깊은 비교를 통해 종속성 배열의 변경을 감지하는 커스텀 훅
|
|
24
|
+
* @param callback 실행할 효과 함수
|
|
25
|
+
* @param dependencies 종속성 배열
|
|
26
|
+
*/
|
|
27
|
+
export function useDeepCompareEffect(callback, dependencies) {
|
|
28
|
+
const previousDependenciesRef = React.useRef();
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
const isSame = _.isEqual(previousDependenciesRef.current, dependencies);
|
|
31
|
+
if (!isSame) {
|
|
32
|
+
previousDependenciesRef.current = _.cloneDeep(dependencies);
|
|
33
|
+
return callback();
|
|
34
|
+
}
|
|
35
|
+
}, [callback, JSON.stringify(dependencies)]);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
|
|
39
|
+
* 깊은 비교와 팩토리 함수를 사용하는 메모이제이션 훅
|
|
40
|
+
* @param factory 계산을 수행하는 팩토리 함수
|
|
41
|
+
* @param deps 의존성 배열
|
|
42
|
+
* @returns 메모이제이션된 계산 결과
|
|
43
|
+
*/
|
|
44
|
+
export function useDeepCompareMemo(factory, deps) {
|
|
45
|
+
// 의존성 배열을 위한 ref
|
|
46
|
+
const depsRef = React.useRef();
|
|
47
|
+
// 현재 값을 저장하기 위한 ref
|
|
48
|
+
const valueRef = React.useRef();
|
|
49
|
+
// 의존성의 깊은 비교 수행
|
|
50
|
+
const depsChanged = !_.isEqual(depsRef.current, deps);
|
|
51
|
+
// 의존성이 변경되었을 때만 값 재계산
|
|
52
|
+
if (depsChanged || valueRef.current === undefined) {
|
|
53
|
+
valueRef.current = factory();
|
|
54
|
+
depsRef.current = _.cloneDeep(deps);
|
|
55
|
+
}
|
|
56
|
+
// deps 배열의 얕은 비교를 위한 문자열화
|
|
57
|
+
// 이는 React의 렌더링 시스템과 함께 작동하기 위함
|
|
58
|
+
return React.useMemo(() => valueRef.current, [JSON.stringify(deps)]);
|
|
59
|
+
}
|
|
20
60
|
export default useUpdateEffect;
|
|
@@ -12,6 +12,7 @@ import CellMode from "./cell/CellMode";
|
|
|
12
12
|
import ImeComponent from "./ime/IMEComponent";
|
|
13
13
|
import NoDataComponent from "./body/NoDataComponent";
|
|
14
14
|
import { useAddApi } from "../hooks/useGridInitialization";
|
|
15
|
+
import { useDeepCompareMemo } from "../common/constants/utils";
|
|
15
16
|
const initialWindowWidth = 800;
|
|
16
17
|
export const initialWindowHeight = 500;
|
|
17
18
|
const overscanTopRow = 4;
|
|
@@ -76,8 +77,19 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
76
77
|
const { __randomDataSourceKey } = useSelector((store) => ({
|
|
77
78
|
__randomDataSourceKey: store.__randomDataSourceKey,
|
|
78
79
|
}));
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
// useDeepCompareEffect(() => {
|
|
81
|
+
// console.log("변경됨", dataSource);
|
|
82
|
+
// }, [dataSource]);
|
|
83
|
+
// const totalHeight = useMemo(
|
|
84
|
+
// () => dataSource.reduce((sum, item) => sum + item.height!, 0),
|
|
85
|
+
// [
|
|
86
|
+
// // dataSource,
|
|
87
|
+
// __randomDataSourceKey,
|
|
88
|
+
// ]
|
|
89
|
+
// );
|
|
90
|
+
const totalHeight = useDeepCompareMemo(() => dataSource.reduce((sum, item) => sum + item.height, 0), [dataSource]);
|
|
91
|
+
const totalWidth = useDeepCompareMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
|
|
92
|
+
// const totalWidth = useMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
|
|
81
93
|
const binarySearchIndex = useCallback((items, target) => {
|
|
82
94
|
let low = 0;
|
|
83
95
|
let high = items.length - 1;
|
|
@@ -95,14 +107,31 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
95
107
|
}
|
|
96
108
|
return Math.max(0, low - 1);
|
|
97
109
|
}, []);
|
|
98
|
-
const cumulativeHeights = useMemo(() => {
|
|
110
|
+
// const cumulativeHeights = useMemo(() => {
|
|
111
|
+
// const heights = [0];
|
|
112
|
+
// for (let i = 0; i < dataSource.length; i++) {
|
|
113
|
+
// heights.push(heights[i] + dataSource[i].height!);
|
|
114
|
+
// }
|
|
115
|
+
// return heights;
|
|
116
|
+
// }, [
|
|
117
|
+
// // dataSource,
|
|
118
|
+
// __randomDataSourceKey,
|
|
119
|
+
// ]);
|
|
120
|
+
const cumulativeHeights = useDeepCompareMemo(() => {
|
|
99
121
|
const heights = [0];
|
|
100
122
|
for (let i = 0; i < dataSource.length; i++) {
|
|
101
123
|
heights.push(heights[i] + dataSource[i].height);
|
|
102
124
|
}
|
|
103
125
|
return heights;
|
|
104
|
-
}, [dataSource
|
|
105
|
-
const cumulativeWidths = useMemo(() => {
|
|
126
|
+
}, [dataSource]);
|
|
127
|
+
// const cumulativeWidths = useMemo(() => {
|
|
128
|
+
// const widths = [0];
|
|
129
|
+
// for (let i = 0; i < columns.length || 0; i++) {
|
|
130
|
+
// widths.push(widths[i] + Number(columns[i].width));
|
|
131
|
+
// }
|
|
132
|
+
// return widths;
|
|
133
|
+
// }, [columns]);
|
|
134
|
+
const cumulativeWidths = useDeepCompareMemo(() => {
|
|
106
135
|
const widths = [0];
|
|
107
136
|
for (let i = 0; i < columns.length || 0; i++) {
|
|
108
137
|
widths.push(widths[i] + Number(columns[i].width));
|
|
@@ -118,9 +147,16 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
118
147
|
}
|
|
119
148
|
end = Math.min(end + overscanBottomRow, dataSource.length);
|
|
120
149
|
return { start, end };
|
|
121
|
-
}, [
|
|
150
|
+
}, [
|
|
151
|
+
JSON.stringify(dataSource),
|
|
152
|
+
scrollTop,
|
|
153
|
+
cumulativeHeights,
|
|
154
|
+
windowSize.height,
|
|
155
|
+
binarySearchIndex,
|
|
156
|
+
// __randomDataSourceKey,
|
|
157
|
+
]);
|
|
122
158
|
const { start, end } = getItemRange();
|
|
123
|
-
const visibleItems =
|
|
159
|
+
const visibleItems = useDeepCompareMemo(() => {
|
|
124
160
|
const result = [];
|
|
125
161
|
const rowIndex = gridRef.current.getCellFocus()[0];
|
|
126
162
|
// 포함 안되어있으면 추가
|
|
@@ -136,10 +172,15 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
136
172
|
result.push(dataSource[rowIndex - 1]); // fixedIndex가 범위에 포함되지 않으면 첫 번째에 추가
|
|
137
173
|
}
|
|
138
174
|
return result;
|
|
139
|
-
}, [
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
175
|
+
}, [
|
|
176
|
+
// __randomDataSourceKey,
|
|
177
|
+
dataSource,
|
|
178
|
+
start,
|
|
179
|
+
end,
|
|
180
|
+
]);
|
|
181
|
+
const startColumnIndex = useDeepCompareMemo(() => Math.max(0, binarySearchIndex(cumulativeWidths, scrollLeft) - overscanColumn), [cumulativeWidths, scrollLeft, binarySearchIndex, overscanColumn]);
|
|
182
|
+
const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
|
|
183
|
+
const offsetLeft = useDeepCompareMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
|
|
143
184
|
const domRef = React.useRef(null);
|
|
144
185
|
const updateScroll = useCallback((newScrollTop, newScrollLeft) => {
|
|
145
186
|
newScrollTop !== undefined && setScrollTop(newScrollTop);
|
|
@@ -181,7 +222,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
|
|
|
181
222
|
}
|
|
182
223
|
return items.length - 1;
|
|
183
224
|
}, [windowSize.width]);
|
|
184
|
-
const columnEndIndex =
|
|
225
|
+
const columnEndIndex = useDeepCompareMemo(() => binarySearchColumnIndex(cumulativeWidths, startColumnIndex, scrollLeft), [cumulativeWidths, startColumnIndex, scrollLeft, windowSize.width]);
|
|
185
226
|
const isSyncingRef = useRef(false);
|
|
186
227
|
const handleScrollController = useCallback((e) => {
|
|
187
228
|
if (isSyncingRef.current)
|
|
@@ -251,7 +292,7 @@ const VirtualListItem = React.memo(({ item, startColumnIndex, cumulativeWidths,
|
|
|
251
292
|
return { start, end };
|
|
252
293
|
}, [startColumnIndex, cumulativeWidths, windowSize, columnEndIndex]);
|
|
253
294
|
const { start, end } = getItemRange();
|
|
254
|
-
const visibleColumns =
|
|
295
|
+
const visibleColumns = useDeepCompareMemo(() => columns.slice(start, end + 1), [start, end, columns]);
|
|
255
296
|
const cellStyle = useMemo(() => ({ height: `${item.height}px` }), [item.height]);
|
|
256
297
|
return (_jsx(TableRow, { "aria-rowindex": item.__ariaRowindex, style: cellStyle, className: classes.TableClasses.body.row.root, children: visibleColumns.map((column) => (_jsx(VirtualItem, { column: column, row: row, rowIndex: item.__dataRowindex, isFocus: isColIndex === column.__ariaColindex, editStatus: isColIndex === column.__ariaColindex ? editStatus : undefined }, column.__uuid))) }, item.id));
|
|
257
298
|
});
|
|
@@ -14,7 +14,7 @@ export const TableBody = styled("div")(({ lineHeight = defaultProps.height }) =>
|
|
|
14
14
|
},
|
|
15
15
|
}));
|
|
16
16
|
export const TableCell = styled("div")(() => ({
|
|
17
|
-
padding: "
|
|
17
|
+
padding: "1px 10px",
|
|
18
18
|
overflow: "hidden",
|
|
19
19
|
textOverflow: "ellipsis",
|
|
20
20
|
whiteSpace: "nowrap",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noraent/nora-datagrid",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.45",
|
|
4
4
|
"module": "./lib/esm/index.js",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"@emotion/react": "^11.13.3",
|
|
29
29
|
"@emotion/styled": "^11.13.0",
|
|
30
30
|
"@noraent/nora-datagrid": "file:",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
31
32
|
"react": "^18.3.1",
|
|
32
33
|
"react-dom": "^18.3.1",
|
|
33
34
|
"rimraf": "^6.0.1",
|