@adaptabletools/adaptable-react-aggrid-cjs 20.0.0-canary.3 → 20.0.0-canary.5

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable-react-aggrid-cjs",
3
- "version": "20.0.0-canary.3",
3
+ "version": "20.0.0-canary.5",
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",
@@ -8,7 +8,7 @@
8
8
  "typings": "src/index.d.ts",
9
9
  "dependencies": {
10
10
  "tslib": "^2.8.1",
11
- "@adaptabletools/adaptable-cjs": "20.0.0-canary.3"
11
+ "@adaptabletools/adaptable-cjs": "20.0.0-canary.5"
12
12
  },
13
13
  "peerDependencies": {
14
14
  "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>;
@@ -7,6 +7,7 @@ const ag_grid_react_1 = require("ag-grid-react");
7
7
  const AdaptableReact_1 = tslib_1.__importDefault(require("./AdaptableReact"));
8
8
  const ag_grid_enterprise_1 = require("ag-grid-enterprise");
9
9
  const ObjectExtensions_1 = require("@adaptabletools/adaptable-cjs/src/Utilities/Extensions/ObjectExtensions");
10
+ const react_1 = require("react");
10
11
  var AdaptableAgGridStateTransitions;
11
12
  (function (AdaptableAgGridStateTransitions) {
12
13
  AdaptableAgGridStateTransitions["AG_GRID_EMIT_PROPS"] = "AG_GRID_EMIT_PROPS";
@@ -24,23 +25,36 @@ const useAdaptableAgGridContext = () => {
24
25
  return context;
25
26
  };
26
27
  exports.useAdaptableAgGridContext = useAdaptableAgGridContext;
28
+ function usePromise() {
29
+ const [promise] = (0, react_1.useState)(() => {
30
+ let resolve;
31
+ let reject;
32
+ const promise = new Promise((a, b) => {
33
+ resolve = a;
34
+ reject = b;
35
+ });
36
+ return {
37
+ promise,
38
+ resolve,
39
+ reject,
40
+ };
41
+ });
42
+ return promise;
43
+ }
27
44
  const AdaptableProvider = (props) => {
28
45
  const [currentTransition, setCurrentTransition] = React.useState(AdaptableAgGridStateTransitions.AG_GRID_EMIT_PROPS);
46
+ const useIdResult = (0, react_1.useId)();
47
+ const id = `${props.adaptableOptions.adaptableId || 'adaptable'}-${useIdResult}`;
29
48
  const [agGridProps, setAgGridProps] = React.useState();
30
49
  const [gridOptions, setGridOptions] = React.useState(props.gridOptions);
31
50
  const [agGridApi, setAgGridApi] = React.useState();
32
51
  const [adaptableApi, setAdaptableApi] = React.useState();
33
52
  const adaptableAgGridReactRenderedRef = React.useRef(false);
34
- const gridApiPromiseResolve = React.useRef(null);
35
- const gridApiPromise = React.useMemo(() => {
36
- return new Promise((resolve) => {
37
- gridApiPromiseResolve.current = resolve;
38
- });
39
- }, []);
53
+ const { promise: gridApiPromise, resolve: gridApiPromiseResolve, reject: gridApiPromiseReject, } = usePromise();
40
54
  const handleSetGridApi = React.useCallback((api) => {
41
55
  setAgGridApi(api);
42
- gridApiPromiseResolve.current(api);
43
- }, []);
56
+ gridApiPromiseResolve(api);
57
+ }, [gridApiPromiseResolve]);
44
58
  const onAdaptableReady = React.useCallback((adaptableReadyInfo) => {
45
59
  setAdaptableApi(adaptableReadyInfo.adaptableApi);
46
60
  props.onAdaptableReady?.(adaptableReadyInfo);
@@ -70,6 +84,7 @@ const AdaptableProvider = (props) => {
70
84
  };
71
85
  }, []);
72
86
  return (React.createElement(AdaptableAgGridContext.Provider, { value: {
87
+ id,
73
88
  onAdaptableReady,
74
89
  adaptableApi,
75
90
  transition: currentTransition,
@@ -79,6 +94,7 @@ const AdaptableProvider = (props) => {
79
94
  setGridOptions,
80
95
  agGridApi,
81
96
  setAgGridApi: handleSetGridApi,
97
+ gridApiPromiseReject,
82
98
  agGridProps,
83
99
  setAgGridProps: (agGridProps) => {
84
100
  adaptableAgGridReactRenderedRef.current = true;
@@ -104,7 +120,7 @@ const AdaptableProvider = (props) => {
104
120
  };
105
121
  // -- ADAPTABLE UI WRAPPER -
106
122
  const AdaptableUI = (props) => {
107
- const { adaptableProps, modules, gridOptions, transition, onAdaptableReady } = (0, exports.useAdaptableAgGridContext)();
123
+ const { adaptableProps, modules, gridOptions, transition, onAdaptableReady, id } = (0, exports.useAdaptableAgGridContext)();
108
124
  if (transition === AdaptableAgGridStateTransitions.AG_GRID_EMIT_PROPS) {
109
125
  return null;
110
126
  }
@@ -112,10 +128,12 @@ const AdaptableUI = (props) => {
112
128
  // This needs to be first, so gridOptions is the one passed and not from props
113
129
  , { ...adaptableProps, onAdaptableReady: onAdaptableReady, style: props.style, className: props.className, gridOptions: gridOptions, modules: modules }));
114
130
  };
131
+ const readyAGGridAdaptableInstances = new Map();
132
+ const destroyCalledInstances = new Map();
115
133
  const AdaptableAgGridReact = (props) => {
116
134
  const agGridRef = React.useRef(null);
117
135
  const [isAgGridReady, setAgGridIsReady] = React.useState(false);
118
- const { modules, gridOptions, setAgGridApi, transition, setAgGridProps, agGridApi } = (0, exports.useAdaptableAgGridContext)();
136
+ const { modules, gridOptions, setAgGridApi, transition, setAgGridProps, agGridApi, gridApiPromiseReject, id, } = (0, exports.useAdaptableAgGridContext)();
119
137
  const propsRef = React.useRef(props);
120
138
  React.useEffect(() => {
121
139
  const prevProps = propsRef.current;
@@ -160,6 +178,7 @@ const AdaptableAgGridReact = (props) => {
160
178
  return null;
161
179
  }
162
180
  return (React.createElement(ag_grid_react_1.AgGridReact, { ref: agGridRef, ...agGridPassThroughProps, modules: modules, onGridReady: (event) => {
181
+ // this is not called extra in strict mode
163
182
  setAgGridApi(event.api);
164
183
  if (props.onGridReady) {
165
184
  props.onGridReady(event);
@@ -168,6 +187,38 @@ const AdaptableAgGridReact = (props) => {
168
187
  gridOptions.onGridReady(event);
169
188
  }
170
189
  setAgGridIsReady(true);
190
+ readyAGGridAdaptableInstances.set(id, true);
191
+ }, onGridPreDestroyed: () => {
192
+ // this is extra called in strict mode
193
+ // when doing the double render
194
+ // when we are in strict mode,
195
+ // if gridPreDestroyed is called the second time
196
+ // then we know it's a real destroy
197
+ if (destroyCalledInstances.get(id) === true) {
198
+ // so go ahead and reject the promise
199
+ gridApiPromiseReject('ag grid destroy');
200
+ destroyCalledInstances.delete(id);
201
+ return;
202
+ }
203
+ destroyCalledInstances.set(id, true);
204
+ if (readyAGGridAdaptableInstances.get(id) === true) {
205
+ // in strict mode, gridPreDestroyed is called extra on mount, before the onGridReady
206
+ // so if the instance is ready, we know it's a real destroy, not due to strict mode
207
+ // so we can reject the promise
208
+ readyAGGridAdaptableInstances.delete(id);
209
+ gridApiPromiseReject('ag grid destroy');
210
+ }
211
+ else {
212
+ // STILL, we might have an exception
213
+ // when strict mode is not enabled,
214
+ // then we really need to destroy the instance
215
+ // but we'll only do this if the instance is not in readyAGGridAdaptableInstances
216
+ setTimeout(() => {
217
+ if (!readyAGGridAdaptableInstances.get(id)) {
218
+ gridApiPromiseReject('ag grid destroy');
219
+ }
220
+ }, 1000);
221
+ }
171
222
  }, gridOptions: gridOptions }));
172
223
  };
173
224
  exports.Adaptable = {
@@ -7,74 +7,68 @@ const ag_grid_enterprise_1 = require("ag-grid-enterprise");
7
7
  const agGrid_1 = require("@adaptabletools/adaptable-cjs/agGrid");
8
8
  const setupFrameworkComponents_1 = require("../setupFrameworkComponents");
9
9
  const join_1 = tslib_1.__importDefault(require("../utils/join"));
10
+ const AdaptableProvider_1 = require("./AdaptableProvider");
10
11
  const getRandomInt = (max) => Math.floor(Math.random() * Math.floor(max));
11
12
  const columnApiModule = ag_grid_enterprise_1.ColumnApiModule;
13
+ const startedInstances = new Map();
14
+ const successInstances = new Map();
15
+ const isInstanceStarted = (id) => {
16
+ return startedInstances.get(id) === true;
17
+ };
12
18
  const AdaptableReact = ({ adaptableOptions, gridOptions, onAdaptableReady, ...props }) => {
19
+ const { id } = (0, AdaptableProvider_1.useAdaptableAgGridContext)();
13
20
  const seedId = (0, react_1.useMemo)(() => `${getRandomInt(1000)}-${Date.now()}`, []);
14
- const adaptableContainerId = `adaptable-${seedId}`;
21
+ const adaptableContainerId = `adaptable-${id}-${seedId}`;
15
22
  const [adaptableJSXElement, setAdaptableJSXElement] = (0, react_1.useState)(null);
16
- const isMounted = (0, react_1.useRef)(true);
17
23
  const adaptableApiRef = (0, react_1.useRef)(null);
18
- const containerRef = (0, react_1.useMemo)(() => {
19
- const cleanup = () => {
20
- if (adaptableApiRef.current) {
21
- adaptableApiRef.current.destroy({
22
- unmount: true,
23
- destroyAgGrid: false,
24
- });
25
- adaptableApiRef.current = null;
26
- }
27
- };
28
- return (node) => {
29
- if (node) {
30
- isMounted.current = true;
31
- agGrid_1._AdaptableAgGrid
32
- ._initInternal({
33
- modules: props.modules,
34
- adaptableOptions: {
35
- ...adaptableOptions,
36
- containerOptions: {
37
- ...adaptableOptions.containerOptions,
38
- adaptableContainer: node,
39
- },
40
- },
41
- gridOptions,
42
- variant: 'react',
43
- renderAgGridFrameworkComponent: props.renderAgGridFrameworkComponent,
44
- getAgGridColumnApiModuleReference: () => {
45
- return columnApiModule;
46
- },
47
- })
48
- .then((api) => {
49
- // If the component was unmounted while initializing, cleanup immediately
50
- if (!isMounted.current) {
51
- api.destroy({
52
- unmount: true,
53
- destroyAgGrid: false,
54
- });
55
- return;
56
- }
57
- adaptableApiRef.current = api;
58
- //see #no_additional_react_root
59
- setAdaptableJSXElement(api.internalApi.getAdaptableJSXElement());
60
- if (onAdaptableReady) {
61
- api.eventApi.on('AdaptableReady', onAdaptableReady);
62
- }
63
- (0, setupFrameworkComponents_1.setupFrameworkComponents)(api);
64
- });
65
- }
66
- else {
67
- isMounted.current = false;
68
- cleanup();
24
+ const cleanup = (0, react_1.useCallback)(() => {
25
+ if (adaptableApiRef.current && successInstances.get(id) === true) {
26
+ adaptableApiRef.current.destroy({
27
+ unmount: true,
28
+ destroyAgGrid: false,
29
+ });
30
+ adaptableApiRef.current = null;
31
+ }
32
+ }, [id]);
33
+ const containerRef = (0, react_1.useCallback)((node) => {
34
+ if (!node) {
35
+ cleanup();
36
+ return;
37
+ }
38
+ if (isInstanceStarted(id)) {
39
+ return;
40
+ }
41
+ startedInstances.set(id, true);
42
+ agGrid_1._AdaptableAgGrid
43
+ ._initInternal({
44
+ modules: props.modules,
45
+ adaptableOptions: {
46
+ ...adaptableOptions,
47
+ containerOptions: {
48
+ ...adaptableOptions.containerOptions,
49
+ adaptableContainer: node,
50
+ },
51
+ },
52
+ gridOptions,
53
+ variant: 'react',
54
+ renderAgGridFrameworkComponent: props.renderAgGridFrameworkComponent,
55
+ getAgGridColumnApiModuleReference: () => {
56
+ return columnApiModule;
57
+ },
58
+ })
59
+ .then((api) => {
60
+ adaptableApiRef.current = api;
61
+ //see #no_additional_react_root
62
+ setAdaptableJSXElement(api.internalApi.getAdaptableJSXElement());
63
+ if (onAdaptableReady) {
64
+ api.eventApi.on('AdaptableReady', onAdaptableReady);
69
65
  }
70
- };
71
- }, []);
72
- // Cleanup on component unmount
73
- React.useEffect(() => {
74
- return () => {
75
- isMounted.current = false;
76
- };
77
- }, []);
66
+ (0, setupFrameworkComponents_1.setupFrameworkComponents)(api);
67
+ successInstances.set(id, true);
68
+ }, (err) => {
69
+ console.error('Failed to initialize AdaptableReact component', err);
70
+ });
71
+ }, [id]);
78
72
  return (React.createElement("div", { style: props.style, ref: containerRef, id: adaptableContainerId, className: (0, join_1.default)(props.className, 'ab__react-wrapper') }, adaptableJSXElement));
79
73
  };
80
74
  exports.default = AdaptableReact;