@infinite-table/infinite-react 0.4.13 → 0.5.1

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.
Files changed (282) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/API.md +0 -0
  3. package/build/buildPackageJson.js +43 -0
  4. package/build/scripts/test.js +37 -0
  5. package/bundler.config.js +25 -0
  6. package/globals.d.ts +7 -0
  7. package/package.json +102 -3
  8. package/rollup.config.js +15 -0
  9. package/run-build-deepmap.js +47 -0
  10. package/run-build.js +45 -0
  11. package/run-dts-concat.js +21 -0
  12. package/src/components/CSSVariableWatch.tsx +82 -0
  13. package/src/components/DataSource/BooleanCollectionState.ts +214 -0
  14. package/src/components/DataSource/BooleanDeepCollectionState.ts +208 -0
  15. package/src/components/DataSource/DataSourceContext.ts +20 -0
  16. package/src/components/DataSource/GroupRowsState.ts +74 -0
  17. package/src/components/DataSource/Indexer.ts +27 -0
  18. package/src/components/DataSource/RowSelectionState.ts +763 -0
  19. package/src/components/DataSource/defaultFilterTypes.ts +64 -0
  20. package/src/components/DataSource/index.tsx +108 -0
  21. package/src/components/DataSource/privateHooks/getChangeDetect.ts +7 -0
  22. package/src/components/DataSource/privateHooks/useLoadData.ts +783 -0
  23. package/src/components/DataSource/publicHooks/useDataSource.ts +19 -0
  24. package/src/components/DataSource/publicHooks/useDataSourceActions.ts +14 -0
  25. package/src/components/DataSource/state/getInitialState.ts +494 -0
  26. package/src/components/DataSource/state/normalizeSortInfo.ts +35 -0
  27. package/src/components/DataSource/state/reducer.ts +466 -0
  28. package/src/components/DataSource/state/rowInfoStatus.ts +27 -0
  29. package/src/components/DataSource/types.ts +548 -0
  30. package/src/components/HeadlessTable/HeadlessTableWithPinnedContainers.tsx +142 -0
  31. package/src/components/HeadlessTable/MappedCells.ts +251 -0
  32. package/src/components/HeadlessTable/RawTable.tsx +98 -0
  33. package/src/components/HeadlessTable/ReactHeadlessTableRenderer.tsx +1516 -0
  34. package/src/components/HeadlessTable/index.tsx +234 -0
  35. package/src/components/InfiniteTable/InfiniteCls.css.ts +164 -0
  36. package/src/components/InfiniteTable/InfiniteTableContext.ts +16 -0
  37. package/src/components/InfiniteTable/api/getImperativeApi.ts +391 -0
  38. package/src/components/InfiniteTable/api/getSelectionApi.ts +364 -0
  39. package/src/components/InfiniteTable/api/type.ts +11 -0
  40. package/src/components/InfiniteTable/components/ActiveCellIndicator.css.ts +51 -0
  41. package/src/components/InfiniteTable/components/ActiveCellIndicator.tsx +116 -0
  42. package/src/components/InfiniteTable/components/ActiveRowIndicator.css.ts +56 -0
  43. package/src/components/InfiniteTable/components/ActiveRowIndicator.tsx +94 -0
  44. package/src/components/InfiniteTable/components/CheckBox.css.ts +13 -0
  45. package/src/components/InfiniteTable/components/CheckBox.tsx +96 -0
  46. package/src/components/InfiniteTable/components/FilterEditors.tsx +52 -0
  47. package/src/components/InfiniteTable/components/InfiniteTableBody/InfiniteTableBody.tsx +27 -0
  48. package/src/components/InfiniteTable/components/InfiniteTableBody/index.tsx +1 -0
  49. package/src/components/InfiniteTable/components/InfiniteTableFooter/InfiniteTableFooter.tsx +31 -0
  50. package/src/components/InfiniteTable/components/InfiniteTableFooter/index.tsx +1 -0
  51. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableColumnHeaderFilter.tsx +102 -0
  52. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeader.tsx +163 -0
  53. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderCell.tsx +574 -0
  54. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderGroup.tsx +79 -0
  55. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderTypes.tsx +25 -0
  56. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderWrapper.tsx +185 -0
  57. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/GroupResizeHandle.tsx +159 -0
  58. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/ResizeHandle.css.ts +124 -0
  59. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/columnResizer.ts +166 -0
  60. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/index.tsx +146 -0
  61. package/src/components/InfiniteTable/components/InfiniteTableHeader/buildColumnAndGroupTree.ts +240 -0
  62. package/src/components/InfiniteTable/components/InfiniteTableHeader/header.css.ts +358 -0
  63. package/src/components/InfiniteTable/components/InfiniteTableHeader/index.tsx +1 -0
  64. package/src/components/InfiniteTable/components/InfiniteTableHeader/useColumnGroupResizeHandle.tsx +114 -0
  65. package/src/components/InfiniteTable/components/InfiniteTableHeader/useColumnResizeHandle.tsx +146 -0
  66. package/src/components/InfiniteTable/components/InfiniteTableLicenseFooter/footer.css.ts +7 -0
  67. package/src/components/InfiniteTable/components/InfiniteTableLicenseFooter/index.tsx +110 -0
  68. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx +120 -0
  69. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCellTypes.ts +74 -0
  70. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableColumnCell.tsx +457 -0
  71. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRow.tsx +107 -0
  72. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowClassName.ts +6 -0
  73. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowTypes.ts +32 -0
  74. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowUnvirtualized.tsx +75 -0
  75. package/src/components/InfiniteTable/components/InfiniteTableRow/columnRendering.tsx +263 -0
  76. package/src/components/InfiniteTable/components/InfiniteTableRow/index.tsx +1 -0
  77. package/src/components/InfiniteTable/components/InfiniteTableRow/row.css.ts +74 -0
  78. package/src/components/InfiniteTable/components/InfiniteTableRow/useRowDOMProps.ts +199 -0
  79. package/src/components/InfiniteTable/components/LoadMask.css.ts +34 -0
  80. package/src/components/InfiniteTable/components/LoadMask.tsx +27 -0
  81. package/src/components/InfiniteTable/components/ScrollbarPlaceholder.tsx +56 -0
  82. package/src/components/InfiniteTable/components/cell.css.ts +192 -0
  83. package/src/components/InfiniteTable/components/icons/ArrowDown.tsx +14 -0
  84. package/src/components/InfiniteTable/components/icons/ArrowUp.tsx +14 -0
  85. package/src/components/InfiniteTable/components/icons/ExpanderIcon.css.ts +31 -0
  86. package/src/components/InfiniteTable/components/icons/ExpanderIcon.tsx +63 -0
  87. package/src/components/InfiniteTable/components/icons/Icon.tsx +18 -0
  88. package/src/components/InfiniteTable/components/icons/InfiniteTableIconClassName.ts +1 -0
  89. package/src/components/InfiniteTable/components/icons/LoadingIcon.css.ts +8 -0
  90. package/src/components/InfiniteTable/components/icons/LoadingIcon.tsx +45 -0
  91. package/src/components/InfiniteTable/components/icons/MenuIcon.tsx +50 -0
  92. package/src/components/InfiniteTable/components/icons/SortIcon.tsx +113 -0
  93. package/src/components/InfiniteTable/eventHandlers/eventHandlerTypes.ts +57 -0
  94. package/src/components/InfiniteTable/eventHandlers/index.ts +95 -0
  95. package/src/components/InfiniteTable/eventHandlers/keyboardNavigation.ts +232 -0
  96. package/src/components/InfiniteTable/eventHandlers/keyboardSelection.ts +110 -0
  97. package/src/components/InfiniteTable/eventHandlers/onCellClick.ts +94 -0
  98. package/src/components/InfiniteTable/eventHandlers/onKeyDown.ts +25 -0
  99. package/src/components/InfiniteTable/hooks/adjustColumnOrderForAllColumns.ts +70 -0
  100. package/src/components/InfiniteTable/hooks/reorderColumnsOnDrag.ts +476 -0
  101. package/src/components/InfiniteTable/hooks/useAutoSizeColumns.ts +206 -0
  102. package/src/components/InfiniteTable/hooks/useCellClassName.ts +80 -0
  103. package/src/components/InfiniteTable/hooks/useCellRendering.tsx +217 -0
  104. package/src/components/InfiniteTable/hooks/useColumnGroups.ts +71 -0
  105. package/src/components/InfiniteTable/hooks/useColumnMenu.ts +72 -0
  106. package/src/components/InfiniteTable/hooks/useColumnPointerEvents.ts +258 -0
  107. package/src/components/InfiniteTable/hooks/useColumnRowspan.ts +43 -0
  108. package/src/components/InfiniteTable/hooks/useColumnSizeFn.ts +24 -0
  109. package/src/components/InfiniteTable/hooks/useColumnsWhen.ts +582 -0
  110. package/src/components/InfiniteTable/hooks/useComputed.ts +186 -0
  111. package/src/components/InfiniteTable/hooks/useComputedVisibleColumns.ts +219 -0
  112. package/src/components/InfiniteTable/hooks/useDOMProps.ts +306 -0
  113. package/src/components/InfiniteTable/hooks/useEffectWithRaf.ts +47 -0
  114. package/src/components/InfiniteTable/hooks/useInfiniteTable.ts +10 -0
  115. package/src/components/InfiniteTable/hooks/useInfiniteTableState.ts +11 -0
  116. package/src/components/InfiniteTable/hooks/useInternalProps.ts +8 -0
  117. package/src/components/InfiniteTable/hooks/useLicense/LicenseDetails.ts +13 -0
  118. package/src/components/InfiniteTable/hooks/useLicense/crc32.ts +56 -0
  119. package/src/components/InfiniteTable/hooks/useLicense/decode.ts +147 -0
  120. package/src/components/InfiniteTable/hooks/useLicense/useLicense.ts +39 -0
  121. package/src/components/InfiniteTable/hooks/useRerenderOnKeyChange.ts +21 -0
  122. package/src/components/InfiniteTable/hooks/useRowHover.ts +18 -0
  123. package/src/components/InfiniteTable/hooks/useScrollToActiveCell.ts +48 -0
  124. package/src/components/InfiniteTable/hooks/useScrollToActiveRow.ts +44 -0
  125. package/src/components/InfiniteTable/hooks/useScrollbars.ts +51 -0
  126. package/src/components/InfiniteTable/hooks/useToggleGroupRow.ts +56 -0
  127. package/src/components/InfiniteTable/hooks/useUnpinnedRendering.tsx +165 -0
  128. package/src/components/InfiniteTable/hooks/useYourBrain.ts +55 -0
  129. package/src/components/InfiniteTable/index.tsx +352 -0
  130. package/src/components/InfiniteTable/internalProps.ts +4 -0
  131. package/src/components/InfiniteTable/state/computeColumnGroupsDepths.ts +29 -0
  132. package/src/components/InfiniteTable/state/getColumnVisibilityForHideEmptyGroupColumns.ts +127 -0
  133. package/src/components/InfiniteTable/state/getInitialState.ts +375 -0
  134. package/src/components/InfiniteTable/theme.css.ts +556 -0
  135. package/src/components/InfiniteTable/types/InfiniteTableAction.ts +6 -0
  136. package/src/components/InfiniteTable/types/InfiniteTableActionType.ts +12 -0
  137. package/src/components/InfiniteTable/types/InfiniteTableColumn.ts +478 -0
  138. package/src/components/InfiniteTable/types/InfiniteTableComputedValues.ts +43 -0
  139. package/src/components/InfiniteTable/types/InfiniteTableContextValue.ts +12 -0
  140. package/src/components/InfiniteTable/types/InfiniteTableInternalProps.ts +3 -0
  141. package/src/components/InfiniteTable/types/InfiniteTableProps.ts +511 -0
  142. package/src/components/InfiniteTable/types/InfiniteTableState.ts +195 -0
  143. package/src/components/InfiniteTable/types/Utility.ts +35 -0
  144. package/src/components/InfiniteTable/types/index.ts +96 -0
  145. package/src/components/InfiniteTable/utilities.css.ts +179 -0
  146. package/src/components/InfiniteTable/utils/MultiRowSelector.ts +111 -0
  147. package/src/components/InfiniteTable/utils/RenderHookComponentForInfinite.tsx +52 -0
  148. package/src/components/InfiniteTable/utils/adjustColumnOrderForPinning.ts +33 -0
  149. package/src/components/InfiniteTable/utils/assignFiltered.ts +29 -0
  150. package/src/components/InfiniteTable/utils/defaultGetColumContextMenuItems.tsx +108 -0
  151. package/src/components/InfiniteTable/utils/getColumnComputedType.ts +33 -0
  152. package/src/components/InfiniteTable/utils/getColumnForGroupBy.tsx +313 -0
  153. package/src/components/InfiniteTable/utils/getComputedVisibleColumns.ts +773 -0
  154. package/src/components/InfiniteTable/utils/getContextMenuForColumn.tsx +72 -0
  155. package/src/components/InfiniteTable/utils/infiniteDOMUtils.ts +189 -0
  156. package/src/components/InfiniteTable/utils/mapToObject.ts +20 -0
  157. package/src/components/InfiniteTable/utils/moveXatY.ts +25 -0
  158. package/src/components/InfiniteTable/utils/objectValuesExcept.ts +9 -0
  159. package/src/components/InfiniteTable/utils/progressiveSpeedScroller.ts +158 -0
  160. package/src/components/InfiniteTable/utils/rafFn.ts +13 -0
  161. package/src/components/InfiniteTable/utils/toCSSVarName.ts +1 -0
  162. package/src/components/InfiniteTable/utils/toMap.ts +24 -0
  163. package/src/components/Menu/Menu.tsx +750 -0
  164. package/src/components/Menu/MenuCls.css.ts +139 -0
  165. package/src/components/Menu/MenuContext.ts +10 -0
  166. package/src/components/Menu/MenuContextValue.ts +15 -0
  167. package/src/components/Menu/MenuProps.ts +98 -0
  168. package/src/components/Menu/MenuState.ts +56 -0
  169. package/src/components/Menu/MenuTriangleContext.ts +352 -0
  170. package/src/components/Menu/childrenToRuntimeItems.tsx +103 -0
  171. package/src/components/Menu/getMenuState.tsx +119 -0
  172. package/src/components/Menu/index.tsx +88 -0
  173. package/src/components/Menu/propToIdentifyMenu.ts +1 -0
  174. package/src/components/RawList/AvoidReactDiff.tsx +48 -0
  175. package/src/components/RawList/MappedItems.ts +143 -0
  176. package/src/components/RawList/ReactVirtualRenderer.tsx +307 -0
  177. package/src/components/RawList/index.tsx +42 -0
  178. package/src/components/RawList/types.ts +23 -0
  179. package/src/components/RawList/useVirtualRenderer.ts +36 -0
  180. package/src/components/RenderHookComponent.tsx +10 -0
  181. package/src/components/ResizeObserver/index.tsx +170 -0
  182. package/src/components/VirtualBrain/MatrixBrain.ts +1621 -0
  183. package/src/components/VirtualBrain/ScrollListener.ts +39 -0
  184. package/src/components/VirtualBrain/index.ts +664 -0
  185. package/src/components/VirtualList/ColumnListWithExternalScrolling.tsx +78 -0
  186. package/src/components/VirtualList/InfiniteListRootClassName.ts +1 -0
  187. package/src/components/VirtualList/RowListWithExternalScrolling.tsx +120 -0
  188. package/src/components/VirtualList/SpacePlaceholder.tsx +32 -0
  189. package/src/components/VirtualList/VirtualList.css.ts +29 -0
  190. package/src/components/VirtualList/VirtualList.tsx +141 -0
  191. package/src/components/VirtualList/VirtualRowList.tsx +34 -0
  192. package/src/components/VirtualList/types.ts +56 -0
  193. package/src/components/VirtualList/useCorrectHeightForRowElements.ts +14 -0
  194. package/src/components/VirtualScrollContainer/VirtualScrollContainer.css.ts +51 -0
  195. package/src/components/VirtualScrollContainer/getScrollableClassName.ts +30 -0
  196. package/src/components/VirtualScrollContainer/index.tsx +63 -0
  197. package/src/components/flexbox/index.ts +562 -0
  198. package/src/components/hooks/useComponentState/index.tsx +562 -0
  199. package/src/components/hooks/useComponentState/types.ts +32 -0
  200. package/src/components/hooks/useEffectOnceWithProperUnmount.ts +33 -0
  201. package/src/components/hooks/useEffectWithChanges.ts +56 -0
  202. package/src/components/hooks/useImmutableRef.ts +7 -0
  203. package/src/components/hooks/useInterceptedMap.ts +71 -0
  204. package/src/components/hooks/useLatest.tsx +8 -0
  205. package/src/components/hooks/useLazyLatest.ts +23 -0
  206. package/src/components/hooks/useMemoShallowObjectMerge.ts +16 -0
  207. package/src/components/hooks/useMounted.ts +18 -0
  208. package/src/components/hooks/useOnMount.ts +21 -0
  209. package/src/components/hooks/useOnScroll.ts +34 -0
  210. package/src/components/hooks/useOnce.ts +10 -0
  211. package/src/components/hooks/useOverlay/index.tsx +418 -0
  212. package/src/components/hooks/usePrevious.ts +8 -0
  213. package/src/components/hooks/usePropertyOld.ts +168 -0
  214. package/src/components/hooks/useRerender.ts +12 -0
  215. package/src/components/hooks/xuseProperty.ts +165 -0
  216. package/src/components/types/CellPosition.ts +4 -0
  217. package/src/components/types/NonUndefined.ts +1 -0
  218. package/src/components/types/RemoveObject.ts +22 -0
  219. package/src/components/types/Renderable.ts +3 -0
  220. package/src/components/types/ScrollPosition.ts +7 -0
  221. package/src/components/types/Setter.ts +2 -0
  222. package/src/components/types/Size.ts +6 -0
  223. package/src/components/types/SubscriptionCallback.ts +10 -0
  224. package/src/components/types/VoidFn.ts +1 -0
  225. package/src/components/utils/buildSubscriptionCallback.tsx +60 -0
  226. package/src/components/utils/clamp.ts +3 -0
  227. package/src/components/utils/debounce.ts +16 -0
  228. package/src/components/utils/decamelize.ts +11 -0
  229. package/src/components/utils/discardCallsWithEqualArg.ts +42 -0
  230. package/src/components/utils/getRenderIndexes.ts +33 -0
  231. package/src/components/utils/getScrollbarWidth.ts +31 -0
  232. package/src/components/utils/getVirtualRenderCount.ts +21 -0
  233. package/src/components/utils/isControlled.ts +12 -0
  234. package/src/components/utils/isControlledValue.ts +5 -0
  235. package/src/index.tsx +34 -0
  236. package/src/test.tsx +18 -0
  237. package/src/utils/DeepMap/index.ts +588 -0
  238. package/src/utils/DeepMap/once.ts +16 -0
  239. package/src/utils/DeepMap/sortAscending.ts +1 -0
  240. package/src/utils/DeepMap/tsconfig.deepmap.json +17 -0
  241. package/src/utils/DeepMap/xpackage.json +26 -0
  242. package/src/utils/debug.ts +40 -0
  243. package/src/utils/deepClone.ts +38 -0
  244. package/src/utils/getGlobal.ts +3 -0
  245. package/src/utils/groupAndPivot/defaultToKey.ts +3 -0
  246. package/src/utils/groupAndPivot/getGroupKeysForDataItem.ts +19 -0
  247. package/src/utils/groupAndPivot/getPivotColumnsAndColumnGroups.ts +361 -0
  248. package/src/utils/groupAndPivot/index.ts +1229 -0
  249. package/src/utils/groupAndPivot/types.ts +10 -0
  250. package/src/utils/join.ts +4 -0
  251. package/src/utils/mathIntersection.ts +21 -0
  252. package/src/utils/minified.d.ts +2 -0
  253. package/src/utils/minified.js +6 -0
  254. package/src/utils/multisort/index.ts +151 -0
  255. package/src/utils/multisort/sortTypes.ts +25 -0
  256. package/src/utils/notes-status.md +92 -0
  257. package/src/utils/pageGeometry/ConvexPoly.ts +34 -0
  258. package/src/utils/pageGeometry/Point.ts +51 -0
  259. package/src/utils/pageGeometry/PolyWithPoints.ts +52 -0
  260. package/src/utils/pageGeometry/Rectangle.ts +98 -0
  261. package/src/utils/pageGeometry/Triangle.ts +16 -0
  262. package/src/utils/pageGeometry/alignment/index.ts +221 -0
  263. package/src/utils/pageGeometry/polyContainsPoint.ts +182 -0
  264. package/src/utils/pageGeometry/types.ts +3 -0
  265. package/src/utils/proxyFnCall.ts +46 -0
  266. package/src/utils/raf.ts +13 -0
  267. package/src/utils/selectParent.ts +18 -0
  268. package/src/utils/shallowEqualObjects.ts +49 -0
  269. package/src/utils/stripVar.ts +3 -0
  270. package/src/utils/toUpperFirst.ts +5 -0
  271. package/todo.md +2 -0
  272. package/tsconfig.build.json +8 -0
  273. package/tsconfig.dev.json +7 -0
  274. package/tsconfig.json +30 -0
  275. package/tsconfig.typebundler.json +13 -0
  276. package/typedoc.json +4 -0
  277. package/README.md +0 -104
  278. package/index.css +0 -857
  279. package/index.d.ts +0 -2111
  280. package/index.esm.css +0 -857
  281. package/index.esm.js +0 -13695
  282. package/index.js +0 -13565
