@adaptabletools/adaptable-react-aggrid 20.0.0-canary.2 → 20.0.0-canary.4
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/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptabletools/adaptable-react-aggrid",
|
|
3
|
-
"version": "20.0.0-canary.
|
|
3
|
+
"version": "20.0.0-canary.4",
|
|
4
4
|
"description": "React version of AdapTable - the powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "contact sales@adaptabletools.com for details",
|
|
7
7
|
"typings": "src/index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"tslib": "^2.8.1",
|
|
10
|
-
"@adaptabletools/adaptable": "20.0.0-canary.
|
|
10
|
+
"@adaptabletools/adaptable": "20.0.0-canary.4"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"ag-grid-enterprise": ">=33.0.0",
|
|
@@ -9,6 +9,7 @@ declare enum AdaptableAgGridStateTransitions {
|
|
|
9
9
|
INITIALIZE_AG_GRID = "INITIALIZE_AG_GRID"
|
|
10
10
|
}
|
|
11
11
|
export declare const useAdaptableAgGridContext: () => {
|
|
12
|
+
id: string;
|
|
12
13
|
adaptableProps: AdaptableReactProps;
|
|
13
14
|
modules: Module[];
|
|
14
15
|
onAdaptableReady: (adaptableReadyInfo: AdaptableReadyInfo) => void;
|
|
@@ -21,6 +22,7 @@ export declare const useAdaptableAgGridContext: () => {
|
|
|
21
22
|
setAgGridProps: (props: AgGridReactPropsWithoutGridOptionsAndModules) => void;
|
|
22
23
|
gridOptions: GridOptions;
|
|
23
24
|
setGridOptions: (gridOptions: GridOptions) => void;
|
|
25
|
+
gridApiPromiseReject: (reason?: any) => void;
|
|
24
26
|
};
|
|
25
27
|
export interface AdaptableProviderProps<TData = any> {
|
|
26
28
|
gridOptions: GridOptions<TData>;
|
|
@@ -3,6 +3,7 @@ import { AgGridReact } from 'ag-grid-react';
|
|
|
3
3
|
import AdaptableReactComponent from './AdaptableReact';
|
|
4
4
|
import { _ALL_GRID_OPTIONS, } from 'ag-grid-enterprise';
|
|
5
5
|
import { diff } from '@adaptabletools/adaptable/src/Utilities/Extensions/ObjectExtensions';
|
|
6
|
+
import { useId, useState } from 'react';
|
|
6
7
|
var AdaptableAgGridStateTransitions;
|
|
7
8
|
(function (AdaptableAgGridStateTransitions) {
|
|
8
9
|
AdaptableAgGridStateTransitions["AG_GRID_EMIT_PROPS"] = "AG_GRID_EMIT_PROPS";
|
|
@@ -19,23 +20,36 @@ export const useAdaptableAgGridContext = () => {
|
|
|
19
20
|
}
|
|
20
21
|
return context;
|
|
21
22
|
};
|
|
23
|
+
function usePromise() {
|
|
24
|
+
const [promise] = useState(() => {
|
|
25
|
+
let resolve;
|
|
26
|
+
let reject;
|
|
27
|
+
const promise = new Promise((a, b) => {
|
|
28
|
+
resolve = a;
|
|
29
|
+
reject = b;
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
promise,
|
|
33
|
+
resolve,
|
|
34
|
+
reject,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
return promise;
|
|
38
|
+
}
|
|
22
39
|
const AdaptableProvider = (props) => {
|
|
23
40
|
const [currentTransition, setCurrentTransition] = React.useState(AdaptableAgGridStateTransitions.AG_GRID_EMIT_PROPS);
|
|
41
|
+
const useIdResult = useId();
|
|
42
|
+
const id = `${props.adaptableOptions.adaptableId || 'adaptable'}-${useIdResult}`;
|
|
24
43
|
const [agGridProps, setAgGridProps] = React.useState();
|
|
25
44
|
const [gridOptions, setGridOptions] = React.useState(props.gridOptions);
|
|
26
45
|
const [agGridApi, setAgGridApi] = React.useState();
|
|
27
46
|
const [adaptableApi, setAdaptableApi] = React.useState();
|
|
28
47
|
const adaptableAgGridReactRenderedRef = React.useRef(false);
|
|
29
|
-
const gridApiPromiseResolve =
|
|
30
|
-
const gridApiPromise = React.useMemo(() => {
|
|
31
|
-
return new Promise((resolve) => {
|
|
32
|
-
gridApiPromiseResolve.current = resolve;
|
|
33
|
-
});
|
|
34
|
-
}, []);
|
|
48
|
+
const { promise: gridApiPromise, resolve: gridApiPromiseResolve, reject: gridApiPromiseReject, } = usePromise();
|
|
35
49
|
const handleSetGridApi = React.useCallback((api) => {
|
|
36
50
|
setAgGridApi(api);
|
|
37
|
-
gridApiPromiseResolve
|
|
38
|
-
}, []);
|
|
51
|
+
gridApiPromiseResolve(api);
|
|
52
|
+
}, [gridApiPromiseResolve]);
|
|
39
53
|
const onAdaptableReady = React.useCallback((adaptableReadyInfo) => {
|
|
40
54
|
setAdaptableApi(adaptableReadyInfo.adaptableApi);
|
|
41
55
|
props.onAdaptableReady?.(adaptableReadyInfo);
|
|
@@ -65,6 +79,7 @@ const AdaptableProvider = (props) => {
|
|
|
65
79
|
};
|
|
66
80
|
}, []);
|
|
67
81
|
return (React.createElement(AdaptableAgGridContext.Provider, { value: {
|
|
82
|
+
id,
|
|
68
83
|
onAdaptableReady,
|
|
69
84
|
adaptableApi,
|
|
70
85
|
transition: currentTransition,
|
|
@@ -74,6 +89,7 @@ const AdaptableProvider = (props) => {
|
|
|
74
89
|
setGridOptions,
|
|
75
90
|
agGridApi,
|
|
76
91
|
setAgGridApi: handleSetGridApi,
|
|
92
|
+
gridApiPromiseReject,
|
|
77
93
|
agGridProps,
|
|
78
94
|
setAgGridProps: (agGridProps) => {
|
|
79
95
|
adaptableAgGridReactRenderedRef.current = true;
|
|
@@ -99,7 +115,7 @@ const AdaptableProvider = (props) => {
|
|
|
99
115
|
};
|
|
100
116
|
// -- ADAPTABLE UI WRAPPER -
|
|
101
117
|
const AdaptableUI = (props) => {
|
|
102
|
-
const { adaptableProps, modules, gridOptions, transition, onAdaptableReady } = useAdaptableAgGridContext();
|
|
118
|
+
const { adaptableProps, modules, gridOptions, transition, onAdaptableReady, id } = useAdaptableAgGridContext();
|
|
103
119
|
if (transition === AdaptableAgGridStateTransitions.AG_GRID_EMIT_PROPS) {
|
|
104
120
|
return null;
|
|
105
121
|
}
|
|
@@ -107,10 +123,12 @@ const AdaptableUI = (props) => {
|
|
|
107
123
|
// This needs to be first, so gridOptions is the one passed and not from props
|
|
108
124
|
, { ...adaptableProps, onAdaptableReady: onAdaptableReady, style: props.style, className: props.className, gridOptions: gridOptions, modules: modules }));
|
|
109
125
|
};
|
|
126
|
+
const readyAGGridAdaptableInstances = new Map();
|
|
127
|
+
const destroyCalledInstances = new Map();
|
|
110
128
|
const AdaptableAgGridReact = (props) => {
|
|
111
129
|
const agGridRef = React.useRef(null);
|
|
112
130
|
const [isAgGridReady, setAgGridIsReady] = React.useState(false);
|
|
113
|
-
const { modules, gridOptions, setAgGridApi, transition, setAgGridProps, agGridApi } = useAdaptableAgGridContext();
|
|
131
|
+
const { modules, gridOptions, setAgGridApi, transition, setAgGridProps, agGridApi, gridApiPromiseReject, id, } = useAdaptableAgGridContext();
|
|
114
132
|
const propsRef = React.useRef(props);
|
|
115
133
|
React.useEffect(() => {
|
|
116
134
|
const prevProps = propsRef.current;
|
|
@@ -155,6 +173,7 @@ const AdaptableAgGridReact = (props) => {
|
|
|
155
173
|
return null;
|
|
156
174
|
}
|
|
157
175
|
return (React.createElement(AgGridReact, { ref: agGridRef, ...agGridPassThroughProps, modules: modules, onGridReady: (event) => {
|
|
176
|
+
// this is not called extra in strict mode
|
|
158
177
|
setAgGridApi(event.api);
|
|
159
178
|
if (props.onGridReady) {
|
|
160
179
|
props.onGridReady(event);
|
|
@@ -163,6 +182,38 @@ const AdaptableAgGridReact = (props) => {
|
|
|
163
182
|
gridOptions.onGridReady(event);
|
|
164
183
|
}
|
|
165
184
|
setAgGridIsReady(true);
|
|
185
|
+
readyAGGridAdaptableInstances.set(id, true);
|
|
186
|
+
}, onGridPreDestroyed: () => {
|
|
187
|
+
// this is extra called in strict mode
|
|
188
|
+
// when doing the double render
|
|
189
|
+
// when we are in strict mode,
|
|
190
|
+
// if gridPreDestroyed is called the second time
|
|
191
|
+
// then we know it's a real destroy
|
|
192
|
+
if (destroyCalledInstances.get(id) === true) {
|
|
193
|
+
// so go ahead and reject the promise
|
|
194
|
+
gridApiPromiseReject('ag grid destroy');
|
|
195
|
+
destroyCalledInstances.delete(id);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
destroyCalledInstances.set(id, true);
|
|
199
|
+
if (readyAGGridAdaptableInstances.get(id) === true) {
|
|
200
|
+
// in strict mode, gridPreDestroyed is called extra on mount, before the onGridReady
|
|
201
|
+
// so if the instance is ready, we know it's a real destroy, not due to strict mode
|
|
202
|
+
// so we can reject the promise
|
|
203
|
+
readyAGGridAdaptableInstances.delete(id);
|
|
204
|
+
gridApiPromiseReject('ag grid destroy');
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// STILL, we might have an exception
|
|
208
|
+
// when strict mode is not enabled,
|
|
209
|
+
// then we really need to destroy the instance
|
|
210
|
+
// but we'll only do this if the instance is not in readyAGGridAdaptableInstances
|
|
211
|
+
setTimeout(() => {
|
|
212
|
+
if (!readyAGGridAdaptableInstances.get(id)) {
|
|
213
|
+
gridApiPromiseReject('ag grid destroy');
|
|
214
|
+
}
|
|
215
|
+
}, 1000);
|
|
216
|
+
}
|
|
166
217
|
}, gridOptions: gridOptions }));
|
|
167
218
|
};
|
|
168
219
|
export const Adaptable = {
|
|
@@ -1,77 +1,71 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useMemo, useState, useRef } from 'react';
|
|
2
|
+
import { useMemo, useState, useRef, useCallback } from 'react';
|
|
3
3
|
import { ColumnApiModule } from 'ag-grid-enterprise';
|
|
4
4
|
import { _AdaptableAgGrid } from '@adaptabletools/adaptable/agGrid';
|
|
5
5
|
import { setupFrameworkComponents } from '../setupFrameworkComponents';
|
|
6
6
|
import join from '../utils/join';
|
|
7
|
+
import { useAdaptableAgGridContext, } from './AdaptableProvider';
|
|
7
8
|
const getRandomInt = (max) => Math.floor(Math.random() * Math.floor(max));
|
|
8
9
|
const columnApiModule = ColumnApiModule;
|
|
10
|
+
const startedInstances = new Map();
|
|
11
|
+
const successInstances = new Map();
|
|
12
|
+
const isInstanceStarted = (id) => {
|
|
13
|
+
return startedInstances.get(id) === true;
|
|
14
|
+
};
|
|
9
15
|
const AdaptableReact = ({ adaptableOptions, gridOptions, onAdaptableReady, ...props }) => {
|
|
16
|
+
const { id } = useAdaptableAgGridContext();
|
|
10
17
|
const seedId = useMemo(() => `${getRandomInt(1000)}-${Date.now()}`, []);
|
|
11
|
-
const adaptableContainerId = `adaptable-${seedId}`;
|
|
18
|
+
const adaptableContainerId = `adaptable-${id}-${seedId}`;
|
|
12
19
|
const [adaptableJSXElement, setAdaptableJSXElement] = useState(null);
|
|
13
|
-
const isMounted = useRef(true);
|
|
14
20
|
const adaptableApiRef = useRef(null);
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
setAdaptableJSXElement(api.internalApi.getAdaptableJSXElement());
|
|
57
|
-
if (onAdaptableReady) {
|
|
58
|
-
api.eventApi.on('AdaptableReady', onAdaptableReady);
|
|
59
|
-
}
|
|
60
|
-
setupFrameworkComponents(api);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
isMounted.current = false;
|
|
65
|
-
cleanup();
|
|
21
|
+
const cleanup = useCallback(() => {
|
|
22
|
+
if (adaptableApiRef.current && successInstances.get(id) === true) {
|
|
23
|
+
adaptableApiRef.current.destroy({
|
|
24
|
+
unmount: true,
|
|
25
|
+
destroyAgGrid: false,
|
|
26
|
+
});
|
|
27
|
+
adaptableApiRef.current = null;
|
|
28
|
+
}
|
|
29
|
+
}, [id]);
|
|
30
|
+
const containerRef = useCallback((node) => {
|
|
31
|
+
if (!node) {
|
|
32
|
+
cleanup();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (isInstanceStarted(id)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
startedInstances.set(id, true);
|
|
39
|
+
_AdaptableAgGrid
|
|
40
|
+
._initInternal({
|
|
41
|
+
modules: props.modules,
|
|
42
|
+
adaptableOptions: {
|
|
43
|
+
...adaptableOptions,
|
|
44
|
+
containerOptions: {
|
|
45
|
+
...adaptableOptions.containerOptions,
|
|
46
|
+
adaptableContainer: node,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
gridOptions,
|
|
50
|
+
variant: 'react',
|
|
51
|
+
renderAgGridFrameworkComponent: props.renderAgGridFrameworkComponent,
|
|
52
|
+
getAgGridColumnApiModuleReference: () => {
|
|
53
|
+
return columnApiModule;
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
.then((api) => {
|
|
57
|
+
adaptableApiRef.current = api;
|
|
58
|
+
//see #no_additional_react_root
|
|
59
|
+
setAdaptableJSXElement(api.internalApi.getAdaptableJSXElement());
|
|
60
|
+
if (onAdaptableReady) {
|
|
61
|
+
api.eventApi.on('AdaptableReady', onAdaptableReady);
|
|
66
62
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
74
|
-
}, []);
|
|
63
|
+
setupFrameworkComponents(api);
|
|
64
|
+
successInstances.set(id, true);
|
|
65
|
+
}, (err) => {
|
|
66
|
+
console.error('Failed to initialize AdaptableReact component', err);
|
|
67
|
+
});
|
|
68
|
+
}, [id]);
|
|
75
69
|
return (React.createElement("div", { style: props.style, ref: containerRef, id: adaptableContainerId, className: join(props.className, 'ab__react-wrapper') }, adaptableJSXElement));
|
|
76
70
|
};
|
|
77
71
|
export default AdaptableReact;
|