@infinite-table/infinite-react 0.5.0 → 0.5.2

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/README.md +104 -0
  2. package/index.css +896 -0
  3. package/index.d.ts +2264 -0
  4. package/index.esm.css +896 -0
  5. package/index.esm.js +15404 -0
  6. package/index.js +15240 -0
  7. package/package.json +9 -94
  8. package/.vscode/settings.json +0 -3
  9. package/API.md +0 -0
  10. package/build/buildPackageJson.js +0 -43
  11. package/build/scripts/test.js +0 -37
  12. package/bundler.config.js +0 -25
  13. package/globals.d.ts +0 -7
  14. package/rollup.config.js +0 -15
  15. package/run-build-deepmap.js +0 -47
  16. package/run-build.js +0 -45
  17. package/run-dts-concat.js +0 -21
  18. package/src/components/CSSVariableWatch.tsx +0 -82
  19. package/src/components/DataSource/BooleanCollectionState.ts +0 -214
  20. package/src/components/DataSource/BooleanDeepCollectionState.ts +0 -208
  21. package/src/components/DataSource/DataSourceContext.ts +0 -20
  22. package/src/components/DataSource/GroupRowsState.ts +0 -74
  23. package/src/components/DataSource/Indexer.ts +0 -27
  24. package/src/components/DataSource/RowSelectionState.ts +0 -763
  25. package/src/components/DataSource/defaultFilterTypes.ts +0 -64
  26. package/src/components/DataSource/index.tsx +0 -108
  27. package/src/components/DataSource/privateHooks/getChangeDetect.ts +0 -7
  28. package/src/components/DataSource/privateHooks/useLoadData.ts +0 -783
  29. package/src/components/DataSource/publicHooks/useDataSource.ts +0 -19
  30. package/src/components/DataSource/publicHooks/useDataSourceActions.ts +0 -14
  31. package/src/components/DataSource/state/getInitialState.ts +0 -494
  32. package/src/components/DataSource/state/normalizeSortInfo.ts +0 -35
  33. package/src/components/DataSource/state/reducer.ts +0 -466
  34. package/src/components/DataSource/state/rowInfoStatus.ts +0 -27
  35. package/src/components/DataSource/types.ts +0 -548
  36. package/src/components/HeadlessTable/HeadlessTableWithPinnedContainers.tsx +0 -142
  37. package/src/components/HeadlessTable/MappedCells.ts +0 -251
  38. package/src/components/HeadlessTable/RawTable.tsx +0 -98
  39. package/src/components/HeadlessTable/ReactHeadlessTableRenderer.tsx +0 -1516
  40. package/src/components/HeadlessTable/index.tsx +0 -234
  41. package/src/components/InfiniteTable/InfiniteCls.css.ts +0 -164
  42. package/src/components/InfiniteTable/InfiniteTableContext.ts +0 -16
  43. package/src/components/InfiniteTable/api/getImperativeApi.ts +0 -391
  44. package/src/components/InfiniteTable/api/getSelectionApi.ts +0 -364
  45. package/src/components/InfiniteTable/api/type.ts +0 -11
  46. package/src/components/InfiniteTable/components/ActiveCellIndicator.css.ts +0 -51
  47. package/src/components/InfiniteTable/components/ActiveCellIndicator.tsx +0 -116
  48. package/src/components/InfiniteTable/components/ActiveRowIndicator.css.ts +0 -56
  49. package/src/components/InfiniteTable/components/ActiveRowIndicator.tsx +0 -94
  50. package/src/components/InfiniteTable/components/CheckBox.css.ts +0 -13
  51. package/src/components/InfiniteTable/components/CheckBox.tsx +0 -96
  52. package/src/components/InfiniteTable/components/FilterEditors.tsx +0 -52
  53. package/src/components/InfiniteTable/components/InfiniteTableBody/InfiniteTableBody.tsx +0 -27
  54. package/src/components/InfiniteTable/components/InfiniteTableBody/index.tsx +0 -1
  55. package/src/components/InfiniteTable/components/InfiniteTableFooter/InfiniteTableFooter.tsx +0 -31
  56. package/src/components/InfiniteTable/components/InfiniteTableFooter/index.tsx +0 -1
  57. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableColumnHeaderFilter.tsx +0 -102
  58. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeader.tsx +0 -163
  59. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderCell.tsx +0 -574
  60. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderGroup.tsx +0 -79
  61. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderTypes.tsx +0 -25
  62. package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderWrapper.tsx +0 -185
  63. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/GroupResizeHandle.tsx +0 -159
  64. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/ResizeHandle.css.ts +0 -124
  65. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/columnResizer.ts +0 -166
  66. package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/index.tsx +0 -146
  67. package/src/components/InfiniteTable/components/InfiniteTableHeader/buildColumnAndGroupTree.ts +0 -240
  68. package/src/components/InfiniteTable/components/InfiniteTableHeader/header.css.ts +0 -358
  69. package/src/components/InfiniteTable/components/InfiniteTableHeader/index.tsx +0 -1
  70. package/src/components/InfiniteTable/components/InfiniteTableHeader/useColumnGroupResizeHandle.tsx +0 -114
  71. package/src/components/InfiniteTable/components/InfiniteTableHeader/useColumnResizeHandle.tsx +0 -146
  72. package/src/components/InfiniteTable/components/InfiniteTableLicenseFooter/footer.css.ts +0 -7
  73. package/src/components/InfiniteTable/components/InfiniteTableLicenseFooter/index.tsx +0 -110
  74. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx +0 -120
  75. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCellTypes.ts +0 -74
  76. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableColumnCell.tsx +0 -457
  77. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRow.tsx +0 -107
  78. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowClassName.ts +0 -6
  79. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowTypes.ts +0 -32
  80. package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowUnvirtualized.tsx +0 -75
  81. package/src/components/InfiniteTable/components/InfiniteTableRow/columnRendering.tsx +0 -263
  82. package/src/components/InfiniteTable/components/InfiniteTableRow/index.tsx +0 -1
  83. package/src/components/InfiniteTable/components/InfiniteTableRow/row.css.ts +0 -74
  84. package/src/components/InfiniteTable/components/InfiniteTableRow/useRowDOMProps.ts +0 -199
  85. package/src/components/InfiniteTable/components/LoadMask.css.ts +0 -34
  86. package/src/components/InfiniteTable/components/LoadMask.tsx +0 -27
  87. package/src/components/InfiniteTable/components/ScrollbarPlaceholder.tsx +0 -56
  88. package/src/components/InfiniteTable/components/cell.css.ts +0 -192
  89. package/src/components/InfiniteTable/components/icons/ArrowDown.tsx +0 -14
  90. package/src/components/InfiniteTable/components/icons/ArrowUp.tsx +0 -14
  91. package/src/components/InfiniteTable/components/icons/ExpanderIcon.css.ts +0 -31
  92. package/src/components/InfiniteTable/components/icons/ExpanderIcon.tsx +0 -63
  93. package/src/components/InfiniteTable/components/icons/Icon.tsx +0 -18
  94. package/src/components/InfiniteTable/components/icons/InfiniteTableIconClassName.ts +0 -1
  95. package/src/components/InfiniteTable/components/icons/LoadingIcon.css.ts +0 -8
  96. package/src/components/InfiniteTable/components/icons/LoadingIcon.tsx +0 -45
  97. package/src/components/InfiniteTable/components/icons/MenuIcon.tsx +0 -50
  98. package/src/components/InfiniteTable/components/icons/SortIcon.tsx +0 -113
  99. package/src/components/InfiniteTable/eventHandlers/eventHandlerTypes.ts +0 -57
  100. package/src/components/InfiniteTable/eventHandlers/index.ts +0 -95
  101. package/src/components/InfiniteTable/eventHandlers/keyboardNavigation.ts +0 -232
  102. package/src/components/InfiniteTable/eventHandlers/keyboardSelection.ts +0 -110
  103. package/src/components/InfiniteTable/eventHandlers/onCellClick.ts +0 -94
  104. package/src/components/InfiniteTable/eventHandlers/onKeyDown.ts +0 -25
  105. package/src/components/InfiniteTable/hooks/adjustColumnOrderForAllColumns.ts +0 -70
  106. package/src/components/InfiniteTable/hooks/reorderColumnsOnDrag.ts +0 -476
  107. package/src/components/InfiniteTable/hooks/useAutoSizeColumns.ts +0 -206
  108. package/src/components/InfiniteTable/hooks/useCellClassName.ts +0 -80
  109. package/src/components/InfiniteTable/hooks/useCellRendering.tsx +0 -217
  110. package/src/components/InfiniteTable/hooks/useColumnGroups.ts +0 -71
  111. package/src/components/InfiniteTable/hooks/useColumnMenu.ts +0 -72
  112. package/src/components/InfiniteTable/hooks/useColumnPointerEvents.ts +0 -258
  113. package/src/components/InfiniteTable/hooks/useColumnRowspan.ts +0 -43
  114. package/src/components/InfiniteTable/hooks/useColumnSizeFn.ts +0 -24
  115. package/src/components/InfiniteTable/hooks/useColumnsWhen.ts +0 -582
  116. package/src/components/InfiniteTable/hooks/useComputed.ts +0 -186
  117. package/src/components/InfiniteTable/hooks/useComputedVisibleColumns.ts +0 -219
  118. package/src/components/InfiniteTable/hooks/useDOMProps.ts +0 -306
  119. package/src/components/InfiniteTable/hooks/useEffectWithRaf.ts +0 -47
  120. package/src/components/InfiniteTable/hooks/useInfiniteTable.ts +0 -10
  121. package/src/components/InfiniteTable/hooks/useInfiniteTableState.ts +0 -11
  122. package/src/components/InfiniteTable/hooks/useInternalProps.ts +0 -8
  123. package/src/components/InfiniteTable/hooks/useLicense/LicenseDetails.ts +0 -13
  124. package/src/components/InfiniteTable/hooks/useLicense/crc32.ts +0 -56
  125. package/src/components/InfiniteTable/hooks/useLicense/decode.ts +0 -147
  126. package/src/components/InfiniteTable/hooks/useLicense/useLicense.ts +0 -39
  127. package/src/components/InfiniteTable/hooks/useRerenderOnKeyChange.ts +0 -21
  128. package/src/components/InfiniteTable/hooks/useRowHover.ts +0 -18
  129. package/src/components/InfiniteTable/hooks/useScrollToActiveCell.ts +0 -48
  130. package/src/components/InfiniteTable/hooks/useScrollToActiveRow.ts +0 -44
  131. package/src/components/InfiniteTable/hooks/useScrollbars.ts +0 -51
  132. package/src/components/InfiniteTable/hooks/useToggleGroupRow.ts +0 -56
  133. package/src/components/InfiniteTable/hooks/useUnpinnedRendering.tsx +0 -165
  134. package/src/components/InfiniteTable/hooks/useYourBrain.ts +0 -55
  135. package/src/components/InfiniteTable/index.tsx +0 -352
  136. package/src/components/InfiniteTable/internalProps.ts +0 -4
  137. package/src/components/InfiniteTable/state/computeColumnGroupsDepths.ts +0 -29
  138. package/src/components/InfiniteTable/state/getColumnVisibilityForHideEmptyGroupColumns.ts +0 -127
  139. package/src/components/InfiniteTable/state/getInitialState.ts +0 -375
  140. package/src/components/InfiniteTable/theme.css.ts +0 -556
  141. package/src/components/InfiniteTable/types/InfiniteTableAction.ts +0 -6
  142. package/src/components/InfiniteTable/types/InfiniteTableActionType.ts +0 -12
  143. package/src/components/InfiniteTable/types/InfiniteTableColumn.ts +0 -478
  144. package/src/components/InfiniteTable/types/InfiniteTableComputedValues.ts +0 -43
  145. package/src/components/InfiniteTable/types/InfiniteTableContextValue.ts +0 -12
  146. package/src/components/InfiniteTable/types/InfiniteTableInternalProps.ts +0 -3
  147. package/src/components/InfiniteTable/types/InfiniteTableProps.ts +0 -511
  148. package/src/components/InfiniteTable/types/InfiniteTableState.ts +0 -195
  149. package/src/components/InfiniteTable/types/Utility.ts +0 -35
  150. package/src/components/InfiniteTable/types/index.ts +0 -96
  151. package/src/components/InfiniteTable/utilities.css.ts +0 -179
  152. package/src/components/InfiniteTable/utils/MultiRowSelector.ts +0 -111
  153. package/src/components/InfiniteTable/utils/RenderHookComponentForInfinite.tsx +0 -52
  154. package/src/components/InfiniteTable/utils/adjustColumnOrderForPinning.ts +0 -33
  155. package/src/components/InfiniteTable/utils/assignFiltered.ts +0 -29
  156. package/src/components/InfiniteTable/utils/defaultGetColumContextMenuItems.tsx +0 -108
  157. package/src/components/InfiniteTable/utils/getColumnComputedType.ts +0 -33
  158. package/src/components/InfiniteTable/utils/getColumnForGroupBy.tsx +0 -313
  159. package/src/components/InfiniteTable/utils/getComputedVisibleColumns.ts +0 -773
  160. package/src/components/InfiniteTable/utils/getContextMenuForColumn.tsx +0 -72
  161. package/src/components/InfiniteTable/utils/infiniteDOMUtils.ts +0 -189
  162. package/src/components/InfiniteTable/utils/mapToObject.ts +0 -20
  163. package/src/components/InfiniteTable/utils/moveXatY.ts +0 -25
  164. package/src/components/InfiniteTable/utils/objectValuesExcept.ts +0 -9
  165. package/src/components/InfiniteTable/utils/progressiveSpeedScroller.ts +0 -158
  166. package/src/components/InfiniteTable/utils/rafFn.ts +0 -13
  167. package/src/components/InfiniteTable/utils/toCSSVarName.ts +0 -1
  168. package/src/components/InfiniteTable/utils/toMap.ts +0 -24
  169. package/src/components/Menu/Menu.tsx +0 -750
  170. package/src/components/Menu/MenuCls.css.ts +0 -139
  171. package/src/components/Menu/MenuContext.ts +0 -10
  172. package/src/components/Menu/MenuContextValue.ts +0 -15
  173. package/src/components/Menu/MenuProps.ts +0 -98
  174. package/src/components/Menu/MenuState.ts +0 -56
  175. package/src/components/Menu/MenuTriangleContext.ts +0 -352
  176. package/src/components/Menu/childrenToRuntimeItems.tsx +0 -103
  177. package/src/components/Menu/getMenuState.tsx +0 -119
  178. package/src/components/Menu/index.tsx +0 -88
  179. package/src/components/Menu/propToIdentifyMenu.ts +0 -1
  180. package/src/components/RawList/AvoidReactDiff.tsx +0 -48
  181. package/src/components/RawList/MappedItems.ts +0 -143
  182. package/src/components/RawList/ReactVirtualRenderer.tsx +0 -307
  183. package/src/components/RawList/index.tsx +0 -42
  184. package/src/components/RawList/types.ts +0 -23
  185. package/src/components/RawList/useVirtualRenderer.ts +0 -36
  186. package/src/components/RenderHookComponent.tsx +0 -10
  187. package/src/components/ResizeObserver/index.tsx +0 -170
  188. package/src/components/VirtualBrain/MatrixBrain.ts +0 -1621
  189. package/src/components/VirtualBrain/ScrollListener.ts +0 -39
  190. package/src/components/VirtualBrain/index.ts +0 -664
  191. package/src/components/VirtualList/ColumnListWithExternalScrolling.tsx +0 -78
  192. package/src/components/VirtualList/InfiniteListRootClassName.ts +0 -1
  193. package/src/components/VirtualList/RowListWithExternalScrolling.tsx +0 -120
  194. package/src/components/VirtualList/SpacePlaceholder.tsx +0 -32
  195. package/src/components/VirtualList/VirtualList.css.ts +0 -29
  196. package/src/components/VirtualList/VirtualList.tsx +0 -141
  197. package/src/components/VirtualList/VirtualRowList.tsx +0 -34
  198. package/src/components/VirtualList/types.ts +0 -56
  199. package/src/components/VirtualList/useCorrectHeightForRowElements.ts +0 -14
  200. package/src/components/VirtualScrollContainer/VirtualScrollContainer.css.ts +0 -51
  201. package/src/components/VirtualScrollContainer/getScrollableClassName.ts +0 -30
  202. package/src/components/VirtualScrollContainer/index.tsx +0 -63
  203. package/src/components/flexbox/index.ts +0 -562
  204. package/src/components/hooks/useComponentState/index.tsx +0 -562
  205. package/src/components/hooks/useComponentState/types.ts +0 -32
  206. package/src/components/hooks/useEffectOnceWithProperUnmount.ts +0 -33
  207. package/src/components/hooks/useEffectWithChanges.ts +0 -56
  208. package/src/components/hooks/useImmutableRef.ts +0 -7
  209. package/src/components/hooks/useInterceptedMap.ts +0 -71
  210. package/src/components/hooks/useLatest.tsx +0 -8
  211. package/src/components/hooks/useLazyLatest.ts +0 -23
  212. package/src/components/hooks/useMemoShallowObjectMerge.ts +0 -16
  213. package/src/components/hooks/useMounted.ts +0 -18
  214. package/src/components/hooks/useOnMount.ts +0 -21
  215. package/src/components/hooks/useOnScroll.ts +0 -34
  216. package/src/components/hooks/useOnce.ts +0 -10
  217. package/src/components/hooks/useOverlay/index.tsx +0 -418
  218. package/src/components/hooks/usePrevious.ts +0 -8
  219. package/src/components/hooks/usePropertyOld.ts +0 -168
  220. package/src/components/hooks/useRerender.ts +0 -12
  221. package/src/components/hooks/xuseProperty.ts +0 -165
  222. package/src/components/types/CellPosition.ts +0 -4
  223. package/src/components/types/NonUndefined.ts +0 -1
  224. package/src/components/types/RemoveObject.ts +0 -22
  225. package/src/components/types/Renderable.ts +0 -3
  226. package/src/components/types/ScrollPosition.ts +0 -7
  227. package/src/components/types/Setter.ts +0 -2
  228. package/src/components/types/Size.ts +0 -6
  229. package/src/components/types/SubscriptionCallback.ts +0 -10
  230. package/src/components/types/VoidFn.ts +0 -1
  231. package/src/components/utils/buildSubscriptionCallback.tsx +0 -60
  232. package/src/components/utils/clamp.ts +0 -3
  233. package/src/components/utils/debounce.ts +0 -16
  234. package/src/components/utils/decamelize.ts +0 -11
  235. package/src/components/utils/discardCallsWithEqualArg.ts +0 -42
  236. package/src/components/utils/getRenderIndexes.ts +0 -33
  237. package/src/components/utils/getScrollbarWidth.ts +0 -31
  238. package/src/components/utils/getVirtualRenderCount.ts +0 -21
  239. package/src/components/utils/isControlled.ts +0 -12
  240. package/src/components/utils/isControlledValue.ts +0 -5
  241. package/src/index.tsx +0 -34
  242. package/src/test.tsx +0 -18
  243. package/src/utils/DeepMap/index.ts +0 -588
  244. package/src/utils/DeepMap/once.ts +0 -16
  245. package/src/utils/DeepMap/sortAscending.ts +0 -1
  246. package/src/utils/DeepMap/tsconfig.deepmap.json +0 -17
  247. package/src/utils/DeepMap/xpackage.json +0 -26
  248. package/src/utils/debug.ts +0 -40
  249. package/src/utils/deepClone.ts +0 -38
  250. package/src/utils/getGlobal.ts +0 -3
  251. package/src/utils/groupAndPivot/defaultToKey.ts +0 -3
  252. package/src/utils/groupAndPivot/getGroupKeysForDataItem.ts +0 -19
  253. package/src/utils/groupAndPivot/getPivotColumnsAndColumnGroups.ts +0 -361
  254. package/src/utils/groupAndPivot/index.ts +0 -1229
  255. package/src/utils/groupAndPivot/types.ts +0 -10
  256. package/src/utils/join.ts +0 -4
  257. package/src/utils/mathIntersection.ts +0 -21
  258. package/src/utils/minified.d.ts +0 -2
  259. package/src/utils/minified.js +0 -6
  260. package/src/utils/multisort/index.ts +0 -151
  261. package/src/utils/multisort/sortTypes.ts +0 -25
  262. package/src/utils/notes-status.md +0 -92
  263. package/src/utils/pageGeometry/ConvexPoly.ts +0 -34
  264. package/src/utils/pageGeometry/Point.ts +0 -51
  265. package/src/utils/pageGeometry/PolyWithPoints.ts +0 -52
  266. package/src/utils/pageGeometry/Rectangle.ts +0 -98
  267. package/src/utils/pageGeometry/Triangle.ts +0 -16
  268. package/src/utils/pageGeometry/alignment/index.ts +0 -221
  269. package/src/utils/pageGeometry/polyContainsPoint.ts +0 -182
  270. package/src/utils/pageGeometry/types.ts +0 -3
  271. package/src/utils/proxyFnCall.ts +0 -46
  272. package/src/utils/raf.ts +0 -13
  273. package/src/utils/selectParent.ts +0 -18
  274. package/src/utils/shallowEqualObjects.ts +0 -49
  275. package/src/utils/stripVar.ts +0 -3
  276. package/src/utils/toUpperFirst.ts +0 -5
  277. package/todo.md +0 -2
  278. package/tsconfig.build.json +0 -8
  279. package/tsconfig.dev.json +0 -7
  280. package/tsconfig.json +0 -30
  281. package/tsconfig.typebundler.json +0 -13
  282. package/typedoc.json +0 -4
