@onepercentio/one-ui 0.28.8 → 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 +4 -1
  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,365 @@
1
+ import React, {
2
+ ComponentProps,
3
+ ForwardedRef,
4
+ forwardRef,
5
+ RefObject,
6
+ useCallback,
7
+ useEffect,
8
+ useImperativeHandle,
9
+ useMemo,
10
+ useRef,
11
+ useState,
12
+ } from "react";
13
+
14
+ const MAX_BALLS = 7;
15
+ const eachBallWidthEm = 1.2;
16
+
17
+ const CENTER_GUIDE_BALL = 1;
18
+
19
+ export enum PaginationIndicatorMode {
20
+ /** This will make the guide ball be kept on center */
21
+ CENTERED,
22
+
23
+ /** This will make the guide ball move, while the indicator balls keep in place */
24
+ START,
25
+ }
26
+ export function PaginationIndicatorView({
27
+ size,
28
+ page: currentPage,
29
+ pages: decimalPages,
30
+ className,
31
+ onClickPage,
32
+ mode = PaginationIndicatorMode.CENTERED,
33
+ infinite,
34
+ }: {
35
+ size: number;
36
+ page: number;
37
+ pages: number;
38
+ className?: string;
39
+ onClickPage?: (page: number) => void;
40
+ mode?: PaginationIndicatorMode;
41
+ infinite?: boolean;
42
+ }) {
43
+ const maxBalls = useMemo(() => (infinite ? 5 : MAX_BALLS), [infinite]);
44
+ const page = useMemo(() => {
45
+ const floor = Math.floor(decimalPages);
46
+ const modulus = decimalPages % floor;
47
+
48
+ if (currentPage > floor) {
49
+ const currentFloorModulus = currentPage % floor;
50
+ const equivalent = (currentFloorModulus * 100) / modulus;
51
+
52
+ return floor + equivalent / 100;
53
+ } else {
54
+ return currentPage;
55
+ }
56
+ }, [currentPage, decimalPages]);
57
+ const rand = useMemo(() => Math.random().toString(), []);
58
+ const pageIndex = page - 1;
59
+ const pages = useMemo(() => Math.ceil(decimalPages), [decimalPages]);
60
+ const numBalls = useMemo(() => {
61
+ const numBalls = pages >= maxBalls ? maxBalls : Math.ceil(pages);
62
+
63
+ return numBalls;
64
+ }, [pages]);
65
+
66
+ const indexForTheBallsCenter = useMemo(
67
+ () => (infinite ? numBalls - 5 : numBalls - 1) / 2,
68
+ [numBalls, infinite]
69
+ );
70
+ const balls = useMemo(() => {
71
+ const indexForLastPages = pages + 1 - indexForTheBallsCenter;
72
+ /**
73
+ * Is the page index (position of the center)
74
+ * after the first pages and
75
+ * before the last pages */
76
+ const isCenterPage =
77
+ numBalls >= maxBalls &&
78
+ pageIndex > indexForTheBallsCenter &&
79
+ pageIndex < indexForLastPages - 1;
80
+ let modulus =
81
+ pageIndex %
82
+ (1 + (indexForTheBallsCenter - Math.floor(indexForTheBallsCenter)));
83
+ const resetPageIndex = isCenterPage
84
+ ? indexForTheBallsCenter + modulus
85
+ : pages < maxBalls
86
+ ? pageIndex
87
+ : pageIndex >= indexForLastPages - 1
88
+ ? numBalls - (pages - pageIndex)
89
+ : pageIndex;
90
+ const left = eachBallWidthEm * resetPageIndex;
91
+ const { pushBallsToRightBy, pushBallsToLeftBy, pushGuideToRightBy } =
92
+ mode === PaginationIndicatorMode.CENTERED
93
+ ? {
94
+ pushBallsToRightBy: Math.min(pages, maxBalls) * eachBallWidthEm,
95
+ pushBallsToLeftBy: left,
96
+ pushGuideToRightBy: 0,
97
+ }
98
+ : {
99
+ pushBallsToRightBy: (eachBallWidthEm - 0.5) / 2,
100
+ pushBallsToLeftBy: 0,
101
+ pushGuideToRightBy: left,
102
+ };
103
+ let pushToLeft: number = 0;
104
+ return new Array(CENTER_GUIDE_BALL + numBalls)
105
+ .fill(undefined)
106
+ .map((_, i) => {
107
+ const isLastBall = i === numBalls - 1;
108
+ const isFirstBall = i === 0;
109
+
110
+ if (i === numBalls) {
111
+ const diameter = 0.45 * 2;
112
+ const padding = (eachBallWidthEm - diameter) / 2;
113
+ return (
114
+ <rect
115
+ fill="#fff"
116
+ width={`${diameter}em`}
117
+ height={`${diameter}em`}
118
+ x={`${
119
+ pushBallsToRightBy - padding + pushGuideToRightBy - pushToLeft
120
+ }em`}
121
+ y={`${padding}em`}
122
+ rx={`${diameter / 2}em`}
123
+ />
124
+ );
125
+ }
126
+
127
+ const ballSize =
128
+ numBalls < maxBalls
129
+ ? 0.5
130
+ : page <= indexForTheBallsCenter + 1 && isLastBall
131
+ ? 0
132
+ : pageIndex >= indexForLastPages - 1 && isFirstBall
133
+ ? 0
134
+ : isCenterPage
135
+ ? isFirstBall
136
+ ? 0.5 - modulus * 0.5
137
+ : isLastBall
138
+ ? modulus * 0.5
139
+ : 0.5
140
+ : 0.5;
141
+
142
+ if (i === 0 && mode === PaginationIndicatorMode.START)
143
+ pushToLeft = (0.5 - ballSize) * 2.4;
144
+
145
+ return (
146
+ <rect
147
+ key={`guide-${i}`}
148
+ width={`${ballSize * 1.2}em`}
149
+ height={`${ballSize * 1.2}em`}
150
+ x={`${
151
+ pushBallsToRightBy +
152
+ i * eachBallWidthEm -
153
+ pushBallsToLeftBy -
154
+ pushToLeft
155
+ }em`}
156
+ y={`${(eachBallWidthEm - ballSize * 1.2) / 2}em`}
157
+ rx={`${(ballSize * 1.2) / 2}em`}
158
+ onClick={() => {
159
+ if (onClickPage) {
160
+ const pageClicked =
161
+ (!isCenterPage
162
+ ? pageIndex >= indexForLastPages - 1
163
+ ? Math.floor(page) - resetPageIndex - 1
164
+ : 0
165
+ : Math.floor(page) - (indexForTheBallsCenter + 1)) +
166
+ 1 +
167
+ i;
168
+ onClickPage(Math.round(pageClicked));
169
+ }
170
+ }}
171
+ />
172
+ );
173
+ });
174
+ }, [indexForTheBallsCenter, pageIndex, pages]);
175
+ const [guideBall, ...pageBalls] = balls.reverse();
176
+ let width = eachBallWidthEm * Math.min(pages, maxBalls) * 2;
177
+ if (mode === PaginationIndicatorMode.START) width /= 2;
178
+
179
+ return (
180
+ <svg
181
+ version="1.1"
182
+ xmlns="http://www.w3.org/2000/svg"
183
+ className={className}
184
+ style={{
185
+ width: `${width}em`,
186
+ minWidth: `${width}em`,
187
+ height: "1.2em",
188
+ fontSize: `${size}px`,
189
+ }}
190
+ >
191
+ <filter id={`goo-${rand}`}>
192
+ <feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="5" />
193
+ <feColorMatrix
194
+ in="blur"
195
+ mode="matrix"
196
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7"
197
+ result="goo"
198
+ />
199
+ <feBlend in2="goo" in="SourceGraphic" result="mix" />
200
+ </filter>
201
+ <mask id={`mask-${rand}`}>
202
+ <g filter={`url(#${`goo-${rand}`})`} fill="#fff">
203
+ {[pageBalls]}
204
+ {guideBall}
205
+ </g>
206
+ </mask>
207
+ <rect
208
+ x="0"
209
+ y="0"
210
+ mask={`url(#${`mask-${rand}`})`}
211
+ width="100%"
212
+ height="100%"
213
+ style={{ fill: "var(--digital-blue)" }}
214
+ ></rect>
215
+ {onClickPage && (
216
+ <g opacity={0} style={{ cursor: "pointer" }}>
217
+ {pageBalls}
218
+ </g>
219
+ )}
220
+ </svg>
221
+ );
222
+ }
223
+
224
+ export function AnimatedPaginationIndicator(
225
+ props: ComponentProps<typeof PaginationIndicatorView> & {
226
+ duration: number;
227
+ }
228
+ ) {
229
+ const prevPage = useRef(props.page);
230
+ const [pageProgress, setPageProgress] = useState(props.page);
231
+ useEffect(() => {
232
+ const diff = props.page - prevPage.current;
233
+ const diffPerStep = diff / 60;
234
+
235
+ const interval = setInterval(() => {
236
+ setPageProgress((prev) => {
237
+ const next = prev + diffPerStep;
238
+ if (diff < 0) {
239
+ if (next <= props.page) {
240
+ clearInterval(interval);
241
+ return props.page;
242
+ }
243
+ } else {
244
+ if (next >= props.page) {
245
+ clearInterval(interval);
246
+ return props.page;
247
+ }
248
+ }
249
+ return Number(next.toFixed(2));
250
+ });
251
+ }, props.duration / 60);
252
+
253
+ return () => {
254
+ prevPage.current = props.page;
255
+ clearInterval(interval);
256
+ };
257
+ }, [props.page]);
258
+
259
+ return <PaginationIndicatorView {...props} page={pageProgress} />;
260
+ }
261
+
262
+ function _PaginationIndicator(
263
+ {
264
+ scrollableRef,
265
+ estimatedWidth,
266
+ size,
267
+ className = "",
268
+ onClickPage,
269
+ mode,
270
+ infinite,
271
+ }: {
272
+ scrollableRef: RefObject<HTMLDivElement>;
273
+ estimatedWidth?: number;
274
+ size: number;
275
+ className?: string;
276
+ onClickPage?: (page: number) => void;
277
+ } & Pick<ComponentProps<typeof PaginationIndicatorView>, "mode" | "infinite">,
278
+ ref: ForwardedRef<{
279
+ refreshPages: () => void;
280
+ }>
281
+ ) {
282
+ const [currentPage, setCurrentPage] = useState(1);
283
+
284
+ const [defs, setDefs] =
285
+ useState<{
286
+ pages: number;
287
+ }>();
288
+
289
+ const refreshPages = useCallback(() => {
290
+ if (!scrollableRef.current) return;
291
+ const maxWidth =
292
+ estimatedWidth === undefined
293
+ ? scrollableRef.current!.scrollWidth
294
+ : estimatedWidth;
295
+
296
+ const pages = maxWidth / scrollableRef.current!.clientWidth;
297
+ if (pages > 1)
298
+ setDefs({
299
+ pages: infinite ? pages + 2 : pages,
300
+ });
301
+ }, [estimatedWidth, infinite]);
302
+
303
+ useEffect(() => refreshPages(), [refreshPages]);
304
+
305
+ const updatePageIndicators = useCallback(
306
+ (target: HTMLDivElement, pages: number) => {
307
+ if (!scrollableRef.current) return;
308
+ const eachPageWidth = scrollableRef.current!.clientWidth;
309
+ const page = 1 + target.scrollLeft / eachPageWidth;
310
+ const lastPageProgress = Math.floor(pages) + 1;
311
+ const maximumProgress = pages + 1;
312
+
313
+ const diffToMax = maximumProgress - lastPageProgress;
314
+ const currentProgressOnDiff = page - lastPageProgress;
315
+
316
+ if (page > lastPageProgress) {
317
+ const p = lastPageProgress + currentProgressOnDiff / diffToMax;
318
+ setCurrentPage(p);
319
+ } else setCurrentPage(page);
320
+ },
321
+ []
322
+ );
323
+
324
+ useImperativeHandle(
325
+ ref,
326
+ () => ({
327
+ refreshPages,
328
+ }),
329
+ []
330
+ );
331
+
332
+ useEffect(() => {
333
+ if (!defs) return;
334
+ const el = scrollableRef.current!;
335
+ const onScroll = (e: Event) =>
336
+ updatePageIndicators(e.currentTarget as HTMLDivElement, defs.pages);
337
+ updatePageIndicators(el, defs.pages);
338
+ el.addEventListener("scroll", onScroll, {
339
+ passive: true,
340
+ });
341
+ return () => {
342
+ el.removeEventListener("scroll", onScroll);
343
+ };
344
+ }, [defs]);
345
+
346
+ const pages = useMemo(() => (defs ? defs.pages : undefined), [defs]);
347
+
348
+ return !pages ? null : (
349
+ <PaginationIndicatorView
350
+ pages={pages}
351
+ page={currentPage}
352
+ size={size}
353
+ className={className}
354
+ onClickPage={onClickPage}
355
+ mode={mode}
356
+ infinite={infinite}
357
+ />
358
+ );
359
+ }
360
+
361
+ /**
362
+ * A cool component to indicate how many pages are
363
+ **/
364
+ const PaginationIndicator = forwardRef(_PaginationIndicator);
365
+ export default PaginationIndicator;
@@ -0,0 +1 @@
1
+ export { default } from './PaginationIndicator';
@@ -0,0 +1,28 @@
1
+ @import "../../assets/styles/index.scss";
2
+
3
+ .parallax {
4
+ display: flex;
5
+ position: relative;
6
+ transition: transform $fast;
7
+ overflow: hidden;
8
+ user-select: none;
9
+ transform: translate3d(0, 0, 0);
10
+ }
11
+
12
+ .reflection {
13
+ transform: translateX(-50%) translateY(-50%);
14
+ width: 40%;
15
+ pointer-events: none;
16
+ &::after {
17
+ background: radial-gradient(#fff2, #fff2 5%, #aaa0 50%);
18
+ background-size: 100% 100%;
19
+ content: "";
20
+ display: block;
21
+ padding-bottom: 100%;
22
+ border-radius: 50%;
23
+ background-repeat: no-repeat;
24
+ }
25
+ position: absolute;
26
+ left: -50%;
27
+ top: -50%;
28
+ }
@@ -0,0 +1,248 @@
1
+ import React, {
2
+ DetailedHTMLProps,
3
+ ForwardedRef,
4
+ forwardRef,
5
+ HTMLAttributes,
6
+ MutableRefObject,
7
+ PropsWithChildren,
8
+ useEffect,
9
+ useRef,
10
+ } from "react";
11
+ import { throttle } from "lodash";
12
+ import Styles from "./Parallax.module.scss";
13
+ import {
14
+ flattenMatrix,
15
+ generateMatrixFromOperations,
16
+ invertMatrix,
17
+ } from "./math/helpers";
18
+
19
+ const MAXIMUM_PARALLAX = {
20
+ x: 20,
21
+ y: 20,
22
+ };
23
+
24
+ export function calculateDistanceRelativeToBounds(
25
+ mousePosition: number,
26
+ elementInitialPosition: number,
27
+ elementSizeDimension: number
28
+ ) {
29
+ const normalizeInitialPosition = mousePosition - elementInitialPosition;
30
+ const doNotAllowGoingBeyondLowerLimit = Math.max(normalizeInitialPosition, 0);
31
+ const doNotAllowHoingBeyondHigherLimit = Math.min(
32
+ doNotAllowGoingBeyondLowerLimit,
33
+ elementSizeDimension
34
+ );
35
+ const threeRule =
36
+ (doNotAllowHoingBeyondHigherLimit * 100) / elementSizeDimension;
37
+ const result = Math.round(threeRule) / 100;
38
+ return result;
39
+ }
40
+
41
+ export function givenTheRelativePositionHowMuchToRotate(
42
+ relativePosition: number,
43
+ maxRotation: number
44
+ ) {
45
+ return relativePosition * maxRotation - maxRotation / 2;
46
+ }
47
+
48
+ type Props = PropsWithChildren<{
49
+ className?: string;
50
+ active: boolean;
51
+ onClick?: (e: any) => void;
52
+ reflection?: boolean;
53
+ maxParallax?: {
54
+ x: number;
55
+ y: number;
56
+ };
57
+ }> &
58
+ DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
59
+
60
+ function _Parallax(
61
+ {
62
+ children,
63
+ className = "",
64
+ active,
65
+ onClick,
66
+ reflection,
67
+ maxParallax = MAXIMUM_PARALLAX,
68
+ ...props
69
+ }: Props,
70
+ ref: ForwardedRef<HTMLDivElement>
71
+ ) {
72
+ const parallaxableRef = useRef<HTMLDivElement>(null);
73
+ const reflectionRef = useRef<HTMLDivElement>(null);
74
+ const multiplierRef = useRef<number>(1);
75
+ const initialPositionRef = useRef<string>(undefined);
76
+ useEffect(() => {
77
+ if (ref)
78
+ (ref as MutableRefObject<HTMLDivElement>).current =
79
+ parallaxableRef.current!;
80
+ const el = parallaxableRef.current!;
81
+ if (active && !initialPositionRef.current) {
82
+ initialPositionRef.current = getComputedStyle(el).transform;
83
+ if (initialPositionRef.current === "none")
84
+ initialPositionRef.current = "";
85
+ el.style.transform = `${initialPositionRef.current} rotateX(0deg) rotateY(0deg) translateZ(0px)`;
86
+ }
87
+ // eslint-disable-next-line
88
+ }, [active]);
89
+
90
+ useEffect(() => {
91
+ const el = parallaxableRef.current!;
92
+ if (active) {
93
+ const updatePositions = (relativeToX: number, relativeToY: number) => {
94
+ const rect = el.getBoundingClientRect();
95
+ const {
96
+ width: [x0, xW],
97
+ height: [y0, yH],
98
+ } = {
99
+ width: [rect.left, el.clientWidth],
100
+ height: [rect.top, el.clientHeight],
101
+ };
102
+ const distanceOffRight = calculateDistanceRelativeToBounds(
103
+ relativeToX,
104
+ x0,
105
+ xW
106
+ );
107
+ const distanceOffBottom = calculateDistanceRelativeToBounds(
108
+ relativeToY,
109
+ y0,
110
+ yH
111
+ );
112
+ const howMuchToRotateY =
113
+ givenTheRelativePositionHowMuchToRotate(
114
+ distanceOffRight,
115
+ maxParallax.y
116
+ ) * multiplierRef.current;
117
+ const howMuchToRotateX =
118
+ givenTheRelativePositionHowMuchToRotate(
119
+ distanceOffBottom,
120
+ maxParallax.x
121
+ ) * multiplierRef.current;
122
+
123
+ const howMuchToOpacify = Math.abs(
124
+ Math.abs(distanceOffBottom - 0.5) / 0.5
125
+ );
126
+ const howMuchToOpacifyHorizontal = Math.max(
127
+ Math.abs(Math.abs(distanceOffRight - 0.5) / 0.5),
128
+ Math.abs(Math.abs(distanceOffBottom - 0.5) / 0.5)
129
+ );
130
+
131
+ el.style.transform = `${
132
+ initialPositionRef.current
133
+ } rotateY(${howMuchToRotateY}deg) rotateX(${-howMuchToRotateX}deg) translateZ(${
134
+ multiplierRef.current === 1 ? 0 : -30
135
+ }px)`;
136
+
137
+ if (reflectionRef.current) {
138
+ reflectionRef.current.style.left = `${(1 - distanceOffRight) * 100}%`;
139
+ reflectionRef.current.style.top = `${(1 - distanceOffBottom) * 100}%`;
140
+ reflectionRef.current.style.opacity = `${Math.min(
141
+ howMuchToOpacify,
142
+ howMuchToOpacifyHorizontal
143
+ )}`;
144
+ }
145
+ };
146
+ const handler = throttle(({ x, y }: MouseEvent) => {
147
+ updatePositions(x, y);
148
+ }, 1000 / 30);
149
+ const touchHandler = throttle(({ touches }: TouchEvent) => {
150
+ const { pageX, pageY } = touches[0];
151
+ updatePositions(pageX, pageY);
152
+ }, 1000 / 30);
153
+ const mouseDownHandler = () => {
154
+ multiplierRef.current = 1.5;
155
+ };
156
+ const mouseUpHandler = () => {
157
+ multiplierRef.current = 1;
158
+ };
159
+ window.addEventListener("mousemove", handler);
160
+ window.addEventListener("touchmove", touchHandler);
161
+ let _inverseMatrix: number[] | undefined;
162
+ const _limits: {
163
+ [k in "beta" | "gamma"]?: [number, number];
164
+ } = {
165
+ beta: undefined,
166
+ gamma: undefined,
167
+ };
168
+ const orientationListener: (e: DeviceOrientationEvent) => void = ({
169
+ beta,
170
+ gamma,
171
+ }) => {
172
+ beta = beta! * 0.5;
173
+ gamma = gamma! * 0.5;
174
+ if (!_inverseMatrix) {
175
+ window.removeEventListener("mousemove", handler);
176
+ window.removeEventListener("touchmove", touchHandler);
177
+ const offset = 12.5;
178
+ _limits.beta = [beta! - offset, beta! + offset];
179
+ _limits.gamma = [gamma! - offset, gamma! + offset];
180
+ }
181
+ const _beta = Math.min(
182
+ _limits.beta![1],
183
+ Math.max(_limits.beta![0], beta!)
184
+ );
185
+ const _gamma = Math.min(
186
+ _limits.gamma![1],
187
+ Math.max(_limits.gamma![0], gamma!)
188
+ );
189
+ if (!_inverseMatrix) {
190
+ _inverseMatrix = flattenMatrix(
191
+ invertMatrix(
192
+ generateMatrixFromOperations(
193
+ {
194
+ type: "rotateY",
195
+ angle: _gamma!,
196
+ },
197
+ {
198
+ type: "rotateX",
199
+ angle: -_beta!,
200
+ }
201
+ )
202
+ )
203
+ );
204
+ }
205
+ el.style.transform = `matrix3d(${_inverseMatrix.join(
206
+ ","
207
+ )}) rotateX(${-_beta!}deg) rotateY(${_gamma}deg)`;
208
+ };
209
+ window.addEventListener("deviceorientation", orientationListener);
210
+ window.addEventListener("touchend", () => {
211
+ _inverseMatrix = undefined;
212
+ });
213
+ el.addEventListener("touchstart", mouseDownHandler);
214
+ el.addEventListener("touchend", mouseUpHandler);
215
+ el.addEventListener("mousedown", mouseDownHandler);
216
+ el.addEventListener("mouseup", mouseUpHandler);
217
+
218
+ return () => {
219
+ window.removeEventListener("deviceorientation", orientationListener);
220
+ window.removeEventListener("mousemove", handler);
221
+ window.removeEventListener("touchmove", touchHandler);
222
+ el.removeEventListener("mousedown", mouseDownHandler);
223
+ el.removeEventListener("mouseup", mouseUpHandler);
224
+ el.removeEventListener("touchstart", mouseDownHandler);
225
+ el.removeEventListener("touchend", mouseUpHandler);
226
+ // el.style.transform = initialPositionRef.current!;
227
+ el.style.transform = `rotateX(0deg) rotateY(0deg) translateZ(0px)`;
228
+ };
229
+ }
230
+ }, [active]);
231
+ return (
232
+ <div
233
+ onClick={onClick}
234
+ ref={parallaxableRef}
235
+ className={`${Styles.parallax} ${className}`}
236
+ {...props}
237
+ >
238
+ {children}
239
+ {reflection && <div ref={reflectionRef} className={Styles.reflection} />}
240
+ </div>
241
+ );
242
+ }
243
+
244
+ /**
245
+ * It holds a children and animates a tilt effect relative to mouse position
246
+ **/
247
+ const Parallax = forwardRef(_Parallax);
248
+ export default Parallax;
@@ -0,0 +1 @@
1
+ export { default } from './Parallax';