@noraent/nora-datagrid 0.0.50 → 0.0.52

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/App.js CHANGED
@@ -24,7 +24,7 @@ const RenderCell = (params) => {
24
24
  return {
25
25
  id: i,
26
26
  code: `${tt} -test-${i}`,
27
- name: `name-${i} ${Math.random() * 20}`,
27
+ name: `name-${i} `,
28
28
  note: `note-${i}`,
29
29
  date: new Date(),
30
30
  currency4: `test-${i}`,
@@ -166,11 +166,11 @@ function App() {
166
166
  const ref = useGridApiRef();
167
167
  const [dataSource, setDataSource] = useState([]);
168
168
  const handleDataSource = () => {
169
- const data = Array.from({ length: 200 }, (_, i) => {
169
+ const data = Array.from({ length: 1000 }, (_, i) => {
170
170
  return {
171
171
  id: i,
172
172
  code: `test-${i}`,
173
- name: `name-${i} ${Math.random() * 20}`,
173
+ name: `name-${i}`,
174
174
  note: `note-${i}`,
175
175
  date: new Date(),
176
176
  currency4: `test=${i}`,
@@ -179,8 +179,13 @@ function App() {
179
179
  // height: Math.floor(Math.random() * 20) + 20,
180
180
  };
181
181
  });
182
+ // requestIdleCallback(() => {
182
183
  setDataSource(data);
184
+ // });
183
185
  };
186
+ useEffect(() => {
187
+ handleDataSource();
188
+ }, []);
184
189
  return (_jsxs(_Fragment, { children: [_jsx("button", { onClick: () => {
185
190
  ref.current.scrollToRowIndex(414);
186
191
  }, children: "414 \uC774\uB3D9" }), _jsx("button", { onClick: () => {
@@ -33,6 +33,7 @@ const DataGridMaster = React.forwardRef((props, _ref) => {
33
33
  startTransition(() => {
34
34
  apiRef.current.setGridContainer(containerRef);
35
35
  apiRef.current.setInitialStore(props);
36
+ apiRef.current.initHeightCache();
36
37
  });
37
38
  }, []);
38
39
  // 변경 된 부분만 반영
@@ -47,6 +48,9 @@ const DataGridMaster = React.forwardRef((props, _ref) => {
47
48
  const basicStore = apiRef.current.setBasicStore(props);
48
49
  apiRef.current.store.original[typedKey] = basicStore[typedKey];
49
50
  apiRef.current.store.state[typedKey] = basicStore[typedKey];
51
+ if (key === "dataSource") {
52
+ apiRef.current.initHeightCache();
53
+ }
50
54
  }
51
55
  });
52
56
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.50",
3
+ "version": "0.0.52",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,
@@ -24,15 +24,24 @@ function useUpdateEffect(callback, deps) {
24
24
  * @param callback 실행할 효과 함수
25
25
  * @param dependencies 종속성 배열
26
26
  */
27
+ // export function useDeepCompareEffect<T>(callback: () => void | (() => void), dependencies: T[]): void {
28
+ // const previousDependenciesRef = React.useRef<T[] | undefined>();
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
+ // }
27
37
  export function useDeepCompareEffect(callback, dependencies) {
28
38
  const previousDependenciesRef = React.useRef();
29
39
  React.useEffect(() => {
30
- const isSame = _.isEqual(previousDependenciesRef.current, dependencies);
31
- if (!isSame) {
40
+ if (!_.isEqual(previousDependenciesRef.current, dependencies)) {
32
41
  previousDependenciesRef.current = _.cloneDeep(dependencies);
33
42
  return callback();
34
43
  }
35
- }, [callback, JSON.stringify(dependencies)]);
44
+ }, [callback]); // dependencies를 직접 참조하여 비교하므로 의존성 배열에서 제거
36
45
  }
37
46
  /**
38
47
  * Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
@@ -41,20 +50,31 @@ export function useDeepCompareEffect(callback, dependencies) {
41
50
  * @param deps 의존성 배열
42
51
  * @returns 메모이제이션된 계산 결과
43
52
  */
53
+ // // 성능 문제로 비활성화
54
+ // // export function useDeepCompareMemo<T>(factory: () => T, deps: any[]): T {
55
+ // // // 의존성 배열을 위한 ref
56
+ // // const depsRef = React.useRef<any[]>();
57
+ // // // 현재 값을 저장하기 위한 ref
58
+ // // const valueRef = React.useRef<T>();
59
+ // // // 의존성의 깊은 비교 수행
60
+ // // const depsChanged = !_.isEqual(depsRef.current, deps);
61
+ // // // 의존성이 변경되었을 때만 값 재계산
62
+ // // if (depsChanged || valueRef.current === undefined) {
63
+ // // valueRef.current = factory();
64
+ // // depsRef.current = _.cloneDeep(deps);
65
+ // // }
66
+ // // // deps 배열의 얕은 비교를 위한 문자열화
67
+ // // // 이는 React의 렌더링 시스템과 함께 작동하기 위함
68
+ // // return React.useMemo(() => valueRef.current as T, [JSON.stringify(deps)]);
69
+ // // }
44
70
  export function useDeepCompareMemo(factory, deps) {
45
- // 의존성 배열을 위한 ref
46
71
  const depsRef = React.useRef();
47
- // 현재 값을 저장하기 위한 ref
48
72
  const valueRef = React.useRef();
49
- // 의존성의 깊은 비교 수행
50
- const depsChanged = !_.isEqual(depsRef.current, deps);
51
- // 의존성이 변경되었을 때만 값 재계산
52
- if (depsChanged || valueRef.current === undefined) {
73
+ // 의존성 배열을 깊은 비교하여 변경 여부 확인
74
+ if (!_.isEqual(depsRef.current, deps)) {
53
75
  valueRef.current = factory();
54
76
  depsRef.current = _.cloneDeep(deps);
55
77
  }
56
- // deps 배열의 얕은 비교를 위한 문자열화
57
- // 이는 React의 렌더링 시스템과 함께 작동하기 위함
58
- return React.useMemo(() => valueRef.current, [JSON.stringify(deps)]);
78
+ return valueRef.current;
59
79
  }
60
80
  export default useUpdateEffect;
@@ -36,7 +36,6 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
36
36
  var _a;
37
37
  const store = gridRef.current.store;
38
38
  const parentElement = (_a = store === null || store === void 0 ? void 0 : store.gridContainer.current) === null || _a === void 0 ? void 0 : _a.parentElement;
39
- // const parentElement = store?.gridContainer.current?.parentElement as HTMLDivElement;
40
39
  // ResizeObserver 인스턴스 생성: 부모 요소의 크기 변화를 감지함
41
40
  const observer = new ResizeObserver((entries) => {
42
41
  for (let entry of entries) {
@@ -46,9 +45,8 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
46
45
  // 새로운 자식 요소의 크기 계산
47
46
  const newWidth = parentWidth;
48
47
  const newHeight = parentHeight;
49
- // if (windowSize.width !== newWidth || windowSize.height !== newHeight) {
50
48
  // // 자식 요소의 현재 크기와 새 크기가 다른 경우, 크기를 업데이트
51
- if (parentElement.style.height) {
49
+ if (parentElement.style.height || parentElement.style.maxHeight) {
52
50
  setWindowSize({
53
51
  width: newWidth,
54
52
  height: newHeight,
@@ -60,27 +58,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
60
58
  height: Math.max(initialWindowHeight, gridRef.current.store.state.dataSource.reduce((sum, item) => sum + item.height, 0) + 54),
61
59
  });
62
60
  }
63
- // }
64
61
  }
65
- // const [entry] = entries;
66
- // const observedHeight = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.height;
67
- // const observedWidth = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.width;
68
- // if (parentElement.style.height) {
69
- // setWindowSize({
70
- // width: observedWidth,
71
- // height: observedHeight,
72
- // });
73
- // } else {
74
- // console.log("@@@", parentElement, parentElement.style.height);
75
- // // 부모 height 없을 경우
76
- // setWindowSize({
77
- // width: observedWidth,
78
- // height: Math.max(
79
- // initialWindowHeight,
80
- // gridRef.current.store.state.dataSource.reduce((sum, item) => sum + item.height!, 0)
81
- // ),
82
- // });
83
- // }
84
62
  });
85
63
  // const observer = new ResizeObserver((entries) => {
86
64
  // // // 감지된 모든 요소에 대해 반복
@@ -124,14 +102,19 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
124
102
  const { __randomDataSourceKey } = useSelector((store) => ({
125
103
  __randomDataSourceKey: store.__randomDataSourceKey,
126
104
  }));
127
- // const totalHeight = useMemo(
128
- // () => dataSource.reduce((sum, item) => sum + item.height!, 0),
129
- // [
130
- // // dataSource,
131
- // __randomDataSourceKey,
132
- // ]
133
- // );
134
- const totalHeight = useDeepCompareMemo(() => dataSource.reduce((sum, item) => sum + item.height, 0), [dataSource]);
105
+ const { cumulativeHeights } = useSelector((store) => ({
106
+ cumulativeHeights: store.cumulativeHeights,
107
+ }));
108
+ // 높이 계산 로직인데 dataSource깊은 복사를 통해 변경을 감지하여 다시 계산하기에는 성능 이슈가 발생할수있어. 수정 필요
109
+ //
110
+ // const totalHeight = useDeepCompareMemo(() => dataSource.reduce((sum, item) => sum + item.height!, 0), [dataSource]);
111
+ const totalHeight = useDeepCompareMemo(() => {
112
+ var _a, _b;
113
+ const heights = (_b = (_a = gridRef.current) === null || _a === void 0 ? void 0 : _a.store) === null || _b === void 0 ? void 0 : _b.cumulativeHeights;
114
+ if (!heights || heights.length === 0)
115
+ return 0;
116
+ return heights[heights.length - 1];
117
+ }, [cumulativeHeights]);
135
118
  const totalWidth = useDeepCompareMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
136
119
  // const totalWidth = useMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
137
120
  const binarySearchIndex = useCallback((items, target) => {
@@ -151,13 +134,13 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
151
134
  }
152
135
  return Math.max(0, low - 1);
153
136
  }, []);
154
- const cumulativeHeights = useDeepCompareMemo(() => {
155
- const heights = [0];
156
- for (let i = 0; i < dataSource.length; i++) {
157
- heights.push(heights[i] + dataSource[i].height);
158
- }
159
- return heights;
160
- }, [dataSource]);
137
+ // const cumulativeHeights = useDeepCompareMemo(() => {
138
+ // const heights = [0];
139
+ // for (let i = 0; i < dataSource.length; i++) {
140
+ // heights.push(heights[i] + dataSource[i].height!);
141
+ // }
142
+ // return heights;
143
+ // }, [dataSource]);
161
144
  const cumulativeWidths = useDeepCompareMemo(() => {
162
145
  const widths = [0];
163
146
  for (let i = 0; i < columns.length || 0; i++) {
@@ -166,6 +149,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
166
149
  return widths;
167
150
  }, [columns]);
168
151
  const getItemRange = useCallback(() => {
152
+ const dataSource = gridRef.current.store.state.dataSource;
169
153
  const start = Math.max(0, binarySearchIndex(cumulativeHeights, scrollTop) - overscanTopRow);
170
154
  let end = Math.min(start + overscanBottomRow, dataSource.length);
171
155
  let startAdjust = start ? start + overscanTopRow : start;
@@ -175,7 +159,8 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
175
159
  end = Math.min(end + overscanBottomRow, dataSource.length);
176
160
  return { start, end };
177
161
  }, [
178
- JSON.stringify(dataSource),
162
+ // dataSource,
163
+ // JSON.stringify(dataSource),
179
164
  scrollTop,
180
165
  cumulativeHeights,
181
166
  windowSize.height,
@@ -184,6 +169,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
184
169
  ]);
185
170
  const { start, end } = getItemRange();
186
171
  const visibleItems = useDeepCompareMemo(() => {
172
+ const dataSource = gridRef.current.store.state.dataSource;
187
173
  const result = [];
188
174
  const rowIndex = gridRef.current.getCellFocus()[0];
189
175
  // 포함 안되어있으면 추가
@@ -200,8 +186,9 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
200
186
  }
201
187
  return result;
202
188
  }, [
189
+ // totalHeight,
203
190
  // __randomDataSourceKey,
204
- dataSource,
191
+ // dataSource,
205
192
  start,
206
193
  end,
207
194
  ]);
@@ -23,9 +23,11 @@ export default function usePublicTest(apiRef) {
23
23
  }, []);
24
24
  const setRowHeight = React.useCallback((rowIndex, height = defaultProps.height) => {
25
25
  apiRef.current.store.state.dataSource[rowIndex] = Object.assign(Object.assign({}, apiRef.current.store.state.dataSource[rowIndex]), { height: height });
26
+ apiRef.current.initHeightCache();
26
27
  apiRef.current.store.__randomDataSourceKey = `${Math.random()}`;
27
28
  apiRef.current.store.updateKeyTemp.add("state, dataSource");
28
29
  apiRef.current.store.updateKeyTemp.add("__randomDataSourceKey");
30
+ apiRef.current.store.updateKeyTemp.add("cumulativeHeights");
29
31
  setTimeout(() => {
30
32
  apiRef.current.getPublicApi().forceUpdate();
31
33
  }, 0);
@@ -125,6 +125,7 @@ export default function useInternalPrivateApi(apiRef) {
125
125
  sum += (_a = row.height) !== null && _a !== void 0 ? _a : 32;
126
126
  return sum;
127
127
  });
128
+ heightCache[0] = 0;
128
129
  apiRef.current.store.cumulativeHeights = heightCache;
129
130
  return heightCache;
130
131
  }, []);
@@ -134,7 +135,7 @@ export default function useInternalPrivateApi(apiRef) {
134
135
  let result = 0;
135
136
  while (low <= high) {
136
137
  const mid = Math.floor((low + high) / 2);
137
- if (mid < rowIndex) {
138
+ if (mid <= rowIndex) {
138
139
  result = apiRef.current.store.cumulativeHeights[mid];
139
140
  low = mid + 1;
140
141
  }
@@ -89,7 +89,7 @@ export const useSelector = (selector) => {
89
89
  const newPath = [...currentPath, prop];
90
90
  const value = obj[prop];
91
91
  // 정확한 경로 저장
92
- if (currentPath.length > 0 || prop === "state" || prop === "original" || prop === "__randomDataSourceKey") {
92
+ if (currentPath.length > 0 || prop === "state" || prop === "original" || prop === "__randomDataSourceKey" || prop === "cumulativeHeights") {
93
93
  if (!isArrayInSet(accessedPaths.current, newPath)) {
94
94
  accessedPaths.current.add(newPath);
95
95
  }
@@ -19,7 +19,6 @@ export class Store {
19
19
  }
20
20
  setState(path, value, isUpdate) {
21
21
  const fullPath = Array.isArray(path) ? path.map(String) : [String(path)];
22
- console.log(">>>>", fullPath);
23
22
  this.state = this.updateNestedState(this.state, fullPath, value);
24
23
  this.notify(fullPath, isUpdate);
25
24
  }
package/lib/esm/App.js CHANGED
@@ -24,7 +24,7 @@ const RenderCell = (params) => {
24
24
  return {
25
25
  id: i,
26
26
  code: `${tt} -test-${i}`,
27
- name: `name-${i} ${Math.random() * 20}`,
27
+ name: `name-${i} `,
28
28
  note: `note-${i}`,
29
29
  date: new Date(),
30
30
  currency4: `test-${i}`,
@@ -166,11 +166,11 @@ function App() {
166
166
  const ref = useGridApiRef();
167
167
  const [dataSource, setDataSource] = useState([]);
168
168
  const handleDataSource = () => {
169
- const data = Array.from({ length: 200 }, (_, i) => {
169
+ const data = Array.from({ length: 1000 }, (_, i) => {
170
170
  return {
171
171
  id: i,
172
172
  code: `test-${i}`,
173
- name: `name-${i} ${Math.random() * 20}`,
173
+ name: `name-${i}`,
174
174
  note: `note-${i}`,
175
175
  date: new Date(),
176
176
  currency4: `test=${i}`,
@@ -179,8 +179,13 @@ function App() {
179
179
  // height: Math.floor(Math.random() * 20) + 20,
180
180
  };
181
181
  });
182
+ // requestIdleCallback(() => {
182
183
  setDataSource(data);
184
+ // });
183
185
  };
186
+ useEffect(() => {
187
+ handleDataSource();
188
+ }, []);
184
189
  return (_jsxs(_Fragment, { children: [_jsx("button", { onClick: () => {
185
190
  ref.current.scrollToRowIndex(414);
186
191
  }, children: "414 \uC774\uB3D9" }), _jsx("button", { onClick: () => {
@@ -33,6 +33,7 @@ const DataGridMaster = React.forwardRef((props, _ref) => {
33
33
  startTransition(() => {
34
34
  apiRef.current.setGridContainer(containerRef);
35
35
  apiRef.current.setInitialStore(props);
36
+ apiRef.current.initHeightCache();
36
37
  });
37
38
  }, []);
38
39
  // 변경 된 부분만 반영
@@ -47,6 +48,9 @@ const DataGridMaster = React.forwardRef((props, _ref) => {
47
48
  const basicStore = apiRef.current.setBasicStore(props);
48
49
  apiRef.current.store.original[typedKey] = basicStore[typedKey];
49
50
  apiRef.current.store.state[typedKey] = basicStore[typedKey];
51
+ if (key === "dataSource") {
52
+ apiRef.current.initHeightCache();
53
+ }
50
54
  }
51
55
  });
52
56
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.50",
3
+ "version": "0.0.52",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,
@@ -24,15 +24,24 @@ function useUpdateEffect(callback, deps) {
24
24
  * @param callback 실행할 효과 함수
25
25
  * @param dependencies 종속성 배열
26
26
  */
27
+ // export function useDeepCompareEffect<T>(callback: () => void | (() => void), dependencies: T[]): void {
28
+ // const previousDependenciesRef = React.useRef<T[] | undefined>();
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
+ // }
27
37
  export function useDeepCompareEffect(callback, dependencies) {
28
38
  const previousDependenciesRef = React.useRef();
29
39
  React.useEffect(() => {
30
- const isSame = _.isEqual(previousDependenciesRef.current, dependencies);
31
- if (!isSame) {
40
+ if (!_.isEqual(previousDependenciesRef.current, dependencies)) {
32
41
  previousDependenciesRef.current = _.cloneDeep(dependencies);
33
42
  return callback();
34
43
  }
35
- }, [callback, JSON.stringify(dependencies)]);
44
+ }, [callback]); // dependencies를 직접 참조하여 비교하므로 의존성 배열에서 제거
36
45
  }
37
46
  /**
38
47
  * Array<Object> 경우 변경 감지하기 힘들기 때문에 별도 hook 구성함
@@ -41,20 +50,31 @@ export function useDeepCompareEffect(callback, dependencies) {
41
50
  * @param deps 의존성 배열
42
51
  * @returns 메모이제이션된 계산 결과
43
52
  */
53
+ // // 성능 문제로 비활성화
54
+ // // export function useDeepCompareMemo<T>(factory: () => T, deps: any[]): T {
55
+ // // // 의존성 배열을 위한 ref
56
+ // // const depsRef = React.useRef<any[]>();
57
+ // // // 현재 값을 저장하기 위한 ref
58
+ // // const valueRef = React.useRef<T>();
59
+ // // // 의존성의 깊은 비교 수행
60
+ // // const depsChanged = !_.isEqual(depsRef.current, deps);
61
+ // // // 의존성이 변경되었을 때만 값 재계산
62
+ // // if (depsChanged || valueRef.current === undefined) {
63
+ // // valueRef.current = factory();
64
+ // // depsRef.current = _.cloneDeep(deps);
65
+ // // }
66
+ // // // deps 배열의 얕은 비교를 위한 문자열화
67
+ // // // 이는 React의 렌더링 시스템과 함께 작동하기 위함
68
+ // // return React.useMemo(() => valueRef.current as T, [JSON.stringify(deps)]);
69
+ // // }
44
70
  export function useDeepCompareMemo(factory, deps) {
45
- // 의존성 배열을 위한 ref
46
71
  const depsRef = React.useRef();
47
- // 현재 값을 저장하기 위한 ref
48
72
  const valueRef = React.useRef();
49
- // 의존성의 깊은 비교 수행
50
- const depsChanged = !_.isEqual(depsRef.current, deps);
51
- // 의존성이 변경되었을 때만 값 재계산
52
- if (depsChanged || valueRef.current === undefined) {
73
+ // 의존성 배열을 깊은 비교하여 변경 여부 확인
74
+ if (!_.isEqual(depsRef.current, deps)) {
53
75
  valueRef.current = factory();
54
76
  depsRef.current = _.cloneDeep(deps);
55
77
  }
56
- // deps 배열의 얕은 비교를 위한 문자열화
57
- // 이는 React의 렌더링 시스템과 함께 작동하기 위함
58
- return React.useMemo(() => valueRef.current, [JSON.stringify(deps)]);
78
+ return valueRef.current;
59
79
  }
60
80
  export default useUpdateEffect;
@@ -36,7 +36,6 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
36
36
  var _a;
37
37
  const store = gridRef.current.store;
38
38
  const parentElement = (_a = store === null || store === void 0 ? void 0 : store.gridContainer.current) === null || _a === void 0 ? void 0 : _a.parentElement;
39
- // const parentElement = store?.gridContainer.current?.parentElement as HTMLDivElement;
40
39
  // ResizeObserver 인스턴스 생성: 부모 요소의 크기 변화를 감지함
41
40
  const observer = new ResizeObserver((entries) => {
42
41
  for (let entry of entries) {
@@ -46,9 +45,8 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
46
45
  // 새로운 자식 요소의 크기 계산
47
46
  const newWidth = parentWidth;
48
47
  const newHeight = parentHeight;
49
- // if (windowSize.width !== newWidth || windowSize.height !== newHeight) {
50
48
  // // 자식 요소의 현재 크기와 새 크기가 다른 경우, 크기를 업데이트
51
- if (parentElement.style.height) {
49
+ if (parentElement.style.height || parentElement.style.maxHeight) {
52
50
  setWindowSize({
53
51
  width: newWidth,
54
52
  height: newHeight,
@@ -60,27 +58,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
60
58
  height: Math.max(initialWindowHeight, gridRef.current.store.state.dataSource.reduce((sum, item) => sum + item.height, 0) + 54),
61
59
  });
62
60
  }
63
- // }
64
61
  }
65
- // const [entry] = entries;
66
- // const observedHeight = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.height;
67
- // const observedWidth = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.width;
68
- // if (parentElement.style.height) {
69
- // setWindowSize({
70
- // width: observedWidth,
71
- // height: observedHeight,
72
- // });
73
- // } else {
74
- // console.log("@@@", parentElement, parentElement.style.height);
75
- // // 부모 height 없을 경우
76
- // setWindowSize({
77
- // width: observedWidth,
78
- // height: Math.max(
79
- // initialWindowHeight,
80
- // gridRef.current.store.state.dataSource.reduce((sum, item) => sum + item.height!, 0)
81
- // ),
82
- // });
83
- // }
84
62
  });
85
63
  // const observer = new ResizeObserver((entries) => {
86
64
  // // // 감지된 모든 요소에 대해 반복
@@ -124,14 +102,19 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
124
102
  const { __randomDataSourceKey } = useSelector((store) => ({
125
103
  __randomDataSourceKey: store.__randomDataSourceKey,
126
104
  }));
127
- // const totalHeight = useMemo(
128
- // () => dataSource.reduce((sum, item) => sum + item.height!, 0),
129
- // [
130
- // // dataSource,
131
- // __randomDataSourceKey,
132
- // ]
133
- // );
134
- const totalHeight = useDeepCompareMemo(() => dataSource.reduce((sum, item) => sum + item.height, 0), [dataSource]);
105
+ const { cumulativeHeights } = useSelector((store) => ({
106
+ cumulativeHeights: store.cumulativeHeights,
107
+ }));
108
+ // 높이 계산 로직인데 dataSource깊은 복사를 통해 변경을 감지하여 다시 계산하기에는 성능 이슈가 발생할수있어. 수정 필요
109
+ //
110
+ // const totalHeight = useDeepCompareMemo(() => dataSource.reduce((sum, item) => sum + item.height!, 0), [dataSource]);
111
+ const totalHeight = useDeepCompareMemo(() => {
112
+ var _a, _b;
113
+ const heights = (_b = (_a = gridRef.current) === null || _a === void 0 ? void 0 : _a.store) === null || _b === void 0 ? void 0 : _b.cumulativeHeights;
114
+ if (!heights || heights.length === 0)
115
+ return 0;
116
+ return heights[heights.length - 1];
117
+ }, [cumulativeHeights]);
135
118
  const totalWidth = useDeepCompareMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
136
119
  // const totalWidth = useMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
137
120
  const binarySearchIndex = useCallback((items, target) => {
@@ -151,13 +134,13 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
151
134
  }
152
135
  return Math.max(0, low - 1);
153
136
  }, []);
154
- const cumulativeHeights = useDeepCompareMemo(() => {
155
- const heights = [0];
156
- for (let i = 0; i < dataSource.length; i++) {
157
- heights.push(heights[i] + dataSource[i].height);
158
- }
159
- return heights;
160
- }, [dataSource]);
137
+ // const cumulativeHeights = useDeepCompareMemo(() => {
138
+ // const heights = [0];
139
+ // for (let i = 0; i < dataSource.length; i++) {
140
+ // heights.push(heights[i] + dataSource[i].height!);
141
+ // }
142
+ // return heights;
143
+ // }, [dataSource]);
161
144
  const cumulativeWidths = useDeepCompareMemo(() => {
162
145
  const widths = [0];
163
146
  for (let i = 0; i < columns.length || 0; i++) {
@@ -166,6 +149,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
166
149
  return widths;
167
150
  }, [columns]);
168
151
  const getItemRange = useCallback(() => {
152
+ const dataSource = gridRef.current.store.state.dataSource;
169
153
  const start = Math.max(0, binarySearchIndex(cumulativeHeights, scrollTop) - overscanTopRow);
170
154
  let end = Math.min(start + overscanBottomRow, dataSource.length);
171
155
  let startAdjust = start ? start + overscanTopRow : start;
@@ -175,7 +159,8 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
175
159
  end = Math.min(end + overscanBottomRow, dataSource.length);
176
160
  return { start, end };
177
161
  }, [
178
- JSON.stringify(dataSource),
162
+ // dataSource,
163
+ // JSON.stringify(dataSource),
179
164
  scrollTop,
180
165
  cumulativeHeights,
181
166
  windowSize.height,
@@ -184,6 +169,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
184
169
  ]);
185
170
  const { start, end } = getItemRange();
186
171
  const visibleItems = useDeepCompareMemo(() => {
172
+ const dataSource = gridRef.current.store.state.dataSource;
187
173
  const result = [];
188
174
  const rowIndex = gridRef.current.getCellFocus()[0];
189
175
  // 포함 안되어있으면 추가
@@ -200,8 +186,9 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
200
186
  }
201
187
  return result;
202
188
  }, [
189
+ // totalHeight,
203
190
  // __randomDataSourceKey,
204
- dataSource,
191
+ // dataSource,
205
192
  start,
206
193
  end,
207
194
  ]);
@@ -23,9 +23,11 @@ export default function usePublicTest(apiRef) {
23
23
  }, []);
24
24
  const setRowHeight = React.useCallback((rowIndex, height = defaultProps.height) => {
25
25
  apiRef.current.store.state.dataSource[rowIndex] = Object.assign(Object.assign({}, apiRef.current.store.state.dataSource[rowIndex]), { height: height });
26
+ apiRef.current.initHeightCache();
26
27
  apiRef.current.store.__randomDataSourceKey = `${Math.random()}`;
27
28
  apiRef.current.store.updateKeyTemp.add("state, dataSource");
28
29
  apiRef.current.store.updateKeyTemp.add("__randomDataSourceKey");
30
+ apiRef.current.store.updateKeyTemp.add("cumulativeHeights");
29
31
  setTimeout(() => {
30
32
  apiRef.current.getPublicApi().forceUpdate();
31
33
  }, 0);
@@ -125,6 +125,7 @@ export default function useInternalPrivateApi(apiRef) {
125
125
  sum += (_a = row.height) !== null && _a !== void 0 ? _a : 32;
126
126
  return sum;
127
127
  });
128
+ heightCache[0] = 0;
128
129
  apiRef.current.store.cumulativeHeights = heightCache;
129
130
  return heightCache;
130
131
  }, []);
@@ -134,7 +135,7 @@ export default function useInternalPrivateApi(apiRef) {
134
135
  let result = 0;
135
136
  while (low <= high) {
136
137
  const mid = Math.floor((low + high) / 2);
137
- if (mid < rowIndex) {
138
+ if (mid <= rowIndex) {
138
139
  result = apiRef.current.store.cumulativeHeights[mid];
139
140
  low = mid + 1;
140
141
  }
@@ -89,7 +89,7 @@ export const useSelector = (selector) => {
89
89
  const newPath = [...currentPath, prop];
90
90
  const value = obj[prop];
91
91
  // 정확한 경로 저장
92
- if (currentPath.length > 0 || prop === "state" || prop === "original" || prop === "__randomDataSourceKey") {
92
+ if (currentPath.length > 0 || prop === "state" || prop === "original" || prop === "__randomDataSourceKey" || prop === "cumulativeHeights") {
93
93
  if (!isArrayInSet(accessedPaths.current, newPath)) {
94
94
  accessedPaths.current.add(newPath);
95
95
  }
@@ -19,7 +19,6 @@ export class Store {
19
19
  }
20
20
  setState(path, value, isUpdate) {
21
21
  const fullPath = Array.isArray(path) ? path.map(String) : [String(path)];
22
- console.log(">>>>", fullPath);
23
22
  this.state = this.updateNestedState(this.state, fullPath, value);
24
23
  this.notify(fullPath, isUpdate);
25
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.50",
3
+ "version": "0.0.52",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,