@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.
- package/lib/cjs/buildPackage.json +1 -1
- package/lib/cjs/common/constants/useEnhancedEffect/index.d.ts +1 -0
- package/lib/cjs/common/constants/useEnhancedEffect/index.js +1 -0
- package/lib/cjs/common/constants/useEnhancedEffect/useEnhancedEffect.d.ts +3 -0
- package/lib/cjs/common/constants/useEnhancedEffect/useEnhancedEffect.js +4 -0
- package/lib/cjs/common/constants/useEventCallback.d.ts +6 -0
- package/lib/cjs/common/constants/useEventCallback.js +13 -0
- package/lib/cjs/components/TwoDimensionalVirtualizedList.js +43 -28
- package/lib/esm/buildPackage.json +1 -1
- package/lib/esm/common/constants/useEnhancedEffect/index.d.ts +1 -0
- package/lib/esm/common/constants/useEnhancedEffect/index.js +1 -0
- package/lib/esm/common/constants/useEnhancedEffect/useEnhancedEffect.d.ts +3 -0
- package/lib/esm/common/constants/useEnhancedEffect/useEnhancedEffect.js +4 -0
- package/lib/esm/common/constants/useEventCallback.d.ts +6 -0
- package/lib/esm/common/constants/useEventCallback.js +13 -0
- package/lib/esm/components/TwoDimensionalVirtualizedList.js +43 -28
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './useEnhancedEffect';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './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 [
|
|
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
|
|
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,
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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 =
|
|
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
|
-
}
|
|
229
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
// 마우스 다운 시작지점점
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './useEnhancedEffect';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './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 [
|
|
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
|
|
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,
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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 =
|
|
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
|
-
}
|
|
229
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
// 마우스 다운 시작지점점
|