@noraent/nora-datagrid 0.0.39 → 0.0.41

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
@@ -7,13 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
11
- import { useDeferredValue, useEffect, useState } from "react";
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ import { useEffect, useState } from "react";
12
12
  import { DataGrid } from "./DataGrid";
13
13
  import { useGridApiRef } from "./hooks/useGridApiRef";
14
14
  const RenderCell = (params) => {
15
- const [value, setValue] = useState(0);
16
- const test = useDeferredValue(value);
15
+ // const [value, setValue] = useState(0);
16
+ // const test = useDeferredValue(value);
17
17
  useEffect(() => {
18
18
  const tt = () => __awaiter(void 0, void 0, void 0, function* () {
19
19
  let tt = 0;
@@ -33,13 +33,15 @@ const RenderCell = (params) => {
33
33
  // height: Math.floor(Math.random() * 20) + 20,
34
34
  };
35
35
  });
36
- setValue(tt);
36
+ // setValue(tt);
37
37
  });
38
38
  requestIdleCallback(() => {
39
39
  tt();
40
40
  });
41
41
  }, []);
42
- return (_jsxs("div", { style: { background: "green" }, children: [test, params.value] }));
42
+ return (_jsxs("div", { style: { background: "green" }, children: [_jsx("button", { onClick: () => {
43
+ params.gridRef.current.setRowHeight(1, 100);
44
+ }, children: "??" }), params.value] }));
43
45
  };
44
46
  const RenderEditCell = (params) => {
45
47
  return (_jsx(_Fragment, { children: _jsx("input", Object.assign({}, params, { style: { background: "yellow" } })) }));
@@ -164,7 +166,7 @@ function App() {
164
166
  const ref = useGridApiRef();
165
167
  const [dataSource, setDataSource] = useState([]);
166
168
  const handleDataSource = () => {
167
- const data = Array.from({ length: 1000000 }, (_, i) => {
169
+ const data = Array.from({ length: 1000 }, (_, i) => {
168
170
  return {
169
171
  id: i,
170
172
  code: `test-${i}`,
@@ -188,7 +190,7 @@ function App() {
188
190
  }, children: "\uB370\uC774\uD130 set" }), _jsx("button", { onClick: () => {
189
191
  const data = ref.current.getData();
190
192
  console.log("!!!!!", data);
191
- }, children: "dd" }), _jsx("button", { children: "dd" }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { gridRef: ref, columns: columns, dataSource: dataSource }) }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { columns: columns, dataSource: dataSource }) }), _jsx("button", { children: "dd" })] }));
193
+ }, children: "\uD558" }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { gridRef: ref, columns: columns, dataSource: dataSource }) }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { columns: columns, dataSource: dataSource }) }), _jsx("button", { children: "dd" })] }));
192
194
  }
193
195
  export const initialItemsData = () => Array.from({ length: 10 }, (_, i) => {
194
196
  return {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,
@@ -11,6 +11,7 @@ import { EditStatus } from "../types/dataGridCoreEnum";
11
11
  import CellMode from "./cell/CellMode";
12
12
  import ImeComponent from "./ime/IMEComponent";
13
13
  import NoDataComponent from "./body/NoDataComponent";
14
+ import { useAddApi } from "../hooks/useGridInitialization";
14
15
  const initialWindowWidth = 800;
15
16
  export const initialWindowHeight = 500;
16
17
  const overscanTopRow = 4;
@@ -72,6 +73,9 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
72
73
  const { dataSource } = useSelector((store) => ({
73
74
  dataSource: store.state.dataSource,
74
75
  }));
76
+ const { __randomDataSourceKey } = useSelector((store) => ({
77
+ __randomDataSourceKey: store.__randomDataSourceKey,
78
+ }));
75
79
  const totalHeight = useMemo(() => dataSource.reduce((sum, item) => sum + item.height, 0), [dataSource]);
76
80
  const totalWidth = useMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
77
81
  const binarySearchIndex = useCallback((items, target) => {
@@ -132,7 +136,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
132
136
  result.push(dataSource[rowIndex - 1]); // fixedIndex가 범위에 포함되지 않으면 첫 번째에 추가
133
137
  }
134
138
  return result;
135
- }, [dataSource, start, end]);
139
+ }, [__randomDataSourceKey, JSON.stringify(dataSource), start, end]);
136
140
  const startColumnIndex = useMemo(() => Math.max(0, binarySearchIndex(cumulativeWidths, scrollLeft) - overscanColumn), [columns, cumulativeWidths, scrollLeft, binarySearchIndex, overscanColumn]);
