@onepercentio/one-ui 0.28.7 → 0.28.9

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 (278) hide show
  1. package/package.json +8 -5
  2. package/src/assets/img/svg/checkbox.svg +3 -0
  3. package/src/assets/styles/index.scss +2 -0
  4. package/src/assets/styles/mixins.scss +12 -0
  5. package/src/assets/styles/variables.scss +49 -0
  6. package/src/components/AdaptiveButton/AdaptiveButton.module.scss +7 -0
  7. package/src/components/AdaptiveButton/AdaptiveButton.tsx +26 -0
  8. package/src/components/AdaptiveButton/index.tsx +1 -0
  9. package/src/components/AdaptiveContainer/AdaptiveContainer.module.scss +53 -0
  10. package/src/components/AdaptiveContainer/AdaptiveContainer.tsx +200 -0
  11. package/src/components/AdaptiveContainer/index.tsx +1 -0
  12. package/src/components/AdaptiveDialog/AdaptiveDialog.module.scss +147 -0
  13. package/src/components/AdaptiveDialog/AdaptiveDialog.tsx +97 -0
  14. package/src/components/AdaptiveDialog/index.tsx +1 -0
  15. package/src/components/AdaptiveSidebar/AdaptiveSidebar.module.scss +49 -0
  16. package/src/components/AdaptiveSidebar/AdaptiveSidebar.sample.tsx +10 -0
  17. package/src/components/AdaptiveSidebar/AdaptiveSidebar.tsx +123 -0
  18. package/src/components/AdaptiveSidebar/index.tsx +1 -0
  19. package/src/components/AnchoredTooltip/AnchoredTooltip.module.scss +64 -0
  20. package/src/components/AnchoredTooltip/AnchoredTooltip.tsx +250 -0
  21. package/src/components/AnchoredTooltip/index.tsx +1 -0
  22. package/src/components/AnimatedEntrance/AnimatedEntrance.module.scss +108 -0
  23. package/src/components/AnimatedEntrance/AnimatedEntrance.tsx +227 -0
  24. package/src/components/AnimatedEntrance/index.tsx +5 -0
  25. package/src/components/AsyncWrapper/AsyncWrapper.tsx +38 -0
  26. package/src/components/AsyncWrapper/index.tsx +1 -0
  27. package/src/components/Avatar/Avatar.module.scss +22 -0
  28. package/src/components/Avatar/Avatar.tsx +31 -0
  29. package/src/components/Avatar/index.tsx +1 -0
  30. package/src/components/BucketFill/BucketFill.module.scss +36 -0
  31. package/src/components/BucketFill/BucketFill.tsx +65 -0
  32. package/src/components/BucketFill/index.tsx +1 -0
  33. package/src/components/Button/Button.module.scss +45 -0
  34. package/src/components/Button/Button.tsx +40 -0
  35. package/src/components/Button/index.tsx +1 -0
  36. package/src/components/Card/Card.module.scss +12 -0
  37. package/src/components/Card/Card.tsx +9 -0
  38. package/src/components/Card/index.tsx +1 -0
  39. package/src/components/Chart/Chart.e2e.ts +4 -0
  40. package/src/components/Chart/Chart.logic.tsx +8 -0
  41. package/src/components/Chart/Chart.module.scss +58 -0
  42. package/src/components/Chart/Chart.types.ts +35 -0
  43. package/src/components/Chart/Chart.view.tsx +240 -0
  44. package/src/components/Chart/index.tsx +1 -0
  45. package/src/components/CheckBox/CheckBox.module.scss +36 -0
  46. package/src/components/CheckBox/CheckBox.tsx +63 -0
  47. package/src/components/CheckBox/index.tsx +1 -0
  48. package/src/components/CodeInput/CodeInput.module.scss +5 -0
  49. package/src/components/CodeInput/CodeInput.tsx +84 -0
  50. package/src/components/CodeInput/index.tsx +1 -0
  51. package/src/components/Collapsable/Collapsable.module.scss +42 -0
  52. package/src/components/Collapsable/Collapsable.tsx +253 -0
  53. package/src/components/Collapsable/index.tsx +1 -0
  54. package/src/components/Countdown/Countdown.tsx +130 -0
  55. package/src/components/Countdown/index.tsx +1 -0
  56. package/src/components/CurrencyInput/CurrencyInput.hook.ts +37 -0
  57. package/src/components/CurrencyInput/CurrencyInput.tsx +25 -0
  58. package/src/components/CurrencyInput/index.tsx +1 -0
  59. package/src/components/Divider/Divider.module.scss +7 -0
  60. package/src/components/Divider/Divider.tsx +13 -0
  61. package/src/components/Divider/index.tsx +1 -0
  62. package/src/components/EmailInput/EmailInput.module.scss +0 -0
  63. package/src/components/EmailInput/EmailInput.tsx +51 -0
  64. package/src/components/EmailInput/index.tsx +1 -0
  65. package/src/components/FadeIn/FadeIn.module.scss +9 -0
  66. package/src/components/FadeIn/FadeIn.tsx +77 -0
  67. package/src/components/FadeIn/index.tsx +1 -0
  68. package/src/components/FileInput/FileInput.module.scss +6 -0
  69. package/src/components/FileInput/FileInput.tsx +75 -0
  70. package/src/components/FileInput/View/BigFactory/BigFactory.module.scss +20 -0
  71. package/src/components/FileInput/View/BigFactory/BigFactory.tsx +48 -0
  72. package/src/components/FileInput/View/BigFactory/index.tsx +1 -0
  73. package/src/components/FileInput/View/Compact/Compact.module.scss +68 -0
  74. package/src/components/FileInput/View/Compact/Compact.tsx +151 -0
  75. package/src/components/FileInput/View/Compact/index.tsx +1 -0
  76. package/src/components/FileInput/View/View.types.ts +12 -0
  77. package/src/components/FileInput/index.tsx +1 -0
  78. package/src/components/FlowController/FlowController.module.scss +47 -0
  79. package/src/components/FlowController/FlowController.tsx +93 -0
  80. package/src/components/FlowController/index.tsx +1 -0
  81. package/src/components/Form/Form.tsx +243 -0
  82. package/src/components/Form/index.ts +1 -0
  83. package/src/components/Form/v2/Form.hook.ts +341 -0
  84. package/src/components/Form/v2/Form.module.scss +0 -0
  85. package/src/components/Form/v2/Form.tsx +78 -0
  86. package/src/components/Form/v2/Form.types.ts +118 -0
  87. package/src/components/Form/v2/FormField/Extensions/DateField/DateField.module.scss +0 -0
  88. package/src/components/Form/v2/FormField/Extensions/DateField/DateField.tsx +73 -0
  89. package/src/components/Form/v2/FormField/Extensions/DateField/index.tsx +1 -0
  90. package/src/components/Form/v2/FormField/Extensions/PhoneField/PhoneField.module.scss +0 -0
  91. package/src/components/Form/v2/FormField/Extensions/PhoneField/PhoneField.tsx +91 -0
  92. package/src/components/Form/v2/FormField/Extensions/PhoneField/index.tsx +1 -0
  93. package/src/components/Form/v2/FormField/FormField.module.scss +0 -0
  94. package/src/components/Form/v2/FormField/FormField.tsx +378 -0
  95. package/src/components/Form/v2/FormField/FormField.types.ts +129 -0
  96. package/src/components/Form/v2/FormField/index.tsx +1 -0
  97. package/src/components/Form/v2/index.tsx +1 -0
  98. package/src/components/Freeze/Freeze.tsx +9 -0
  99. package/src/components/Freeze/index.tsx +1 -0
  100. package/src/components/HSForms/HSForms.tsx +57 -0
  101. package/src/components/HSForms/index.tsx +1 -0
  102. package/src/components/Header/Header.module.scss +119 -0
  103. package/src/components/Header/Header.tsx +138 -0
  104. package/src/components/Header/index.tsx +1 -0
  105. package/src/components/HeaderCloseBtn/HeaderCloseBtn.module.scss +44 -0
  106. package/src/components/HeaderCloseBtn/HeaderCloseBtn.tsx +28 -0
  107. package/src/components/HeaderCloseBtn/index.tsx +1 -0
  108. package/src/components/InfinityScroll/InfinityScroll.module.scss +30 -0
  109. package/src/components/InfinityScroll/InfinityScroll.tsx +187 -0
  110. package/src/components/InfinityScroll/index.tsx +1 -0
  111. package/src/components/Input/Input.module.scss +71 -0
  112. package/src/components/Input/Input.tsx +134 -0
  113. package/src/components/Input/index.tsx +1 -0
  114. package/src/components/InstantCounter/InstantCounter.tsx +77 -0
  115. package/src/components/InstantCounter/index.tsx +1 -0
  116. package/src/components/LavaLamp/LavaLamp.data.tsx +114 -0
  117. package/src/components/LavaLamp/LavaLamp.module.scss +26 -0
  118. package/src/components/LavaLamp/LavaLamp.tsx +131 -0
  119. package/src/components/LavaLamp/index.tsx +1 -0
  120. package/src/components/LavaLamp/v2/LavaLamp.module.scss +23 -0
  121. package/src/components/LavaLamp/v2/LavaLamp.tsx +197 -0
  122. package/src/components/LinkToId/LinkToId.module.scss +4 -0
  123. package/src/components/LinkToId/LinkToId.tsx +51 -0
  124. package/src/components/LinkToId/index.tsx +1 -0
  125. package/src/components/Loader/Loader.module.scss +40 -0
  126. package/src/components/Loader/Loader.tsx +18 -0
  127. package/src/components/Loader/index.tsx +1 -0
  128. package/src/components/LoaderDotsIndicator/LoaderDotsIndicator.tsx +34 -0
  129. package/src/components/LoaderDotsIndicator/index.tsx +1 -0
  130. package/src/components/LoopableVideo/LoopableVideo.tsx +37 -0
  131. package/src/components/LoopableVideo/index.tsx +1 -0
  132. package/src/components/MainGrid/MainGrid.module.scss +28 -0
  133. package/src/components/MainGrid/MainGrid.tsx +68 -0
  134. package/src/components/MainGrid/index.tsx +1 -0
  135. package/src/components/MutableHamburgerButton/MutableHamburgerButton.module.scss +220 -0
  136. package/src/components/MutableHamburgerButton/MutableHamburgerButton.tsx +38 -0
  137. package/src/components/MutableHamburgerButton/index.tsx +1 -0
  138. package/src/components/Notification/Notification.module.scss +25 -0
  139. package/src/components/Notification/Notification.tsx +13 -0
  140. package/src/components/Notification/index.tsx +1 -0
  141. package/src/components/OrderableList/OrderableList.module.scss +98 -0
  142. package/src/components/OrderableList/OrderableList.tsx +564 -0
  143. package/src/components/OrderableList/index.tsx +1 -0
  144. package/src/components/PaginationIndicator/PaginationIndicator.tsx +365 -0
  145. package/src/components/PaginationIndicator/index.tsx +1 -0
  146. package/src/components/Parallax/Parallax.module.scss +28 -0
  147. package/src/components/Parallax/Parallax.tsx +248 -0
  148. package/src/components/Parallax/index.tsx +1 -0
  149. package/src/components/Parallax/math/helpers.ts +289 -0
  150. package/src/components/PasswordInput/PasswordInput.module.scss +17 -0
  151. package/src/components/PasswordInput/PasswordInput.tsx +154 -0
  152. package/src/components/PasswordInput/index.tsx +1 -0
  153. package/src/components/PingPongText/PingPongText.module.scss +4 -0
  154. package/src/components/PingPongText/PingPongText.tsx +83 -0
  155. package/src/components/PingPongText/index.tsx +1 -0
  156. package/src/components/PixelatedScan/PixelatedScan.module.scss +86 -0
  157. package/src/components/PixelatedScan/PixelatedScan.tsx +175 -0
  158. package/src/components/PixelatedScan/index.tsx +1 -0
  159. package/src/components/Portal/Portal.module.scss +3 -0
  160. package/src/components/Portal/Portal.tsx +68 -0
  161. package/src/components/Portal/index.tsx +1 -0
  162. package/src/components/ProgressBar/ProgressBar.module.scss +44 -0
  163. package/src/components/ProgressBar/ProgressBar.tsx +124 -0
  164. package/src/components/ProgressBar/index.tsx +1 -0
  165. package/src/components/ProgressTexts/ProgressTexts.module.scss +37 -0
  166. package/src/components/ProgressTexts/ProgressTexts.tsx +85 -0
  167. package/src/components/ProgressTexts/index.tsx +1 -0
  168. package/src/components/Radio/Radio.module.scss +36 -0
  169. package/src/components/Radio/Radio.tsx +53 -0
  170. package/src/components/Radio/index.tsx +1 -0
  171. package/src/components/SectionContainer/SectionContainer.module.scss +30 -0
  172. package/src/components/SectionContainer/SectionContainer.tsx +49 -0
  173. package/src/components/SectionContainer/index.tsx +1 -0
  174. package/src/components/Select/Select.module.scss +58 -0
  175. package/src/components/Select/Select.tsx +192 -0
  176. package/src/components/Select/index.tsx +1 -0
  177. package/src/components/Skeleton/Skeleton.module.scss +21 -0
  178. package/src/components/Skeleton/Skeleton.tsx +29 -0
  179. package/src/components/Skeleton/index.tsx +1 -0
  180. package/src/components/Spacing/Spacing.module.scss +13 -0
  181. package/src/components/Spacing/Spacing.tsx +24 -0
  182. package/src/components/Spacing/index.tsx +1 -0
  183. package/src/components/StaticScroller/StaticScroller.module.scss +14 -0
  184. package/src/components/StaticScroller/StaticScroller.tsx +83 -0
  185. package/src/components/StaticScroller/index.tsx +1 -0
  186. package/src/components/Switch/Switch.module.scss +43 -0
  187. package/src/components/Switch/Switch.tsx +41 -0
  188. package/src/components/Switch/index.tsx +1 -0
  189. package/src/components/Table/Table.module.scss +76 -0
  190. package/src/components/Table/Table.tsx +152 -0
  191. package/src/components/Table/index.tsx +1 -0
  192. package/src/components/Tabs/Tabs.module.scss +40 -0
  193. package/src/components/Tabs/Tabs.tsx +104 -0
  194. package/src/components/Tabs/index.tsx +1 -0
  195. package/src/components/Text/Text.module.scss +81 -0
  196. package/src/components/Text/Text.tsx +42 -0
  197. package/src/components/Text/index.tsx +1 -0
  198. package/src/components/Transition/MasksFactory/DiagonalReveal.tsx +47 -0
  199. package/src/components/Transition/MasksFactory/DiagonalSquareToBalls.tsx +78 -0
  200. package/src/components/Transition/MasksFactory/PhysicsSquares.tsx +106 -0
  201. package/src/components/Transition/MasksFactory/SquareToBalls.tsx +66 -0
  202. package/src/components/Transition/MasksFactory/utils.ts +35 -0
  203. package/src/components/Transition/Transition.module.scss +211 -0
  204. package/src/components/Transition/Transition.tsx +495 -0
  205. package/src/components/Transition/index.tsx +1 -0
  206. package/src/components/UncontrolledTransition/UncontrolledTransition.ai.md +9 -0
  207. package/src/components/UncontrolledTransition/UncontrolledTransition.sample.tsx +34 -0
  208. package/src/components/UncontrolledTransition/UncontrolledTransition.tsx +143 -0
  209. package/src/components/UncontrolledTransition/index.tsx +2 -0
  210. package/src/components/WalletConnectionWrapper/WalletConnectionWrapper.tsx +212 -0
  211. package/src/components/WalletConnectionWrapper/index.tsx +1 -0
  212. package/src/components/utilitary/ScrollAndFocusLock/ScrollAndFocusLock.module.scss +5 -0
  213. package/src/components/utilitary/ScrollAndFocusLock/ScrollAndFocusLock.tsx +52 -0
  214. package/src/components/utilitary/ScrollAndFocusLock/index.tsx +1 -0
  215. package/src/context/AsyncProcess.tsx +107 -0
  216. package/src/context/ContextAsyncControl.tsx +89 -0
  217. package/src/context/CustomBrowserRouter.tsx +55 -0
  218. package/src/context/OneUIProvider.tsx +308 -0
  219. package/src/hooks/logs/useDependencyChangeDetection.ts +25 -0
  220. package/src/hooks/logs/useIsMounting.ts +7 -0
  221. package/src/hooks/persistence/useLocalStorage.ts +45 -0
  222. package/src/hooks/shims/ObjectWatchShim.ts +56 -0
  223. package/src/hooks/ui/useAdaptiveImage.tsx +36 -0
  224. package/src/hooks/ui/useAlternating.tsx +22 -0
  225. package/src/hooks/ui/useBreakpoint.tsx +21 -0
  226. package/src/hooks/ui/useCustomScrollbar.module.scss +20 -0
  227. package/src/hooks/ui/useCustomScrollbar.tsx +22 -0
  228. package/src/hooks/ui/useEffectIf.ts +11 -0
  229. package/src/hooks/ui/useMouseHover.tsx +26 -0
  230. package/src/hooks/ui/usePaginationControls.module.scss +16 -0
  231. package/src/hooks/ui/usePaginationControls.tsx +176 -0
  232. package/src/hooks/ui/useSnapToViewport.module.scss +6 -0
  233. package/src/hooks/ui/useSnapToViewport.ts +28 -0
  234. package/src/hooks/ui/useTilt.tsx +219 -0
  235. package/src/hooks/ui/useZoomable.module.scss +34 -0
  236. package/src/hooks/ui/useZoomable.tsx +144 -0
  237. package/src/hooks/useAsyncControl.ai.md +25 -0
  238. package/src/hooks/useAsyncControl.ts +101 -0
  239. package/src/hooks/useContainedRepositioning.ts +110 -0
  240. package/src/hooks/useCustomHistory.ts +14 -0
  241. package/src/hooks/useElementFit.ts +82 -0
  242. package/src/hooks/useFirestoreWatch.ts +54 -0
  243. package/src/hooks/useForm.ts +49 -0
  244. package/src/hooks/useFreeze.ts +12 -0
  245. package/src/hooks/useHero.module.scss +41 -0
  246. package/src/hooks/useHero.ts +512 -0
  247. package/src/hooks/useIntersection.ts +32 -0
  248. package/src/hooks/useMergeRefs.ts +29 -0
  249. package/src/hooks/useObserve.ts +24 -0
  250. package/src/hooks/usePagination.ts +228 -0
  251. package/src/hooks/usePooledOperation.ts +54 -0
  252. package/src/hooks/usePooling.ts +46 -0
  253. package/src/hooks/useRebound.ts +23 -0
  254. package/src/hooks/useShortIntl.ai.md +5 -0
  255. package/src/hooks/useShortIntl.ts +97 -0
  256. package/src/hooks/utility/useAsyncMemo.ts +43 -0
  257. package/src/hooks/utility/useDepChange.ts +11 -0
  258. package/src/hooks/utility/useEvents.ts +33 -0
  259. package/src/hooks/utility/useImmediate.ts +8 -0
  260. package/src/hooks/utility/useManualInit.ts +24 -0
  261. package/src/hooks/utility/useModule.ts +15 -0
  262. package/src/hooks/utility/useQuery.ts +15 -0
  263. package/src/hooks/utility/useUniqueEffect.ts +22 -0
  264. package/src/index.ts +3 -0
  265. package/src/models/DebugLogger.ts +7 -0
  266. package/src/models/GenericContract.ts +169 -0
  267. package/src/models/Orbs.ts +97 -0
  268. package/src/reac-app-env.d.ts +6 -0
  269. package/src/storybook/assets/video/txt-reversed.mp4 +0 -0
  270. package/src/storybookUtils/index.tsx +53 -0
  271. package/src/type-utils.ts +49 -0
  272. package/src/utility.d.ts +70 -0
  273. package/src/utils/blockchain.ts +43 -0
  274. package/src/utils/flatten.ts +17 -0
  275. package/src/utils/formatters.ts +36 -0
  276. package/src/utils/html.utils.ts +3 -0
  277. package/src/utils/ownEvent.ts +8 -0
  278. package/src/utils/test.ts +19 -0