@@ -1,39 +0,0 @@
1
- import { OnScrollFn, ScrollPosition } from '../types/ScrollPosition';
2
-
3
- const initialScrollPosition = {
4
- scrollLeft: 0,
5
- scrollTop: 0,
6
- };
7
- export class ScrollListener {
8
- private scrollPosition: ScrollPosition = initialScrollPosition;
9
- private onScrollFns: OnScrollFn[] = [];
10
-
11
- public getScrollPosition = () => {
12
- return this.scrollPosition;
13
- };
14
-
15
- public onScroll = (fn: OnScrollFn) => {
16
- this.onScrollFns.push(fn);
17
- return () => {
18
- this.onScrollFns = this.onScrollFns.filter((f) => f !== fn);
19
- };
20
- };
21
- public setScrollPosition = (scrollPosition: ScrollPosition) => {
22
- this.scrollPosition = scrollPosition;
23
-
24
- this.notifyScrollChange();
25
- };
26
-
27
- private notifyScrollChange() {
28
- const { scrollPosition } = this;
29
-
30
- const fns = this.onScrollFns;
31
- for (let i = 0, len = fns.length; i < len; i++) {
32
- fns[i](scrollPosition);
33
- }
34
- }
35
-
36
- destroy = () => {
37
- this.onScrollFns = [];
38
- };
39
- }
@@ -1,664 +0,0 @@
1
- import binarySearch from 'binary-search';
2
- import { Logger } from '../../utils/debug';
3
- import type { Size } from '../types/Size';
4
-
5
- import type { OnScrollFn, ScrollPosition } from '../types/ScrollPosition';
6
-
7
- type MainAxisOptions = 'vertical' | 'horizontal';
8
-
9
- const initialScrollPosition = {
10
- scrollLeft: 0,
11
- scrollTop: 0,
12
- };
13
-
14
- const raf =
15
- typeof window !== 'undefined'
16
- ? requestAnimationFrame
17
- : (fn: () => void) => setTimeout(fn, 0);
18
-
19
- export type VirtualBrainOptions = {
20
- mainAxis: MainAxisOptions;
21
- itemSize: MainAxisSize;
22
-
23
- itemSpan?: ({ itemIndex }: { itemIndex: number }) => number;
24
-
25
- count: number;
26
- name?: string;
27
- };
28
-
29
- const ItemIndexBag = Object.seal({ itemIndex: 0 });
30
-
31
- export type MainAxisSize = number | ((itemIndex: number) => number);
32
- type BrainCache = number[];
33
- type OnRenderCountChangeFn = (renderCount: number) => void;
34
- type OnSizeChangeFn = (size: number) => void;
35
- type OnDestroyFn = () => void;
36
-
37
- export type GetItemPositionFn = (itemIndex: number) => number;
38
-
39
- export type RenderRange = {
40
- renderStartIndex: number;
41
- renderEndIndex: number;
42
- };
43
- export type OnRenderRangeChangeFn = (renderRange: RenderRange) => void;
44
-
45
- const SORT_ASC = (a: number, b: number) => a - b;
46
-
47
- export class VirtualBrain extends Logger {
48
- private scrollPosition: ScrollPosition = initialScrollPosition;
49
- private scrollPositionOnMainAxis: number = 0;
50
-
51
- private itemSpanParent!: BrainCache;
52
- private itemSpanValue!: BrainCache;
53
- private itemSizeCache!: BrainCache;
54
- private itemOffsetCache!: BrainCache;
55
- private options!: VirtualBrainOptions;
56
-
57
- private destroyed: boolean = false;
58
-
59
- private totalSize: number = 0;
60
-
61
- private onScrollFns: OnScrollFn[] = [];
62
- private onTotalSizeChangeFns: OnSizeChangeFn[] = [];
63
- private onRenderCountChangeFns: OnRenderCountChangeFn[] = [];
64
- private onRenderRangeChangeFns: OnRenderRangeChangeFn[] = [];
65
- private onDestroyFns: OnDestroyFn[] = [];
66
-
67
- name: string | undefined;
68
-
69
- private renderCount: number = 0;
70
- private renderRange: RenderRange = {
71
- renderStartIndex: -1,
72
- renderEndIndex: -1,
73
- };
74
- private availableSize: Size = { width: 0, height: 0 };
75
-
76
- constructor(options: VirtualBrainOptions) {
77
- super(`VirtualBrain:${options.mainAxis}`);
78
-
79
- this.options = options;
80
-
81
- this.reset();
82
-
83
- this.renderCount = 0;
84
-
85
- this.debug(`Init ${options.mainAxis}`);
86
- }
87
-
88
- public setAvailableSize = (size: Size) => {
89
- this.availableSize = size;
90
- if (__DEV__) {
91
- this.debug(
92
- 'New available size %d',
93
- size[this.options.mainAxis === 'vertical' ? 'height' : 'width'],
94
- );
95
- }
96
-
97
- this.updateRenderCount();
98
- };
99
-
100
- getOptions() {
101
- return this.options;
102
- }
103
-
104
- private updateRenderCount(renderCount?: number) {
105
- const { itemSize, mainAxis, count } = this.options;
106
- const size =
107
- this.availableSize[mainAxis === 'vertical' ? 'height' : 'width'];
108
-
109
- if (!size) {
110
- this.setRenderCount(0);
111
- return;
112
- }
113
-
114
- this.setRenderCount(
115
- renderCount ?? this.computeRenderCount({ itemSize, count, size }),
116
- );
117
- }
118
-
119
- private computeRenderCount = ({
120
- itemSize,
121
- count,
122
- size,
123
- }: {
124
- itemSize: MainAxisSize;
125
- count: number;
126
- size: number;
127
- }) => {
128
- let renderCount = 0;
129
- if (typeof itemSize === 'function') {
130
- const sizes = [];
131
- for (let i = 0; i < count; i++) {
132
- sizes.push(this.getItemSize(i));
133
- }
134
- sizes.sort(SORT_ASC);
135
- let sum = 0;
136
- for (let i = 0; i < count; i++) {
137
- sum += sizes[i];
138
-
139
- renderCount++;
140
- if (sum > size) {
141
- break;
142
- }
143
- }
144
- renderCount += 1;
145
- } else {
146
- renderCount = Math.ceil(size / itemSize) + 1;
147
- }
148
-
149
- renderCount = Math.min(count, renderCount);
150
-
151
- return renderCount;
152
- };
153
-
154
- private setRenderCount = (renderCount: number) => {
155
- if (renderCount === this.renderCount) {
156
- this.notifyTotalSizeChange();
157
- return;
158
- }
159
-
160
- if (__DEV__) {
161
- this.debug('set renderCount to %d', renderCount);
162
- }
163
- this.renderCount = renderCount;
164
-
165
- this.updateRenderRange();
166
-
167
- this.notifyRenderCountChange();
168
- this.notifyTotalSizeChange();
169
- };
170
-
171
- private updateRenderRange() {
172
- this.setRenderRange(this.computeRenderRange());
173
- }
174
-
175
- public getRenderStartIndex() {
176
- return this.renderRange.renderStartIndex;
177
- }
178
-
179
- public getRenderCount = () => {
180
- return this.renderCount ?? 0;
181
- };
182
-
183
- public setScrollPosition = (scrollPosition: ScrollPosition) => {
184
- this.scrollPosition = scrollPosition;
185
-
186
- const oldScrollPosOnMainAxis = this.scrollPositionOnMainAxis;
187
-
188
- this.scrollPositionOnMainAxis =
189
- this.scrollPosition[
190
- this.options.mainAxis === 'vertical' ? 'scrollTop' : 'scrollLeft'
191
- ];
192
-
193
- if (this.scrollPositionOnMainAxis !== oldScrollPosOnMainAxis) {
194
- this.updateRenderRange();
195
- }
196
- this.notifyScrollChange();
197
- };
198
-
199
- private notifyScrollChange() {
200
- const { scrollPosition } = this;
201
-
202
- const fns = this.onScrollFns;
203
- for (let i = 0, len = fns.length; i < len; i++) {
204
- fns[i](scrollPosition);
205
- }
206
- }
207
-
208
- private notifyDestroy() {
209
- const fns = this.onDestroyFns;
210
- for (let i = 0, len = fns.length; i < len; i++) {
211
- fns[i]();
212
- }
213
- }
214
-
215
- private notifyTotalSizeChange() {
216
- const totalSize = this.getTotalSize();
217
-
218
- const fns = this.onTotalSizeChangeFns;
219
- for (let i = 0, len = fns.length; i < len; i++) {
220
- raf(() => {
221
- fns[i](totalSize);
222
- });
223
- }
224
- }
225
-
226
- private notifyRenderCountChange() {
227
- const { renderCount } = this;
228
-
229
- const fns = this.onRenderCountChangeFns;
230
- for (let i = 0, len = fns.length; i < len; i++) {
231
- raf(() => {
232
- fns[i](renderCount);
233
- });
234
- }
235
- }
236
-
237
- private notifyRenderRangeChange() {
238
- const { renderRange } = this;
239
-
240
- const fns = this.onRenderRangeChangeFns;
241
-
242
- for (let i = 0, len = fns.length; i < len; i++) {
243
- raf(() => {
244
- fns[i](renderRange);
245
- });
246
- }
247
- }
248
-
249
- public getRenderRange = (): RenderRange => {
250
- return this.renderRange;
251
- };
252
-
253
- private setRenderRange(renderRange: RenderRange) {
254
- const { renderStartIndex, renderEndIndex } = this.renderRange;
255
-
256
- if (
257
- renderEndIndex !== renderRange.renderEndIndex ||
258
- renderStartIndex !== renderRange.renderStartIndex
259
- ) {
260
- this.renderRange = renderRange;
261
- if (__DEV__) {
262
- this.debug(
263
- 'Set renderRange to %d-%d',
264
- renderRange.renderStartIndex,
265
- renderRange.renderEndIndex,
266
- );
267
- }
268
-
269
- this.notifyRenderRangeChange();
270
- }
271
- }
272
-
273
- private computeRenderRange(): RenderRange {
274
- const count = this.getOptions().count;
275
- let renderCount = this.getRenderCount();
276
-
277
- if (renderCount === 0) {
278
- return {
279
- renderStartIndex: -1,
280
- renderEndIndex: -1,
281
- };
282
- }
283
-
284
- let renderStartIndex = this.getItemAt(this.scrollPositionOnMainAxis);
285
- let renderEndIndex = renderStartIndex + this.renderCount - 1;
286
-
287
- if (renderEndIndex >= count) {
288
- renderEndIndex = count - 1;
289
- renderStartIndex = renderEndIndex - renderCount + 1;
290
- }
291
-
292
- //TODO we can avoid doing this expand here
293
- // if the renderStartIndex row is spanned over, we only need to render the span parent instead
294
- // of the current row - so big wins
295
- if (this.options.itemSpan) {
296
- this.computeItemSpanUpTo(renderStartIndex);
297
-
298
- while (this.itemSpanParent[renderStartIndex] != renderStartIndex) {
299
- renderStartIndex--;
300
- }
301
- }
302
-
303
- return {
304
- renderStartIndex,
305
- renderEndIndex,
306
- };
307
- }
308
-
309
- public getScrollPosition = () => {
310
- return this.scrollPosition;
311
- };
312
-
313
- public onScroll = (fn: OnScrollFn) => {
314
- this.onScrollFns.push(fn);
315
- return () => {
316
- this.onScrollFns = this.onScrollFns.filter((f) => f !== fn);
317
- };
318
- };
319
-
320
- public onTotalSizeChange = (fn: OnSizeChangeFn) => {
321
- this.onTotalSizeChangeFns.push(fn);
322
- return () => {
323
- this.onTotalSizeChangeFns = this.onTotalSizeChangeFns.filter(
324
- (f) => f !== fn,
325
- );
326
- };
327
- };
328
- public onRenderCountChange = (fn: OnRenderCountChangeFn) => {
329
- this.onRenderCountChangeFns.push(fn);
330
- return () => {
331
- this.onRenderCountChangeFns = this.onRenderCountChangeFns.filter(
332
- (f) => f !== fn,
333
- );
334
- };
335
- };
336
- public onRenderRangeChange = (fn: OnRenderRangeChangeFn) => {
337
- this.onRenderRangeChangeFns.push(fn);
338
-
339
- return () => {
340
- this.onRenderRangeChangeFns = this.onRenderRangeChangeFns.filter(
341
- (f) => f !== fn,
342
- );
343
- };
344
- };
345
-
346
- public onDestroy = (fn: OnDestroyFn) => {
347
- this.onDestroyFns.push(fn);
348
-
349
- return () => {
350
- this.onDestroyFns = this.onDestroyFns.filter((f) => f !== fn);
351
- };
352
- };
353
-
354
- public update = (
355
- newCount: VirtualBrainOptions['count'],
356
- newItemSize: VirtualBrainOptions['itemSize'],
357
- newItemSpan?: VirtualBrainOptions['itemSpan'],
358
- ) => {
359
- const { itemSize, count, itemSpan } = this.options;
360
-
361
- const countChange = count !== newCount;
362
- const itemSizeChange = itemSize !== newItemSize;
363
- const itemSpanChange = itemSpan !== newItemSpan;
364
-
365
- if (!countChange && !itemSizeChange && !itemSpanChange) {
366
- // this.debug(
367
- // `Range (count=${count}, itemSize=${
368
- // typeof itemSize === 'number' ? itemSize : 'fn'
369
- // }) has not changed, so skip update`,
370
- // );
371
-
372
- return;
373
- }
374
-
375
- // this.debug(
376
- // `Range changed (count=${newCount}, itemSize=${
377
- // typeof newItemSize === 'number' ? newItemSize : 'fn'
378
- // }), so update`,
379
- // );
380
-
381
- this.options.count = newCount;
382
- this.options.itemSize = newItemSize;
383
- this.options.itemSpan = newItemSpan;
384
-
385
- const size =
386
- this.availableSize[
387
- this.options.mainAxis === 'vertical' ? 'height' : 'width'
388
- ];
389
-
390
- const newRenderCount = this.computeRenderCount({
391
- itemSize: newItemSize,
392
- count: newCount,
393
- size,
394
- });
395
-
396
- //TODO this can be optimized even further
397
- // since when just count changes, even if it's smaller, the cache should be kept
398
- if (!itemSizeChange && !itemSpanChange && countChange && newCount > count) {
399
- const currentRenderCount = this.getRenderCount();
400
-
401
- // no need to continue, since just the count grew - with the exception when the render count was zero before
402
- if (currentRenderCount > newRenderCount) {
403
- return;
404
- }
405
- }
406
-
407
- if (__DEV__) {
408
- if (itemSizeChange && countChange) {
409
- this.debug(
410
- `Reset brain: reason itemSize changed and count changed (old ${count}, new ${newCount})`,
411
- {
412
- oldItemSize: itemSize,
413
- newItemSize,
414
- },
415
- );
416
- } else if (itemSizeChange) {
417
- this.debug(`Reset brain: reason itemSize changed`, {
418
- oldItemSize: itemSize,
419
- newItemSize,
420
- });
421
- } else if (countChange) {
422
- this.debug(
423
- `Reset brain: reason count changed (old ${count}, new ${newCount})`,
424
- );
425
- }
426
- }
427
-
428
- this.reset();
429
-
430
- this.updateRenderCount(newRenderCount);
431
- };
432
-
433
- private reset = () => {
434
- this.itemSpanParent = [];
435
- this.itemSpanValue = [];
436
- this.itemSizeCache = [];
437
- this.itemOffsetCache = [0];
438
- this.renderCount = -1;
439
- this.totalSize = 0;
440
- };
441
-
442
- private computeItemSpanUpTo = (itemIndex: number) => {
443
- const { count, itemSpan } = this.options;
444
-
445
- if (!itemSpan) {
446
- return;
447
- }
448
-
449
- const cache = this.itemSpanParent;
450
- const spanResultArr = this.itemSpanValue;
451
-
452
- if (cache[itemIndex] === undefined) {
453
- let i = cache.length;
454
- let lastIndex = Math.min(itemIndex, count - 1);
455
-
456
- for (; i <= lastIndex; i++) {
457
- if (cache[i] === undefined) {
458
- ItemIndexBag.itemIndex = i;
459
- let spanValue = itemSpan(ItemIndexBag);
460
-
461
- if (__DEV__ && spanValue < 1) {
462
- this.debug(
463
- 'itemSpan cannot be less than 1 - got %d for index %d',
464
- spanValue,
465
- i,
466
- );
467
- }
468
- // this is it's own span parent
469
- cache[i] = i;
470
- spanResultArr[i] = spanValue;
471
-
472
- let spannedItemIndex: number = i;
473
- while (spanValue > 1) {
474
- spannedItemIndex += 1;
475
- cache[spannedItemIndex] = i;
476
- spanResultArr[spannedItemIndex] = 0;
477
-
478
- spanValue -= 1;
479
- }
480
- }
481
- }
482
- // spanParent = this.getItemSizeCacheFor(itemIndex);
483
- }
484
- };
485
-
486
- private computeCacheFor = (itemIndex: number) => {
487
- if (typeof this.options.itemSize !== 'function') {
488
- return;
489
- }
490
-
491
- const itemSize: number = this.options.itemSize(itemIndex);
492
- this.itemSizeCache[itemIndex] = itemSize;
493
-
494
- if (itemIndex > 0) {
495
- const prevOffset = this.itemOffsetCache[itemIndex - 1];
496
- const prevSize = this.itemSizeCache[itemIndex - 1];
497
- if (prevOffset == null) {
498
- console.error(`Offset was not available for item ${itemIndex - 1}`);
499
- }
500
- if (prevSize == null) {
501
- console.error(`Size was not available for item ${itemIndex - 1}`);
502
- }
503
- const offset = prevOffset + prevSize;
504
- this.itemOffsetCache[itemIndex] = offset;
505
- }
506
- };
507
-
508
- private getItemSizeCacheFor(itemIndex: number): number {
509
- return this.itemSizeCache[itemIndex];
510
- }
511
-
512
- getItemSpan = (itemIndex: number) => {
513
- if (!this.options.itemSpan) {
514
- return 1;
515
- }
516
- if (this.itemSpanValue[itemIndex] === undefined) {
517
- this.computeItemSpanUpTo(itemIndex);
518
- }
519
- return this.itemSpanValue[itemIndex] || 1;
520
- };
521
-
522
- getItemSpanParent = (itemIndex: number) => {
523
- if (!this.options.itemSpan) {
524
- return itemIndex;
525
- }
526
- if (this.itemSpanParent[itemIndex] === undefined) {
527
- this.computeItemSpanUpTo(itemIndex);
528
- }
529
- return this.itemSpanParent[itemIndex];
530
- };
531
-
532
- getItemSizeWithSpan = (itemIndex: number, itemSpan: number) => {
533
- let itemSize = this.getItemSize(itemIndex);
534
-
535
- while (itemSpan > 1) {
536
- itemIndex += 1;
537
- itemSpan -= 1;
538
- itemSize += this.getItemSize(itemIndex);
539
- }
540
-
541
- return itemSize;
542
- };
543
-
544
- /**
545
- * For now, this doesn't take into account the itemspan, and it's okay not to
546
- * @param itemIndex
547
- * @returns the size of the specified item
548
- */
549
- getItemSize = (itemIndex: number): number => {
550
- const { itemSize, count } = this.options;
551
-
552
- if (typeof itemSize !== 'function') {
553
- return itemSize;
554
- }
555
-
556
- // we make sure when we request the size for an item at a given index
557
- // all previous items have their size cached
558
-
559
- // we could take a more optimized approach, but for now, we only have
560
- // itemMainAxisSize as a function for column virtualization
561
- // which doesn't need a more performant approach right now, as we dont expect a column count > 10k
562
-
563
- let cachedSize = this.getItemSizeCacheFor(itemIndex);
564
-
565
- if (cachedSize === undefined) {
566
- let i = this.itemSizeCache.length;
567
- let lastIndex = Math.min(itemIndex, count - 1);
568
-
569
- for (; i <= lastIndex; i++) {
570
- this.computeCacheFor(i);
571
- }
572
- cachedSize = this.getItemSizeCacheFor(itemIndex);
573
- }
574
-
575
- return cachedSize;
576
- };
577
-
578
- getTotalSize = () => {
579
- const { count, itemSize } = this.options;
580
- if (typeof itemSize !== 'function') {
581
- return itemSize * count;
582
- }
583
- if (this.totalSize !== 0) {
584
- return this.totalSize;
585
- }
586
-
587
- const lastItemSize = this.getItemSize(count - 1);
588
- const lastItemOffset = this.itemOffsetCache[count - 1];
589
-
590
- return (this.totalSize = lastItemSize + lastItemOffset);
591
- };
592
-
593
- public getItemAt = (scrollPos: number): number => {
594
- const { itemSize, count } = this.options;
595
- if (typeof itemSize !== 'function') {
596
- return Math.min(Math.max(0, Math.floor(scrollPos / itemSize)), count - 1);
597
- }
598
-
599
- let lastOffsetIndex = this.itemOffsetCache.length - 1;
600
- let lastSizeIndex = this.itemSizeCache.length - 1;
601
- let lastOffset = this.itemOffsetCache[lastOffsetIndex];
602
-
603
- let _prev: number;
604
-
605
- while (lastOffset < scrollPos) {
606
- if (lastOffsetIndex >= count) {
607
- return count - 1;
608
- }
609
- lastSizeIndex += 1;
610
- this.computeCacheFor(lastSizeIndex);
611
- _prev = lastOffset;
612
- lastOffset = this.itemOffsetCache[lastSizeIndex];
613
- if (_prev === lastOffset && _prev != 0) {
614
- return count - 1;
615
- }
616
- }
617
-
618
- const searchResult = binarySearch(
619
- this.itemOffsetCache,
620
- scrollPos,
621
- SORT_ASC,
622
- );
623
-
624
- if (searchResult >= 0) {
625
- return searchResult;
626
- }
627
-
628
- return ~searchResult - 1;
629
- };
630
-
631
- public getItemOffsetFor = (itemIndex: number): number => {
632
- if (typeof this.options.itemSize !== 'function') {
633
- return itemIndex * this.options.itemSize;
634
- }
635
- let result = this.itemOffsetCache[itemIndex];
636
-
637
- if (result == null) {
638
- let lastSizeIndex = this.itemSizeCache.length - 1;
639
-
640
- while (lastSizeIndex < itemIndex) {
641
- lastSizeIndex += 1;
642
- this.computeCacheFor(lastSizeIndex);
643
- }
644
-
645
- result = this.itemOffsetCache[itemIndex];
646
- }
647
- return result;
648
- };
649
-
650
- destroy = () => {
651
- if (this.destroyed) {
652
- return;
653
- }
654
- this.notifyDestroy();
655
- this.reset();
656
-
657
- this.destroyed = true;
658
- this.onDestroyFns = [];
659
- this.onScrollFns = [];
660
- this.onTotalSizeChangeFns = [];
661
- this.onRenderCountChangeFns = [];
662
- this.onRenderRangeChangeFns = [];
663
- };
664
- }