137
141
  const offsetTop = useMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
138
142
  const offsetLeft = useMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
@@ -267,6 +271,7 @@ const VirtualItem = React.memo(({ column, row, isFocus, editStatus, rowIndex, })
267
271
  export const TwoDimensionalVirtualizedList = React.memo(() => {
268
272
  // 마우스 다운 시작지점점
269
273
  const gridRef = useGridApiContext();
274
+ useAddApi(gridRef);
270
275
  const mouseDownStartPointRef = useRef(0);
271
276
  const mouseDownStartWidthRef = useRef(0);
272
277
  const colIndexRef = useRef(0);
@@ -2,9 +2,7 @@ import React from "react";
2
2
  import { useGridApiMethod } from "../useGridApiMethod";
3
3
  import { classes } from "../../types/classes";
4
4
  import { defaultProps } from "../../common/constants";
5
- import { useStore } from "../../provider/GridStoreContent";
6
5
  export default function usePublicTest(apiRef) {
7
- const store = useStore();
8
6
  const getData = React.useCallback(() => {
9
7
  return apiRef.current.store.state.dataSource;
10
8
  }, []);
@@ -25,7 +23,12 @@ export default function usePublicTest(apiRef) {
25
23
  }, []);
26
24
  const setRowHeight = React.useCallback((rowIndex, height = defaultProps.height) => {
27
25
  apiRef.current.store.state.dataSource[rowIndex] = Object.assign(Object.assign({}, apiRef.current.store.state.dataSource[rowIndex]), { height: height });
28
- store.setState(["state", "dataSource"], apiRef.current.store.state.dataSource);
26
+ apiRef.current.store.__randomDataSourceKey = `${Math.random()}`;
27
+ console.log("!!!", apiRef.current.store.__randomDataSourceKey);
28
+ apiRef.current.store.updateKeyTemp.add("__randomDataSourceKey");
29
+ setTimeout(() => {
30
+ apiRef.current.getPublicApi().forceUpdate();
31
+ }, 0);
29
32
  }, []);
30
33
  const apiMethods = { addCellRange, getData, scrollToRowIndex, setRowHeight };
31
34
  useGridApiMethod(apiRef, apiMethods, "public");
@@ -31,7 +31,11 @@ export default function useInternalPrivateApi(apiRef) {
31
31
  const basicStore = setBasicStore(props);
32
32
  apiRef.current = Object.assign(Object.assign({}, apiRef.current), { store: Object.assign(Object.assign({}, apiRef.current.store), { original: basicStore, state: Object.assign({}, basicStore),
33
33
  // 현재 내부에서 사용되는 속성은 수동으로 초기화 해야함.
34
- __cellRange: [], __cellRangeTemp: {} }) });
34
+ __cellRange: [], __cellRangeTemp: {},
35
+ /**
36
+ * 누적 높이 캐싱
37
+ */
38
+ cumulativeHeights: [], updateKeyTemp: new Set(), __randomDataSourceKey: "" }) });
35
39
  return apiRef.current;
36
40
  }, []);
37
41
  const setBasicStore = React.useCallback((props) => {
@@ -121,16 +125,17 @@ export default function useInternalPrivateApi(apiRef) {
121
125
  sum += (_a = row.height) !== null && _a !== void 0 ? _a : 32;
122
126
  return sum;
123
127
  });
124
- apiRef.current.store.heightCache = heightCache;
128
+ apiRef.current.store.cumulativeHeights = heightCache;
129
+ return heightCache;
125
130
  }, []);
