Skip to content

Commit 46cd7ba

Browse files
committed
[WIP] useActiveElement hook
1 parent 2408bfa commit 46cd7ba

8 files changed

Lines changed: 100 additions & 8 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { useActiveElement } from "../../../../../../packages/react-tools/src"
2+
3+
/**
4+
DEMO
5+
*/
6+
export const UseActiveElement = () => {
7+
const activeElement = useActiveElement();
8+
console.log("render", activeElement?.tagName)
9+
10+
return (<>
11+
<p>Active element is: {activeElement?.tagName}</p>
12+
<div style={{ display: "grid", gridTemplateColumns: "auto auto auto", justifyContent: "center", gap: 50 }}>
13+
<span tabIndex={0}>Span</span>
14+
<p tabIndex={0}>P</p>
15+
<button>Button</button>
16+
</div>
17+
</>)
18+
}

apps/react-tools-demo/src/constants/components.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ export const COMPONENTS = [
4444
"useEventListener",
4545
"useEvents",
4646
"useEventDispatcher",
47-
"useDebounce",
48-
"useThrottle"
4947
],
5048
//API DOM
5149
[
5250
"usePublishSubscribe",
53-
"useScript"
51+
"useScript",
52+
"useDebounce",
53+
"useThrottle",
54+
"useActiveElement"
5455
]
5556
],
5657
//UTILS

apps/react-tools-demo/src/markdown/isAsync.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ It detects if a function is asynchronous.
44
## API
55

66
```tsx
7-
isAsync <T extends unknown[], E = unknown>(fn: (...args: T)=> E | Promise<E>): boolean
7+
isAsync <T extends unknown[], E = unknown>(fn: E | Promise<E> | ((...args: T)=> E | Promise<E>)): boolean
88
```
99
1010
> ### Params
1111
>
12-
> - ____: _(...args: unknown[])=> Eìunknown | Promise<unknown>_
12+
> - ____: _(...args: unknown[])=> unknown | Promise<unknown>_
1313
>
1414
1515
> ### Returns
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# useActiveElement
2+
Hook that returns activeElement and listen its changes.
3+
4+
## Usage
5+
6+
```tsx
7+
export const UseActiveElement = () => {
8+
const activeElement = useActiveElement();
9+
10+
return (<>
11+
<p>Active element is: {activeElement?.tagName}</p>
12+
<div style={{ display: "grid", gridTemplateColumns: "auto auto auto", justifyContent: "center", gap: 50 }}>
13+
<span tabIndex={0}>Span</span>
14+
<p tabIndex={0}>P</p>
15+
<button>Button</button>
16+
</div>
17+
</>)
18+
}
19+
```
20+
21+
> DEMO
22+
23+
24+
## API
25+
26+
```tsx
27+
useActiveElement ():Element|null
28+
```
29+
30+
> ### Params
31+
>
32+
>
33+
>
34+
35+
> ### Returns
36+
>
37+
> __activeELement__
38+
> - __Union of__:
39+
> - _Element_
40+
> - _null_
41+
>

packages/react-tools/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
- [x] useScript
6161
- [x] useDebounce
6262
- [x] useThrottle
63-
- [ ] useActiveElement
63+
- [-] useActiveElement
6464
- [ ] useTimeout
6565
- [ ] useInterval
6666
- [ ] useTextSelection

packages/react-tools/src/hooks/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ export { useScript } from './useScript';
3131
export { useSyncExternalStore } from './useSyncExternalStore';
3232
export { useIsMounted } from './useIsMounted';
3333
export { useDebounce } from './useDebounce';
34-
export { useThrottle } from './useThrottle';
34+
export { useThrottle } from './useThrottle';
35+
export { useActiveElement } from './useActiveElement';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useCallback, useRef } from "react";
2+
import { useSyncExternalStore } from ".";
3+
4+
/**
5+
* **`useActiveElement`**: Hook that returns activeElement and listen its changes.
6+
* @returns {Element | null} activeELement
7+
*/
8+
export const useActiveElement = ():Element|null => {
9+
const previousElem = useRef<Element | null>(null);
10+
11+
return useSyncExternalStore(
12+
useCallback(notif => {
13+
previousElem.current = document.activeElement;
14+
const listener = () => notif();
15+
addEventListener("focusin", listener, true);
16+
addEventListener("focusout", listener, true);
17+
18+
return () => {
19+
addEventListener("focusin", listener, true);
20+
addEventListener("focusout", listener, true);
21+
previousElem.current = null;
22+
}
23+
}, []),
24+
useCallback(() => {
25+
const elem = document.activeElement;
26+
previousElem.current !== elem && (previousElem.current = elem);
27+
return previousElem.current;
28+
}, [])
29+
)
30+
}

packages/react-tools/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export {
4040
useSyncExternalStore,
4141
useIsMounted,
4242
useDebounce,
43-
useThrottle
43+
useThrottle,
44+
useActiveElement
4445
} from './hooks'
4546

4647
export {

0 commit comments

Comments
 (0)