@@ -0,0 +1,228 @@
1
+ import {
2
+ useCallback,
3
+ useEffect,
4
+ useLayoutEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ } from "react";
9
+ import useAsyncControl from "./useAsyncControl";
10
+ import throttle from "lodash/throttle";
11
+
12
+ type UpdateEvent<I extends any> = {
13
+ finished: boolean;
14
+ items: I[];
15
+ totalItems: number;
16
+ };
17
+
18
+ export default function usePagination<I extends any>(
19
+ request: (
20
+ page: number,
21
+ pageSize: number | "all",
22
+ currItems?: I[]
23
+ ) => Promise<UpdateEvent<I>>,
24
+ paginationId: object | any[] | (() => string) = () => "default",
25
+ startingItems?: I[]
26
+ ): Paginable<I> {
27
+ const paginationDataRef = useRef<{
28
+ [d: string]:
29
+ | {
30
+ finished: boolean;
31
+ totalItems: number;
32
+ }
33
+ | undefined;
34
+ }>({});
35
+ const { current: paginationData } = paginationDataRef;
36
+ const paginationIdFactory = useMemo(
37
+ () => {
38
+ if (typeof paginationId === "object") {
39
+ const randId = Math.random();
40
+ return () => randId.toString();
41
+ } else return paginationId;
42
+ },
43
+ Array.isArray(paginationId) ? paginationId : [paginationId]
44
+ );
45
+
46
+ const [items, setItems] =
47
+ useState<[paginationId: string, items: I[]] | undefined>();
48
+
49
+ const [id, setId] = useState(() => paginationIdFactory());
50
+
51
+ useEffect(() => {
52
+ setId(paginationIdFactory());
53
+ if (startingItems) setItems([paginationIdFactory(), startingItems]);
54
+ else setItems(undefined);
55
+ }, [paginationIdFactory()]);
56
+
57
+ const { process, ...control } = useAsyncControl();
58
+
59
+ function updateItems(cb: (prevItems?: I) => UpdateEvent<I>["items"]) {
60
+ setItems((prev) => [prev![0], cb()]);
61
+ }
62
+
63
+ const derivateCurrentPage = (pageSize: number) => {
64
+ if (items === undefined) return 0;
65
+ const currentPage = Math.floor((items?.[1].length ?? 0) / pageSize) - 1;
66
+ return currentPage;
67
+ };
68
+
69
+ const _requestPage = useCallback(
70
+ function (page: number, pageSize: number | "all") {
71
+ const id = paginationIdFactory();
72
+ if (paginationData[id]?.finished) return;
73
+ process(async () => {
74
+ const result = await request(
75
+ page,
76
+ pageSize,
77
+ items?.[0] === id && page !== 0
78
+ ? pageSize === "all"
79
+ ? undefined
80
+ : items?.[1].slice(0, page * pageSize)
81
+ : undefined
82
+ );
83
+ paginationData[id] = {
84
+ finished: result.finished,
85
+ totalItems: result.totalItems,
86
+ };
87
+ setItems((prev) => {
88
+ if (page === 0) return [id, result.items];
89
+ else if (!prev || id === prev[0]) return [id, result.items];
90
+ return prev;
91
+ });
92
+ });
93
+ },
94
+ [items, request]
95
+ );
96
+
97
+ return {
98
+ updateItems,
99
+ getNextPage: (pageSize: number) => {
100
+ _requestPage(derivateCurrentPage(pageSize) + 1, pageSize);
101
+ },
102
+ getPage: _requestPage,
103
+ getAll: () => {
104
+ _requestPage(0, "all");
105
+ },
106
+ refreshCurrentPage: (pageSize: number) => {
107
+ _requestPage(derivateCurrentPage(pageSize), pageSize);
108
+ },
109
+ totalItems: () => paginationData[paginationIdFactory()]?.totalItems,
110
+ id: () => id,
111
+ loading: control.loading,
112
+ error: control.error,
113
+ items: items?.[1],
114
+ setError: control.setError,
115
+ };
116
+ }
117
+
118
+ export type Paginable<I extends any, E extends any = any> = {
119
+ updateItems: (cb: (prevItems?: I) => UpdateEvent<I>["items"]) => void;
120
+ getNextPage: (pageSize: number) => void;
121
+ refreshCurrentPage: (pageSize: number) => void;
122
+ getPage: (page: number, pageSize: number) => void;
123
+ getAll: () => void;
124
+ totalItems: () => number | undefined;
125
+ loading: boolean;
126
+ error: E | Error | undefined;
127
+ items: I[] | undefined;
128
+ setError: ReturnType<typeof useAsyncControl>["setError"];
129
+ id: () => string;
130
+ };
131
+
132
+ export type LocalPaginable<I extends any, E extends any = any> = Paginable<
133
+ I,
134
+ E
135
+ > & {
136
+ src: I;
137
+ };
138
+
139
+ /**
140
+ * This returns a ref to be bound to an elements so it can be able to detect when a pagination whould occur
141
+ */
142
+ export function useContainerPagination(
143
+ cb: (pageSize: number) => void,
144
+ pageSize: number,
145
+ direction: "h" | "v" = "v"
146
+ ) {
147
+ const scrollableRef = useRef<HTMLDivElement>(undefined);
148
+ const customOptionsRef =
149
+ useRef<() => { offsetBottom?: number; offsetLeft?: number }>(undefined);
150
+
151
+ useEffect(() => {
152
+ const el = scrollableRef.current!;
153
+ const scrollElement =
154
+ (el as unknown as typeof window.document).scrollingElement || el;
155
+ const calculateIfReachedLimit = throttle(
156
+ (e: Event) => {
157
+ if (e.target !== el) return;
158
+ const { offsetBottom = 0, offsetLeft = 0 } =
159
+ customOptionsRef.current?.() || {};
160
+ const offsetLimit =
161
+ direction === "v"
162
+ ? scrollElement.scrollHeight -
163
+ offsetBottom -
164
+ scrollElement.clientHeight * 0.6
165
+ : scrollElement.scrollWidth -
166
+ offsetLeft -
167
+ scrollElement.clientWidth * 0.6;
168
+ const offset =
169
+ direction === "v"
170
+ ? scrollElement.clientHeight + scrollElement.scrollTop
171
+ : scrollElement.clientWidth + scrollElement.scrollLeft;
172
+ if (offset >= offsetLimit) {
173
+ cb(pageSize);
174
+ }
175
+ },
176
+ 250,
177
+ {
178
+ leading: false,
179
+ trailing: true,
180
+ }
181
+ );
182
+
183
+ el.addEventListener("scroll", calculateIfReachedLimit, {
184
+ passive: true,
185
+ });
186
+ return () => el.removeEventListener("scroll", calculateIfReachedLimit);
187
+ }, [cb, pageSize]);
188
+
189
+ return {
190
+ scrollableRef,
191
+ customOptionsRef,
192
+ };
193
+ }
194
+
195
+ /**
196
+ * This function receives an amount of local instances and paginates it
197
+ */
198
+ export function useLocalPagination<L>(items: L[] | undefined) {
199
+ const instanceID = useMemo(() => Date.now(), [items]);
200
+ const cb = useCallback(
201
+ (page: number, pageSize: number | "all", currItems: L[] = []) => {
202
+ if (!items)
203
+ return Promise.resolve({
204
+ finished: false,
205
+ totalItems: 0,
206
+ items: [],
207
+ });
208
+ if (pageSize === "all") pageSize = items.length;
209
+ const from = pageSize * page;
210
+ const newArray = [...currItems, ...items.slice(from, from + pageSize)];
211
+
212
+ return Promise.resolve({
213
+ finished: newArray.length === items.length,
214
+ totalItems: items.length,
215
+ items: newArray,
216
+ });
217
+ },
218
+ [items]
219
+ );
220
+ const pagination = usePagination<L>(cb, () => `${instanceID}`);
221
+ const pagSrc = useMemo(() => items, [pagination.items]);
222
+
223
+ return {
224
+ ...pagination,
225
+ loading: items === undefined,
226
+ src: pagSrc,
227
+ };
228
+ }
@@ -0,0 +1,54 @@
1
+ import { createRef, useRef } from "react";
2
+ import useAsyncControl from "./useAsyncControl";
3
+ import usePooling from "./usePooling";
4
+
5
+ /**
6
+ * A toolkit hook to trigger an request to start a process and execute a pooling operation to validate when the operation is finished
7
+ */
8
+ export default function usePooledOperation() {
9
+ const requestOperation = useRef<() => Promise<void>>(undefined);
10
+ const poolingOperation = useRef<() => Promise<boolean>>(undefined);
11
+ const requestControl = useAsyncControl();
12
+ const pollingControl = usePooling();
13
+
14
+ function triggerRequest() {
15
+ requestControl.process(async () => {
16
+ await requestOperation.current!();
17
+ triggerPooling();
18
+ });
19
+ }
20
+
21
+ function triggerPooling() {
22
+ pollingControl.startPolling(poolingOperation.current!);
23
+ }
24
+
25
+ return {
26
+ /** Indicates when it's loading */
27
+ loading: requestControl.loading || pollingControl.isPooling,
28
+ /** Indicates error of pooling or request */
29
+ error: !!requestControl.error || !!pollingControl.failed,
30
+ /** Retries the operation based on the current failed step */
31
+ retry: requestControl.error
32
+ ? triggerRequest
33
+ : pollingControl.failed
34
+ ? triggerPooling
35
+ : undefined,
36
+ /** Initiates the request followed by the pooling operation */
37
+ start: (
38
+ /** An arbitrary request */
39
+ _requestOperation: () => Promise<void>,
40
+ /** Resolves to a boolean that indicated if is finished (true) or not (false) */
41
+ _poolingOperation: () => Promise<boolean>
42
+ ) => {
43
+ requestOperation.current = _requestOperation;
44
+ poolingOperation.current = _poolingOperation;
45
+
46
+ triggerRequest();
47
+ },
48
+ /** Clear any error that is registered */
49
+ clearError: () => {
50
+ requestControl.setError(undefined);
51
+ pollingControl.setFailed(false);
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,46 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ /**
4
+ * This callback should return a boolean that indicates if the pooling has finished (true) or it should continue (false)
5
+ */
6
+ type PoolingAction = () => Promise<boolean>;
7
+
8
+ export default function usePooling(intervalMs = 1000, maxPoolingTime: number | null = 60000) {
9
+ const [intervalId, setIntervalId] = useState<NodeJS.Timer>();
10
+ const [failed, setFailed] = useState<boolean>(false);
11
+
12
+ const cancelPooling = () => {
13
+ if (intervalId) clearInterval(intervalId);
14
+ }
15
+ useEffect(
16
+ () => cancelPooling,
17
+ [intervalId]
18
+ );
19
+
20
+ return {
21
+ failed,
22
+ setFailed,
23
+ isPooling: !!intervalId,
24
+ /**
25
+ *
26
+ * @param cb {@link PoolingAction} - Executes and returns if has finished (true) or not (false)
27
+ */
28
+ startPolling: (cb: PoolingAction) => {
29
+ let poolingCount = 0;
30
+ const maxPoolings = (maxPoolingTime !== null) ? Math.ceil(maxPoolingTime / intervalMs) : undefined;
31
+ const intervalId = setInterval(async () => {
32
+ poolingCount++;
33
+ const finished = await cb();
34
+ if (finished) setIntervalId(undefined);
35
+ else if (poolingCount === maxPoolings) {
36
+ setIntervalId(undefined);
37
+ setFailed(true);
38
+ }
39
+ }, intervalMs);
40
+ setIntervalId(intervalId);
41
+ setFailed(false);
42
+ return () => clearInterval(intervalId)
43
+ },
44
+ stop: cancelPooling,
45
+ };
46
+ }
@@ -0,0 +1,23 @@
1
+ import { useEffect, useState } from "react"
2
+
3
+ /**
4
+ * This hook adds a prop that you can toggle and returns to initial
5
+ * state after a defined time (usefull for notification)
6
+ */
7
+ export default function useRebound<T extends any>(initialValue: T, timeoutSec: number = 1) {
8
+ const [state, setState] = useState<T>(initialValue)
9
+
10
+ useEffect(() => {
11
+ if (state !== initialValue) {
12
+ const timeout = setTimeout(() => {
13
+ setState(initialValue)
14
+ }, timeoutSec * 1000);
15
+
16
+ return () => clearTimeout(timeout);
17
+ }
18
+ }, [state]);
19
+ return {
20
+ current: state,
21
+ setState
22
+ }
23
+ }
@@ -0,0 +1,5 @@
1
+ # Referencing a text
2
+ ```tsx
3
+ const { txt } = useShortIntl();
4
+ const theText = txt("text.hierarchy.id");
5
+ ```
@@ -0,0 +1,97 @@
1
+ import { IntlFormatters, IntlShape, useIntl } from "react-intl";
2
+ import { BigNumber } from "bignumber.js";
3
+ import { ReactElement, useEffect, useState } from "react";
4
+
5
+ export default function useShortIntl(): IntlShape & {
6
+ txt: <R extends ReturnType<IntlFormatters["formatMessage"]> = string>(
7
+ id: OnepercentUtility.IntlIds,
8
+ params?: Record<string, string | ReactElement>
9
+ ) => R;
10
+ formatToDoubleDecimal(
11
+ number: number,
12
+ options?: Parameters<IntlFormatters["formatNumber"]>[1]
13
+ ): string;
14
+ formatBigNumber(
15
+ number: BigNumber,
16
+ options?: Parameters<IntlFormatters["formatNumber"]>[1]
17
+ ): string;
18
+ } {
19
+ const intl = useIntl();
20
+ const { formatMessage, formatNumber } = intl;
21
+ const [devMode, setDevMode] = useState(false);
22
+
23
+ useEffect(() => {
24
+ if (process.env.NODE_ENV === "development") {
25
+ const keyDownDetect = (ev: KeyboardEvent) => {
26
+ if (ev.key === "i" && ev.ctrlKey) {
27
+ const keyUpDetect = (ev: KeyboardEvent) => {
28
+ if (ev.key === "i") {
29
+ setDevMode(false);
30
+ }
31
+ };
32
+ setDevMode(true);
33
+ window.addEventListener("keyup", keyUpDetect);
34
+ }
35
+ };
36
+ window.addEventListener("keydown", keyDownDetect);
37
+ }
38
+ });
39
+
40
+ return {
41
+ ...intl,
42
+ txt: (id, params) => {
43
+ return devMode ? id : formatMessage({ id }, params) as any;
44
+ },
45
+ formatToDoubleDecimal(val: number, options = {}) {
46
+ return formatNumber(val, {
47
+ minimumFractionDigits: 2,
48
+ maximumFractionDigits: 2,
49
+ ...options,
50
+ });
51
+ },
52
+ formatBigNumber(bigNumber, options) {
53
+ const { decimalSeparator } = intl
54
+ .formatNumberToParts(1000.1)
55
+ .reduce((r, a) => {
56
+ if (a.type === "decimal") return { ...r, decimalSeparator: a.value };
57
+ if (a.type === "group") return { ...r, thousandSeparator: a.value };
58
+ return r;
59
+ }, {} as { decimalSeparator: string; thousandSeparator: string });
60
+
61
+ const integerPart = bigNumber.integerValue(1);
62
+ const integer = intl.formatNumber(integerPart.toNumber(), options);
63
+ const decimals = bigNumber
64
+ .minus(integerPart)
65
+ .decimalPlaces(
66
+ options?.maximumFractionDigits || bigNumber.decimalPlaces()!,
67
+ 5
68
+ )
69
+ .toString()
70
+ .replace("0.", "");
71
+ return `${integer}${
72
+ decimals !== "0" ? `${decimalSeparator}${decimals}` : ""
73
+ }`;
74
+ },
75
+ };
76
+ }
77
+
78
+ type StrMap = {
79
+ [s: string]: string;
80
+ };
81
+
82
+ type IsolatedMessages<A extends string, M extends StrMap, P extends string> = {
83
+ [s1 in `${P}.${keyof M extends string ? keyof M : ""}`]: M[keyof M];
84
+ };
85
+
86
+ export function isolateMessages<A extends string, M extends StrMap>(
87
+ preffix: A,
88
+ strings: M
89
+ ) {
90
+ return Object.entries(strings).reduce(
91
+ (r, [k, v]) => ({
92
+ ...r,
93
+ [`${preffix}.${k}`]: v,
94
+ }),
95
+ {} as IsolatedMessages<A, M, typeof preffix>
96
+ );
97
+ }
@@ -0,0 +1,43 @@
1
+ import { useEffect, useState } from "react";
2
+ import useAsyncControl from "../useAsyncControl";
3
+
4
+ /**
5
+ * It can assume 3 states
6
+ * [undefined] = The hook has just initialized, and will call the memoize function
7
+ * [T] = The hook initialized the value
8
+ * [null, error] = The hook failed to initialize and the error is available
9
+ */
10
+ export default function useAsyncMemo<T>(
11
+ funcToMemoize: () => Promise<T>,
12
+ depArr: any[]
13
+ ): [
14
+ value: T | undefined | null,
15
+ error: any,
16
+ loading: boolean,
17
+ retry: () => Promise<void>,
18
+ setValue: (value: T) => void
19
+ ] {
20
+ const { process, error, ...control } = useAsyncControl();
21
+ const [memo, setMemo] = useState<T | null>();
22
+
23
+ useEffect(() => {
24
+ let depBasedSet: typeof setMemo | undefined = setMemo;
25
+ process(funcToMemoize)
26
+ .then((whatToStore) => depBasedSet?.(() => whatToStore))
27
+ .catch(() => depBasedSet?.(null));
28
+ return () => {
29
+ depBasedSet = undefined;
30
+ };
31
+ }, depArr);
32
+
33
+ return [
34
+ memo,
35
+ error,
36
+ control.loading,
37
+ () =>
38
+ process(funcToMemoize)
39
+ .then((whatToStore) => setMemo(() => whatToStore))
40
+ .catch(() => setMemo(null)),
41
+ setMemo,
42
+ ];
43
+ }
@@ -0,0 +1,11 @@
1
+ import { useInsertionEffect, useRef } from "react";
2
+
3
+ export default function useDepChange<T>(callback: (prevDep: T) => void, dep: T) {
4
+ const prevStep = useRef<T>(undefined);
5
+ useInsertionEffect(() => {
6
+ if (prevStep.current) callback(prevStep.current);
7
+ return () => {
8
+ prevStep.current = dep;
9
+ };
10
+ }, [dep]);
11
+ }
@@ -0,0 +1,33 @@
1
+ import { useRef } from "react";
2
+
3
+ /**
4
+ * This hook allows for easier declaration of events and unsubscribers
5
+ */
6
+ export default function useEvents<
7
+ EN extends string,
8
+ E extends { [k in EN]: any[] }
9
+ >() {
10
+ const _eventSUbscriptionsMap = useRef<
11
+ {
12
+ [k in EN]?: ((...args: E[k]) => void)[];
13
+ }
14
+ >({});
15
+ const subscriber = <X extends EN>(e: X, cb: (...args: E[X]) => void) => {
16
+ if (!_eventSUbscriptionsMap.current[e])
17
+ _eventSUbscriptionsMap.current[e] = [];
18
+ _eventSUbscriptionsMap.current[e]!.push(cb);
19
+ return () => {
20
+ const arr = _eventSUbscriptionsMap.current[e]!;
21
+ arr.splice(arr.indexOf(cb), 1);
22
+ };
23
+ };
24
+ const dispatcher = <X extends EN>(eventName: X, ...args: E[X]) => {
25
+ const subscriptions = _eventSUbscriptionsMap.current[eventName] || [];
26
+
27
+ subscriptions.forEach((cb) => cb(...args));
28
+ };
29
+ return {
30
+ subscriber,
31
+ dispatcher,
32
+ };
33
+ }
@@ -0,0 +1,8 @@
1
+ import { useMemo } from "react";
2
+
3
+ /**
4
+ * Runs this function as soon as the hook is invoked
5
+ */
6
+ export default function useImmediate(execute: () => void, deps?: any[]) {
7
+ useMemo(execute, deps ?? []);
8
+ }
@@ -0,0 +1,24 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import useAsyncControl from "../useAsyncControl";
3
+
4
+ /**
5
+ * Provides a way to manually trigger a function and store it's result on a state
6
+ */
7
+ export default function useManualInit<T>(
8
+ funcToMemoize: () => Promise<T>,
9
+ depArr: any[]
10
+ ): [init: () => Promise<T>, memo: T | undefined | null, error: any] {
11
+ const { process, error } = useAsyncControl();
12
+ const [memo, setMemo] = useState<T | null>();
13
+ const initCb = useCallback(
14
+ () =>
15
+ process(funcToMemoize)
16
+ .then((result) => {
17
+ setMemo(result);
18
+ return result;
19
+ })
20
+ .catch(() => setMemo(null)),
21
+ depArr
22
+ );
23
+ return [initCb, memo, error];
24
+ }
@@ -0,0 +1,15 @@
1
+ import { useLayoutEffect, useState } from "react";
2
+
3
+ /**
4
+ * This provides an interface for async loading of modules
5
+ */
6
+ export default function useModule<T>(
7
+ moduleLoadPromiseFactory: () => Promise<T>
8
+ ): T | undefined {
9
+ const [moduleLoaded, setModuleLoaded] = useState<T>();
10
+ useLayoutEffect(() => {
11
+ moduleLoadPromiseFactory().then(setModuleLoaded);
12
+ }, []);
13
+
14
+ return moduleLoaded;
15
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ *
3
+ * @returns A hook to obtain the query params from a url
4
+ */
5
+
6
+ import { useMemo } from "react";
7
+ import { useLocation } from "react-router-dom";
8
+
9
+ export default function useQuery<E extends {}>() {
10
+ const { search } = useLocation();
11
+
12
+ return useMemo(() => new URLSearchParams(search), [search]) as unknown as {
13
+ get: (p: keyof E) => E[typeof p];
14
+ };
15
+ }
@@ -0,0 +1,22 @@
1
+ import { useLayoutEffect, useMemo } from "react";
2
+ import { useShareState } from "../../context/ContextAsyncControl";
3
+
4
+ export default function useUniqueEffect(
5
+ id: string,
6
+ effect: () => void,
7
+ deps: any[]
8
+ ) {
9
+ const lockId = useMemo(() => Math.random(), []);
10
+ const [currLock, setCurrLock] = useShareState<number | undefined>(
11
+ "unique-effect",
12
+ id
13
+ );
14
+ useLayoutEffect(() => {
15
+ if (currLock === lockId) effect();
16
+ }, [...deps, currLock]);
17
+
18
+ useLayoutEffect(() => {
19
+ if (currLock === undefined) setCurrLock(lockId);
20
+ if (currLock === lockId) return () => setCurrLock(undefined);
21
+ }, [currLock]);
22
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./types";
2
+ export * from "./hooks/useAsyncControl";
3
+ export * from "./components/UncontrolledTransition"
@@ -0,0 +1,7 @@
1
+ const rand = require("color-seed");
2
+ const win = window as any;
3
+
4
+ export default function log(filter: string, obj: any) {
5
+ if (win.DEBUG === "*" || filter.includes(win.DEBUG))
6
+ console.log(`%c ${filter}`, `color: ${rand.getColor(filter)}`, obj);
7
+ }