@noraent/nora-datagrid 0.0.55 → 0.0.56

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,
@@ -0,0 +1 @@
1
+ export { default } from './useEnhancedEffect';
@@ -0,0 +1 @@
1
+ export { default } from './useEnhancedEffect';
@@ -0,0 +1,3 @@
1
+ import * as React from "react";
2
+ declare const useEnhancedEffect: typeof React.useEffect;
3
+ export default useEnhancedEffect;
@@ -0,0 +1,4 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ const useEnhancedEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
4
+ export default useEnhancedEffect;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 항상 최신 상태를 유지 해야할떄 사용
3
+ */
4
+ declare function useEventCallback<Fn extends (...args: any[]) => any = (...args: unknown[]) => unknown>(fn: Fn): Fn;
5
+ declare function useEventCallback<Args extends unknown[], Return>(fn: (...args: Args) => Return): (...args: Args) => Return;
6
+ export default useEventCallback;
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import useEnhancedEffect from "./useEnhancedEffect";
4
+ function useEventCallback(fn) {
5
+ const ref = React.useRef(fn);
6
+ useEnhancedEffect(() => {
7
+ ref.current = fn;
8
+ });
9
+ return React.useRef((...args) =>
10
+ // @ts-expect-error hide `this`
11
+ (0, ref.current)(...args)).current;
12
+ }
13
+ export default useEventCallback;
@@ -13,6 +13,7 @@ import ImeComponent from "./ime/IMEComponent";
13
13
  import NoDataComponent from "./body/NoDataComponent";
14
14
  import { useAddApi } from "../hooks/useGridInitialization";
15
15
  import { useDeepCompareMemo } from "../common/constants/utils";
16
+ import useEventCallback from "../common/constants/useEventCallback";
16
17
  const initialWindowWidth = 800;
17
18
  export const initialWindowHeight = 500;
18
19
  const overscanTopRow = 4;
@@ -23,7 +24,7 @@ const frameInterval = 1000 / targetFPS;
23
24
  const DynamicVirtualScroll = React.memo(({ children }) => {
24
25
  const prevScrollTop = useRef(0);
25
26
  const prevScrollLeft = useRef(0);
26
- const [scrollTop, setScrollTop] = useState(0);
27
+ const [_scrollTop, setScrollTop] = useState(0);
27
28
  const [scrollLeft, setScrollLeft] = useState(0);
28
29
  const [windowSize, setWindowSize] = useState({
29
30
  width: initialWindowWidth,
@@ -148,26 +149,42 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
148
149
  }
149
150
  return widths;
150
151
  }, [columns]);
151
- const getItemRange = useCallback(() => {
152
+ const prevRightScrollRef = useRef(0);
153
+ const prevStartRef = useRef(0);
154
+ const prevEndRef = useRef(0);
155
+ const getItemRange = useEventCallback(() => {
156
+ var _a, _b;
157
+ const rightScrollTop = Math.round((_b = (_a = rightScrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollTop) !== null && _b !== void 0 ? _b : 0);
158
+ if (prevRightScrollRef.current !== 0 && prevRightScrollRef.current === rightScrollTop) {
159
+ return {
160
+ start: prevStartRef.current,
161
+ end: prevEndRef.current,
162
+ };
163
+ }
152
164
  const dataSource = gridRef.current.store.state.dataSource;
153
- const start = Math.max(0, binarySearchIndex(cumulativeHeights, scrollTop) - overscanTopRow);
165
+ const start = Math.max(0, binarySearchIndex(cumulativeHeights, rightScrollTop) - overscanTopRow);
154
166
  let end = Math.min(start + overscanBottomRow, dataSource.length);
155
167
  let startAdjust = start ? start + overscanTopRow : start;
156
168
  while (end < dataSource.length && cumulativeHeights[end] - cumulativeHeights[startAdjust] <= windowSize.height) {
157
169
  end++;
158
170
  }
159
171
  end = Math.min(end + overscanBottomRow, dataSource.length);
172
+ prevRightScrollRef.current = rightScrollTop;
173
+ prevStartRef.current = start;
174
+ prevEndRef.current = end;
160
175
  return { start, end };
161
- }, [
162
- // dataSource,
163
- // JSON.stringify(dataSource),
164
- scrollTop,
165
- cumulativeHeights,
166
- windowSize.height,
167
- binarySearchIndex,
168
- cumulativeHeights,
169
- // __randomDataSourceKey,
170
- ]);
176
+ }
177
+ // , [
178
+ // // dataSource,
179
+ // // JSON.stringify(dataSource),
180
+ // scrollTop,
181
+ // cumulativeHeights,
182
+ // windowSize.height,
183
+ // binarySearchIndex,
184
+ // cumulativeHeights,
185
+ // // __randomDataSourceKey,
186
+ // ]
187
+ );
171
188
  const { start, end } = getItemRange();
172
189
  const visibleItems = useDeepCompareMemo(() => {
173
190
  const dataSource = gridRef.current.store.state.dataSource;
@@ -195,9 +212,11 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
195
212
  end,
196
213
  ]);
197
214
  const startColumnIndex = useDeepCompareMemo(() => Math.max(0, binarySearchIndex(cumulativeWidths, scrollLeft) - overscanColumn), [cumulativeWidths, scrollLeft, binarySearchIndex, overscanColumn]);
198
- const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
199
- const offsetLeft = useDeepCompareMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
200
215
  const domRef = React.useRef(null);
216
+ // const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
217
+ // const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
218
+ const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start], [cumulativeHeights, start]);
219
+ const offsetLeft = useDeepCompareMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
201
220
  const updateScroll = useCallback((newScrollTop, newScrollLeft) => {
202
221
  newScrollTop !== undefined && setScrollTop(newScrollTop);
203
222
  newScrollLeft !== undefined && setScrollLeft(newScrollLeft);
@@ -206,7 +225,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
206
225
  if (newScrollLeft !== undefined)
207
226
  prevScrollLeft.current = newScrollLeft;
208
227
  }, []);
