@infinite-table/infinite-react 0.4.13 → 0.5.0

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 +95 -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,71 @@
1
+ import { useEffect } from 'react';
2
+
3
+ type InterceptedMapFns<K, V> = {
4
+ set?: (k: K, v: V) => void;
5
+ beforeClear?: (map: Map<K, V>) => void;
6
+ clear?: () => void;
7
+ delete?: (k: K) => void;
8
+ };
9
+
10
+ /**
11
+ *
12
+ * @param map Map to intercept
13
+ * @param fns fns to inject
14
+ * @returns a function to restore the map to initial methods
15
+ */
16
+ export function interceptMap<K, V>(
17
+ map: Map<K, V>,
18
+ fns: InterceptedMapFns<K, V>,
19
+ ) {
20
+ const { set, delete: deleteKey, clear } = map;
21
+
22
+ if (fns.set) {
23
+ map.set = (key: K, value: V) => {
24
+ set.call(map, key, value);
25
+ fns.set!(key, value);
26
+
27
+ return map;
28
+ };
29
+ }
30
+ if (fns.delete) {
31
+ map.delete = (key: any) => {
32
+ const removed = deleteKey.call(map, key);
33
+ fns.delete!(key)!;
34
+
35
+ return removed;
36
+ };
37
+ }
38
+ if (fns.clear || fns.beforeClear) {
39
+ map.clear = () => {
40
+ if (fns.beforeClear) {
41
+ fns.beforeClear(map);
42
+ }
43
+ const result = clear.call(map);
44
+ if (fns.clear) {
45
+ fns.clear();
46
+ }
47
+ return result;
48
+ };
49
+ }
50
+
51
+ return () => {
52
+ if (set) {
53
+ map.set = set;
54
+ }
55
+ if (deleteKey) {
56
+ map.delete = deleteKey;
57
+ }
58
+ if (clear) {
59
+ map.clear = clear;
60
+ }
61
+ };
62
+ }
63
+
64
+ export function useInterceptedMap<K, V>(
65
+ map: Map<K, V>,
66
+ fns: InterceptedMapFns<K, V>,
67
+ ) {
68
+ useEffect(() => {
69
+ return interceptMap(map, fns);
70
+ }, [map]);
71
+ }
@@ -0,0 +1,8 @@
1
+ import { useCallback, useRef } from 'react';
2
+
3
+ export function useLatest<T>(value: T): () => T {
4
+ const ref = useRef(value);
5
+ ref.current = value;
6
+
7
+ return useCallback(() => ref.current, []);
8
+ }
@@ -0,0 +1,23 @@
1
+ import { useCallback, useMemo, useRef } from 'react';
2
+
3
+ export type LazyLatest<T> = {
4
+ (): T | undefined;
5
+ current: T;
6
+ };
7
+
8
+ export const useLazyLatest = <T>(value?: T): LazyLatest<T> => {
9
+ const ref = useRef(value);
10
+ ref.current = value;
11
+
12
+ const fn = useCallback(() => ref.current, []);
13
+
14
+ return useMemo(() => {
15
+ Object.defineProperty(fn, 'current', {
16
+ set(value: T) {
17
+ ref.current = value;
18
+ },
19
+ });
20
+
21
+ return fn as LazyLatest<T>;
22
+ }, [fn]);
23
+ };
@@ -0,0 +1,16 @@
1
+ import { useRef } from 'react';
2
+ import { shallowEqualObjects } from '../../utils/shallowEqualObjects';
3
+
4
+ export function useMemoShallowObjectMerge<T1 extends object, T2 extends object>(
5
+ a: T1,
6
+ b: T2,
7
+ merger?: (a: T1, b: T2) => T1 & T2,
8
+ ) {
9
+ const result = merger ? merger(a, b) : { ...a, ...b };
10
+ const ref = useRef(result);
11
+
12
+ if (!shallowEqualObjects(result, ref.current)) {
13
+ ref.current = result;
14
+ }
15
+ return ref.current;
16
+ }
@@ -0,0 +1,18 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+
3
+ export function useMounted() {
4
+ let mountedRef = useRef<boolean>(true);
5
+
6
+ useEffect(() => {
7
+ // because React StrictMode (in >=18.0.0) will call useEffect twice
8
+ // we need to make sure that we set this back to true in useEffect
9
+ mountedRef.current = true;
10
+ return () => {
11
+ mountedRef.current = false;
12
+ };
13
+ }, []);
14
+
15
+ const isMounted = useCallback(() => mountedRef.current, []);
16
+
17
+ return isMounted;
18
+ }
@@ -0,0 +1,21 @@
1
+ import { RefObject, useEffect } from 'react';
2
+
3
+ export type OnMountProps = {
4
+ onMount?: (node: HTMLElement) => void;
5
+ onUnmount?: (node: HTMLElement) => void;
6
+ };
7
+ export function useOnMount(
8
+ domRef: RefObject<HTMLElement>,
9
+ props: OnMountProps,
10
+ ) {
11
+ useEffect(() => {
12
+ const { onMount, onUnmount } = props;
13
+
14
+ const node = domRef?.current;
15
+ onMount?.(node!);
16
+
17
+ return () => {
18
+ onUnmount?.(node!);
19
+ };
20
+ }, []);
21
+ }
@@ -0,0 +1,34 @@
1
+ import { RefObject, useEffect } from 'react';
2
+
3
+ type OnScroll = (scrollPosition: {
4
+ scrollTop: number;
5
+ scrollLeft: number;
6
+ }) => void;
7
+
8
+ export const useOnScroll = (
9
+ domRef: RefObject<HTMLElement>,
10
+ onScroll: OnScroll | undefined,
11
+ ) => {
12
+ useEffect(() => {
13
+ const domNode = domRef?.current;
14
+
15
+ const scrollFn = (event: Event) => {
16
+ const node = event.target as HTMLElement;
17
+
18
+ onScroll?.({
19
+ scrollTop: node.scrollTop,
20
+ scrollLeft: node.scrollLeft,
21
+ });
22
+ };
23
+
24
+ const options: AddEventListenerOptions = {
25
+ passive: false,
26
+ };
27
+
28
+ domNode?.addEventListener('scroll', scrollFn, options);
29
+
30
+ return () => {
31
+ domNode?.removeEventListener('scroll', scrollFn);
32
+ };
33
+ }, [onScroll, domRef?.current]);
34
+ };
@@ -0,0 +1,10 @@
1
+ import { useMemo } from 'react';
2
+ import { once } from '../../utils/DeepMap/once';
3
+
4
+ export function useOnce<ReturnType>(fn: () => ReturnType): ReturnType {
5
+ const onceFn = useMemo<() => ReturnType>(() => {
6
+ return once(fn);
7
+ }, []);
8
+
9
+ return onceFn();
10
+ }
@@ -0,0 +1,418 @@
1
+ import * as React from 'react';
2
+ import {
3
+ ReactNode,
4
+ useCallback,
5
+ useEffect,
6
+ useLayoutEffect,
7
+ useState,
8
+ } from 'react';
9
+ import { createPortal } from 'react-dom';
10
+ import {
11
+ Alignable,
12
+ AlignPositionOptions,
13
+ getAlignPosition,
14
+ } from '../../../utils/pageGeometry/alignment';
15
+
16
+ import type { PointCoords } from '../../../utils/pageGeometry/Point';
17
+ import type { RectangleCoords } from '../../../utils/pageGeometry/Rectangle';
18
+ import { Rectangle } from '../../../utils/pageGeometry/Rectangle';
19
+
20
+ import { getChangeDetect } from '../../DataSource/privateHooks/getChangeDetect';
21
+ import { propToIdentifyMenu } from '../../Menu/propToIdentifyMenu';
22
+ import { SubscriptionCallback } from '../../types/SubscriptionCallback';
23
+ import { buildSubscriptionCallback } from '../../utils/buildSubscriptionCallback';
24
+ import { useRerender } from '../useRerender';
25
+
26
+ type OverlayParams = {
27
+ portalContainer?: ElementContainerGetter | null | false;
28
+ constrainTo?: OverlayShowParams['constrainTo'];
29
+ };
30
+
31
+ export type ElementContainerGetter =
32
+ | (() => HTMLElement | string | Promise<HTMLElement | string>)
33
+ | string
34
+ | HTMLElement
35
+ | Promise<HTMLElement | string>;
36
+
37
+ function isPromise<T extends any = any>(p: any): p is Promise<T> {
38
+ return (p && typeof p.then === 'function') || p instanceof Promise;
39
+ }
40
+ function isHTMLElement(
41
+ el: null | string | HTMLElement | Promise<any> | any,
42
+ ): el is HTMLElement {
43
+ if (el == null) {
44
+ return false;
45
+ }
46
+ if (typeof el === 'string') {
47
+ return false;
48
+ }
49
+ //@ts-ignore
50
+ return typeof el.tagName === 'string';
51
+ }
52
+
53
+ export type AdvancedAlignable = Alignable | ElementContainerGetter;
54
+
55
+ async function retrieveAdvancedAlignable(
56
+ target: AdvancedAlignable,
57
+ ): Promise<RectangleCoords | null> {
58
+ if (typeof target === 'function') {
59
+ //@ts-ignore
60
+ target = target();
61
+ }
62
+
63
+ if (isPromise(target)) {
64
+ target = await target;
65
+ }
66
+ if (typeof target === 'string') {
67
+ target = document.querySelector(target) as HTMLElement;
68
+ }
69
+ if (target && isHTMLElement(target)) {
70
+ target = target.getBoundingClientRect();
71
+ }
72
+
73
+ //@ts-ignore
74
+ return target ? Rectangle.from(target) : null;
75
+ }
76
+
77
+ async function retrieveElement(
78
+ elementGetter: ElementContainerGetter,
79
+ ): Promise<HTMLElement | null> {
80
+ let result: HTMLElement | string | Promise<HTMLElement | string> | null =
81
+ null;
82
+
83
+ if (typeof elementGetter === 'function') {
84
+ //@ts-ignore
85
+ result = elementGetter();
86
+ } else {
87
+ result = elementGetter;
88
+ }
89
+
90
+ function queryForElement(result: HTMLElement | string | null) {
91
+ let el: HTMLElement | null = null;
92
+
93
+ if (typeof result === 'string') {
94
+ el = document.querySelector(result)!;
95
+ }
96
+ if (isHTMLElement(result)) {
97
+ el = result;
98
+ }
99
+
100
+ return el || null;
101
+ }
102
+
103
+ return queryForElement(await result);
104
+ }
105
+
106
+ function DefaultOverlayPortal(props: { children: ReactNode }) {
107
+ return (
108
+ <div style={{ position: 'fixed', top: 0, left: 0 }}>{props.children}</div>
109
+ );
110
+ }
111
+
112
+ function OverlayContent(
113
+ props: {
114
+ children: () => ReactNode;
115
+ } & OverlayHandle,
116
+ ) {
117
+ const nodeRef = React.useRef<HTMLDivElement | null>(null);
118
+ useEffect(() => {
119
+ return props.realign.onChange((handle) => {
120
+ if (nodeRef.current && handle) {
121
+ alignOverlayNode(nodeRef.current, handle);
122
+ }
123
+ });
124
+ }, [props.realign]);
125
+
126
+ return (
127
+ <div
128
+ style={{ position: 'absolute', top: 0, left: 0 }}
129
+ ref={useCallback((node: HTMLDivElement) => {
130
+ if (node) {
131
+ alignOverlayNode(node, props);
132
+ // const rect = alignOverlayNode(node, props);
133
+ // const realignEvent = new CustomEvent('realign', {
134
+ // bubbles: true,
135
+ // detail: {
136
+ // rect,
137
+ // },
138
+ // });
139
+
140
+ // node.firstChild?.dispatchEvent(realignEvent);
141
+ }
142
+ nodeRef.current = node;
143
+ }, [])}
144
+ >
145
+ {typeof props.children === 'function' ? props.children() : props.children}
146
+ </div>
147
+ );
148
+ }
149
+
150
+ async function alignOverlayNode(
151
+ node: HTMLDivElement,
152
+ params: OverlayShowParams,
153
+ ) {
154
+ let { constrainTo, alignTo, alignPosition } = params;
155
+
156
+ if (
157
+ Object.keys(alignTo).length === 2 &&
158
+ (alignTo as PointCoords).top !== undefined &&
159
+ (alignTo as PointCoords).left !== undefined
160
+ ) {
161
+ alignTo = {
162
+ ...(alignTo as PointCoords),
163
+ width: 0,
164
+ height: 0,
165
+ } as RectangleCoords;
166
+ }
167
+ if (typeof constrainTo === 'boolean') {
168
+ constrainTo = constrainTo
169
+ ? document.documentElement.getBoundingClientRect()
170
+ : undefined;
171
+ }
172
+ const constrainToRectangle = constrainTo
173
+ ? (await retrieveAdvancedAlignable(constrainTo)) || undefined
174
+ : undefined;
175
+
176
+ const alignToRectangle = alignTo
177
+ ? await retrieveAdvancedAlignable(alignTo as AdvancedAlignable)
178
+ : undefined;
179
+ const alignTarget = Rectangle.from(node.getBoundingClientRect());
180
+
181
+ if (!alignToRectangle) {
182
+ return;
183
+ }
184
+
185
+ const { alignedRect } = getAlignPosition({
186
+ constrainTo: constrainToRectangle,
187
+ alignAnchor: alignToRectangle,
188
+ alignTarget,
189
+ alignPosition,
190
+ });
191
+
192
+ node.style.transform = `translate3d(${alignedRect.left}px,${alignedRect.top}px, 0px)`;
193
+
194
+ const rect = node.getBoundingClientRect();
195
+
196
+ if (rect.left !== alignedRect.left || rect.top !== alignedRect.top) {
197
+ // let's take the diff from offsetParent to the alignRect
198
+ // and adjust it like that
199
+ const offsetParent = node.offsetParent as HTMLElement;
200
+
201
+ if (offsetParent) {
202
+ const offsetParentRect = offsetParent.getBoundingClientRect();
203
+ const offsetParentLeft = offsetParentRect.left;
204
+ const offsetParentTop = offsetParentRect.top;
205
+
206
+ const leftDiff = alignedRect.left - offsetParentLeft;
207
+ const topDiff = alignedRect.top - offsetParentTop;
208
+
209
+ node.style.transform = `translate3d(${leftDiff}px,${topDiff}px, 0px)`;
210
+ }
211
+ }
212
+ }
213
+
214
+ /**
215
+ * If portal container is given, it will create a React portal from that element
216
+ * otherwise it will simply render another node as portal
217
+ *
218
+ * @param portalContainer
219
+ */
220
+ export function useOverlayPortal(
221
+ content: ReactNode,
222
+ portalContainer?: ElementContainerGetter | null | false,
223
+ ) {
224
+ const [container, setContainer] = useState<HTMLElement | null>(null);
225
+
226
+ useLayoutEffect(() => {
227
+ async function getContainer() {
228
+ const container = portalContainer
229
+ ? await retrieveElement(portalContainer)
230
+ : null;
231
+
232
+ if (container != null) {
233
+ setContainer(container);
234
+ }
235
+ }
236
+
237
+ if (!portalContainer) {
238
+ return;
239
+ }
240
+ getContainer();
241
+ }, [portalContainer]);
242
+
243
+ return portalContainer ? (
244
+ container ? (
245
+ createPortal(content, container)
246
+ ) : (
247
+ // we're probably still fetching the container
248
+ <></>
249
+ )
250
+ ) : portalContainer === null || portalContainer === false ? (
251
+ content
252
+ ) : (
253
+ <DefaultOverlayPortal>{content}</DefaultOverlayPortal>
254
+ );
255
+ }
256
+
257
+ export type OverlayShowParams = {
258
+ id?: string | number;
259
+ constrainTo?: AdvancedAlignable | boolean;
260
+ alignPosition: AlignPositionOptions['alignPosition'];
261
+ alignTo: AdvancedAlignable | PointCoords;
262
+ };
263
+
264
+ type OverlayHandle = {
265
+ key: string;
266
+ children: () => ReactNode;
267
+
268
+ constrainTo: OverlayShowParams['constrainTo'];
269
+ alignPosition: OverlayShowParams['alignPosition'];
270
+ alignTo: OverlayShowParams['alignTo'];
271
+
272
+ realign: SubscriptionCallback<OverlayHandle>;
273
+ };
274
+
275
+ function getIdForReactOnlyChild(children: ReactNode | (() => ReactNode)) {
276
+ if (React.Children.count(children) === 1) {
277
+ const child = React.Children.only(children);
278
+ if (React.isValidElement(child)) {
279
+ return child.props.id || child.key;
280
+ }
281
+ }
282
+ return null;
283
+ }
284
+
285
+ function injectPortalContainerAndConstrainInMenuChild(
286
+ children: ReactNode,
287
+ portalContainer: OverlayParams['portalContainer'],
288
+ constrainTo: OverlayParams['constrainTo'],
289
+ ) {
290
+ if (React.Children.count(children) === 1) {
291
+ const child = React.Children.only(children);
292
+ // here we could have tested for child.type === Menu,
293
+ // but if we had done that, we could have had to import the `Menu` component
294
+ // which in turns imports this, so we try to avoid that
295
+ if (React.isValidElement(child) && child.props[propToIdentifyMenu]) {
296
+ const newProps: Partial<OverlayParams> = {};
297
+ if (child.props.portalContainer === undefined) {
298
+ newProps.portalContainer = portalContainer;
299
+ }
300
+ if (child.props.constrainTo === undefined) {
301
+ newProps.constrainTo = constrainTo;
302
+ }
303
+ return React.cloneElement(child, newProps);
304
+ }
305
+ }
306
+ return children;
307
+ }
308
+
309
+ //@ts-ignore
310
+ globalThis.allhandles = {};
311
+ //@ts-ignore
312
+ globalThis.thehandles = {};
313
+
314
+ export function useOverlay(params: OverlayParams) {
315
+ const rootParams = params;
316
+
317
+ const [handles] = useState<Map<string, OverlayHandle>>(() => new Map());
318
+
319
+ const [handleToRealign, setHandleToRealign] = useState<string | null>(null);
320
+ const [realignTimestamp, setRealignTimestamp] = useState(0);
321
+
322
+ const getContentForPortal = useCallback(() => {
323
+ const contentForPortal: ReactNode[] = [];
324
+
325
+ for (const [_, handle] of handles) {
326
+ contentForPortal.push(
327
+ <OverlayContent {...handle} key={handle.key}></OverlayContent>,
328
+ );
329
+ }
330
+
331
+ return contentForPortal;
332
+ }, []);
333
+
334
+ const portal = useOverlayPortal(
335
+ getContentForPortal(),
336
+ params.portalContainer,
337
+ );
338
+
339
+ const [_, updateContent] = useRerender();
340
+
341
+ const showOverlay = useCallback(
342
+ (content: ReactNode | (() => ReactNode), params: OverlayShowParams) => {
343
+ const id =
344
+ params.id || getIdForReactOnlyChild(content) || getChangeDetect();
345
+ const key = `${id}`;
346
+
347
+ let handle = handles.get(key);
348
+
349
+ const childrenFn = () => {
350
+ const children = typeof content === 'function' ? content() : content;
351
+
352
+ return injectPortalContainerAndConstrainInMenuChild(
353
+ children,
354
+ rootParams.portalContainer,
355
+ params.constrainTo ?? rootParams.constrainTo,
356
+ );
357
+ };
358
+
359
+ if (handle) {
360
+ Object.assign(handle, params, { children: childrenFn });
361
+ updateContent();
362
+ setHandleToRealign(handle.key);
363
+ setRealignTimestamp(Date.now());
364
+ return;
365
+ }
366
+
367
+ handle = {
368
+ key,
369
+ children: childrenFn,
370
+ alignPosition: params.alignPosition,
371
+ alignTo: params.alignTo,
372
+ constrainTo: params.constrainTo,
373
+ realign: buildSubscriptionCallback<OverlayHandle>(),
374
+ };
375
+
376
+ handles.set(handle.key, handle);
377
+
378
+ updateContent();
379
+
380
+ return () => updateContent();
381
+ },
382
+ [handles, rootParams.portalContainer, updateContent],
383
+ );
384
+
385
+ React.useEffect(() => {
386
+ if (handleToRealign) {
387
+ const handle = handles.get(handleToRealign);
388
+ if (handle) {
389
+ handle.realign(handle);
390
+ }
391
+ }
392
+ }, [handleToRealign, realignTimestamp]);
393
+
394
+ const hideOverlay = (id: string) => {
395
+ id = `${id}`;
396
+ if (handles.has(id)) {
397
+ handles.delete(id);
398
+ updateContent();
399
+ }
400
+ };
401
+
402
+ const clearAll = () => {
403
+ handles.clear();
404
+ updateContent();
405
+ };
406
+
407
+ React.useEffect(() => {
408
+ // return clearAll;
409
+ }, []);
410
+
411
+ return {
412
+ portal,
413
+ hideOverlay,
414
+ clearAll,
415
+ rerenderOverlays: updateContent,
416
+ showOverlay,
417
+ };
418
+ }
@@ -0,0 +1,8 @@
1
+ import { useRef, useLayoutEffect } from 'react';
2
+ export const usePrevious = <T>(value: T, initialValue?: T): T => {
3
+ const ref = useRef(initialValue === undefined ? value : initialValue);
4
+ useLayoutEffect(() => {
5
+ ref.current = value;
6
+ });
7
+ return ref.current;
8
+ };