@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,512 @@
1
+ import React, {
2
+ CSSProperties,
3
+ useCallback,
4
+ useEffect,
5
+ useLayoutEffect,
6
+ useMemo,
7
+ useRef,
8
+ } from "react";
9
+ import ownEvent from "../utils/ownEvent";
10
+ import Styles from "./useHero.module.scss";
11
+
12
+ const ID = (id: string) => `${id}-hero`;
13
+ type ShouldSkip = boolean;
14
+ type Result = [
15
+ originContainer: Element | VisualViewport,
16
+ targetContainer: Element | VisualViewport
17
+ ];
18
+ const viewport = window.visualViewport!;
19
+ const DATA_TAG_HERO_COMPONENT = "data-hero-component";
20
+
21
+ function triggerDynamicComponents(
22
+ clone: HTMLDivElement,
23
+ componentsFromOriginThatWillAppear: HTMLDivElement[],
24
+ origin: HTMLDivElement
25
+ ) {
26
+ const idsThatWillAppear = componentsFromOriginThatWillAppear.map((a) =>
27
+ a.getAttribute(DATA_TAG_HERO_COMPONENT)
28
+ );
29
+ const preexistingComponents = Array.from(
30
+ clone.querySelectorAll(`[${DATA_TAG_HERO_COMPONENT}]`)
31
+ ) as HTMLDivElement[];
32
+ const removedElements: HTMLDivElement[] = preexistingComponents.filter(
33
+ (el) =>
34
+ !idsThatWillAppear.includes(el.getAttribute(DATA_TAG_HERO_COMPONENT))
35
+ );
36
+
37
+ for (let elementThatIsBeingRemoved of removedElements) {
38
+ for (let heightKey of ["height", "minHeight", "maxHeight"] as const)
39
+ elementThatIsBeingRemoved.style[
40
+ heightKey
41
+ ] = `${elementThatIsBeingRemoved.clientHeight}px`;
42
+ }
43
+ setTimeout(() => {
44
+ for (let elementThatIsBeingRemoved of removedElements) {
45
+ for (let heightKey of ["height", "minHeight", "maxHeight"] as const)
46
+ elementThatIsBeingRemoved.style[heightKey] = `0px`;
47
+ elementThatIsBeingRemoved.style.opacity = `0`;
48
+ }
49
+ }, 0);
50
+
51
+ for (let componentThatWillAppear of componentsFromOriginThatWillAppear) {
52
+ const alreadyInjectedElement = !!clone.querySelector(
53
+ `[${DATA_TAG_HERO_COMPONENT}="${componentThatWillAppear.getAttribute(
54
+ DATA_TAG_HERO_COMPONENT
55
+ )}"]`
56
+ );
57
+ if (!alreadyInjectedElement) {
58
+ function recursiveBuildPath(
59
+ fromElement: HTMLElement,
60
+ pathSuffix: string = ""
61
+ ): string | undefined {
62
+ if (fromElement === origin) return pathSuffix;
63
+ const parent = fromElement.parentElement!;
64
+ const parentChilds = Array.from(parent.children);
65
+ const elChildSelector = `:nth-child(${
66
+ parentChilds.indexOf(fromElement) + 1
67
+ })`;
68
+
69
+ if (fromElement !== origin)
70
+ return recursiveBuildPath(
71
+ parent,
72
+ `${elChildSelector}${pathSuffix ? `>${pathSuffix}` : ""}`
73
+ );
74
+ else return pathSuffix;
75
+ }
76
+ const whatIsTheElementPathFromCloneElement = recursiveBuildPath(
77
+ componentThatWillAppear.parentElement!
78
+ );
79
+ const insertAtIndex = Array.from(
80
+ componentThatWillAppear.parentElement!.children
81
+ ).indexOf(componentThatWillAppear);
82
+
83
+ const targetElementClone = componentThatWillAppear.cloneNode(
84
+ true
85
+ ) as HTMLDivElement;
86
+ for (let heightKey of ["height", "minHeight", "maxHeight"] as const)
87
+ targetElementClone.style[heightKey] = "0px";
88
+ const shouldBeInsertedAtElement = whatIsTheElementPathFromCloneElement
89
+ ? clone.querySelector(whatIsTheElementPathFromCloneElement)!
90
+ : clone;
91
+ const remainingIndexes = Array.from(shouldBeInsertedAtElement.children)
92
+ .map((el, i) =>
93
+ removedElements.includes(el as HTMLDivElement) ? undefined : i
94
+ )
95
+ .filter((e) => e !== undefined) as number[];
96
+
97
+ if (insertAtIndex === remainingIndexes.length)
98
+ shouldBeInsertedAtElement.append(targetElementClone);
99
+ else
100
+ shouldBeInsertedAtElement.insertBefore(
101
+ targetElementClone,
102
+ shouldBeInsertedAtElement.childNodes.item(
103
+ remainingIndexes[insertAtIndex]
104
+ )
105
+ );
106
+ setTimeout(() => {
107
+ for (let heightKey of ["height", "minHeight", "maxHeight"] as const)
108
+ targetElementClone.style[
109
+ heightKey
110
+ ] = `${componentThatWillAppear.clientHeight}px`;
111
+ }, 0);
112
+ }
113
+ }
114
+ }
115
+
116
+ const ALWAYS_TRANSITION = ["top", "left"];
117
+
118
+ /**
119
+ * This hook implements the logic for a hero animation between 2 elements sharing the same id
120
+ */
121
+ export default function useHero(
122
+ id: string,
123
+ options: Partial<{
124
+ propsToTransition: Exclude<
125
+ keyof CSSProperties,
126
+ "width" | "height" | "top" | "left"
127
+ >[];
128
+ /** If set, the default properties (width, height, etc...) will not transition, and propsToTransition will be the only ones that will be transitioned */
129
+ overridePropsToTransition: boolean;
130
+
131
+ "data-preffix": string;
132
+ /** This indicates this hero animation will probably be repeated multiple time */
133
+ repeatable: boolean;
134
+ }> = {
135
+ propsToTransition: [],
136
+ },
137
+ events: {
138
+ /**
139
+ * Should return if the detected element should be "heroed"
140
+ *
141
+ * Usefull for when the hero has 2 possible origins.
142
+ * For example, one could hero only the current hovered element with el.matches(":hover")
143
+ */
144
+ onHeroDetect?: (origin: HTMLDivElement, target: HTMLDivElement) => boolean;
145
+
146
+ /**
147
+ * Do something when the hero ends
148
+ *
149
+ * Usefull for triggering secondary animations
150
+ */
151
+ onHeroEnd?: () => void;
152
+
153
+ /** Do somethign with the clone before it goes to the html */
154
+ onHeroCloned?: (clone: HTMLDivElement) => void;
155
+
156
+ /**
157
+ * Do something when the hero starts the transition
158
+ * Here it's usefull to switch classNames with the target.
159
+ *
160
+ * If done correctly, it will transition from state a to b smoothly
161
+ */
162
+ onHeroStart?: (
163
+ clone: HTMLDivElement,
164
+ origin: HTMLDivElement,
165
+ target: HTMLDivElement
166
+ ) => void;
167
+
168
+ /**
169
+ * Is called when the hero is coming/going outside the viewport
170
+ *
171
+ * By default it's set to skip all heroes that have these conditions
172
+ *
173
+ * @returns If the hero should be skipped or not
174
+ */
175
+ onHeroSkip?: (origin: HTMLDivElement, target: HTMLDivElement) => ShouldSkip;
176
+
177
+ /**
178
+ * Called when a hero is skipped
179
+ */
180
+ onHeroSkipped?: () => void;
181
+
182
+ /**
183
+ * Before transition start, setup the properties that will be used for hero animation
184
+ * @returns The container that will be used to check if the hero is out or in the view
185
+ */
186
+ onBeforeTransition?: (
187
+ origin: HTMLDivElement,
188
+ target: HTMLDivElement
189
+ ) => Result | Readonly<Result>;
190
+ } = {}
191
+ ) {
192
+ const {
193
+ propsToTransition: _p = [],
194
+ "data-preffix": dataPreffix,
195
+ repeatable,
196
+ } = options;
197
+ const propsToTransition = useMemo(
198
+ () =>
199
+ _p.map((p) => p.replace(/([A-Z])/g, (_, val) => `-${val.toLowerCase()}`)),
200
+ [_p]
201
+ );
202
+ const _dataPreffix = dataPreffix ? `-${dataPreffix}` : "";
203
+ const dataProperty = `data${_dataPreffix}-hero`;
204
+ const heroRef = useRef<HTMLDivElement>(null);
205
+
206
+ useLayoutEffect(() => {
207
+ heroRef.current!.setAttribute(dataProperty, id);
208
+ }, [id]);
209
+
210
+ const getHerosOnScreen = useCallback(() => {
211
+ const otherElements = (
212
+ Array.from(
213
+ document.querySelectorAll(`[${dataProperty}="${id}"]`)
214
+ ) as HTMLDivElement[]
215
+ ).filter((el) => el !== heroRef.current);
216
+ return otherElements;
217
+ }, [id]);
218
+
219
+ function triggerHeroAnimation() {
220
+ const allPropsToTransition = options.overridePropsToTransition
221
+ ? [...ALWAYS_TRANSITION, ...propsToTransition]
222
+ : ["width", "height", ...ALWAYS_TRANSITION, ...propsToTransition];
223
+ const shouldHeroFn = events.onHeroDetect || ((...a: any[]) => true);
224
+ const otherElements = getHerosOnScreen().filter((el) =>
225
+ shouldHeroFn(el, heroRef.current!)
226
+ );
227
+ const currentElement = heroRef.current!;
228
+ const currentElCoordinates = currentElement.getBoundingClientRect();
229
+
230
+ if (process.env.NODE_ENV === "development" && otherElements.length > 2)
231
+ console.warn(
232
+ "There are too many elements to transition to, I will transition to the first I find",
233
+ otherElements
234
+ );
235
+ const otherElement = otherElements.find(
236
+ (el) => el !== heroRef.current!
237
+ ) as HTMLDivElement;
238
+
239
+ if (otherElement) {
240
+ const [originContainer, targetContainer] = events.onBeforeTransition
241
+ ? events.onBeforeTransition(otherElement, heroRef.current!)
242
+ : [viewport, viewport];
243
+ const shouldSkip =
244
+ isElementOutsideContainer(targetContainer, currentElCoordinates) ||
245
+ isElementOutsideContainer(
246
+ originContainer,
247
+ otherElement.getBoundingClientRect()
248
+ )
249
+ ? (events.onHeroSkip || (() => true))(otherElement, heroRef.current!)
250
+ : false;
251
+ if (shouldSkip) {
252
+ events.onHeroSkipped?.();
253
+ return;
254
+ }
255
+ const oldClone = document.querySelector(
256
+ `[${dataProperty}-clone="${ID(id)}"]`
257
+ );
258
+ const clone = (oldClone ||
259
+ otherElement.cloneNode(true)) as HTMLDivElement;
260
+
261
+ if (events.onHeroCloned && !oldClone) events.onHeroCloned(clone);
262
+
263
+ // Clean up thos properties that can cause confusion since it's a clone
264
+ clone.style.visibility = "";
265
+ clone.removeAttribute(dataProperty);
266
+
267
+ clone.setAttribute(`${dataProperty}-clone`, ID(id));
268
+
269
+ /**
270
+ * If it's repeatable, we should keep the flag that indicates the hero existance
271
+ */
272
+ if (!repeatable)
273
+ // Since a transition is now triggering from the old element, he cannot be considered for other transitions
274
+ otherElement.removeAttribute(dataProperty);
275
+
276
+ function willTheHeroMove(origin: DOMRect, target: DOMRect) {
277
+ return !(
278
+ origin.top === target.top &&
279
+ origin.left === target.left &&
280
+ origin.width === target.width &&
281
+ origin.height === target.height
282
+ );
283
+ }
284
+
285
+ /**
286
+ *
287
+ * @param el
288
+ * @returns Returns if it will move
289
+ */
290
+ function setCloneToCoordinatesOf(el: HTMLDivElement) {
291
+ const coordinates = el.getBoundingClientRect();
292
+ const currentCoordinates = clone.getBoundingClientRect();
293
+ const willMove = willTheHeroMove(coordinates, currentCoordinates);
294
+
295
+ clone.style.position = "fixed";
296
+ clone.style.top = `${coordinates.top}px`;
297
+ clone.style.left = `${coordinates.left}px`;
298
+ if (allPropsToTransition.includes("width"))
299
+ clone.style.width = `${coordinates.width}px`;
300
+ if (allPropsToTransition.includes("height"))
301
+ clone.style.height = `${coordinates.height}px`;
302
+
303
+ return willMove;
304
+ }
305
+
306
+ const coordinates = otherElement.getBoundingClientRect();
307
+ const currentCoordinates = heroRef.current!.getBoundingClientRect();
308
+ const itWontMove = !willTheHeroMove(coordinates, currentCoordinates);
309
+ if (itWontMove) return;
310
+
311
+ if (!oldClone) {
312
+ /** Set the clone over the starting element */
313
+ setCloneToCoordinatesOf(otherElement);
314
+ document.body.appendChild(clone);
315
+ }
316
+ heroRef.current!.style.visibility = "hidden";
317
+ otherElement.style.visibility = "hidden";
318
+
319
+ for (let propToTransition of propsToTransition) {
320
+ clone.style[propToTransition as any] =
321
+ window.getComputedStyle(otherElement)[propToTransition as any];
322
+ }
323
+
324
+ clone.style.transition = `${allPropsToTransition
325
+ .map(
326
+ (prop) =>
327
+ `${prop.replace(
328
+ /[A-Z]/g,
329
+ (sub) => `-${sub.toLowerCase()}`
330
+ )} var(--animation--speed-fast, 250ms) ease-out`
331
+ )
332
+ .join(", ")}`;
333
+
334
+ setTimeout(() => {
335
+ const elItWillTransitionTo = heroRef.current;
336
+ const cleanup = () => {
337
+ if (events.onHeroEnd) events.onHeroEnd();
338
+ if (elItWillTransitionTo) {
339
+ if (repeatable)
340
+ elItWillTransitionTo!.setAttribute(dataProperty, id);
341
+ elItWillTransitionTo.style.visibility = "";
342
+ }
343
+ setTimeout(() => {
344
+ clone.remove();
345
+ }, 0);
346
+ };
347
+ triggerDynamicComponents(
348
+ clone,
349
+ Array.from(
350
+ heroRef.current!.querySelectorAll(`[${DATA_TAG_HERO_COMPONENT}]`)
351
+ ) as HTMLDivElement[],
352
+ currentElement
353
+ );
354
+ if (events.onHeroStart) {
355
+ events.onHeroStart(clone, otherElement, heroRef.current!);
356
+ }
357
+ if (!elItWillTransitionTo) {
358
+ cleanup();
359
+ return;
360
+ }
361
+ /** Set the clone over the new position */
362
+ const willMove = setCloneToCoordinatesOf(elItWillTransitionTo);
363
+ if (!willMove) cleanup();
364
+ else {
365
+ for (let propToTransition of propsToTransition)
366
+ clone.style[propToTransition as any] =
367
+ window.getComputedStyle(elItWillTransitionTo)[
368
+ propToTransition as any
369
+ ];
370
+ let initialOffset: number;
371
+ const s = ({ target }: MouseEvent) => {
372
+ const d = target as HTMLDivElement;
373
+ if (d.contains(elItWillTransitionTo)) {
374
+ if (initialOffset === undefined) initialOffset = d.scrollTop;
375
+ else
376
+ clone.style.marginTop = `${-(d.scrollTop - initialOffset)}px`;
377
+ }
378
+ };
379
+ const transitionEndCb = ownEvent(
380
+ ({ target, currentTarget }: TransitionEvent) => {
381
+ if (target === currentTarget) cleanup();
382
+ document.removeEventListener("scroll", s as any, true);
383
+ }
384
+ );
385
+ document.addEventListener("scroll", s as any, true);
386
+ clone.addEventListener("transitionend", transitionEndCb);
387
+ clone.addEventListener("transitionstart", () => {
388
+ const onCancelCb = ownEvent((e) => {
389
+ clone.removeEventListener("transitionend", transitionEndCb);
390
+ clone.removeEventListener("transitioncancel", onCancelCb);
391
+ });
392
+ clone.addEventListener("transitioncancel", onCancelCb);
393
+ });
394
+ }
395
+ }, 0);
396
+ }
397
+ }
398
+
399
+ useEffect(() => {
400
+ triggerHeroAnimation();
401
+ }, []);
402
+
403
+ return {
404
+ heroRef,
405
+ getHerosOnScreen,
406
+ trigger: triggerHeroAnimation,
407
+ heroComponentRef:
408
+ (componentId: string) => (elRef: HTMLDivElement | null) => {
409
+ if (elRef) {
410
+ elRef.setAttribute(DATA_TAG_HERO_COMPONENT, componentId);
411
+ elRef.classList.add(Styles.component);
412
+ }
413
+ },
414
+ };
415
+ }
416
+
417
+ function isElementOutsideViewport(coordinates: DOMRect) {
418
+ const elementOverflowsViewport =
419
+ coordinates.left >= viewport.width || coordinates.top >= viewport.height;
420
+ const elementUnderflowsViewport =
421
+ coordinates.left <= -coordinates.width ||
422
+ coordinates.top <= -coordinates.height;
423
+ return elementOverflowsViewport || elementUnderflowsViewport;
424
+ }
425
+
426
+ function isElementOutsideContainer(
427
+ container: VisualViewport | Element,
428
+ coordinates: DOMRect
429
+ ) {
430
+ if (container instanceof VisualViewport) {
431
+ return isElementOutsideViewport(coordinates);
432
+ } else {
433
+ const containerBounds = container.getBoundingClientRect();
434
+
435
+ const isContainerOutsideViewport =
436
+ isElementOutsideViewport(containerBounds);
437
+
438
+ if (isContainerOutsideViewport) return true;
439
+
440
+ const elementOverflowsViewport =
441
+ coordinates.left >= containerBounds.left + containerBounds.width ||
442
+ coordinates.top >= containerBounds.top + containerBounds.height;
443
+
444
+ const elementUnderflowsViewport =
445
+ containerBounds.left - coordinates.left >= coordinates.width ||
446
+ containerBounds.top - coordinates.top >= coordinates.height;
447
+
448
+ return elementUnderflowsViewport || elementOverflowsViewport;
449
+ }
450
+ }
451
+
452
+ type EVENTS_INTERFACE = Parameters<typeof useHero>[2];
453
+ type TRANSITION_TYPES = "ACCELERATION";
454
+ function centerPoint(rect: DOMRect) {
455
+ return [rect.left + rect.width / 2, rect.top + rect.height / 2] as const;
456
+ }
457
+ const angle = (
458
+ pointA: readonly [x: number, y: number],
459
+ pointB: readonly [x: number, y: number]
460
+ ) =>
461
+ Number(
462
+ (
463
+ Math.atan2(pointA[1] - pointB[1], pointA[0] - pointB[0]) *
464
+ (179.08 / Math.PI)
465
+ ).toFixed(5)
466
+ );
467
+ export const TRANSITION_FACTORY: {
468
+ [n in TRANSITION_TYPES]: (events?: EVENTS_INTERFACE) => EVENTS_INTERFACE;
469
+ } = {
470
+ ACCELERATION: (events) => ({
471
+ ...events,
472
+ onHeroStart(clone, origin, target) {
473
+ if (events?.onHeroStart) events.onHeroStart(clone, origin, target);
474
+ clone.classList.add(Styles.acceleration);
475
+ const centerPointOrigin = centerPoint(origin.getBoundingClientRect());
476
+ const centerPointDestination = centerPoint(
477
+ target.getBoundingClientRect()
478
+ );
479
+ const angleBetweenElements = angle(
480
+ centerPointOrigin,
481
+ centerPointDestination
482
+ );
483
+ const vectorX = Math.sin(angleBetweenElements);
484
+ const vectorY = Math.cos(angleBetweenElements);
485
+
486
+ const rotateY = (10 * vectorY).toFixed(0);
487
+ const originX = (vectorY + 1) * 50;
488
+
489
+ const rotateX = -(10 * vectorX).toFixed(0);
490
+ const originY = (vectorX + 1) * 50;
491
+
492
+ clone.style.setProperty(
493
+ "--stage-1",
494
+ `rotateY(${rotateY}deg) rotateX(${-rotateX}deg)`
495
+ );
496
+ clone.style.setProperty(
497
+ "--stage-2",
498
+ `rotateY(${-rotateY * 0.3}deg) rotateX(${rotateX * 0.3}deg)`
499
+ );
500
+ clone.style.setProperty("--origin-1", `${originX}% ${originY}%`);
501
+ clone.style.setProperty(
502
+ "--origin-2",
503
+ `${100 - originX}% ${100 - originY}%`
504
+ );
505
+ document.body.style.perspective = "100vw";
506
+ },
507
+ onHeroEnd() {
508
+ if (events?.onHeroEnd) events.onHeroEnd();
509
+ document.body.style.perspective = "";
510
+ },
511
+ }),
512
+ };
@@ -0,0 +1,32 @@
1
+ import { useMemo, useRef } from "react";
2
+
3
+ export default function useIntersection() {
4
+ const { current: targetMap } = useRef<[HTMLOrSVGElement, () => void][]>([]);
5
+ const { current: observer } = useRef(
6
+ ("IntersectionObserver" in window) ? new IntersectionObserver((els) => {
7
+ els.forEach((e, i) => {
8
+ const result = targetMap.find((el) => el[0] === e.target as any);
9
+ if (result && e.isIntersecting) {
10
+ result[1]();
11
+ }
12
+ });
13
+ }) : null
14
+ );
15
+ return useMemo(() => {
16
+ return {
17
+ observe: (e: HTMLOrSVGElement, cb: () => void) => {
18
+ targetMap.push([e, cb]);
19
+ if (observer)
20
+ observer.observe(e as any);
21
+ },
22
+ unobserve: (e: HTMLOrSVGElement) => {
23
+ if (observer)
24
+ observer.unobserve(e as any);
25
+ targetMap.splice(
26
+ targetMap.findIndex((el) => el[0] === e),
27
+ 1
28
+ );
29
+ },
30
+ };
31
+ }, []);
32
+ }
@@ -0,0 +1,29 @@
1
+ import { RefObject, useLayoutEffect, useRef } from "react";
2
+
3
+ /**
4
+ * This function exists so we can work with multiple refs as a single one
5
+ */
6
+ export default function useMergeRefs<T extends ReturnType<typeof useRef>>(
7
+ mainRef: T,
8
+ ...otherRefs: T[]
9
+ ) {
10
+ useLayoutEffect(() => {
11
+ for (let ref of otherRefs) ref.current = mainRef.current;
12
+ }, []);
13
+ return mainRef;
14
+ }
15
+
16
+ /**
17
+ * This function exists so we can work with multiple refs as a single one, almost immediatly
18
+ */
19
+ export function useMergeRefsFunc<
20
+ T extends ReturnType<typeof useRef> | ((ref: any) => void)
21
+ >(mainRef: T, ...otherRefs: T[]) {
22
+ return (providedRef: any) => {
23
+ if (providedRef)
24
+ for (let ref of [mainRef, ...otherRefs]) {
25
+ if (typeof ref === "function") ref(providedRef);
26
+ else ref.current = providedRef;
27
+ }
28
+ };
29
+ }
@@ -0,0 +1,24 @@
1
+ import { useEffect, useLayoutEffect, useState } from "react";
2
+ import "./shims/ObjectWatchShim.js";
3
+
4
+ interface Object {
5
+ watch<T extends Object>(prop: (keyof T)[], handler: () => void): () => void;
6
+ unwatch(): void;
7
+ }
8
+
9
+ export default function useObserve<T extends any>(
10
+ toObserve: T | T[],
11
+ keysToObserve: (keyof T)[]
12
+ ) {
13
+ const [_, ss] = useState(0);
14
+ useLayoutEffect(() => {
15
+ const arr = Array.isArray(toObserve) ? toObserve : [toObserve]
16
+ const unwatchers = arr.map(object => (object as Object).watch(keysToObserve as any, () => {
17
+ ss((p) => {
18
+ return p + 1
19
+ });
20
+ }))
21
+
22
+ return () => unwatchers.forEach(unwatch => unwatch())
23
+ }, [toObserve]);
24
+ }