126
131
  const getScrollTop = React.useCallback((rowIndex) => {
127
132
  let low = 0;
128
- let high = apiRef.current.store.heightCache.length - 1;
133
+ let high = apiRef.current.store.cumulativeHeights.length - 1;
129
134
  let result = 0;
130
135
  while (low <= high) {
131
136
  const mid = Math.floor((low + high) / 2);
132
137
  if (mid < rowIndex) {
133
- result = apiRef.current.store.heightCache[mid];
138
+ result = apiRef.current.store.cumulativeHeights[mid];
134
139
  low = mid + 1;
135
140
  }
136
141
  else {
@@ -1,3 +1,4 @@
1
1
  import React from "react";
2
- import DataGridBasicProps, { GirdApiCommon } from "../types/dataGridProps";
3
- export declare function useGridInitialization(apiRef: DataGridBasicProps["gridRef"], props: DataGridBasicProps): React.MutableRefObject<GirdApiCommon<import("../types/dataGridProps").DataGridPrivateApiModel>>;
2
+ import DataGridBasicProps, { DataGridPrivateApiModel, GirdApiCommon } from "../types/dataGridProps";
3
+ export declare function useAddApi(ref: React.MutableRefObject<GirdApiCommon<DataGridPrivateApiModel>>): void;
4
+ export declare function useGridInitialization(apiRef: DataGridBasicProps["gridRef"], props: DataGridBasicProps): React.MutableRefObject<GirdApiCommon<DataGridPrivateApiModel>>;
@@ -2,18 +2,30 @@ import React from "react";
2
2
  import useTest from "./internal/useInternalPrivateApi";
3
3
  import usePublicTest from "./external/usePublicTest";
4
4
  import { useGridApiMethod } from "./useGridApiMethod";
5
+ import { useStore } from "../provider/GridStoreContent";
6
+ import useGridApiContext from "./useGridApiContext";
7
+ export function useAddApi(ref) {
8
+ const store = useStore();
9
+ const gridRef = useGridApiContext();
10
+ const forceUpdate = React.useCallback(() => {
11
+ gridRef.current.store.updateKeyTemp.forEach((v) => {
12
+ //타입 및 코드 정리 필요
13
+ // 그리드 외부에서 접근시
14
+ const value = v.split(",").reduce((acc, key) => acc === null || acc === void 0 ? void 0 : acc[key], gridRef.current.store);
15
+ store.setState([v.split(",")], value);
16
+ });
17
+ // store.setState(gridRef.current.store.updateKeyTemp)
18
+ }, []);
19
+ useGridApiMethod(ref, { forceUpdate }, "public");
20
+ }
5
21
  export function useGridInitialization(apiRef, props) {
6
22
  // const memoizedProps = React.useMemo(() => _.cloneDeep(props), [props]); // props를 메모이제이션
7
23
  const privateAipRef = useGridApiInitialization(apiRef, Object.assign({}, props));
8
24
  usePublicTest(privateAipRef);
9
25
  useTest(privateAipRef);
10
- //test
11
- const [, rawForceUpdate] = React.useState();
12
- // React.useState<GirdApiCommon<DataGridPublicApi>["store"]>();
13
- const forceUpdate = React.useCallback(() => rawForceUpdate(() => privateAipRef.current.store.state),
14
- // () => rawForceUpdate(() => privateAipRef.current.store),
15
- [privateAipRef]);
16
- useGridApiMethod(privateAipRef, { forceUpdate }, "public");
26
+ // const [, rawForceUpdate] = React.useState<any>();
27
+ // const forceUpdate = React.useCallback<DataGridPublicApi["forceUpdate"]>(() => rawForceUpdate(() => privateAipRef.current.store.state), [privateAipRef]);
28
+ // useGridApiMethod(privateAipRef, { forceUpdate }, "public");
17
29
  return privateAipRef;
18
30
  }
19
31
  /**
@@ -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") {
92
+ if (currentPath.length > 0 || prop === "state" || prop === "original" || prop === "__randomDataSourceKey") {
93
93
  if (!isArrayInSet(accessedPaths.current, newPath)) {
94
94
  accessedPaths.current.add(newPath);
95
95
  }
@@ -52,11 +52,24 @@ export interface DataGridOptionPropsModel {
52
52
  * @private
53
53
  * @namespace NoraDataGrid.DataGridBasicStorePropsModel
54
54
  */
55
- interface DataGridBasicStorePropsModel {
55
+ export interface DataGridBasicStorePropsModel {
56
56
  gridContainer: React.RefObject<HTMLDivElement>;
57
- heightCache: number[];
57
+ /**
58
+ * 누적 높이 캐싱
59
+ */
60
+ cumulativeHeights: number[];
58
61
  __cellRange: Array<CellRangeDef>;
59
62
  __cellRangeTemp: CellRangeTempDef;
63
+ /**
64
+ * 변경된 store를 Temp로 관리 합니다.
65
+ * 일괄 업데이트용으로 사용해주세요.
66
+ */
67
+ updateKeyTemp: Set<string>;
68
+ /**
69
+ * dataSource 값이 변경되었을때 값이 변합니다.
70
+ * Object는 변경된 값을 감지하기 어렵기 때문에 별도 키 관리
71
+ */
72
+ __randomDataSourceKey: string;
60
73
  }
61
74
  /**
62
75
  * DataGrid를 구성하는 내부 메소드들을 관리 합니다.
@@ -124,7 +137,7 @@ export interface DataGridPrivateApiModel {
124
137
  */
125
138
  setEditStatus: (editStatus: DataGridStoreDef["state"]["editStatus"]) => Promise<DataGridStoreDef["state"]["editStatus"]>;
126
139
  /**
127
- * 데이터에 있는 모든 행 높이를 초기화 합니다.
140
+ * 데이터에 있는 모든 행 높의 누적값을 생성합니다.
128
141
  * @private
129
142
  * @namespace NoraDataGrid.DataGridPublicApiModel.getData
130
143
  */
@@ -176,7 +189,7 @@ export declare class Store<T> {
176
189
  private updateNestedState;
177
190
  private isPathAffected;
178
191
  }
179
- export interface DataGridStoreDef extends DataGridBasicStorePropsModel {
192
+ export interface DataGridStoreDef extends DataGridBasicStorePropsModel, DataGridBasicStorePropsModel {
180
193
  original: DataGridBasicPropsModel & DataGridOptionPropsModel;
181
194
  state: DataGridBasicPropsModel & DataGridOptionPropsModel;
182
195
  }
@@ -19,6 +19,7 @@ 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);
22
23
  this.state = this.updateNestedState(this.state, fullPath, value);
23
24
  this.notify(fullPath, isUpdate);
24
25
  }
package/lib/esm/App.js CHANGED
@@ -7,13 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
11
- import { useDeferredValue, useEffect, useState } from "react";
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ import { useEffect, useState } from "react";
12
12
  import { DataGrid } from "./DataGrid";
13
13
  import { useGridApiRef } from "./hooks/useGridApiRef";
14
14
  const RenderCell = (params) => {
15
- const [value, setValue] = useState(0);
16
- const test = useDeferredValue(value);
15
+ // const [value, setValue] = useState(0);
16
+ // const test = useDeferredValue(value);
17
17
  useEffect(() => {
18
18
  const tt = () => __awaiter(void 0, void 0, void 0, function* () {
19
19
  let tt = 0;
@@ -33,13 +33,15 @@ const RenderCell = (params) => {
33
33
  // height: Math.floor(Math.random() * 20) + 20,
34
34
  };
35
35
  });
36
- setValue(tt);
36
+ // setValue(tt);
37
37
  });
38
38
  requestIdleCallback(() => {
39
39
  tt();
40
40
  });
41
41
  }, []);
42
- return (_jsxs("div", { style: { background: "green" }, children: [test, params.value] }));
42
+ return (_jsxs("div", { style: { background: "green" }, children: [_jsx("button", { onClick: () => {
43
+ params.gridRef.current.setRowHeight(1, 100);
44
+ }, children: "??" }), params.value] }));
43
45
  };
44
46
  const RenderEditCell = (params) => {
45
47
  return (_jsx(_Fragment, { children: _jsx("input", Object.assign({}, params, { style: { background: "yellow" } })) }));
@@ -164,7 +166,7 @@ function App() {
164
166
  const ref = useGridApiRef();
165
167
  const [dataSource, setDataSource] = useState([]);
166
168
  const handleDataSource = () => {
167
- const data = Array.from({ length: 1000000 }, (_, i) => {
169
+ const data = Array.from({ length: 1000 }, (_, i) => {
168
170
  return {
169
171
  id: i,
170
172
  code: `test-${i}`,
@@ -188,7 +190,7 @@ function App() {
188
190
  }, children: "\uB370\uC774\uD130 set" }), _jsx("button", { onClick: () => {
189
191
  const data = ref.current.getData();
190
192
  console.log("!!!!!", data);
191
- }, children: "dd" }), _jsx("button", { children: "dd" }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { gridRef: ref, columns: columns, dataSource: dataSource }) }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { columns: columns, dataSource: dataSource }) }), _jsx("button", { children: "dd" })] }));
193
+ }, children: "\uD558" }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { gridRef: ref, columns: columns, dataSource: dataSource }) }), _jsx("div", { style: { width: "1200px", height: "300px" }, children: _jsx(DataGrid, { columns: columns, dataSource: dataSource }) }), _jsx("button", { children: "dd" })] }));
192
194
  }