209
- const handleScroll = useCallback((e) => {
228
+ const handleScroll = useEventCallback((e) => {
210
229
  if (isSyncingRef.current)
211
230
  return;
212
231
  isSyncingRef.current = true;
@@ -225,8 +244,10 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
225
244
  }
226
245
  isSyncingRef.current = false;
227
246
  });
228
- }, [updateScroll, frameInterval]);
229
- const binarySearchColumnIndex = useCallback((items, start, scrollLeft) => {
247
+ }
248
+ // ,[updateScroll, frameInterval]
249
+ );
250
+ const binarySearchColumnIndex = useEventCallback((items, start, scrollLeft) => {
230
251
  let high = items.length - 1;
231
252
  let target = windowSize.width;
232
253
  let end = start;
@@ -237,7 +258,9 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
237
258
  }
238
259
  }
239
260
  return items.length - 1;
240
- }, [windowSize.width]);
261
+ }
262
+ // , [windowSize.width]
263
+ );
241
264
  const columnEndIndex = useDeepCompareMemo(() => binarySearchColumnIndex(cumulativeWidths, startColumnIndex, scrollLeft), [cumulativeWidths, startColumnIndex, scrollLeft, windowSize.width]);
242
265
  const isSyncingRef = useRef(false);
243
266
  const handleScrollController = useCallback((e) => {
@@ -316,15 +339,7 @@ const cellClassName = cx(classes.TableClasses.body.row.cell.root, classes.TableC
316
339
  const VirtualItem = React.memo(({ column, row, isFocus, editStatus, rowIndex, }) => {
317
340
  const cellStyle = useMemo(() => ({ width: `${column.width}px` }), [column.width]);
318
341
  const deferredValue = React.useDeferredValue(row ? row[column.fieldId] : "");
319
- const [showChild, setShowChild] = React.useState(true);
320
- React.useEffect(() => {
321
- // requestIdleCallback(() => {
322
- requestAnimationFrame(() => {
323
- // 브라우저 여유가 있을때 show
324
- setShowChild(true);
325
- });
326
- }, []);
327
- return (_jsx(TableCell, { "aria-colindex": column.__ariaColindex, tabIndex: isFocus ? 0 : -1, style: cellStyle, className: cellClassName, children: showChild && _jsx(CellMode, { column: column, value: deferredValue, editStatus: editStatus, rowIndex: rowIndex }) }, column.__uuid));
342
+ return (_jsx(TableCell, { "aria-colindex": column.__ariaColindex, tabIndex: isFocus ? 0 : -1, style: cellStyle, className: cellClassName, children: deferredValue && _jsx(CellMode, { column: column, value: deferredValue, editStatus: editStatus, rowIndex: rowIndex }) }, column.__uuid));
328
343
  });
329
344
  export const TwoDimensionalVirtualizedList = React.memo(() => {
330
345
  // 마우스 다운 시작지점점
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,
@@ -0,0 +1 @@
1
+ export { default } from './useEnhancedEffect';
@@ -0,0 +1 @@
1
+ export { default } from './useEnhancedEffect';
@@ -0,0 +1,3 @@
1
+ import * as React from "react";
2
+ declare const useEnhancedEffect: typeof React.useEffect;
3
+ export default useEnhancedEffect;
@@ -0,0 +1,4 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ const useEnhancedEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
4
+ export default useEnhancedEffect;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 항상 최신 상태를 유지 해야할떄 사용
3
+ */
4
+ declare function useEventCallback<Fn extends (...args: any[]) => any = (...args: unknown[]) => unknown>(fn: Fn): Fn;
5
+ declare function useEventCallback<Args extends unknown[], Return>(fn: (...args: Args) => Return): (...args: Args) => Return;
6
+ export default useEventCallback;
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import useEnhancedEffect from "./useEnhancedEffect";
4
+ function useEventCallback(fn) {
5
+ const ref = React.useRef(fn);
6
+ useEnhancedEffect(() => {
7
+ ref.current = fn;
8
+ });
9
+ return React.useRef((...args) =>
10
+ // @ts-expect-error hide `this`
11
+ (0, ref.current)(...args)).current;
12
+ }
13
+ export default useEventCallback;
@@ -13,6 +13,7 @@ import ImeComponent from "./ime/IMEComponent";
13
13
  import NoDataComponent from "./body/NoDataComponent";
14
14
  import { useAddApi } from "../hooks/useGridInitialization";
15
15
  import { useDeepCompareMemo } from "../common/constants/utils";
16
+ import useEventCallback from "../common/constants/useEventCallback";
16
17
  const initialWindowWidth = 800;
17
18
  export const initialWindowHeight = 500;
18
19
  const overscanTopRow = 4;
@@ -23,7 +24,7 @@ const frameInterval = 1000 / targetFPS;
23
24
  const DynamicVirtualScroll = React.memo(({ children }) => {
24
25
  const prevScrollTop = useRef(0);
25
26
  const prevScrollLeft = useRef(0);
26
- const [scrollTop, setScrollTop] = useState(0);
27
+ const [_scrollTop, setScrollTop] = useState(0);
27
28
  const [scrollLeft, setScrollLeft] = useState(0);
28
29
  const [windowSize, setWindowSize] = useState({
29
30
  width: initialWindowWidth,
@@ -148,26 +149,42 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
148
149
  }
149
150
  return widths;
150
151
  }, [columns]);
151
- const getItemRange = useCallback(() => {
152
+ const prevRightScrollRef = useRef(0);
153
+ const prevStartRef = useRef(0);
154
+ const prevEndRef = useRef(0);
155
+ const getItemRange = useEventCallback(() => {
156
+ var _a, _b;
157
+ const rightScrollTop = Math.round((_b = (_a = rightScrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollTop) !== null && _b !== void 0 ? _b : 0);
158
+ if (prevRightScrollRef.current !== 0 && prevRightScrollRef.current === rightScrollTop) {
159
+ return {
160
+ start: prevStartRef.current,
161
+ end: prevEndRef.current,
162
+ };
163
+ }
152
164
  const dataSource = gridRef.current.store.state.dataSource;
153
- const start = Math.max(0, binarySearchIndex(cumulativeHeights, scrollTop) - overscanTopRow);
165
+ const start = Math.max(0, binarySearchIndex(cumulativeHeights, rightScrollTop) - overscanTopRow);
154
166
  let end = Math.min(start + overscanBottomRow, dataSource.length);
155
167
  let startAdjust = start ? start + overscanTopRow : start;
156
168
  while (end < dataSource.length && cumulativeHeights[end] - cumulativeHeights[startAdjust] <= windowSize.height) {
157
169
  end++;
158
170
  }
159
171
  end = Math.min(end + overscanBottomRow, dataSource.length);
172
+ prevRightScrollRef.current = rightScrollTop;
173
+ prevStartRef.current = start;
174
+ prevEndRef.current = end;
160
175
  return { start, end };
161
- }, [
162
- // dataSource,
163
- // JSON.stringify(dataSource),
164
- scrollTop,
165
- cumulativeHeights,
166
- windowSize.height,
167
- binarySearchIndex,
168
- cumulativeHeights,
169
- // __randomDataSourceKey,
170
- ]);
176
+ }
177
+ // , [
178
+ // // dataSource,
179
+ // // JSON.stringify(dataSource),
180
+ // scrollTop,
181
+ // cumulativeHeights,
182
+ // windowSize.height,
183
+ // binarySearchIndex,
184
+ // cumulativeHeights,
185
+ // // __randomDataSourceKey,
186
+ // ]
187
+ );
171
188
  const { start, end } = getItemRange();
172
189
  const visibleItems = useDeepCompareMemo(() => {
173
190
  const dataSource = gridRef.current.store.state.dataSource;
@@ -195,9 +212,11 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
195
212
  end,
196
213
  ]);
197
214
  const startColumnIndex = useDeepCompareMemo(() => Math.max(0, binarySearchIndex(cumulativeWidths, scrollLeft) - overscanColumn), [cumulativeWidths, scrollLeft, binarySearchIndex, overscanColumn]);
198
- const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
199
- const offsetLeft = useDeepCompareMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
200
215
  const domRef = React.useRef(null);
216
+ // const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
217
+ // const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
218
+ const offsetTop = useDeepCompareMemo(() => cumulativeHeights[start], [cumulativeHeights, start]);
219
+ const offsetLeft = useDeepCompareMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
201
220
  const updateScroll = useCallback((newScrollTop, newScrollLeft) => {
202
221
  newScrollTop !== undefined && setScrollTop(newScrollTop);
203
222
  newScrollLeft !== undefined && setScrollLeft(newScrollLeft);
@@ -206,7 +225,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
206
225
  if (newScrollLeft !== undefined)
207
226
  prevScrollLeft.current = newScrollLeft;
208
227
  }, []);
209
- const handleScroll = useCallback((e) => {
228
+ const handleScroll = useEventCallback((e) => {
210
229
  if (isSyncingRef.current)
211
230
  return;
212
231
  isSyncingRef.current = true;
@@ -225,8 +244,10 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
225
244
  }
226
245
  isSyncingRef.current = false;
227
246
  });
228
- }, [updateScroll, frameInterval]);
229
- const binarySearchColumnIndex = useCallback((items, start, scrollLeft) => {
247
+ }
248
+ // ,[updateScroll, frameInterval]
249
+ );
250
+ const binarySearchColumnIndex = useEventCallback((items, start, scrollLeft) => {
230
251
  let high = items.length - 1;
231
252
  let target = windowSize.width;
232
253
  let end = start;
@@ -237,7 +258,9 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
237
258
  }
238
259
  }
239
260
  return items.length - 1;
240
- }, [windowSize.width]);
261
+ }
262
+ // , [windowSize.width]
263
+ );
241
264
  const columnEndIndex = useDeepCompareMemo(() => binarySearchColumnIndex(cumulativeWidths, startColumnIndex, scrollLeft), [cumulativeWidths, startColumnIndex, scrollLeft, windowSize.width]);
242
265
  const isSyncingRef = useRef(false);
243
266
  const handleScrollController = useCallback((e) => {
@@ -316,15 +339,7 @@ const cellClassName = cx(classes.TableClasses.body.row.cell.root, classes.TableC
316
339
  const VirtualItem = React.memo(({ column, row, isFocus, editStatus, rowIndex, }) => {
317
340
  const cellStyle = useMemo(() => ({ width: `${column.width}px` }), [column.width]);
318
341
  const deferredValue = React.useDeferredValue(row ? row[column.fieldId] : "");
319
- const [showChild, setShowChild] = React.useState(true);
320
- React.useEffect(() => {
321
- // requestIdleCallback(() => {
322
- requestAnimationFrame(() => {
323
- // 브라우저 여유가 있을때 show
324
- setShowChild(true);
325
- });
326
- }, []);
327
- return (_jsx(TableCell, { "aria-colindex": column.__ariaColindex, tabIndex: isFocus ? 0 : -1, style: cellStyle, className: cellClassName, children: showChild && _jsx(CellMode, { column: column, value: deferredValue, editStatus: editStatus, rowIndex: rowIndex }) }, column.__uuid));
342
+ return (_jsx(TableCell, { "aria-colindex": column.__ariaColindex, tabIndex: isFocus ? 0 : -1, style: cellStyle, className: cellClassName, children: deferredValue && _jsx(CellMode, { column: column, value: deferredValue, editStatus: editStatus, rowIndex: rowIndex }) }, column.__uuid));
328
343
  });
329
344
  export const TwoDimensionalVirtualizedList = React.memo(() => {
330
345
  // 마우스 다운 시작지점점
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,