Skip to content

Commit 2100990

Browse files
authored
feat: add useSynchronizedAnimation hook (#15)
1 parent e19e905 commit 2100990

3 files changed

Lines changed: 81 additions & 38 deletions

File tree

README.md

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,33 @@ const MyComponent = () => {
9393

9494
</details>
9595

96+
<details>
97+
<summary>useClickOutside</summary>
98+
99+
A hook that fires a callback when a click (pointerdown) was registered outside of a component. Outside is defined as outside of your react tree, which means that this works with portals.
100+
101+
```tsx
102+
import { useDraggable } from 'react-hooks-shareable'
103+
104+
const MyComponent = () => {
105+
const handler = useClickOutside(e => {
106+
console.log('Clicked outside!')
107+
})
108+
109+
return (
110+
<div onPointerDown={handler}>
111+
<span>Clicks here is inside</span>
112+
{ReactDOM.createPortal(
113+
<span>Clicks here are also inside</span>,
114+
portalContainer
115+
)}
116+
</div>
117+
)
118+
}
119+
```
120+
121+
</details>
122+
96123
<details>
97124
<summary>useDeferredTrigger</summary>
98125

@@ -152,44 +179,35 @@ const MyComponent = () => {
152179
</details>
153180

154181
<details>
155-
<summary>useClickOutside</summary>
182+
<summary>useFocusDetection</summary>
156183

157-
A hook that fires a callback when a click (pointerdown) was registered outside of a component. Outside is defined as outside of your react tree, which means that this works with portals.
184+
A hook which detects if the browser and your page is in focus.
158185

159186
```tsx
160-
import { useDraggable } from 'react-hooks-shareable'
187+
import { useFocusDetection } from 'react-hooks-shareable'
161188

162189
const MyComponent = () => {
163-
const handler = useClickOutside(e => {
164-
console.log('Clicked outside!')
165-
})
190+
const hasFocus = useFocusDetection(1000)
166191

167-
return (
168-
<div onPointerDown={handler}>
169-
<span>Clicks here is inside</span>
170-
{ReactDOM.createPortal(
171-
<span>Clicks here are also inside</span>,
172-
portalContainer
173-
)}
174-
</div>
175-
)
192+
return <span>{`User ${hasFocus ? : 'is' : 'is not'} focusing on this page`}</span>
176193
}
177194
```
178195

179196
</details>
180197

181198
<details>
182-
<summary>useFocusDetection</summary>
199+
<summary>useHasOverflow</summary>
183200

184-
A hook which detects if the browser and your page is in focus.
201+
A hook for checking if an element has overflow.
185202

186203
```tsx
187-
import { useFocusDetection } from 'react-hooks-shareable'
204+
import { useHasOverflow } from 'react-hooks-shareable'
205+
import { SomeComponent } from 'someComponentLibrary'
188206

189207
const MyComponent = () => {
190-
const hasFocus = useFocusDetection(1000)
208+
const { hasOverflow, ref } = useHasOverflow()
191209

192-
return <span>{`User ${hasFocus ? : 'is' : 'is not'} focusing on this page`}</span>
210+
return <SomeComponent ref={ref} hasOverflow={hasOverflow} />
193211
}
194212
```
195213

@@ -397,6 +415,37 @@ const MyComponent = () => {
397415

398416
</details>
399417

418+
<details>
419+
<summary>useSynchronizedAnimation</summary>
420+
421+
A hook for synchronizing web animations. The animations are synchronized to
422+
the `document.timeline`. This can for example be used to make spinners
423+
always be in sync with another, and over remounts.
424+
425+
```css
426+
.animation {
427+
animation: spin 4s linear infinite;
428+
}
429+
430+
@keyframes spin {
431+
100% {
432+
transform: rotate(360deg);
433+
}
434+
}
435+
```
436+
437+
```tsx
438+
import { useSynchronizedAnimation } from 'react-hooks-shareable'
439+
440+
const MyAnimation = () => {
441+
const ref = useSynchronizedAnimation()
442+
443+
return <div className="animation" ref={ref} />
444+
}
445+
```
446+
447+
</details>
448+
400449
<details>
401450
<summary>useTrigger</summary>
402451

@@ -494,21 +543,3 @@ const MyComponent = () => {
494543
```
495544

496545
</details>
497-
498-
<details>
499-
<summary>useHasOverflow</summary>
500-
501-
A hook for checking if an element has overflow.
502-
503-
```tsx
504-
import { useHasOverflow } from 'react-hooks-shareable'
505-
import { SomeComponent } from 'someComponentLibrary'
506-
507-
const MyComponent = () => {
508-
const { hasOverflow, ref } = useHasOverflow()
509-
510-
return <SomeComponent ref={ref} hasOverflow={hasOverflow} />
511-
}
512-
```
513-
514-
</details>

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export * from './usePressed'
1414
export * from './useResetScroll'
1515
export * from './useScrollPosition'
1616
export * from './useSelection'
17+
export * from './useSynchronizedAnimation'
1718
export * from './useTrigger'
1819
export * from './useUserActive'
1920
export * from './useVisibleFocus'

src/useSynchronizedAnimation.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { useLayoutEffect, useRef } from 'react'
2+
3+
export const useSynchronizedAnimation = (options?: GetAnimationsOptions) => {
4+
const ref = useRef<HTMLElement>()
5+
useLayoutEffect(() => {
6+
ref.current
7+
?.getAnimations(options)
8+
.forEach(a => (a.currentTime = document.timeline.currentTime))
9+
}, [options])
10+
return ref
11+
}

0 commit comments

Comments
 (0)