193
195
  export const initialItemsData = () => Array.from({ length: 10 }, (_, i) => {
194
196
  return {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,
@@ -11,6 +11,7 @@ import { EditStatus } from "../types/dataGridCoreEnum";
11
11
  import CellMode from "./cell/CellMode";
12
12
  import ImeComponent from "./ime/IMEComponent";
13
13
  import NoDataComponent from "./body/NoDataComponent";
14
+ import { useAddApi } from "../hooks/useGridInitialization";
14
15
  const initialWindowWidth = 800;
15
16
  export const initialWindowHeight = 500;
16
17
  const overscanTopRow = 4;
@@ -72,6 +73,9 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
72
73
  const { dataSource } = useSelector((store) => ({
73
74
  dataSource: store.state.dataSource,
74
75
  }));
76
+ const { __randomDataSourceKey } = useSelector((store) => ({
77
+ __randomDataSourceKey: store.__randomDataSourceKey,
78
+ }));
75
79
  const totalHeight = useMemo(() => dataSource.reduce((sum, item) => sum + item.height, 0), [dataSource]);
76
80
  const totalWidth = useMemo(() => columns.reduce((sum, column) => sum + Number(column.width), 0) || 0, [columns]);
77
81
  const binarySearchIndex = useCallback((items, target) => {
@@ -132,7 +136,7 @@ const DynamicVirtualScroll = React.memo(({ children }) => {
132
136
  result.push(dataSource[rowIndex - 1]); // fixedIndex가 범위에 포함되지 않으면 첫 번째에 추가
133
137
  }
134
138
  return result;
135
- }, [dataSource, start, end]);
139
+ }, [__randomDataSourceKey, JSON.stringify(dataSource), start, end]);
136
140
  const startColumnIndex = useMemo(() => Math.max(0, binarySearchIndex(cumulativeWidths, scrollLeft) - overscanColumn), [columns, cumulativeWidths, scrollLeft, binarySearchIndex, overscanColumn]);
137
141
  const offsetTop = useMemo(() => cumulativeHeights[start] || 0, [cumulativeHeights, start]);
138
142
  const offsetLeft = useMemo(() => cumulativeWidths[startColumnIndex] || 0, [cumulativeWidths, startColumnIndex]);
@@ -267,6 +271,7 @@ const VirtualItem = React.memo(({ column, row, isFocus, editStatus, rowIndex, })
267
271
  export const TwoDimensionalVirtualizedList = React.memo(() => {
268
272
  // 마우스 다운 시작지점점
269
273
  const gridRef = useGridApiContext();
274
+ useAddApi(gridRef);
270
275
  const mouseDownStartPointRef = useRef(0);
271
276
  const mouseDownStartWidthRef = useRef(0);
272
277
  const colIndexRef = useRef(0);
@@ -2,9 +2,7 @@ import React from "react";
2
2
  import { useGridApiMethod } from "../useGridApiMethod";
3
3
  import { classes } from "../../types/classes";
4
4
  import { defaultProps } from "../../common/constants";
5
- import { useStore } from "../../provider/GridStoreContent";
6
5
  export default function usePublicTest(apiRef) {
7
- const store = useStore();
8
6
  const getData = React.useCallback(() => {
9
7
  return apiRef.current.store.state.dataSource;
10
8
  }, []);
@@ -25,7 +23,12 @@ export default function usePublicTest(apiRef) {
25
23
  }, []);
26
24
  const setRowHeight = React.useCallback((rowIndex, height = defaultProps.height) => {
27
25
  apiRef.current.store.state.dataSource[rowIndex] = Object.assign(Object.assign({}, apiRef.current.store.state.dataSource[rowIndex]), { height: height });
28
- store.setState(["state", "dataSource"], apiRef.current.store.state.dataSource);
26
+ apiRef.current.store.__randomDataSourceKey = `${Math.random()}`;
27
+ console.log("!!!", apiRef.current.store.__randomDataSourceKey);
28
+ apiRef.current.store.updateKeyTemp.add("__randomDataSourceKey");
29
+ setTimeout(() => {
30
+ apiRef.current.getPublicApi().forceUpdate();
31
+ }, 0);
29
32
  }, []);
30
33
  const apiMethods = { addCellRange, getData, scrollToRowIndex, setRowHeight };
31
34
  useGridApiMethod(apiRef, apiMethods, "public");
@@ -31,7 +31,11 @@ export default function useInternalPrivateApi(apiRef) {
31
31
  const basicStore = setBasicStore(props);
32
32
  apiRef.current = Object.assign(Object.assign({}, apiRef.current), { store: Object.assign(Object.assign({}, apiRef.current.store), { original: basicStore, state: Object.assign({}, basicStore),
33
33
  // 현재 내부에서 사용되는 속성은 수동으로 초기화 해야함.
34
- __cellRange: [], __cellRangeTemp: {} }) });
34
+ __cellRange: [], __cellRangeTemp: {},
35
+ /**
36
+ * 누적 높이 캐싱
37
+ */
38
+ cumulativeHeights: [], updateKeyTemp: new Set(), __randomDataSourceKey: "" }) });
35
39
  return apiRef.current;
36
40
  }, []);