@@ -0,0 +1,783 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+
3
+ import { LazyGroupDataItem, LazyRowInfoGroup } from '..';
4
+ import { DeepMap } from '../../../utils/DeepMap';
5
+ import { LAZY_ROOT_KEY_FOR_GROUPS } from '../../../utils/groupAndPivot';
6
+ import { raf } from '../../../utils/raf';
7
+ import { useComponentState } from '../../hooks/useComponentState';
8
+ import { ComponentStateGeneratedActions } from '../../hooks/useComponentState/types';
9
+ import { useEffectWithChanges } from '../../hooks/useEffectWithChanges';
10
+ import { Scrollbars } from '../../InfiniteTable';
11
+ import { assignExcept } from '../../InfiniteTable/utils/assignFiltered';
12
+ import { debounce } from '../../utils/debounce';
13
+ import { RenderRange } from '../../VirtualBrain';
14
+ import {
15
+ DataSourceDataParams,
16
+ DataSourceData,
17
+ DataSourceState,
18
+ DataSourceRemoteData,
19
+ DataSourceDataParamsChanges,
20
+ } from '../types';
21
+
22
+ import { getChangeDetect } from './getChangeDetect';
23
+
24
+ const CACHE_DEFAULT = true;
25
+
26
+ const getRafPromise = () =>
27
+ new Promise((resolve) => {
28
+ raf(resolve);
29
+ });
30
+
31
+ const SKIP_DATA_CHANGES_KEYS = {
32
+ originalDataArray: true,
33
+ changes: true,
34
+ };
35
+
36
+ export function buildDataSourceDataParams<T>(
37
+ componentState: DataSourceState<T>,
38
+ overrides?: Partial<DataSourceDataParams<T>>,
39
+ ): DataSourceDataParams<T> {
40
+ const sortInfo = componentState.multiSort
41
+ ? componentState.sortInfo
42
+ : componentState.sortInfo?.[0] ?? null;
43
+
44
+ const dataSourceParams: DataSourceDataParams<T> = {
45
+ append: false,
46
+ originalDataArray: componentState.originalDataArray,
47
+ sortInfo,
48
+ groupBy: componentState.groupBy,
49
+ pivotBy: componentState.pivotBy,
50
+ filterValue: componentState.filterValue,
51
+ aggregationReducers: componentState.aggregationReducers,
52
+ };
53
+
54
+ if (dataSourceParams.groupBy) {
55
+ dataSourceParams.groupRowsState = componentState.groupRowsState.getState();
56
+ }
57
+
58
+ if (componentState.livePagination !== undefined) {
59
+ dataSourceParams.livePaginationCursor = componentState.livePaginationCursor;
60
+ dataSourceParams.__cursorId = componentState.cursorId;
61
+ }
62
+
63
+ if (componentState.lazyLoad) {
64
+ if (
65
+ componentState.lazyLoadBatchSize != null &&
66
+ componentState.lazyLoadBatchSize > 0
67
+ ) {
68
+ dataSourceParams.lazyLoadBatchSize = componentState.lazyLoadBatchSize;
69
+ dataSourceParams.lazyLoadStartIndex = 0;
70
+ }
71
+ dataSourceParams.groupKeys = [];
72
+ }
73
+
74
+ if (overrides) {
75
+ Object.assign(dataSourceParams, overrides);
76
+ }
77
+
78
+ if (dataSourceParams.filterValue && dataSourceParams.filterValue.length) {
79
+ dataSourceParams.filterValue = dataSourceParams.filterValue.map((f) => {
80
+ const value = { ...f };
81
+ // delete it as it's not serializable
82
+ // and we want to make it easier for developers to send this filterValue
83
+ // as is on the server
84
+ delete value.valueGetter;
85
+ return value;
86
+ });
87
+ }
88
+
89
+ const changes: DataSourceDataParamsChanges<T> = {};
90
+
91
+ const oldDataSourceParams: Partial<DataSourceDataParams<T>> =
92
+ componentState.dataParams || {};
93
+
94
+ for (const k in dataSourceParams) {
95
+ //@ts-ignore
96
+ if (dataSourceParams.hasOwnProperty(k) && !SKIP_DATA_CHANGES_KEYS[k]) {
97
+ const key = k as keyof DataSourceDataParams<T>;
98
+ if (dataSourceParams[key] !== oldDataSourceParams[key]) {
99
+ //@ts-ignore
100
+ changes[key] = true;
101
+ }
102
+ }
103
+ }
104
+
105
+ dataSourceParams.changes = changes;
106
+
107
+ return dataSourceParams;
108
+ }
109
+
110
+ export function loadData<T>(
111
+ data: DataSourceData<T>,
112
+ componentState: DataSourceState<T>,
113
+ actions: ComponentStateGeneratedActions<DataSourceState<T>>,
114
+ overrides?: Partial<DataSourceDataParams<T>>,
115
+ ) {
116
+ const dataParams = buildDataSourceDataParams(componentState, overrides);
117
+ const append = dataParams.append;
118
+
119
+ if (componentState.lazyLoad) {
120
+ const lazyGroupData = componentState.originalLazyGroupData;
121
+ const key = [LAZY_ROOT_KEY_FOR_GROUPS, ...(dataParams.groupKeys || [])];
122
+ const existingGroupRowInfo = lazyGroupData.get(key);
123
+
124
+ if (!existingGroupRowInfo) {
125
+ const groupCacheKeys = [
126
+ ...(dataParams.groupKeys || []),
127
+ dataParams.lazyLoadStartIndex,
128
+ ];
129
+ componentState.lazyLoadCacheOfLoadedBatches.set(groupCacheKeys, true);
130
+ }
131
+
132
+ if (existingGroupRowInfo && existingGroupRowInfo.cache && key.length > 1) {
133
+ const items = existingGroupRowInfo.children;
134
+ const len = items.length;
135
+ let allLoaded = true;
136
+ for (let i = 0; i < len; i++) {
137
+ if (items[i] == null) {
138
+ allLoaded = false;
139
+ break;
140
+ }
141
+ }
142
+ if (allLoaded) {
143
+ return Promise.resolve<any>(true);
144
+ }
145
+ }
146
+
147
+ if (existingGroupRowInfo) {
148
+ // if there's a group row already, make sure it's marked as loading its children
149
+ if (!existingGroupRowInfo.childrenLoading) {
150
+ existingGroupRowInfo.childrenLoading = true;
151
+ }
152
+ } else {
153
+ // there's no info for this group yet, so create it
154
+ // #creategroupdatabeforeload
155
+ lazyGroupData.set(key, {
156
+ error: undefined,
157
+ children: [],
158
+ childrenLoading: true,
159
+ childrenAvailable: false,
160
+ cache: CACHE_DEFAULT,
161
+ totalCount: 0,
162
+ totalCountUnfiltered: 0,
163
+ });
164
+ }
165
+ actions.originalLazyGroupDataChangeDetect = getChangeDetect();
166
+ }
167
+
168
+ if (typeof data === 'function') {
169
+ data = data(dataParams);
170
+ }
171
+
172
+ const dataIsPromise =
173
+ //@ts-ignore
174
+ typeof data === 'object' && typeof data.then === 'function';
175
+
176
+ if (dataIsPromise && !componentState.lazyLoad) {
177
+ actions.loading = true;
178
+ }
179
+
180
+ return Promise.resolve(data).then((dataParam) => {
181
+ // dataParam can either be an array or an object with a `data` array property
182
+ let dataArray: T[] | LazyGroupDataItem<T>[] = [] as T[];
183
+ let skipAssign = false;
184
+
185
+ if (Array.isArray((dataParam as DataSourceRemoteData<T>).data)) {
186
+ const remoteData = dataParam as DataSourceRemoteData<T>;
187
+ dataArray = remoteData.data;
188
+
189
+ if (remoteData.livePaginationCursor !== undefined) {
190
+ actions.livePaginationCursor = remoteData.livePaginationCursor;
191
+ }
192
+ if (remoteData.mappings) {
193
+ actions.pivotMappings = remoteData.mappings;
194
+ }
195
+ if (remoteData.totalCountUnfiltered) {
196
+ actions.unfilteredCount = remoteData.totalCountUnfiltered;
197
+ }
198
+
199
+ if (componentState.lazyLoad) {
200
+ // #staleLazyGroupData
201
+ // because cloning would make a copy of it and
202
+ // multiple promised calls can be concurrent
203
+ // they would act on clones of the data
204
+ // and the last one will win and override
205
+ // previous ones (in the same concurrency window)
206
+ // therefore we use originalLazyGroupDataChangeDetect
207
+ // to trigger re-renders and in hooks (useEffect, etc)
208
+ // whenever we want to check if originalLazyGroupData has changed
209
+
210
+ // const lazyGroupData = DeepMap.clone(
211
+ // componentState.originalLazyGroupData,
212
+ // );
213
+
214
+ const lazyGroupData = componentState.originalLazyGroupData;
215
+
216
+ function resolveRemoteData(
217
+ keys: any[],
218
+ remoteData: DataSourceRemoteData<T>,
219
+ parentKeys?: any[],
220
+ ) {
221
+ const theKey = [LAZY_ROOT_KEY_FOR_GROUPS, ...keys];
222
+ const dataArray = remoteData.data as LazyGroupDataItem<T>[];
223
+ const newGroupRowInfo: LazyRowInfoGroup<T> = {
224
+ cache: !!remoteData.cache ?? CACHE_DEFAULT,
225
+ childrenLoading: false,
226
+ childrenAvailable: true,
227
+ totalCount: remoteData.totalCount ?? dataArray.length,
228
+ totalCountUnfiltered: remoteData.totalCount ?? dataArray.length,
229
+ children: dataArray,
230
+ error: remoteData.error,
231
+ };
232
+
233
+ const childDatasets: {
234
+ keys: KeyType[];
235
+ dataset: DataSourceRemoteData<T>;
236
+ }[] = [];
237
+
238
+ if (dataParams.lazyLoadBatchSize && !parentKeys) {
239
+ const existingGroupRowInfo = lazyGroupData.get(theKey);
240
+ const isGroupNew = !existingGroupRowInfo;
241
+
242
+ // make sure we update the existing info with what we received from the server
243
+ // because the existing one was probably created artificially
244
+ // even before the initial response is received - see #creategroupdatabeforeload
245
+ // so the totalCount was not set correctly
246
+ const currentGroupRowInfo = assignExcept(
247
+ {
248
+ children: true,
249
+ },
250
+ existingGroupRowInfo || {},
251
+ newGroupRowInfo,
252
+ );
253
+
254
+ if (isGroupNew) {
255
+ currentGroupRowInfo.chidren = [];
256
+ }
257
+
258
+ currentGroupRowInfo.children.length =
259
+ currentGroupRowInfo.totalCount;
260
+
261
+ const start = dataParams.lazyLoadStartIndex ?? 0;
262
+ const end = Math.min(
263
+ remoteData.totalCount ?? dataArray.length,
264
+ start + dataParams.lazyLoadBatchSize,
265
+ );
266
+
267
+ for (let i = start; i < end; i++) {
268
+ const it = newGroupRowInfo.children[i - start];
269
+ if (!it) {
270
+ throw `lazily loaded item not found at index ${i - start}`;
271
+ }
272
+ currentGroupRowInfo.children[i] = it;
273
+
274
+ if (it.dataset) {
275
+ childDatasets.push({
276
+ keys: it.keys,
277
+ dataset: it.dataset,
278
+ });
279
+ }
280
+ }
281
+ if (isGroupNew) {
282
+ lazyGroupData.set(theKey, currentGroupRowInfo);
283
+ }
284
+ } else {
285
+ // if (parentKeys) {
286
+ newGroupRowInfo.children.forEach((child) => {
287
+ if (child && child.dataset) {
288
+ childDatasets.push({
289
+ keys: child.keys,
290
+ dataset: child.dataset,
291
+ });
292
+ }
293
+ });
294
+
295
+ // we need this assignment, in order to make the group
296
+ // accomodate all children that will potentially be lazily loaded
297
+ newGroupRowInfo.children.length = newGroupRowInfo.totalCount;
298
+ // }
299
+
300
+ lazyGroupData.set(theKey, newGroupRowInfo);
301
+ }
302
+
303
+ let skipTriggerChangeAsAlreadyOriginalArrayWasUpdated = false;
304
+
305
+ if (!keys || !keys.length) {
306
+ const topLevelLazyGroupData = lazyGroupData.get([
307
+ LAZY_ROOT_KEY_FOR_GROUPS,
308
+ ]);
309
+
310
+ //@ts-ignore
311
+ actions.originalDataArray = [...topLevelLazyGroupData.children];
312
+ skipTriggerChangeAsAlreadyOriginalArrayWasUpdated = true;
313
+ }
314
+ // actions.originalLazyGroupData = lazyGroupData;
315
+ // see above #staleLazyGroupData
316
+ if (!skipTriggerChangeAsAlreadyOriginalArrayWasUpdated) {
317
+ actions.originalLazyGroupDataChangeDetect = getChangeDetect();
318
+ }
319
+
320
+ if (childDatasets.length) {
321
+ const parentKeys = keys;
322
+ childDatasets.forEach(({ keys, dataset }) => {
323
+ resolveRemoteData(keys, dataset, parentKeys);
324
+ });
325
+ }
326
+ }
327
+
328
+ skipAssign = true;
329
+ resolveRemoteData(dataParams.groupKeys || [], remoteData);
330
+ }
331
+ } else {
332
+ dataArray = dataParam as T[];
333
+ }
334
+
335
+ if (!skipAssign) {
336
+ actions.originalDataArray = append
337
+ ? componentState.originalDataArray.concat(dataArray as any as T[])
338
+ : (dataArray as any as T[]);
339
+ }
340
+
341
+ if (dataIsPromise && !componentState.lazyLoad) {
342
+ // if on the same raf as the actions.loading = true above
343
+ // this could fail if #samevaluecheckfailswhennotflushed is present
344
+ actions.loading = false;
345
+ }
346
+ });
347
+ }
348
+
349
+ export function useLoadData<T>() {
350
+ const {
351
+ getComponentState,
352
+ componentActions: actions,
353
+ componentState,
354
+ } = useComponentState<DataSourceState<T>>();
355
+
356
+ const {
357
+ data,
358
+ dataArray,
359
+ notifyScrollbarsChange,
360
+ sortInfo,
361
+ groupBy,
362
+ pivotBy,
363
+ filterValue,
364
+ livePagination,
365
+ livePaginationCursor,
366
+ cursorId: stateCursorId,
367
+ } = componentState;
368
+
369
+ const [scrollbars, setScrollbars] = useState<Scrollbars>({
370
+ vertical: false,
371
+ horizontal: false,
372
+ });
373
+
374
+ const scrollbarsRef = useRef<Scrollbars>(scrollbars);
375
+
376
+ useEffect(() => {
377
+ notifyScrollbarsChange.onChange((scrollbars: Scrollbars | null) => {
378
+ if (!scrollbars) {
379
+ return;
380
+ }
381
+
382
+ scrollbarsRef.current = scrollbars;
383
+ setScrollbars(scrollbars);
384
+ });
385
+ return () => notifyScrollbarsChange.destroy();
386
+ }, [notifyScrollbarsChange]);
387
+
388
+ useEffect(() => {
389
+ if (!livePagination) {
390
+ return;
391
+ }
392
+ // this is synced with - ref #lvpgn - search in codebase this ref to understand more
393
+ const frameId = requestAnimationFrame(() => {
394
+ if (!scrollbarsRef.current?.vertical) {
395
+ if (livePaginationCursor) {
396
+ // this line makes it so that when we have live pagination, with a livePaginationCursor,
397
+ // if the data that was loaded does not fill the whole viewport, we need to keep requesting the new
398
+ // batch of data - so this assignment here does that
399
+ actions.cursorId = livePaginationCursor;
400
+ }
401
+ }
402
+ });
403
+
404
+ return () => cancelAnimationFrame(frameId);
405
+ }, [livePaginationCursor]);
406
+
407
+ useEffect(() => {
408
+ if (!livePagination || livePaginationCursor !== undefined) {
409
+ // the case when `livePaginationCursor` is defined is handled in the effect above
410
+ return;
411
+ }
412
+
413
+ const frameId = requestAnimationFrame(() => {
414
+ if (!scrollbarsRef.current?.vertical) {
415
+ // this line makes it so that when we have live pagination, with a livePaginationCursor,
416
+ // if the data that was loaded does not fill the whole viewport, we need to keep requesting the new
417
+ // batch of data - so this assignment here does that - basically we're use dataArray.length as the cursor
418
+ // #useDataArrayLengthAsCursor ref
419
+
420
+ if (stateCursorId != null && dataArray.length) {
421
+ actions.cursorId = dataArray.length;
422
+ }
423
+ }
424
+ });
425
+
426
+ return () => cancelAnimationFrame(frameId);
427
+ }, [dataArray.length, livePaginationCursor]);
428
+
429
+ useEffect(() => {
430
+ const state = getComponentState();
431
+
432
+ const { livePaginationCursor, livePagination, dataArray } = state;
433
+
434
+ if (!scrollbars.vertical && livePagination) {
435
+ // it had vertical scroll but now it doesn't
436
+
437
+ // the current case is when the grid was loaded initially and had data + vertical scrollbar
438
+ // but now the viewport has been resized to fit all the rows and there is extra vertical space
439
+ // so we're in a position where we need to request the next batch of data
440
+
441
+ if (livePaginationCursor) {
442
+ // only do this if livePaginationCursor is defined and not zero
443
+ actions.cursorId = livePaginationCursor;
444
+ } else if (livePaginationCursor === undefined && dataArray.length) {
445
+ // there is no cursor passed as a prop, so we use dataArray.length as a cursor
446
+ // so only do this if the length > 0
447
+ // #useDataArrayLengthAsCursor ref
448
+
449
+ actions.cursorId = dataArray.length;
450
+ }
451
+ }
452
+ }, [scrollbars.vertical]);
453
+
454
+ const depsObject = {
455
+ sortInfo,
456
+ groupBy,
457
+ pivotBy,
458
+ filterValue,
459
+ cursorId: livePagination ? stateCursorId : null,
460
+ };
461
+
462
+ const initialRef = useRef(true);
463
+
464
+ useLazyLoadRange<T>();
465
+
466
+ useEffectWithChanges(
467
+ () => {
468
+ const componentState = getComponentState();
469
+ if (typeof componentState.data !== 'function') {
470
+ loadData(componentState.data, componentState, actions);
471
+ }
472
+ },
473
+ { data },
474
+ );
475
+
476
+ useEffectWithChanges(
477
+ (changes) => {
478
+ const appendWhenLivePagination =
479
+ Object.keys(changes).length === 1 && !!changes.cursorId;
480
+
481
+ const componentState = getComponentState();
482
+ if (typeof componentState.data === 'function') {
483
+ loadData(componentState.data, componentState, actions, {
484
+ append: appendWhenLivePagination,
485
+ });
486
+ }
487
+ },
488
+ { ...depsObject, data },
489
+ );
490
+
491
+ // only for initial triggering `onDataParamsChange`
492
+ useEffectWithChanges((_changes, _prevValues) => {
493
+ const componentState = getComponentState();
494
+ if (initialRef.current) {
495
+ initialRef.current = false;
496
+
497
+ const dataParams = buildDataSourceDataParams(componentState);
498
+ actions.dataParams = dataParams;
499
+ }
500
+ }, depsObject);
501
+ }
502
+
503
+ function useLazyLoadRange<T>() {
504
+ const {
505
+ getComponentState,
506
+ componentActions: actions,
507
+ componentState,
508
+ } = useComponentState<DataSourceState<T>>();
509
+
510
+ useEffect(() => {
511
+ actions.lazyLoadCacheOfLoadedBatches = new DeepMap<string, true>();
512
+ }, [componentState.data, componentState.dataParams]);
513
+
514
+ // const loadingCache = useMemo<Map<string, true>>(() => {
515
+ // return new Map();
516
+ // }, [componentState.data, componentState.dataParams]);
517
+
518
+ const {
519
+ lazyLoadBatchSize,
520
+ lazyLoad,
521
+ originalLazyGroupDataChangeDetect,
522
+ notifyRenderRangeChange,
523
+ dataArray,
524
+ groupRowsState,
525
+ scrollStopDelayUpdatedByTable,
526
+ } = componentState;
527
+
528
+ const latestRenderRangeRef = useRef<RenderRange | null>(null);
529
+
530
+ const loadRange = (
531
+ renderRange?: RenderRange | null,
532
+ cache: DeepMap<string, true> = getComponentState()
533
+ .lazyLoadCacheOfLoadedBatches,
534
+ ) => {
535
+ const componentState = getComponentState();
536
+ renderRange = renderRange || latestRenderRangeRef.current;
537
+ if (!renderRange) {
538
+ return;
539
+ }
540
+ const { renderStartIndex: startIndex, renderEndIndex: endIndex } =
541
+ renderRange;
542
+
543
+ const { lazyLoadBatchSize, lazyLoad } = componentState;
544
+
545
+ if (!lazyLoad) {
546
+ return;
547
+ }
548
+
549
+ if (!lazyLoadBatchSize || lazyLoadBatchSize <= 0) {
550
+ // when the batch size is not defined
551
+ // we could still have rows that should be lazily loaded
552
+ // eg: some rows are defined as expanded in the `groupRowsState`, so
553
+ // if we detect some rows like this, we need to try and lazily load them
554
+
555
+ // but if there is no grouping, there will be no such rows,
556
+ // so we can safely return
557
+ if (!componentState.groupBy || componentState.groupBy.length === 0) {
558
+ return;
559
+ }
560
+ }
561
+
562
+ lazyLoadRange(
563
+ {
564
+ startIndex,
565
+ endIndex,
566
+ lazyLoadBatchSize,
567
+ componentState,
568
+ componentActions: actions,
569
+ },
570
+ cache,
571
+ );
572
+ };
573
+
574
+ const debouncedLoadRange = useMemo(
575
+ () => debounce(loadRange, { wait: scrollStopDelayUpdatedByTable }),
576
+ [scrollStopDelayUpdatedByTable],
577
+ );
578
+
579
+ useEffectWithChanges(
580
+ (changes) => {
581
+ if (lazyLoad) {
582
+ // when there is changes in lazily loaded data or group row state
583
+ // we need to trigger another loadRange immediately,
584
+
585
+ if (
586
+ changes.originalLazyGroupDataChangeDetect ||
587
+ changes.groupRowsState
588
+ ) {
589
+ loadRange(notifyRenderRangeChange.get());
590
+ }
591
+ // even before waiting for the render range change, as that will only
592
+ // happen on user scroll or table viewport resize
593
+
594
+ // though loading a new range when the render range has changed is needed
595
+ return notifyRenderRangeChange.onChange(
596
+ (renderRange: RenderRange | null) => {
597
+ latestRenderRangeRef.current = renderRange;
598
+ loadRange(renderRange);
599
+ },
600
+ );
601
+ }
602
+ return;
603
+ },
604
+ {
605
+ lazyLoadBatchSize,
606
+ lazyLoad,
607
+ originalLazyGroupDataChangeDetect,
608
+ groupRowsState,
609
+ },
610
+ );
611
+
612
+ useEffect(() => {
613
+ if (lazyLoadBatchSize && lazyLoadBatchSize > 0) {
614
+ debouncedLoadRange();
615
+ }
616
+ }, [dataArray]);
617
+ }
618
+
619
+ function lazyLoadRange<T>(
620
+ options: {
621
+ startIndex: number;
622
+ endIndex: number;
623
+ lazyLoadBatchSize: number | undefined;
624
+ componentState: DataSourceState<T>;
625
+ componentActions: ComponentStateGeneratedActions<DataSourceState<T>>;
626
+ },
627
+ cache?: DeepMap<string, true>,
628
+ ) {
629
+ const {
630
+ startIndex,
631
+ endIndex,
632
+ lazyLoadBatchSize,
633
+ componentState,
634
+ componentActions,
635
+ } = options;
636
+
637
+ const { dataArray } = componentState;
638
+ const isRowLoaded = (index: number) => {
639
+ const rowInfo = dataArray[index];
640
+
641
+ // if (
642
+ // rowInfo.isGroupRow &&
643
+ // rowInfo.dataSourceHasGrouping &&
644
+ // !rowInfo.collapsed && rowInfo.childrenAvailable
645
+ // ) {
646
+ // return rowInfo.childrenAvailable;
647
+ // }
648
+
649
+ return rowInfo.data != null;
650
+ };
651
+
652
+ type FnCall = {
653
+ lazyLoadStartIndex: number;
654
+ lazyLoadBatchSize: number | undefined;
655
+ groupKeys: any[];
656
+ };
657
+
658
+ const perGroupFnCalls = new DeepMap<any, Record<any, FnCall>>();
659
+
660
+ // TODO remove this hack when DeepMap supports empty arrays as keys
661
+ const rootGroupKeys = ['_______xxx______'];
662
+
663
+ /**
664
+ * We're iterating on all rows from start to end indexes
665
+ */
666
+ for (let i = startIndex; i <= endIndex; i++) {
667
+ const rowInfo = dataArray[i];
668
+ if (!rowInfo) {
669
+ continue;
670
+ }
671
+ const rowLoaded = isRowLoaded(i);
672
+ const theGroupKeys =
673
+ rowInfo.dataSourceHasGrouping && rowInfo.groupKeys
674
+ ? [...rowInfo.groupKeys]
675
+ : [];
676
+
677
+ if (
678
+ rowInfo.isGroupRow &&
679
+ rowInfo.dataSourceHasGrouping &&
680
+ rowInfo.groupKeys
681
+ ) {
682
+ theGroupKeys.pop();
683
+ }
684
+ const cacheKeys = theGroupKeys.length ? theGroupKeys : rootGroupKeys;
685
+ const indexInGroup = rowInfo.dataSourceHasGrouping
686
+ ? rowInfo.indexInGroup
687
+ : rowInfo.indexInAll;
688
+
689
+ if (
690
+ rowInfo.isGroupRow &&
691
+ !rowInfo.collapsed &&
692
+ !rowInfo.childrenAvailable
693
+ ) {
694
+ // we might have expanded groups that have never been loaded
695
+ // so we need to try load them as well - not their batch in the parent group
696
+ // but rather the group they are expanding
697
+
698
+ const currentFnCall: FnCall = {
699
+ lazyLoadStartIndex: 0,
700
+ lazyLoadBatchSize,
701
+ groupKeys: rowInfo.groupKeys,
702
+ };
703
+ const cacheKeys = rowInfo.groupKeys;
704
+ let cachedFnCalls = perGroupFnCalls.get(cacheKeys);
705
+
706
+ if (!cachedFnCalls?.[rowInfo.id]) {
707
+ const shouldSetFnCalls = !cachedFnCalls;
708
+
709
+ cachedFnCalls = cachedFnCalls || {};
710
+
711
+ if (!cachedFnCalls[rowInfo.id]) {
712
+ cachedFnCalls[rowInfo.id] = currentFnCall;
713
+ }
714
+
715
+ if (shouldSetFnCalls) {
716
+ perGroupFnCalls.set(cacheKeys, cachedFnCalls);
717
+ }
718
+ }
719
+ }
720
+
721
+ if (!rowLoaded && lazyLoadBatchSize != undefined) {
722
+ let cachedFnCalls = perGroupFnCalls.get(cacheKeys);
723
+
724
+ const batchStartIndexInGroup =
725
+ Math.floor(indexInGroup / lazyLoadBatchSize) * lazyLoadBatchSize;
726
+ const offset = indexInGroup - batchStartIndexInGroup;
727
+ const absoluteIndexOfBatchStart =
728
+ dataArray[rowInfo.indexInAll - offset].indexInAll;
729
+
730
+ const batchStartRowLoaded = isRowLoaded(absoluteIndexOfBatchStart);
731
+ const batchStartRowId = dataArray[absoluteIndexOfBatchStart].id;
732
+
733
+ if (batchStartRowLoaded || cachedFnCalls?.[batchStartRowId]) {
734
+ continue;
735
+ }
736
+
737
+ const shouldSetFnCalls = !cachedFnCalls;
738
+
739
+ cachedFnCalls = cachedFnCalls || {};
740
+
741
+ const currentFnCall: FnCall = {
742
+ lazyLoadStartIndex: batchStartIndexInGroup,
743
+ lazyLoadBatchSize,
744
+ groupKeys: theGroupKeys,
745
+ };
746
+
747
+ if (!cachedFnCalls[batchStartRowId]) {
748
+ cachedFnCalls[batchStartRowId] = currentFnCall;
749
+ }
750
+
751
+ if (shouldSetFnCalls) {
752
+ perGroupFnCalls.set(cacheKeys, cachedFnCalls);
753
+ }
754
+ }
755
+ }
756
+
757
+ const initialPromise: Promise<any> = Promise.resolve(true);
758
+
759
+ const allFnCalls: FnCall[] = [];
760
+ perGroupFnCalls.topDownValues().forEach((record) => {
761
+ allFnCalls.push(...Object.values(record));
762
+ });
763
+
764
+ allFnCalls.reduce((promise, fnCall: FnCall) => {
765
+ const cacheKey = [...fnCall.groupKeys, fnCall.lazyLoadStartIndex];
766
+
767
+ if (cache && cache.has(cacheKey)) {
768
+ return promise;
769
+ }
770
+
771
+ cache?.set(cacheKey, true);
772
+ const args: [
773
+ DataSourceData<T>,
774
+ DataSourceState<T>,
775
+ ComponentStateGeneratedActions<DataSourceState<T>>,
776
+ Partial<DataSourceDataParams<T>>,
777
+ ] = [componentState.data, componentState, componentActions, fnCall];
778
+
779
+ // TODO make this whole function testable, so we can properly test multiple calls are not issued for the same batch (in the same group)
780
+
781
+ return promise.then(() => getRafPromise()).then(() => loadData(...args));
782
+ }, initialPromise);
783
+ }