@aweebit/react-essentials 0.7.0 → 0.8.0
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.
- package/README.md +358 -187
- package/dist/hooks/useEventListener.d.ts +59 -40
- package/dist/hooks/useEventListener.d.ts.map +1 -1
- package/dist/hooks/useEventListener.js +23 -19
- package/dist/hooks/useEventListener.js.map +1 -1
- package/dist/hooks/useReducerWithDeps.d.ts.map +1 -1
- package/dist/hooks/useReducerWithDeps.js +3 -3
- package/dist/hooks/useReducerWithDeps.js.map +1 -1
- package/dist/hooks/useStateWithDeps.d.ts.map +1 -1
- package/dist/hooks/useStateWithDeps.js +3 -3
- package/dist/hooks/useStateWithDeps.js.map +1 -1
- package/dist/misc/createSafeContext.d.ts +8 -2
- package/dist/misc/createSafeContext.d.ts.map +1 -1
- package/dist/misc/createSafeContext.js +3 -0
- package/dist/misc/createSafeContext.js.map +1 -1
- package/package.json +1 -1
- package/src/hooks/useEventListener.ts +102 -120
- package/src/hooks/useReducerWithDeps.ts +3 -3
- package/src/hooks/useStateWithDeps.ts +2 -3
- package/src/misc/createSafeContext.ts +8 -2
package/README.md
CHANGED
|
@@ -2,19 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@aweebit/react-essentials)
|
|
4
4
|
|
|
5
|
+
### Requirements
|
|
6
|
+
|
|
7
|
+
- React ≥ 18
|
|
8
|
+
- TypeScript ≥ 5.4
|
|
9
|
+
|
|
10
|
+
### Functions
|
|
11
|
+
|
|
5
12
|
- [useEventListener()](#useeventlistener)
|
|
6
13
|
- [useForceUpdate()](#useforceupdate)
|
|
7
14
|
- [useReducerWithDeps()](#usereducerwithdeps)
|
|
8
15
|
- [useStateWithDeps()](#usestatewithdeps)
|
|
9
16
|
- [createSafeContext()](#createsafecontext)
|
|
17
|
+
|
|
18
|
+
### Types
|
|
19
|
+
|
|
20
|
+
- [UseEventListener](#useeventlistener-1)
|
|
21
|
+
- [UseEventListenerWithImplicitWindowTarget](#useeventlistenerwithimplicitwindowtarget)
|
|
22
|
+
- [UseEventListenerWithExplicitTarget](#useeventlistenerwithexplicittarget)
|
|
23
|
+
- [UseEventListenerWithAnyExplicitTarget](#useeventlistenerwithanyexplicittarget)
|
|
24
|
+
- [UseEventListenerWithImplicitWindowTargetArgs](#useeventlistenerwithimplicitwindowtargetargs)
|
|
25
|
+
- [UseEventListenerWithExplicitTargetArgs](#useeventlistenerwithexplicittargetargs)
|
|
10
26
|
- [RestrictedContext](#restrictedcontext)
|
|
11
27
|
- [SafeContext](#safecontext)
|
|
12
28
|
|
|
13
|
-
## useEventListener
|
|
29
|
+
## useEventListener
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const useEventListener: UseEventListener;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Defined in: [hooks/useEventListener.ts:133](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L133)
|
|
14
36
|
|
|
15
37
|
Adds `handler` as a listener for the event `eventName` of `target` with the
|
|
16
38
|
provided `options` applied
|
|
17
39
|
|
|
40
|
+
The following call signatures are available:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
function useEventListener(eventName, handler, options?): void;
|
|
44
|
+
function useEventListener(target, eventName, handler, options?): void;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For the full definition of the hook's type, see [`UseEventListener`](#useeventlistener).
|
|
48
|
+
|
|
18
49
|
If `target` is not provided, `window` is used instead.
|
|
19
50
|
|
|
20
51
|
If `target` is `null`, no event listener is added. This is useful when
|
|
@@ -33,188 +64,12 @@ useEventListener(document, 'visibilitychange', () => {
|
|
|
33
64
|
});
|
|
34
65
|
|
|
35
66
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
36
|
-
useEventListener(buttonRef
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Call Signature
|
|
40
|
-
|
|
41
|
-
```ts
|
|
42
|
-
function useEventListener<K>(eventName, handler, options?): void;
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Defined in: [hooks/useEventListener.ts:99](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/hooks/useEventListener.ts#L99)
|
|
46
|
-
|
|
47
|
-
#### Type Parameters
|
|
48
|
-
|
|
49
|
-
<table>
|
|
50
|
-
<thead>
|
|
51
|
-
<tr>
|
|
52
|
-
<th>Type Parameter</th>
|
|
53
|
-
</tr>
|
|
54
|
-
</thead>
|
|
55
|
-
<tbody>
|
|
56
|
-
<tr>
|
|
57
|
-
<td>
|
|
58
|
-
|
|
59
|
-
`K` _extends_ keyof `WindowEventMap`
|
|
60
|
-
|
|
61
|
-
</td>
|
|
62
|
-
</tr>
|
|
63
|
-
</tbody>
|
|
64
|
-
</table>
|
|
65
|
-
|
|
66
|
-
#### Parameters
|
|
67
|
-
|
|
68
|
-
<table>
|
|
69
|
-
<thead>
|
|
70
|
-
<tr>
|
|
71
|
-
<th>Parameter</th>
|
|
72
|
-
<th>Type</th>
|
|
73
|
-
</tr>
|
|
74
|
-
</thead>
|
|
75
|
-
<tbody>
|
|
76
|
-
<tr>
|
|
77
|
-
<td>
|
|
78
|
-
|
|
79
|
-
`eventName`
|
|
80
|
-
|
|
81
|
-
</td>
|
|
82
|
-
<td>
|
|
83
|
-
|
|
84
|
-
`K`
|
|
85
|
-
|
|
86
|
-
</td>
|
|
87
|
-
</tr>
|
|
88
|
-
<tr>
|
|
89
|
-
<td>
|
|
90
|
-
|
|
91
|
-
`handler`
|
|
92
|
-
|
|
93
|
-
</td>
|
|
94
|
-
<td>
|
|
95
|
-
|
|
96
|
-
(`this`, `event`) => `void`
|
|
97
|
-
|
|
98
|
-
</td>
|
|
99
|
-
</tr>
|
|
100
|
-
<tr>
|
|
101
|
-
<td>
|
|
102
|
-
|
|
103
|
-
`options?`
|
|
104
|
-
|
|
105
|
-
</td>
|
|
106
|
-
<td>
|
|
107
|
-
|
|
108
|
-
`boolean` \| `AddEventListenerOptions`
|
|
109
|
-
|
|
110
|
-
</td>
|
|
111
|
-
</tr>
|
|
112
|
-
</tbody>
|
|
113
|
-
</table>
|
|
114
|
-
|
|
115
|
-
#### Returns
|
|
116
|
-
|
|
117
|
-
`void`
|
|
118
|
-
|
|
119
|
-
#### See
|
|
120
|
-
|
|
121
|
-
[`useEventListener`](#useeventlistener)
|
|
122
|
-
|
|
123
|
-
### Call Signature
|
|
124
|
-
|
|
125
|
-
```ts
|
|
126
|
-
function useEventListener<T>(target, eventName, handler, options?): void;
|
|
67
|
+
useEventListener(buttonRef, 'click', () => console.log('click'));
|
|
127
68
|
```
|
|
128
69
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
#### Type Parameters
|
|
132
|
-
|
|
133
|
-
<table>
|
|
134
|
-
<thead>
|
|
135
|
-
<tr>
|
|
136
|
-
<th>Type Parameter</th>
|
|
137
|
-
</tr>
|
|
138
|
-
</thead>
|
|
139
|
-
<tbody>
|
|
140
|
-
<tr>
|
|
141
|
-
<td>
|
|
142
|
-
|
|
143
|
-
`T` _extends_ `EventTarget`
|
|
144
|
-
|
|
145
|
-
</td>
|
|
146
|
-
</tr>
|
|
147
|
-
</tbody>
|
|
148
|
-
</table>
|
|
149
|
-
|
|
150
|
-
#### Parameters
|
|
151
|
-
|
|
152
|
-
<table>
|
|
153
|
-
<thead>
|
|
154
|
-
<tr>
|
|
155
|
-
<th>Parameter</th>
|
|
156
|
-
<th>Type</th>
|
|
157
|
-
</tr>
|
|
158
|
-
</thead>
|
|
159
|
-
<tbody>
|
|
160
|
-
<tr>
|
|
161
|
-
<td>
|
|
162
|
-
|
|
163
|
-
`target`
|
|
164
|
-
|
|
165
|
-
</td>
|
|
166
|
-
<td>
|
|
167
|
-
|
|
168
|
-
`null` \| `T`
|
|
169
|
-
|
|
170
|
-
</td>
|
|
171
|
-
</tr>
|
|
172
|
-
<tr>
|
|
173
|
-
<td>
|
|
174
|
-
|
|
175
|
-
`eventName`
|
|
176
|
-
|
|
177
|
-
</td>
|
|
178
|
-
<td>
|
|
179
|
-
|
|
180
|
-
`string`
|
|
181
|
-
|
|
182
|
-
</td>
|
|
183
|
-
</tr>
|
|
184
|
-
<tr>
|
|
185
|
-
<td>
|
|
186
|
-
|
|
187
|
-
`handler`
|
|
188
|
-
|
|
189
|
-
</td>
|
|
190
|
-
<td>
|
|
191
|
-
|
|
192
|
-
(`this`, `event`) => `void`
|
|
193
|
-
|
|
194
|
-
</td>
|
|
195
|
-
</tr>
|
|
196
|
-
<tr>
|
|
197
|
-
<td>
|
|
198
|
-
|
|
199
|
-
`options?`
|
|
200
|
-
|
|
201
|
-
</td>
|
|
202
|
-
<td>
|
|
203
|
-
|
|
204
|
-
`boolean` \| `AddEventListenerOptions`
|
|
205
|
-
|
|
206
|
-
</td>
|
|
207
|
-
</tr>
|
|
208
|
-
</tbody>
|
|
209
|
-
</table>
|
|
210
|
-
|
|
211
|
-
#### Returns
|
|
212
|
-
|
|
213
|
-
`void`
|
|
214
|
-
|
|
215
|
-
#### See
|
|
70
|
+
### See
|
|
216
71
|
|
|
217
|
-
[`
|
|
72
|
+
[`UseEventListener`](#useeventlistener)
|
|
218
73
|
|
|
219
74
|
---
|
|
220
75
|
|
|
@@ -224,7 +79,7 @@ Defined in: [hooks/useEventListener.ts:108](https://github.com/aweebit/react-ess
|
|
|
224
79
|
function useForceUpdate(callback?): [() => void, bigint];
|
|
225
80
|
```
|
|
226
81
|
|
|
227
|
-
Defined in: [hooks/useForceUpdate.ts:81](https://github.com/aweebit/react-essentials/blob/v0.
|
|
82
|
+
Defined in: [hooks/useForceUpdate.ts:81](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useForceUpdate.ts#L81)
|
|
228
83
|
|
|
229
84
|
Enables you to imperatively trigger re-rendering of components
|
|
230
85
|
|
|
@@ -344,7 +199,7 @@ function useReducerWithDeps<S, A>(
|
|
|
344
199
|
): [S, ActionDispatch<A>];
|
|
345
200
|
```
|
|
346
201
|
|
|
347
|
-
Defined in: [hooks/useReducerWithDeps.ts:52](https://github.com/aweebit/react-essentials/blob/v0.
|
|
202
|
+
Defined in: [hooks/useReducerWithDeps.ts:52](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useReducerWithDeps.ts#L52)
|
|
348
203
|
|
|
349
204
|
`useReducer` hook with an additional dependency array `deps` that resets the
|
|
350
205
|
state to `initialState` when dependencies change
|
|
@@ -480,7 +335,7 @@ function useStateWithDeps<S>(
|
|
|
480
335
|
): [S, Dispatch<SetStateAction<S>>];
|
|
481
336
|
```
|
|
482
337
|
|
|
483
|
-
Defined in: [hooks/useStateWithDeps.ts:
|
|
338
|
+
Defined in: [hooks/useStateWithDeps.ts:65](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useStateWithDeps.ts#L65)
|
|
484
339
|
|
|
485
340
|
`useState` hook with an additional dependency array `deps` that resets the
|
|
486
341
|
state to `initialState` when dependencies change
|
|
@@ -607,7 +462,7 @@ function createSafeContext<T>(): <DisplayName>(
|
|
|
607
462
|
) => SafeContext<DisplayName, T>;
|
|
608
463
|
```
|
|
609
464
|
|
|
610
|
-
Defined in: [misc/createSafeContext.ts:
|
|
465
|
+
Defined in: [misc/createSafeContext.ts:95](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/misc/createSafeContext.ts#L95)
|
|
611
466
|
|
|
612
467
|
For a given type `T`, returns a function that produces both a context of that
|
|
613
468
|
type and a hook that returns the current context value if one was provided,
|
|
@@ -744,6 +599,321 @@ A function that accepts a single string argument `displayName` (e.g.
|
|
|
744
599
|
|
|
745
600
|
[`SafeContext`](#safecontext)\<`DisplayName`, `T`\>
|
|
746
601
|
|
|
602
|
+
### See
|
|
603
|
+
|
|
604
|
+
[`SafeContext`](#safecontext)
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## UseEventListener
|
|
609
|
+
|
|
610
|
+
```ts
|
|
611
|
+
type UseEventListener = UseEventListenerWithImplicitWindowTarget &
|
|
612
|
+
UseEventListenerWithExplicitTarget<Window, WindowEventMap> &
|
|
613
|
+
UseEventListenerWithExplicitTarget<Document, DocumentEventMap> &
|
|
614
|
+
UseEventListenerWithExplicitTarget<HTMLElement, HTMLElementEventMap> &
|
|
615
|
+
UseEventListenerWithExplicitTarget<SVGElement, SVGElementEventMap> &
|
|
616
|
+
UseEventListenerWithExplicitTarget<MathMLElement, MathMLElementEventMap> &
|
|
617
|
+
UseEventListenerWithAnyExplicitTarget;
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
Defined in: [hooks/useEventListener.ts:19](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L19)
|
|
621
|
+
|
|
622
|
+
The type of [`useEventListener`](#useeventlistener-1)
|
|
623
|
+
|
|
624
|
+
### See
|
|
625
|
+
|
|
626
|
+
[`useEventListener`](#useeventlistener-1),
|
|
627
|
+
[`UseEventListenerWithImplicitWindowTarget`](#useeventlistenerwithimplicitwindowtarget),
|
|
628
|
+
[`UseEventListenerWithExplicitTarget`](#useeventlistenerwithexplicittarget),
|
|
629
|
+
[`UseEventListenerWithAnyExplicitTarget`](#useeventlistenerwithanyexplicittarget)
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## UseEventListenerWithImplicitWindowTarget()
|
|
634
|
+
|
|
635
|
+
```ts
|
|
636
|
+
type UseEventListenerWithImplicitWindowTarget = <K>(...args) => void;
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Defined in: [hooks/useEventListener.ts:31](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L31)
|
|
640
|
+
|
|
641
|
+
### Type Parameters
|
|
642
|
+
|
|
643
|
+
<table>
|
|
644
|
+
<thead>
|
|
645
|
+
<tr>
|
|
646
|
+
<th>Type Parameter</th>
|
|
647
|
+
</tr>
|
|
648
|
+
</thead>
|
|
649
|
+
<tbody>
|
|
650
|
+
<tr>
|
|
651
|
+
<td>
|
|
652
|
+
|
|
653
|
+
`K` _extends_ keyof `WindowEventMap`
|
|
654
|
+
|
|
655
|
+
</td>
|
|
656
|
+
</tr>
|
|
657
|
+
</tbody>
|
|
658
|
+
</table>
|
|
659
|
+
|
|
660
|
+
### Parameters
|
|
661
|
+
|
|
662
|
+
<table>
|
|
663
|
+
<thead>
|
|
664
|
+
<tr>
|
|
665
|
+
<th>Parameter</th>
|
|
666
|
+
<th>Type</th>
|
|
667
|
+
</tr>
|
|
668
|
+
</thead>
|
|
669
|
+
<tbody>
|
|
670
|
+
<tr>
|
|
671
|
+
<td>
|
|
672
|
+
|
|
673
|
+
...`args`
|
|
674
|
+
|
|
675
|
+
</td>
|
|
676
|
+
<td>
|
|
677
|
+
|
|
678
|
+
[`UseEventListenerWithImplicitWindowTargetArgs`](#useeventlistenerwithimplicitwindowtargetargs)\<`K`\>
|
|
679
|
+
|
|
680
|
+
</td>
|
|
681
|
+
</tr>
|
|
682
|
+
</tbody>
|
|
683
|
+
</table>
|
|
684
|
+
|
|
685
|
+
### Returns
|
|
686
|
+
|
|
687
|
+
`void`
|
|
688
|
+
|
|
689
|
+
### See
|
|
690
|
+
|
|
691
|
+
[`useEventListener`](#useeventlistener-1),
|
|
692
|
+
[`UseEventListenerWithImplicitWindowTargetArgs`](#useeventlistenerwithimplicitwindowtargetargs)
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## UseEventListenerWithExplicitTarget()
|
|
697
|
+
|
|
698
|
+
```ts
|
|
699
|
+
type UseEventListenerWithExplicitTarget<Target, EventMap> = <T, K>(
|
|
700
|
+
...args
|
|
701
|
+
) => void;
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
Defined in: [hooks/useEventListener.ts:42](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L42)
|
|
705
|
+
|
|
706
|
+
### Type Parameters
|
|
707
|
+
|
|
708
|
+
<table>
|
|
709
|
+
<thead>
|
|
710
|
+
<tr>
|
|
711
|
+
<th>Type Parameter</th>
|
|
712
|
+
<th>Default type</th>
|
|
713
|
+
</tr>
|
|
714
|
+
</thead>
|
|
715
|
+
<tbody>
|
|
716
|
+
<tr>
|
|
717
|
+
<td>
|
|
718
|
+
|
|
719
|
+
`Target` _extends_ `EventTarget`
|
|
720
|
+
|
|
721
|
+
</td>
|
|
722
|
+
<td>
|
|
723
|
+
|
|
724
|
+
‐
|
|
725
|
+
|
|
726
|
+
</td>
|
|
727
|
+
</tr>
|
|
728
|
+
<tr>
|
|
729
|
+
<td>
|
|
730
|
+
|
|
731
|
+
`EventMap`
|
|
732
|
+
|
|
733
|
+
</td>
|
|
734
|
+
<td>
|
|
735
|
+
|
|
736
|
+
`Record`\<`string`, `Event`\>
|
|
737
|
+
|
|
738
|
+
</td>
|
|
739
|
+
</tr>
|
|
740
|
+
</tbody>
|
|
741
|
+
</table>
|
|
742
|
+
|
|
743
|
+
### Type Parameters
|
|
744
|
+
|
|
745
|
+
<table>
|
|
746
|
+
<thead>
|
|
747
|
+
<tr>
|
|
748
|
+
<th>Type Parameter</th>
|
|
749
|
+
</tr>
|
|
750
|
+
</thead>
|
|
751
|
+
<tbody>
|
|
752
|
+
<tr>
|
|
753
|
+
<td>
|
|
754
|
+
|
|
755
|
+
`T` _extends_ `Target`
|
|
756
|
+
|
|
757
|
+
</td>
|
|
758
|
+
</tr>
|
|
759
|
+
<tr>
|
|
760
|
+
<td>
|
|
761
|
+
|
|
762
|
+
`K` _extends_ keyof `EventMap`
|
|
763
|
+
|
|
764
|
+
</td>
|
|
765
|
+
</tr>
|
|
766
|
+
</tbody>
|
|
767
|
+
</table>
|
|
768
|
+
|
|
769
|
+
### Parameters
|
|
770
|
+
|
|
771
|
+
<table>
|
|
772
|
+
<thead>
|
|
773
|
+
<tr>
|
|
774
|
+
<th>Parameter</th>
|
|
775
|
+
<th>Type</th>
|
|
776
|
+
</tr>
|
|
777
|
+
</thead>
|
|
778
|
+
<tbody>
|
|
779
|
+
<tr>
|
|
780
|
+
<td>
|
|
781
|
+
|
|
782
|
+
...`args`
|
|
783
|
+
|
|
784
|
+
</td>
|
|
785
|
+
<td>
|
|
786
|
+
|
|
787
|
+
[`UseEventListenerWithExplicitTargetArgs`](#useeventlistenerwithexplicittargetargs)\<`EventMap`, `T`, `K`\>
|
|
788
|
+
|
|
789
|
+
</td>
|
|
790
|
+
</tr>
|
|
791
|
+
</tbody>
|
|
792
|
+
</table>
|
|
793
|
+
|
|
794
|
+
### Returns
|
|
795
|
+
|
|
796
|
+
`void`
|
|
797
|
+
|
|
798
|
+
### See
|
|
799
|
+
|
|
800
|
+
[`useEventListener`](#useeventlistener-1),
|
|
801
|
+
[`UseEventListenerWithExplicitTargetArgs`](#useeventlistenerwithexplicittargetargs)
|
|
802
|
+
|
|
803
|
+
---
|
|
804
|
+
|
|
805
|
+
## UseEventListenerWithAnyExplicitTarget
|
|
806
|
+
|
|
807
|
+
```ts
|
|
808
|
+
type UseEventListenerWithAnyExplicitTarget =
|
|
809
|
+
UseEventListenerWithExplicitTarget<EventTarget>;
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
Defined in: [hooks/useEventListener.ts:54](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L54)
|
|
813
|
+
|
|
814
|
+
### See
|
|
815
|
+
|
|
816
|
+
[`useEventListener`](#useeventlistener-1),
|
|
817
|
+
[`UseEventListenerWithExplicitTarget`](#useeventlistenerwithexplicittarget)
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## UseEventListenerWithImplicitWindowTargetArgs
|
|
822
|
+
|
|
823
|
+
```ts
|
|
824
|
+
type UseEventListenerWithImplicitWindowTargetArgs<K> =
|
|
825
|
+
UseEventListenerWithExplicitTargetArgs<WindowEventMap, Window, K> extends [
|
|
826
|
+
unknown,
|
|
827
|
+
...infer Args,
|
|
828
|
+
]
|
|
829
|
+
? Args
|
|
830
|
+
: never;
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
Defined in: [hooks/useEventListener.ts:62](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L62)
|
|
834
|
+
|
|
835
|
+
### Type Parameters
|
|
836
|
+
|
|
837
|
+
<table>
|
|
838
|
+
<thead>
|
|
839
|
+
<tr>
|
|
840
|
+
<th>Type Parameter</th>
|
|
841
|
+
</tr>
|
|
842
|
+
</thead>
|
|
843
|
+
<tbody>
|
|
844
|
+
<tr>
|
|
845
|
+
<td>
|
|
846
|
+
|
|
847
|
+
`K` _extends_ keyof `WindowEventMap`
|
|
848
|
+
|
|
849
|
+
</td>
|
|
850
|
+
</tr>
|
|
851
|
+
</tbody>
|
|
852
|
+
</table>
|
|
853
|
+
|
|
854
|
+
### See
|
|
855
|
+
|
|
856
|
+
[`useEventListener`](#useeventlistener-1),
|
|
857
|
+
[`UseEventListenerWithExplicitTargetArgs`](#useeventlistenerwithexplicittargetargs)
|
|
858
|
+
|
|
859
|
+
---
|
|
860
|
+
|
|
861
|
+
## UseEventListenerWithExplicitTargetArgs
|
|
862
|
+
|
|
863
|
+
```ts
|
|
864
|
+
type UseEventListenerWithExplicitTargetArgs<EventMap, T, K> = [
|
|
865
|
+
(
|
|
866
|
+
| T
|
|
867
|
+
| (RefObject<T> & {
|
|
868
|
+
addEventListener?: never;
|
|
869
|
+
})
|
|
870
|
+
| null
|
|
871
|
+
),
|
|
872
|
+
K,
|
|
873
|
+
(this, event) => void,
|
|
874
|
+
AddEventListenerOptions | boolean | undefined,
|
|
875
|
+
];
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
Defined in: [hooks/useEventListener.ts:76](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/hooks/useEventListener.ts#L76)
|
|
879
|
+
|
|
880
|
+
### Type Parameters
|
|
881
|
+
|
|
882
|
+
<table>
|
|
883
|
+
<thead>
|
|
884
|
+
<tr>
|
|
885
|
+
<th>Type Parameter</th>
|
|
886
|
+
</tr>
|
|
887
|
+
</thead>
|
|
888
|
+
<tbody>
|
|
889
|
+
<tr>
|
|
890
|
+
<td>
|
|
891
|
+
|
|
892
|
+
`EventMap`
|
|
893
|
+
|
|
894
|
+
</td>
|
|
895
|
+
</tr>
|
|
896
|
+
<tr>
|
|
897
|
+
<td>
|
|
898
|
+
|
|
899
|
+
`T` _extends_ `EventTarget`
|
|
900
|
+
|
|
901
|
+
</td>
|
|
902
|
+
</tr>
|
|
903
|
+
<tr>
|
|
904
|
+
<td>
|
|
905
|
+
|
|
906
|
+
`K` _extends_ keyof `EventMap`
|
|
907
|
+
|
|
908
|
+
</td>
|
|
909
|
+
</tr>
|
|
910
|
+
</tbody>
|
|
911
|
+
</table>
|
|
912
|
+
|
|
913
|
+
### See
|
|
914
|
+
|
|
915
|
+
[`useEventListener`](#useeventlistener-1)
|
|
916
|
+
|
|
747
917
|
---
|
|
748
918
|
|
|
749
919
|
## RestrictedContext
|
|
@@ -761,7 +931,7 @@ type RestrictedContext<T> =
|
|
|
761
931
|
};
|
|
762
932
|
```
|
|
763
933
|
|
|
764
|
-
Defined in: [misc/createSafeContext.ts:
|
|
934
|
+
Defined in: [misc/createSafeContext.ts:18](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/misc/createSafeContext.ts#L18)
|
|
765
935
|
|
|
766
936
|
A React context with a required `displayName` and the obsolete `Consumer`
|
|
767
937
|
property purposefully omitted so that it is impossible to pass the context
|
|
@@ -801,7 +971,7 @@ type SafeContext<DisplayName, T> = {
|
|
|
801
971
|
} & { [K in `use${DisplayName}`]: () => T };
|
|
802
972
|
```
|
|
803
973
|
|
|
804
|
-
Defined in: [misc/createSafeContext.ts:
|
|
974
|
+
Defined in: [misc/createSafeContext.ts:30](https://github.com/aweebit/react-essentials/blob/v0.8.0/src/misc/createSafeContext.ts#L30)
|
|
805
975
|
|
|
806
976
|
The return type of [`createSafeContext`](#createsafecontext)
|
|
807
977
|
|
|
@@ -833,4 +1003,5 @@ The return type of [`createSafeContext`](#createsafecontext)
|
|
|
833
1003
|
|
|
834
1004
|
### See
|
|
835
1005
|
|
|
836
|
-
[`createSafeContext`](#createsafecontext)
|
|
1006
|
+
[`createSafeContext`](#createsafecontext),
|
|
1007
|
+
[`RestrictedContext`](#restrictedcontext)
|
|
@@ -4,16 +4,68 @@
|
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2020 Julien CARON
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { type RefObject } from 'react';
|
|
8
|
+
/**
|
|
9
|
+
* The type of {@linkcode useEventListener}
|
|
10
|
+
*
|
|
11
|
+
* @see
|
|
12
|
+
* {@linkcode useEventListener},
|
|
13
|
+
* {@linkcode UseEventListenerWithImplicitWindowTarget},
|
|
14
|
+
* {@linkcode UseEventListenerWithExplicitTarget},
|
|
15
|
+
* {@linkcode UseEventListenerWithAnyExplicitTarget}
|
|
16
|
+
*/
|
|
17
|
+
export type UseEventListener = UseEventListenerWithImplicitWindowTarget & UseEventListenerWithExplicitTarget<Window, WindowEventMap> & UseEventListenerWithExplicitTarget<Document, DocumentEventMap> & UseEventListenerWithExplicitTarget<HTMLElement, HTMLElementEventMap> & UseEventListenerWithExplicitTarget<SVGElement, SVGElementEventMap> & UseEventListenerWithExplicitTarget<MathMLElement, MathMLElementEventMap> & UseEventListenerWithAnyExplicitTarget;
|
|
18
|
+
/**
|
|
19
|
+
* @see
|
|
20
|
+
* {@linkcode useEventListener},
|
|
21
|
+
* {@linkcode UseEventListenerWithImplicitWindowTargetArgs} */
|
|
22
|
+
export type UseEventListenerWithImplicitWindowTarget = <K extends keyof WindowEventMap>(...args: UseEventListenerWithImplicitWindowTargetArgs<K>) => void;
|
|
23
|
+
/**
|
|
24
|
+
* @see
|
|
25
|
+
* {@linkcode useEventListener},
|
|
26
|
+
* {@linkcode UseEventListenerWithExplicitTargetArgs}
|
|
27
|
+
*/
|
|
28
|
+
export type UseEventListenerWithExplicitTarget<Target extends EventTarget, EventMap = Record<string, Event>> = <T extends Target, K extends keyof EventMap>(...args: UseEventListenerWithExplicitTargetArgs<EventMap, T, K>) => void;
|
|
29
|
+
/**
|
|
30
|
+
* @see
|
|
31
|
+
* {@linkcode useEventListener},
|
|
32
|
+
* {@linkcode UseEventListenerWithExplicitTarget}
|
|
33
|
+
*/
|
|
34
|
+
export type UseEventListenerWithAnyExplicitTarget = UseEventListenerWithExplicitTarget<EventTarget>;
|
|
35
|
+
/**
|
|
36
|
+
* @see
|
|
37
|
+
* {@linkcode useEventListener},
|
|
38
|
+
* {@linkcode UseEventListenerWithExplicitTargetArgs}
|
|
39
|
+
*/
|
|
40
|
+
export type UseEventListenerWithImplicitWindowTargetArgs<K extends keyof WindowEventMap> = UseEventListenerWithExplicitTargetArgs<WindowEventMap, Window, K> extends [
|
|
41
|
+
unknown,
|
|
42
|
+
...infer Args
|
|
43
|
+
] ? Args : never;
|
|
44
|
+
/**
|
|
45
|
+
* @see
|
|
46
|
+
* {@linkcode useEventListener}
|
|
47
|
+
*/
|
|
48
|
+
export type UseEventListenerWithExplicitTargetArgs<EventMap, T extends EventTarget, K extends keyof EventMap> = [
|
|
49
|
+
target: T | (RefObject<T> & {
|
|
50
|
+
addEventListener?: never;
|
|
51
|
+
}) | null,
|
|
9
52
|
eventName: K,
|
|
10
53
|
handler: (this: NoInfer<T>, event: EventMap[K]) => void,
|
|
11
|
-
options?: AddEventListenerOptions | boolean
|
|
54
|
+
options?: AddEventListenerOptions | boolean | undefined
|
|
12
55
|
];
|
|
13
56
|
/**
|
|
14
57
|
* Adds `handler` as a listener for the event `eventName` of `target` with the
|
|
15
58
|
* provided `options` applied
|
|
16
59
|
*
|
|
60
|
+
* The following call signatures are available:
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* function useEventListener(eventName, handler, options?): void;
|
|
64
|
+
* function useEventListener(target, eventName, handler, options?): void;
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* For the full definition of the hook's type, see {@linkcode UseEventListener}.
|
|
68
|
+
*
|
|
17
69
|
* If `target` is not provided, `window` is used instead.
|
|
18
70
|
*
|
|
19
71
|
* If `target` is `null`, no event listener is added. This is useful when
|
|
@@ -31,44 +83,11 @@ type UseEventListenerOverloadArgs<EventMap, K extends keyof EventMap, T extends
|
|
|
31
83
|
* });
|
|
32
84
|
*
|
|
33
85
|
* const buttonRef = useRef<HTMLButtonElement>(null);
|
|
34
|
-
* useEventListener(buttonRef
|
|
86
|
+
* useEventListener(buttonRef, 'click', () => console.log('click'));
|
|
35
87
|
* ```
|
|
36
88
|
*
|
|
37
|
-
* @
|
|
38
|
-
|
|
39
|
-
export declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (this: Window, event: WindowEventMap[K]) => void, options?: AddEventListenerOptions | boolean): void;
|
|
40
|
-
/**
|
|
41
|
-
* @see {@linkcode useEventListener}
|
|
42
|
-
* @ignore
|
|
43
|
-
*/
|
|
44
|
-
export declare function useEventListener<K extends keyof WindowEventMap>(...args: UseEventListenerOverloadArgs<WindowEventMap, K, Window>): void;
|
|
45
|
-
/**
|
|
46
|
-
* @see {@linkcode useEventListener}
|
|
47
|
-
* @ignore
|
|
48
|
-
*/
|
|
49
|
-
export declare function useEventListener<K extends keyof DocumentEventMap>(...args: UseEventListenerOverloadArgs<DocumentEventMap, K, Document>): void;
|
|
50
|
-
/**
|
|
51
|
-
* @see {@linkcode useEventListener}
|
|
52
|
-
* @ignore
|
|
53
|
-
*/
|
|
54
|
-
export declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement>(...args: UseEventListenerOverloadArgs<HTMLElementEventMap, K, T>): void;
|
|
55
|
-
/**
|
|
56
|
-
* @see {@linkcode useEventListener}
|
|
57
|
-
* @ignore
|
|
58
|
-
*/
|
|
59
|
-
export declare function useEventListener<K extends keyof SVGElementEventMap, T extends SVGElement>(...args: UseEventListenerOverloadArgs<SVGElementEventMap, K, T>): void;
|
|
60
|
-
/**
|
|
61
|
-
* @see {@linkcode useEventListener}
|
|
62
|
-
* @ignore
|
|
63
|
-
*/
|
|
64
|
-
export declare function useEventListener<K extends keyof MathMLElementEventMap, T extends MathMLElement>(...args: UseEventListenerOverloadArgs<MathMLElementEventMap, K, T>): void;
|
|
65
|
-
/**
|
|
66
|
-
* @see {@linkcode useEventListener}
|
|
67
|
-
*/
|
|
68
|
-
export declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (this: Window, event: WindowEventMap[K]) => void, options?: AddEventListenerOptions | boolean): void;
|
|
69
|
-
/**
|
|
70
|
-
* @see {@linkcode useEventListener}
|
|
89
|
+
* @see
|
|
90
|
+
* {@linkcode UseEventListener}
|
|
71
91
|
*/
|
|
72
|
-
export declare
|
|
73
|
-
export {};
|
|
92
|
+
export declare const useEventListener: UseEventListener;
|
|
74
93
|
//# sourceMappingURL=useEventListener.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEventListener.d.ts","sourceRoot":"","sources":["../../src/hooks/useEventListener.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"useEventListener.d.ts","sourceRoot":"","sources":["../../src/hooks/useEventListener.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,wCAAwC,GACrE,kCAAkC,CAAC,MAAM,EAAE,cAAc,CAAC,GAC1D,kCAAkC,CAAC,QAAQ,EAAE,gBAAgB,CAAC,GAC9D,kCAAkC,CAAC,WAAW,EAAE,mBAAmB,CAAC,GACpE,kCAAkC,CAAC,UAAU,EAAE,kBAAkB,CAAC,GAClE,kCAAkC,CAAC,aAAa,EAAE,qBAAqB,CAAC,GACxE,qCAAqC,CAAC;AAExC;;;8DAG8D;AAC9D,MAAM,MAAM,wCAAwC,GAAG,CACrD,CAAC,SAAS,MAAM,cAAc,EAE9B,GAAG,IAAI,EAAE,4CAA4C,CAAC,CAAC,CAAC,KACrD,IAAI,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,kCAAkC,CAC5C,MAAM,SAAS,WAAW,EAC1B,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAC9B,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,QAAQ,EAC7C,GAAG,IAAI,EAAE,sCAAsC,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,KAC5D,IAAI,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,qCAAqC,GAC/C,kCAAkC,CAAC,WAAW,CAAC,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,4CAA4C,CACtD,CAAC,SAAS,MAAM,cAAc,IAE9B,sCAAsC,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS;IACxE,OAAO;IACP,GAAG,MAAM,IAAI;CACd,GACG,IAAI,GACJ,KAAK,CAAC;AAEZ;;;GAGG;AACH,MAAM,MAAM,sCAAsC,CAChD,QAAQ,EACR,CAAC,SAAS,WAAW,EACrB,CAAC,SAAS,MAAM,QAAQ,IACtB;IACF,MAAM,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG;QAAE,gBAAgB,CAAC,EAAE,KAAK,CAAA;KAAE,CAAC,GAAG,IAAI;IAChE,SAAS,EAAE,CAAC;IACZ,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI;IACvD,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,GAAG,SAAS;CACxD,CAAC;AAYF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAkDV,CAAC"}
|
|
@@ -9,6 +9,15 @@ import { useEffect, useMemo, useRef } from 'react';
|
|
|
9
9
|
* Adds `handler` as a listener for the event `eventName` of `target` with the
|
|
10
10
|
* provided `options` applied
|
|
11
11
|
*
|
|
12
|
+
* The following call signatures are available:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* function useEventListener(eventName, handler, options?): void;
|
|
16
|
+
* function useEventListener(target, eventName, handler, options?): void;
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* For the full definition of the hook's type, see {@linkcode UseEventListener}.
|
|
20
|
+
*
|
|
12
21
|
* If `target` is not provided, `window` is used instead.
|
|
13
22
|
*
|
|
14
23
|
* If `target` is `null`, no event listener is added. This is useful when
|
|
@@ -26,21 +35,17 @@ import { useEffect, useMemo, useRef } from 'react';
|
|
|
26
35
|
* });
|
|
27
36
|
*
|
|
28
37
|
* const buttonRef = useRef<HTMLButtonElement>(null);
|
|
29
|
-
* useEventListener(buttonRef
|
|
38
|
+
* useEventListener(buttonRef, 'click', () => console.log('click'));
|
|
30
39
|
* ```
|
|
40
|
+
*
|
|
41
|
+
* @see
|
|
42
|
+
* {@linkcode UseEventListener}
|
|
31
43
|
*/
|
|
32
|
-
export function useEventListener(...args) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (typeof args[0] === 'string') {
|
|
38
|
-
[eventName, handler, options] = args;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
[target, eventName, handler, options] =
|
|
42
|
-
args;
|
|
43
|
-
}
|
|
44
|
+
export const useEventListener = function useEventListener(...args) {
|
|
45
|
+
const [target, eventName, handler, options] = typeof args[0] === 'string'
|
|
46
|
+
? [window, ...args]
|
|
47
|
+
: args;
|
|
48
|
+
const unwrappedTarget = target && !('addEventListener' in target) ? target.current : target;
|
|
44
49
|
const handlerRef = useRef(handler);
|
|
45
50
|
handlerRef.current = handler;
|
|
46
51
|
const { capture = false, once = false, passive, signal, } = typeof options === 'boolean' ? { capture: options } : (options ?? {});
|
|
@@ -48,18 +53,17 @@ export function useEventListener(...args) {
|
|
|
48
53
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
54
|
[capture, once, passive, signal]);
|
|
50
55
|
useEffect(() => {
|
|
51
|
-
if (
|
|
56
|
+
if (unwrappedTarget === null) {
|
|
52
57
|
// No element has been attached to the ref yet
|
|
53
58
|
return;
|
|
54
59
|
}
|
|
55
|
-
const definedTarget = target ?? window;
|
|
56
60
|
const listener = function (event) {
|
|
57
61
|
handlerRef.current.call(this, event);
|
|
58
62
|
};
|
|
59
|
-
|
|
63
|
+
unwrappedTarget.addEventListener(eventName, listener, memoizedOptions);
|
|
60
64
|
return () => {
|
|
61
|
-
|
|
65
|
+
unwrappedTarget.removeEventListener(eventName, listener, memoizedOptions);
|
|
62
66
|
};
|
|
63
|
-
}, [
|
|
64
|
-
}
|
|
67
|
+
}, [unwrappedTarget, eventName, memoizedOptions]);
|
|
68
|
+
};
|
|
65
69
|
//# sourceMappingURL=useEventListener.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEventListener.js","sourceRoot":"","sources":["../../src/hooks/useEventListener.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"useEventListener.js","sourceRoot":"","sources":["../../src/hooks/useEventListener.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAyFnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAqB,SAAS,gBAAgB,CACzE,GAAG,IAE0C;IAE7C,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,GAMzC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;QACzB,CAAC,CAAC,CAAC,MAAM,EAAE,GAAI,IAAwD,CAAC;QACxE,CAAC,CAAE,IAAkD,CAAC;IAE1D,MAAM,eAAe,GACnB,MAAM,IAAI,CAAC,CAAC,kBAAkB,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAEtE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,MAAM,EACJ,OAAO,GAAG,KAAK,EACf,IAAI,GAAG,KAAK,EACZ,OAAO,EACP,MAAM,GACP,GAAG,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAE1E,MAAM,eAAe,GAAG,OAAO,CAC7B,GAAG,EAAE,CAAC,OAAO;IACb,uDAAuD;IACvD,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CACjC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;YAC7B,8CAA8C;YAC9C,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAmB,UAAU,KAAK;YAC9C,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC;QAEF,eAAe,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;QAEvE,OAAO,GAAG,EAAE;YACV,eAAe,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC5E,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,eAAe,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;AACpD,CAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useReducerWithDeps.d.ts","sourceRoot":"","sources":["../../src/hooks/useReducerWithDeps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"useReducerWithDeps.d.ts","sourceRoot":"","sources":["../../src/hooks/useReducerWithDeps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAU,MAAM,OAAO,CAAC;AAOpD,cAAc;AAEd,MAAM,MAAM,YAAY,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAEtC,cAAc;AACd,MAAM,MAAM,cAAc,CAAC,SAAS,SAAS,YAAY,IAAI,CAC3D,GAAG,IAAI,EAAE,SAAS,KACf,IAAI,CAAC;AAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,SAAS,YAAY,EAC1D,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,EACxC,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAC5C,IAAI,EAAE,cAAc,GACnB,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAYxB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useRef } from 'react';
|
|
2
2
|
import { useStateWithDeps } from './useStateWithDeps.js';
|
|
3
3
|
/**
|
|
4
4
|
* `useReducer` hook with an additional dependency array `deps` that resets the
|
|
@@ -40,9 +40,9 @@ export function useReducerWithDeps(reducer, initialState, deps) {
|
|
|
40
40
|
const [state, setState] = useStateWithDeps(initialState, deps);
|
|
41
41
|
// Only the initially provided reducer is used
|
|
42
42
|
const reducerRef = useRef(reducer);
|
|
43
|
-
const dispatch =
|
|
43
|
+
const dispatch = useRef(function dispatch(...args) {
|
|
44
44
|
setState((previousState) => reducerRef.current(previousState, ...args));
|
|
45
|
-
}
|
|
45
|
+
}).current;
|
|
46
46
|
return [state, dispatch];
|
|
47
47
|
}
|
|
48
48
|
//# sourceMappingURL=useReducerWithDeps.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useReducerWithDeps.js","sourceRoot":"","sources":["../../src/hooks/useReducerWithDeps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,
|
|
1
|
+
{"version":3,"file":"useReducerWithDeps.js","sourceRoot":"","sources":["../../src/hooks/useReducerWithDeps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,MAAM,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAezD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAwC,EACxC,YAA4C,EAC5C,IAAoB;IAEpB,uDAAuD;IACvD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAE/D,8CAA8C;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,QAAQ,CAAC,GAAG,IAAO;QAClD,QAAQ,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC,OAAO,CAAC;IAEX,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStateWithDeps.d.ts","sourceRoot":"","sources":["../../src/hooks/useStateWithDeps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"useStateWithDeps.d.ts","sourceRoot":"","sources":["../../src/hooks/useStateWithDeps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAIf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAC5C,IAAI,EAAE,cAAc,GACnB,CAAC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CA0ClC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2020 Peter Juras
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { useRef, } from 'react';
|
|
8
8
|
import { depsAreEqual, isFunction } from '../utils.js';
|
|
9
9
|
import { useForceUpdate } from './useForceUpdate.js';
|
|
10
10
|
/**
|
|
@@ -78,7 +78,7 @@ export function useStateWithDeps(initialState, deps) {
|
|
|
78
78
|
isMounted.current = true;
|
|
79
79
|
}
|
|
80
80
|
const [forceUpdate] = useForceUpdate();
|
|
81
|
-
const updateState =
|
|
81
|
+
const updateState = useRef(function updateState(newState) {
|
|
82
82
|
let nextState;
|
|
83
83
|
if (isFunction(newState)) {
|
|
84
84
|
nextState = newState(state.current);
|
|
@@ -90,7 +90,7 @@ export function useStateWithDeps(initialState, deps) {
|
|
|
90
90
|
state.current = nextState;
|
|
91
91
|
forceUpdate();
|
|
92
92
|
}
|
|
93
|
-
}
|
|
93
|
+
}).current;
|
|
94
94
|
return [state.current, updateState];
|
|
95
95
|
}
|
|
96
96
|
//# sourceMappingURL=useStateWithDeps.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStateWithDeps.js","sourceRoot":"","sources":["../../src/hooks/useStateWithDeps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"useStateWithDeps.js","sourceRoot":"","sources":["../../src/hooks/useStateWithDeps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,MAAM,GAIP,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,UAAU,gBAAgB,CAC9B,YAA4C,EAC5C,IAAoB;IAEpB,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,8EAA8E;IAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,SAAc,CAAC,CAAC;IAErC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhC,mEAAmE;IACnE,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;QAChE,wBAAwB;QACxB,IAAI,SAAY,CAAC;QACjB,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,YAAY,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;QAC1B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;QACxB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,GAAG,cAAc,EAAE,CAAC;IAEvC,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,WAAW,CAC7C,QAAuC;QAEvC,IAAI,SAAY,CAAC;QACjB,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,QAAQ,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;YACzC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;YAC1B,WAAW,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC,OAAO,CAAC;IAEX,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -6,7 +6,8 @@ import type { ArgumentFallback } from '../utils.js';
|
|
|
6
6
|
* as an argument to `useContext` or `use` (the hook produced with
|
|
7
7
|
* {@linkcode createSafeContext} should be used instead)
|
|
8
8
|
*
|
|
9
|
-
* @see
|
|
9
|
+
* @see
|
|
10
|
+
* {@linkcode createSafeContext}
|
|
10
11
|
*/
|
|
11
12
|
export type RestrictedContext<T> = Context<T> extends Provider<T> ? {
|
|
12
13
|
Provider: Provider<T>;
|
|
@@ -18,7 +19,9 @@ export type RestrictedContext<T> = Context<T> extends Provider<T> ? {
|
|
|
18
19
|
/**
|
|
19
20
|
* The return type of {@linkcode createSafeContext}
|
|
20
21
|
*
|
|
21
|
-
* @see
|
|
22
|
+
* @see
|
|
23
|
+
* {@linkcode createSafeContext},
|
|
24
|
+
* {@linkcode RestrictedContext}
|
|
22
25
|
*/
|
|
23
26
|
export type SafeContext<DisplayName extends string, T> = {
|
|
24
27
|
[K in `${DisplayName}Context`]: RestrictedContext<T>;
|
|
@@ -80,6 +83,9 @@ export type SafeContext<DisplayName extends string, T> = {
|
|
|
80
83
|
* - ``` `${displayName}Context` ``` (e.g. `DirectionContext`): the context
|
|
81
84
|
* - ``` `use${displayName}` ``` (e.g. `useDirection`): a hook that returns the
|
|
82
85
|
* current context value if one was provided, or throws an error otherwise
|
|
86
|
+
*
|
|
87
|
+
* @see
|
|
88
|
+
* {@linkcode SafeContext}
|
|
83
89
|
*/
|
|
84
90
|
export declare function createSafeContext<T = never>(): <DisplayName extends string>(displayName: [T] extends [never] ? never : ArgumentFallback<DisplayName, never, string>) => SafeContext<DisplayName, T>;
|
|
85
91
|
//# sourceMappingURL=createSafeContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSafeContext.d.ts","sourceRoot":"","sources":["../../src/misc/createSafeContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAA6B,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD
|
|
1
|
+
{"version":3,"file":"createSafeContext.d.ts","sourceRoot":"","sources":["../../src/misc/createSafeContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAA6B,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD;;;;;;;;GAQG;AAIH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAC7B,OAAO,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,GAC1B;IAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAC5D;IAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,CAAC,WAAW,SAAS,MAAM,EAAE,CAAC,IAAI;KACtD,CAAC,IAAI,GAAG,WAAW,SAAS,GAAG,iBAAiB,CAAC,CAAC,CAAC;CACrD,GAAG;KACD,CAAC,IAAI,MAAM,WAAW,EAAE,GAAG,MAAM,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,KAAK,MACjC,WAAW,SAAS,MAAM,EAChC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC5B,KAAK,GACL,gBAAgB,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,KAC/C,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC,CAsB/B"}
|
|
@@ -55,6 +55,9 @@ const moValueSymbol = Symbol('noValue');
|
|
|
55
55
|
* - ``` `${displayName}Context` ``` (e.g. `DirectionContext`): the context
|
|
56
56
|
* - ``` `use${displayName}` ``` (e.g. `useDirection`): a hook that returns the
|
|
57
57
|
* current context value if one was provided, or throws an error otherwise
|
|
58
|
+
*
|
|
59
|
+
* @see
|
|
60
|
+
* {@linkcode SafeContext}
|
|
58
61
|
*/
|
|
59
62
|
export function createSafeContext() {
|
|
60
63
|
return (displayName) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSafeContext.js","sourceRoot":"","sources":["../../src/misc/createSafeContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG/E,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"createSafeContext.js","sourceRoot":"","sources":["../../src/misc/createSafeContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG/E,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AAgCxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,CACL,WAEgD,EACnB,EAAE;QAC/B,MAAM,WAAW,GAAG,GAAG,WAA0B,SAAkB,CAAC;QACpE,MAAM,QAAQ,GAAG,MAAM,WAA0B,EAAW,CAAC;QAE7D,MAAM,OAAO,GAAG,aAAa,CAA2B,aAAa,CAAC,CAAC;QACvE,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;QAElC,OAAO;YACL,CAAC,WAAW,CAAC,EAAE,OAA+B;YAC9C,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE;gBACf,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;gBAClC,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,MAAM,WAAW,qBAAqB,CAAC,CAAC;gBAC1D,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;SAKF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -5,117 +5,108 @@
|
|
|
5
5
|
* @copyright 2020 Julien CARON
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
9
|
-
|
|
10
|
-
type UseEventListenerOverloadArgs<
|
|
11
|
-
EventMap,
|
|
12
|
-
K extends keyof EventMap,
|
|
13
|
-
T extends EventTarget,
|
|
14
|
-
> = [
|
|
15
|
-
target: T | null,
|
|
16
|
-
eventName: K,
|
|
17
|
-
handler: (this: NoInfer<T>, event: EventMap[K]) => void,
|
|
18
|
-
options?: AddEventListenerOptions | boolean,
|
|
19
|
-
];
|
|
8
|
+
import { useEffect, useMemo, useRef, type RefObject } from 'react';
|
|
20
9
|
|
|
21
10
|
/**
|
|
22
|
-
*
|
|
23
|
-
* provided `options` applied
|
|
24
|
-
*
|
|
25
|
-
* If `target` is not provided, `window` is used instead.
|
|
26
|
-
*
|
|
27
|
-
* If `target` is `null`, no event listener is added. This is useful when
|
|
28
|
-
* working with DOM element refs, or when the event listener needs to be removed
|
|
29
|
-
* temporarily.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```tsx
|
|
33
|
-
* useEventListener('resize', () => {
|
|
34
|
-
* console.log(window.innerWidth, window.innerHeight);
|
|
35
|
-
* });
|
|
36
|
-
*
|
|
37
|
-
* useEventListener(document, 'visibilitychange', () => {
|
|
38
|
-
* console.log(document.visibilityState);
|
|
39
|
-
* });
|
|
40
|
-
*
|
|
41
|
-
* const buttonRef = useRef<HTMLButtonElement>(null);
|
|
42
|
-
* useEventListener(buttonRef.current, 'click', () => console.log('click'));
|
|
43
|
-
* ```
|
|
11
|
+
* The type of {@linkcode useEventListener}
|
|
44
12
|
*
|
|
45
|
-
* @
|
|
13
|
+
* @see
|
|
14
|
+
* {@linkcode useEventListener},
|
|
15
|
+
* {@linkcode UseEventListenerWithImplicitWindowTarget},
|
|
16
|
+
* {@linkcode UseEventListenerWithExplicitTarget},
|
|
17
|
+
* {@linkcode UseEventListenerWithAnyExplicitTarget}
|
|
46
18
|
*/
|
|
47
|
-
export
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
19
|
+
export type UseEventListener = UseEventListenerWithImplicitWindowTarget &
|
|
20
|
+
UseEventListenerWithExplicitTarget<Window, WindowEventMap> &
|
|
21
|
+
UseEventListenerWithExplicitTarget<Document, DocumentEventMap> &
|
|
22
|
+
UseEventListenerWithExplicitTarget<HTMLElement, HTMLElementEventMap> &
|
|
23
|
+
UseEventListenerWithExplicitTarget<SVGElement, SVGElementEventMap> &
|
|
24
|
+
UseEventListenerWithExplicitTarget<MathMLElement, MathMLElementEventMap> &
|
|
25
|
+
UseEventListenerWithAnyExplicitTarget;
|
|
52
26
|
|
|
53
27
|
/**
|
|
54
|
-
* @see
|
|
55
|
-
* @
|
|
56
|
-
*/
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
|
|
28
|
+
* @see
|
|
29
|
+
* {@linkcode useEventListener},
|
|
30
|
+
* {@linkcode UseEventListenerWithImplicitWindowTargetArgs} */
|
|
31
|
+
export type UseEventListenerWithImplicitWindowTarget = <
|
|
32
|
+
K extends keyof WindowEventMap,
|
|
33
|
+
>(
|
|
34
|
+
...args: UseEventListenerWithImplicitWindowTargetArgs<K>
|
|
35
|
+
) => void;
|
|
60
36
|
|
|
61
37
|
/**
|
|
62
|
-
* @see
|
|
63
|
-
* @
|
|
38
|
+
* @see
|
|
39
|
+
* {@linkcode useEventListener},
|
|
40
|
+
* {@linkcode UseEventListenerWithExplicitTargetArgs}
|
|
64
41
|
*/
|
|
65
|
-
export
|
|
66
|
-
|
|
67
|
-
|
|
42
|
+
export type UseEventListenerWithExplicitTarget<
|
|
43
|
+
Target extends EventTarget,
|
|
44
|
+
EventMap = Record<string, Event>,
|
|
45
|
+
> = <T extends Target, K extends keyof EventMap>(
|
|
46
|
+
...args: UseEventListenerWithExplicitTargetArgs<EventMap, T, K>
|
|
47
|
+
) => void;
|
|
68
48
|
|
|
69
49
|
/**
|
|
70
|
-
* @see
|
|
71
|
-
* @
|
|
50
|
+
* @see
|
|
51
|
+
* {@linkcode useEventListener},
|
|
52
|
+
* {@linkcode UseEventListenerWithExplicitTarget}
|
|
72
53
|
*/
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
T extends HTMLElement,
|
|
76
|
-
>(...args: UseEventListenerOverloadArgs<HTMLElementEventMap, K, T>): void;
|
|
54
|
+
export type UseEventListenerWithAnyExplicitTarget =
|
|
55
|
+
UseEventListenerWithExplicitTarget<EventTarget>;
|
|
77
56
|
|
|
78
57
|
/**
|
|
79
|
-
* @see
|
|
80
|
-
* @
|
|
58
|
+
* @see
|
|
59
|
+
* {@linkcode useEventListener},
|
|
60
|
+
* {@linkcode UseEventListenerWithExplicitTargetArgs}
|
|
81
61
|
*/
|
|
82
|
-
export
|
|
83
|
-
K extends keyof
|
|
84
|
-
|
|
85
|
-
|
|
62
|
+
export type UseEventListenerWithImplicitWindowTargetArgs<
|
|
63
|
+
K extends keyof WindowEventMap,
|
|
64
|
+
> =
|
|
65
|
+
UseEventListenerWithExplicitTargetArgs<WindowEventMap, Window, K> extends [
|
|
66
|
+
unknown,
|
|
67
|
+
...infer Args,
|
|
68
|
+
]
|
|
69
|
+
? Args
|
|
70
|
+
: never;
|
|
86
71
|
|
|
87
72
|
/**
|
|
88
|
-
* @see
|
|
89
|
-
* @
|
|
73
|
+
* @see
|
|
74
|
+
* {@linkcode useEventListener}
|
|
90
75
|
*/
|
|
91
|
-
export
|
|
92
|
-
|
|
93
|
-
T extends
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
* @see {@linkcode useEventListener}
|
|
98
|
-
*/
|
|
99
|
-
export function useEventListener<K extends keyof WindowEventMap>(
|
|
76
|
+
export type UseEventListenerWithExplicitTargetArgs<
|
|
77
|
+
EventMap,
|
|
78
|
+
T extends EventTarget,
|
|
79
|
+
K extends keyof EventMap,
|
|
80
|
+
> = [
|
|
81
|
+
target: T | (RefObject<T> & { addEventListener?: never }) | null,
|
|
100
82
|
eventName: K,
|
|
101
|
-
handler: (this:
|
|
102
|
-
options?: AddEventListenerOptions | boolean,
|
|
103
|
-
|
|
83
|
+
handler: (this: NoInfer<T>, event: EventMap[K]) => void,
|
|
84
|
+
options?: AddEventListenerOptions | boolean | undefined,
|
|
85
|
+
];
|
|
104
86
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
87
|
+
type UseEventListenerWithImplicitWindowTargetArgsAny =
|
|
88
|
+
UseEventListenerWithImplicitWindowTargetArgs<keyof WindowEventMap>;
|
|
89
|
+
|
|
90
|
+
type UseEventListenerWithExplicitTargetArgsAny =
|
|
91
|
+
UseEventListenerWithExplicitTargetArgs<
|
|
92
|
+
Record<string, Event>,
|
|
93
|
+
EventTarget,
|
|
94
|
+
string
|
|
95
|
+
>;
|
|
114
96
|
|
|
115
97
|
/**
|
|
116
98
|
* Adds `handler` as a listener for the event `eventName` of `target` with the
|
|
117
99
|
* provided `options` applied
|
|
118
100
|
*
|
|
101
|
+
* The following call signatures are available:
|
|
102
|
+
*
|
|
103
|
+
* ```ts
|
|
104
|
+
* function useEventListener(eventName, handler, options?): void;
|
|
105
|
+
* function useEventListener(target, eventName, handler, options?): void;
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* For the full definition of the hook's type, see {@linkcode UseEventListener}.
|
|
109
|
+
*
|
|
119
110
|
* If `target` is not provided, `window` is used instead.
|
|
120
111
|
*
|
|
121
112
|
* If `target` is `null`, no event listener is added. This is useful when
|
|
@@ -133,23 +124,29 @@ export function useEventListener<T extends EventTarget>(
|
|
|
133
124
|
* });
|
|
134
125
|
*
|
|
135
126
|
* const buttonRef = useRef<HTMLButtonElement>(null);
|
|
136
|
-
* useEventListener(buttonRef
|
|
127
|
+
* useEventListener(buttonRef, 'click', () => console.log('click'));
|
|
137
128
|
* ```
|
|
129
|
+
*
|
|
130
|
+
* @see
|
|
131
|
+
* {@linkcode UseEventListener}
|
|
138
132
|
*/
|
|
139
|
-
export function useEventListener(
|
|
140
|
-
...args:
|
|
133
|
+
export const useEventListener: UseEventListener = function useEventListener(
|
|
134
|
+
...args:
|
|
135
|
+
| UseEventListenerWithImplicitWindowTargetArgsAny
|
|
136
|
+
| UseEventListenerWithExplicitTargetArgsAny
|
|
141
137
|
) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
[
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
138
|
+
const [target, eventName, handler, options]: [
|
|
139
|
+
target: EventTarget | RefObject<EventTarget> | null,
|
|
140
|
+
eventName: string,
|
|
141
|
+
handler: (this: never, event: Event) => void,
|
|
142
|
+
options?: AddEventListenerOptions | boolean | undefined,
|
|
143
|
+
] =
|
|
144
|
+
typeof args[0] === 'string'
|
|
145
|
+
? [window, ...(args as UseEventListenerWithImplicitWindowTargetArgsAny)]
|
|
146
|
+
: (args as UseEventListenerWithExplicitTargetArgsAny);
|
|
147
|
+
|
|
148
|
+
const unwrappedTarget =
|
|
149
|
+
target && !('addEventListener' in target) ? target.current : target;
|
|
153
150
|
|
|
154
151
|
const handlerRef = useRef(handler);
|
|
155
152
|
handlerRef.current = handler;
|
|
@@ -168,34 +165,19 @@ export function useEventListener(
|
|
|
168
165
|
);
|
|
169
166
|
|
|
170
167
|
useEffect(() => {
|
|
171
|
-
if (
|
|
168
|
+
if (unwrappedTarget === null) {
|
|
172
169
|
// No element has been attached to the ref yet
|
|
173
170
|
return;
|
|
174
171
|
}
|
|
175
172
|
|
|
176
|
-
const definedTarget = target ?? window;
|
|
177
|
-
|
|
178
173
|
const listener: typeof handler = function (event) {
|
|
179
174
|
handlerRef.current.call(this, event);
|
|
180
175
|
};
|
|
181
176
|
|
|
182
|
-
|
|
177
|
+
unwrappedTarget.addEventListener(eventName, listener, memoizedOptions);
|
|
183
178
|
|
|
184
179
|
return () => {
|
|
185
|
-
|
|
180
|
+
unwrappedTarget.removeEventListener(eventName, listener, memoizedOptions);
|
|
186
181
|
};
|
|
187
|
-
}, [
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
type UseEventListenerArgsWithoutTarget = [
|
|
191
|
-
eventName: string,
|
|
192
|
-
handler: (event: Event) => void,
|
|
193
|
-
options?: AddEventListenerOptions | boolean | undefined,
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
type UseEventListenerArgsWithTarget = [
|
|
197
|
-
target: EventTarget | null,
|
|
198
|
-
eventName: string,
|
|
199
|
-
handler: (event: Event) => void,
|
|
200
|
-
options?: AddEventListenerOptions | boolean | undefined,
|
|
201
|
-
];
|
|
182
|
+
}, [unwrappedTarget, eventName, memoizedOptions]);
|
|
183
|
+
} as UseEventListener;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DependencyList,
|
|
1
|
+
import { type DependencyList, useRef } from 'react';
|
|
2
2
|
import { useStateWithDeps } from './useStateWithDeps.js';
|
|
3
3
|
|
|
4
4
|
// We cannot simply import the following types from @types/react since they are
|
|
@@ -60,9 +60,9 @@ export function useReducerWithDeps<S, A extends AnyActionArg>(
|
|
|
60
60
|
// Only the initially provided reducer is used
|
|
61
61
|
const reducerRef = useRef(reducer);
|
|
62
62
|
|
|
63
|
-
const dispatch =
|
|
63
|
+
const dispatch = useRef(function dispatch(...args: A): void {
|
|
64
64
|
setState((previousState) => reducerRef.current(previousState, ...args));
|
|
65
|
-
}
|
|
65
|
+
}).current;
|
|
66
66
|
|
|
67
67
|
return [state, dispatch];
|
|
68
68
|
}
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
-
useCallback,
|
|
10
9
|
useRef,
|
|
11
10
|
type DependencyList,
|
|
12
11
|
type Dispatch,
|
|
@@ -92,7 +91,7 @@ export function useStateWithDeps<S>(
|
|
|
92
91
|
|
|
93
92
|
const [forceUpdate] = useForceUpdate();
|
|
94
93
|
|
|
95
|
-
const updateState =
|
|
94
|
+
const updateState = useRef(function updateState(
|
|
96
95
|
newState: S | ((previousState: S) => S),
|
|
97
96
|
): void {
|
|
98
97
|
let nextState: S;
|
|
@@ -105,7 +104,7 @@ export function useStateWithDeps<S>(
|
|
|
105
104
|
state.current = nextState;
|
|
106
105
|
forceUpdate();
|
|
107
106
|
}
|
|
108
|
-
}
|
|
107
|
+
}).current;
|
|
109
108
|
|
|
110
109
|
return [state.current, updateState];
|
|
111
110
|
}
|
|
@@ -9,7 +9,8 @@ const moValueSymbol = Symbol('noValue');
|
|
|
9
9
|
* as an argument to `useContext` or `use` (the hook produced with
|
|
10
10
|
* {@linkcode createSafeContext} should be used instead)
|
|
11
11
|
*
|
|
12
|
-
* @see
|
|
12
|
+
* @see
|
|
13
|
+
* {@linkcode createSafeContext}
|
|
13
14
|
*/
|
|
14
15
|
// The type is conditional so that both React 18 and 19 are correctly supported.
|
|
15
16
|
// The code duplication is necessary for the type to be displayed correctly by
|
|
@@ -22,7 +23,9 @@ export type RestrictedContext<T> =
|
|
|
22
23
|
/**
|
|
23
24
|
* The return type of {@linkcode createSafeContext}
|
|
24
25
|
*
|
|
25
|
-
* @see
|
|
26
|
+
* @see
|
|
27
|
+
* {@linkcode createSafeContext},
|
|
28
|
+
* {@linkcode RestrictedContext}
|
|
26
29
|
*/
|
|
27
30
|
export type SafeContext<DisplayName extends string, T> = {
|
|
28
31
|
[K in `${DisplayName}Context`]: RestrictedContext<T>;
|
|
@@ -85,6 +88,9 @@ export type SafeContext<DisplayName extends string, T> = {
|
|
|
85
88
|
* - ``` `${displayName}Context` ``` (e.g. `DirectionContext`): the context
|
|
86
89
|
* - ``` `use${displayName}` ``` (e.g. `useDirection`): a hook that returns the
|
|
87
90
|
* current context value if one was provided, or throws an error otherwise
|
|
91
|
+
*
|
|
92
|
+
* @see
|
|
93
|
+
* {@linkcode SafeContext}
|
|
88
94
|
*/
|
|
89
95
|
export function createSafeContext<T = never>() {
|
|
90
96
|
return <DisplayName extends string>(
|