37
41
  const setBasicStore = React.useCallback((props) => {
@@ -121,16 +125,17 @@ export default function useInternalPrivateApi(apiRef) {
121
125
  sum += (_a = row.height) !== null && _a !== void 0 ? _a : 32;
122
126
  return sum;
123
127
  });
124
- apiRef.current.store.heightCache = heightCache;
128
+ apiRef.current.store.cumulativeHeights = heightCache;
129
+ return heightCache;
125
130
  }, []);
126
131
  const getScrollTop = React.useCallback((rowIndex) => {
127
132
  let low = 0;
128
- let high = apiRef.current.store.heightCache.length - 1;
133
+ let high = apiRef.current.store.cumulativeHeights.length - 1;
129
134
  let result = 0;
130
135
  while (low <= high) {
131
136
  const mid = Math.floor((low + high) / 2);
132
137
  if (mid < rowIndex) {
133
- result = apiRef.current.store.heightCache[mid];
138
+ result = apiRef.current.store.cumulativeHeights[mid];
134
139
  low = mid + 1;
135
140
  }
136
141
  else {
@@ -1,3 +1,4 @@
1
1
  import React from "react";
2
- import DataGridBasicProps, { GirdApiCommon } from "../types/dataGridProps";
3
- export declare function useGridInitialization(apiRef: DataGridBasicProps["gridRef"], props: DataGridBasicProps): React.MutableRefObject<GirdApiCommon<import("../types/dataGridProps").DataGridPrivateApiModel>>;
2
+ import DataGridBasicProps, { DataGridPrivateApiModel, GirdApiCommon } from "../types/dataGridProps";
3
+ export declare function useAddApi(ref: React.MutableRefObject<GirdApiCommon<DataGridPrivateApiModel>>): void;
4
+ export declare function useGridInitialization(apiRef: DataGridBasicProps["gridRef"], props: DataGridBasicProps): React.MutableRefObject<GirdApiCommon<DataGridPrivateApiModel>>;
@@ -2,18 +2,30 @@ import React from "react";
2
2
  import useTest from "./internal/useInternalPrivateApi";
3
3
  import usePublicTest from "./external/usePublicTest";
4
4
  import { useGridApiMethod } from "./useGridApiMethod";
5
+ import { useStore } from "../provider/GridStoreContent";
6
+ import useGridApiContext from "./useGridApiContext";
7
+ export function useAddApi(ref) {
8
+ const store = useStore();
9
+ const gridRef = useGridApiContext();
10
+ const forceUpdate = React.useCallback(() => {
11
+ gridRef.current.store.updateKeyTemp.forEach((v) => {
12
+ //타입 및 코드 정리 필요
13
+ // 그리드 외부에서 접근시
14
+ const value = v.split(",").reduce((acc, key) => acc === null || acc === void 0 ? void 0 : acc[key], gridRef.current.store);
15
+ store.setState([v.split(",")], value);
16
+ });
17
+ // store.setState(gridRef.current.store.updateKeyTemp)
18
+ }, []);
19
+ useGridApiMethod(ref, { forceUpdate }, "public");
20
+ }
5
21
  export function useGridInitialization(apiRef, props) {
6
22
  // const memoizedProps = React.useMemo(() => _.cloneDeep(props), [props]); // props를 메모이제이션
7
23
  const privateAipRef = useGridApiInitialization(apiRef, Object.assign({}, props));
8
24
  usePublicTest(privateAipRef);
9
25
  useTest(privateAipRef);
10
- //test
11
- const [, rawForceUpdate] = React.useState();
12
- // React.useState<GirdApiCommon<DataGridPublicApi>["store"]>();
13
- const forceUpdate = React.useCallback(() => rawForceUpdate(() => privateAipRef.current.store.state),
14
- // () => rawForceUpdate(() => privateAipRef.current.store),
15
- [privateAipRef]);
16
- useGridApiMethod(privateAipRef, { forceUpdate }, "public");
26
+ // const [, rawForceUpdate] = React.useState<any>();
27
+ // const forceUpdate = React.useCallback<DataGridPublicApi["forceUpdate"]>(() => rawForceUpdate(() => privateAipRef.current.store.state), [privateAipRef]);
28
+ // useGridApiMethod(privateAipRef, { forceUpdate }, "public");
17
29
  return privateAipRef;
18
30
  }
19
31
  /**
@@ -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") {
92
+ if (currentPath.length > 0 || prop === "state" || prop === "original" || prop === "__randomDataSourceKey") {
93
93
  if (!isArrayInSet(accessedPaths.current, newPath)) {
94
94
  accessedPaths.current.add(newPath);
95
95
  }
@@ -52,11 +52,24 @@ export interface DataGridOptionPropsModel {
52
52
  * @private
53
53
  * @namespace NoraDataGrid.DataGridBasicStorePropsModel
54
54
  */
55
- interface DataGridBasicStorePropsModel {
55
+ export interface DataGridBasicStorePropsModel {
56
56
  gridContainer: React.RefObject<HTMLDivElement>;
57
- heightCache: number[];
57
+ /**
58
+ * 누적 높이 캐싱
59
+ */
60
+ cumulativeHeights: number[];
58
61
  __cellRange: Array<CellRangeDef>;
59
62
  __cellRangeTemp: CellRangeTempDef;
63
+ /**
64
+ * 변경된 store를 Temp로 관리 합니다.
65
+ * 일괄 업데이트용으로 사용해주세요.
66
+ */
67
+ updateKeyTemp: Set<string>;
68
+ /**
69
+ * dataSource 값이 변경되었을때 값이 변합니다.
70
+ * Object는 변경된 값을 감지하기 어렵기 때문에 별도 키 관리
71
+ */
72
+ __randomDataSourceKey: string;
60
73
  }
61
74
  /**
62
75
  * DataGrid를 구성하는 내부 메소드들을 관리 합니다.
@@ -124,7 +137,7 @@ export interface DataGridPrivateApiModel {
124
137
  */
125
138
  setEditStatus: (editStatus: DataGridStoreDef["state"]["editStatus"]) => Promise<DataGridStoreDef["state"]["editStatus"]>;
126
139
  /**
127
- * 데이터에 있는 모든 행 높이를 초기화 합니다.
140
+ * 데이터에 있는 모든 행 높의 누적값을 생성합니다.
128
141
  * @private
129
142
  * @namespace NoraDataGrid.DataGridPublicApiModel.getData
130
143
  */
@@ -176,7 +189,7 @@ export declare class Store<T> {
176
189
  private updateNestedState;
177
190
  private isPathAffected;
178
191
  }
179
- export interface DataGridStoreDef extends DataGridBasicStorePropsModel {
192
+ export interface DataGridStoreDef extends DataGridBasicStorePropsModel, DataGridBasicStorePropsModel {
180
193
  original: DataGridBasicPropsModel & DataGridOptionPropsModel;
181
194
  state: DataGridBasicPropsModel & DataGridOptionPropsModel;
182
195
  }
@@ -19,6 +19,7 @@ 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);
22
23
  this.state = this.updateNestedState(this.state, fullPath, value);
23
24
  this.notify(fullPath, isUpdate);
24
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noraent/nora-datagrid",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "module": "./lib/esm/index.js",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "private": false,