@himanshu-sorathiya/react-kit 1.0.25 → 1.0.27
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/dist/events.d.ts +369 -11
- package/dist/events2.js +34 -57
- package/dist/index.d.ts +639 -24
- package/dist/storage.d.ts +270 -13
- package/dist/storage2.js +150 -213
- package/dist/useEventListener.js +32 -24
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,33 +3,264 @@
|
|
|
3
3
|
import React$1 from 'react';
|
|
4
4
|
import { CSSProperties, Key, RefObject } from 'react';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* The native event that triggered a `useClickOutside` handler. Determined
|
|
8
|
+
* by whichever `eventType` was configured — `MouseEvent` for
|
|
9
|
+
* `click`/`mousedown`/`mouseup`, `TouchEvent` for `touchstart`/`touchend`,
|
|
10
|
+
* `PointerEvent` for `pointerdown`/`pointerup`.
|
|
11
|
+
*/
|
|
6
12
|
export type ClickOutsideEvent = MouseEvent | TouchEvent | PointerEvent | Event;
|
|
7
|
-
|
|
13
|
+
/**
|
|
14
|
+
* A single element to check clicks against, or `null` if it isn't mounted
|
|
15
|
+
* yet.
|
|
16
|
+
*/
|
|
17
|
+
export type ClickOutsideTarget = Element | null;
|
|
18
|
+
/**
|
|
19
|
+
* A way of referring to a single {@link ClickOutsideTarget}: a React ref
|
|
20
|
+
* that will (eventually) point at the element, the element itself, or
|
|
21
|
+
* `null`.
|
|
22
|
+
*
|
|
23
|
+
* A ref whose `current` is `null` — for example, because the element hasn't
|
|
24
|
+
* mounted yet — is treated as "outside" for that entry rather than blocking
|
|
25
|
+
* detection. See `useClickOutside`'s docs for details.
|
|
26
|
+
*/
|
|
8
27
|
export type ClickOutsideTargetRef = React$1.RefObject<ClickOutsideTarget> | ClickOutsideTarget;
|
|
28
|
+
/**
|
|
29
|
+
* Native events `useClickOutside` can listen for. Defaults to `mousedown`
|
|
30
|
+
* and `touchstart`, which fire before `click`/`mouseup` — this avoids
|
|
31
|
+
* misfiring when a user starts a drag or text selection inside the target
|
|
32
|
+
* and releases outside it.
|
|
33
|
+
*/
|
|
34
|
+
export type ClickOutsideEventName = "mousedown" | "mouseup" | "click" | "touchstart" | "touchend" | "pointerdown" | "pointerup";
|
|
35
|
+
/**
|
|
36
|
+
* Options accepted by `useClickOutside`.
|
|
37
|
+
*/
|
|
9
38
|
export interface UseClickOutsideOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Whether the listener is active. Setting this to `false` fully detaches
|
|
41
|
+
* the underlying listener rather than just skipping the check on each
|
|
42
|
+
* click, so there's no runtime cost while disabled.
|
|
43
|
+
*
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
10
46
|
enabled?: boolean;
|
|
11
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The event(s) that count as a "click." See {@link ClickOutsideEventName}
|
|
49
|
+
* for why `mousedown`/`touchstart` are the default.
|
|
50
|
+
*
|
|
51
|
+
* @default ["mousedown", "touchstart"]
|
|
52
|
+
*/
|
|
53
|
+
eventType?: ClickOutsideEventName | ClickOutsideEventName[];
|
|
54
|
+
/**
|
|
55
|
+
* Whether the listener is registered in the capture phase.
|
|
56
|
+
*
|
|
57
|
+
* Defaults to `true` so this keeps working even if some element between
|
|
58
|
+
* the click and `document` calls `event.stopPropagation()` — a common
|
|
59
|
+
* cause of "click outside stopped working" bugs in bubble-phase
|
|
60
|
+
* listeners.
|
|
61
|
+
*
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
capture?: boolean;
|
|
12
65
|
}
|
|
13
|
-
|
|
66
|
+
/**
|
|
67
|
+
* A function that detaches the listener registered by `useClickOutside`
|
|
68
|
+
* immediately, without waiting for the component to unmount.
|
|
69
|
+
*
|
|
70
|
+
* Safe to call more than once. Note that this does not permanently disable
|
|
71
|
+
* the hook: if `target`, `eventType`, `enabled`, or `capture` change
|
|
72
|
+
* afterwards, a new listener may be attached again on the next render.
|
|
73
|
+
*/
|
|
74
|
+
export type UseClickOutsideReturn = () => void;
|
|
75
|
+
/**
|
|
76
|
+
* Calls `handler` when a click (or the configured event type) happens
|
|
77
|
+
* outside of `target`.
|
|
78
|
+
*
|
|
79
|
+
* `target` may be a single element/ref, or an array of them — the handler
|
|
80
|
+
* only fires when the click is outside *every* target in the array. An
|
|
81
|
+
* unmounted target (a ref whose `current` is `null`) is treated as
|
|
82
|
+
* "outside" for its own entry rather than blocking detection for the
|
|
83
|
+
* others, so it's safe to pass refs that haven't attached yet.
|
|
84
|
+
*
|
|
85
|
+
* @param target The element(s) to detect clicks outside of. Accepts a ref, a direct
|
|
86
|
+
* element, `null`, or an array mixing any of those.
|
|
87
|
+
* @param handler Called with the native event when a click outside is detected. Doesn't
|
|
88
|
+
* need to be memoized.
|
|
89
|
+
* @param options See {@link UseClickOutsideOptions}.
|
|
90
|
+
* @returns A function that detaches the listener on demand.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* const modalRef = useRef<HTMLDivElement>(null);
|
|
95
|
+
* useClickOutside(modalRef, () => setOpen(false));
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* Checking outside multiple elements at once — for example, a dropdown that
|
|
100
|
+
* shouldn't close when its own trigger button is clicked:
|
|
101
|
+
* ```tsx
|
|
102
|
+
* const triggerRef = useRef<HTMLButtonElement>(null);
|
|
103
|
+
* const panelRef = useRef<HTMLDivElement>(null);
|
|
104
|
+
* useClickOutside([triggerRef, panelRef], () => setOpen(false));
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
14
107
|
export declare function useClickOutside(target: ClickOutsideTargetRef | ClickOutsideTargetRef[], handler: (event: ClickOutsideEvent) => void, options?: UseClickOutsideOptions): UseClickOutsideReturn;
|
|
108
|
+
/**
|
|
109
|
+
* Any valid DOM event target — the broadest type a listener can be attached
|
|
110
|
+
* to. Used as the generic constraint for {@link UseEventListenerOptions} and
|
|
111
|
+
* {@link TargetRef}.
|
|
112
|
+
*/
|
|
15
113
|
export type TargetType = EventTarget;
|
|
114
|
+
/**
|
|
115
|
+
* A way of referring to a listener target: a React ref that will
|
|
116
|
+
* (eventually) point at the target, the target itself, or `null`.
|
|
117
|
+
*
|
|
118
|
+
* Passing `null` — or a ref whose `current` is `null` — means no listener is
|
|
119
|
+
* attached.
|
|
120
|
+
*/
|
|
16
121
|
export type TargetRef<T extends TargetType> = React$1.RefObject<T | null> | T | null;
|
|
122
|
+
/**
|
|
123
|
+
* Options accepted by `useEventListener`, extending the native
|
|
124
|
+
* `AddEventListenerOptions` (`capture`, `passive`, `once`) with a `target`
|
|
125
|
+
* to attach to.
|
|
126
|
+
*/
|
|
17
127
|
export interface UseEventListenerOptions<T extends TargetType> extends AddEventListenerOptions {
|
|
128
|
+
/**
|
|
129
|
+
* The element, ref, `window`, or `document` to attach the listener to.
|
|
130
|
+
*
|
|
131
|
+
* - Omitted → defaults to `window` (or does nothing during SSR, where
|
|
132
|
+
* `window` doesn't exist).
|
|
133
|
+
* - `null`, or a ref whose `current` is `null` → no listener is attached.
|
|
134
|
+
*/
|
|
18
135
|
target?: TargetRef<T>;
|
|
136
|
+
/**
|
|
137
|
+
* An `AbortSignal` to detach the listener(s) from outside the hook.
|
|
138
|
+
*
|
|
139
|
+
* This is combined with the hook's own internal cleanup — aborting this
|
|
140
|
+
* signal detaches the listener(s) immediately, the same as calling the
|
|
141
|
+
* function the hook returns.
|
|
142
|
+
*/
|
|
143
|
+
signal?: AbortSignal;
|
|
19
144
|
}
|
|
20
|
-
|
|
145
|
+
/**
|
|
146
|
+
* A function that detaches the listener(s) registered by `useEventListener`
|
|
147
|
+
* immediately, without waiting for the component to unmount.
|
|
148
|
+
*
|
|
149
|
+
* Safe to call more than once — it's a no-op after the first call. Note
|
|
150
|
+
* that this does not permanently disable the hook: if its dependencies
|
|
151
|
+
* (event name(s), target, `capture`, `passive`, `once`, or `signal`) change
|
|
152
|
+
* afterwards, a new listener may be attached again on the next render.
|
|
153
|
+
*/
|
|
154
|
+
export type UseEventListenerReturn = () => void;
|
|
155
|
+
/**
|
|
156
|
+
* Listens for one or more events on `window` — the default target when none
|
|
157
|
+
* is specified.
|
|
158
|
+
*
|
|
159
|
+
* @param eventName A single event name, or an array of event names, to listen for.
|
|
160
|
+
* @param handler Called with the native event whenever it fires. Doesn't need to be
|
|
161
|
+
* memoized — the latest `handler` is always used, and changing it does not
|
|
162
|
+
* re-attach the listener.
|
|
163
|
+
* @param options Optional. `target` may be omitted (defaults to `window`), or set
|
|
164
|
+
* explicitly to `window` or `null` (to disable).
|
|
165
|
+
* @returns A function that detaches the listener(s) on demand.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```tsx
|
|
169
|
+
* useEventListener("resize", () => {
|
|
170
|
+
* console.log(window.innerWidth);
|
|
171
|
+
* });
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
21
174
|
export declare function useEventListener<K extends keyof WindowEventMap>(eventName: K | K[], handler: (event: WindowEventMap[K]) => void, options?: UseEventListenerOptions<Window> & {
|
|
22
175
|
target?: Window | null | undefined;
|
|
23
176
|
}): UseEventListenerReturn;
|
|
177
|
+
/**
|
|
178
|
+
* Listens for one or more events on `document`. `target` is required to
|
|
179
|
+
* distinguish this overload from the `window` one.
|
|
180
|
+
*
|
|
181
|
+
* @param eventName A single event name, or an array of event names, to listen for.
|
|
182
|
+
* @param handler Called with the native event whenever it fires. Doesn't need to be
|
|
183
|
+
* memoized — the latest `handler` is always used, and changing it does not
|
|
184
|
+
* re-attach the listener.
|
|
185
|
+
* @param options `target` must be `document`, a ref pointing at `document`, or `null`
|
|
186
|
+
* (to disable).
|
|
187
|
+
* @returns A function that detaches the listener(s) on demand.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```tsx
|
|
191
|
+
* useEventListener("visibilitychange", () => {
|
|
192
|
+
* console.log(document.visibilityState);
|
|
193
|
+
* }, { target: document });
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
24
196
|
export declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K | K[], handler: (event: DocumentEventMap[K]) => void, options: UseEventListenerOptions<Document> & {
|
|
25
197
|
target: Document | React$1.RefObject<Document | null> | null;
|
|
26
198
|
}): UseEventListenerReturn;
|
|
199
|
+
/**
|
|
200
|
+
* Listens for one or more events on an `HTMLElement`, via a ref or the
|
|
201
|
+
* element itself.
|
|
202
|
+
*
|
|
203
|
+
* @param eventName A single event name, or an array of event names, to listen for.
|
|
204
|
+
* @param handler Called with the native event whenever it fires. Doesn't need to be
|
|
205
|
+
* memoized — the latest `handler` is always used, and changing it does not
|
|
206
|
+
* re-attach the listener.
|
|
207
|
+
* @param options `target` must be the element, a ref to it, or `null` (to disable —
|
|
208
|
+
* for example while the ref hasn't attached to a DOM node yet).
|
|
209
|
+
* @returns A function that detaches the listener(s) on demand.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```tsx
|
|
213
|
+
* const buttonRef = useRef<HTMLButtonElement>(null);
|
|
214
|
+
* useEventListener("click", () => {
|
|
215
|
+
* console.log("clicked");
|
|
216
|
+
* }, { target: buttonRef });
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
27
219
|
export declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLElement>(eventName: K | K[], handler: (event: HTMLElementEventMap[K]) => void, options: UseEventListenerOptions<T> & {
|
|
28
220
|
target: T | React$1.RefObject<T | null> | null;
|
|
29
221
|
}): UseEventListenerReturn;
|
|
222
|
+
/**
|
|
223
|
+
* Listens for one or more events on an `SVGElement`, via a ref or the
|
|
224
|
+
* element itself.
|
|
225
|
+
*
|
|
226
|
+
* @param eventName A single event name, or an array of event names, to listen for.
|
|
227
|
+
* @param handler Called with the native event whenever it fires. Doesn't need to be
|
|
228
|
+
* memoized — the latest `handler` is always used, and changing it does not
|
|
229
|
+
* re-attach the listener.
|
|
230
|
+
* @param options `target` must be the element, a ref to it, or `null` (to disable).
|
|
231
|
+
* @returns A function that detaches the listener(s) on demand.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```tsx
|
|
235
|
+
* const circleRef = useRef<SVGCircleElement>(null);
|
|
236
|
+
* useEventListener("click", () => {
|
|
237
|
+
* console.log("circle clicked");
|
|
238
|
+
* }, { target: circleRef });
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
30
241
|
export declare function useEventListener<K extends keyof SVGElementEventMap, T extends SVGElement = SVGElement>(eventName: K | K[], handler: (event: SVGElementEventMap[K]) => void, options: UseEventListenerOptions<T> & {
|
|
31
242
|
target: T | React$1.RefObject<T | null> | null;
|
|
32
243
|
}): UseEventListenerReturn;
|
|
244
|
+
/**
|
|
245
|
+
* Listens for one or more events on any other `EventTarget` — a custom
|
|
246
|
+
* event emitter, `ShadowRoot`, `MessagePort`, and so on. Since there's no
|
|
247
|
+
* matching `*EventMap` for arbitrary targets, events are typed as the
|
|
248
|
+
* generic `Event`.
|
|
249
|
+
*
|
|
250
|
+
* @param eventName A single event name, or an array of event names, to listen for.
|
|
251
|
+
* @param handler Called with the native event whenever it fires. Doesn't need to be
|
|
252
|
+
* memoized — the latest `handler` is always used, and changing it does not
|
|
253
|
+
* re-attach the listener.
|
|
254
|
+
* @param options `target` must be the target, a ref to it, or `null` (to disable).
|
|
255
|
+
* @returns A function that detaches the listener(s) on demand.
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* ```tsx
|
|
259
|
+
* useEventListener("message", (event) => {
|
|
260
|
+
* console.log(event);
|
|
261
|
+
* }, { target: myMessagePort });
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
33
264
|
export declare function useEventListener<K extends string, T extends TargetType = TargetType>(eventName: K | K[], handler: (event: Event) => void, options: UseEventListenerOptions<T> & {
|
|
34
265
|
target: T | React$1.RefObject<T | null> | null;
|
|
35
266
|
}): UseEventListenerReturn;
|
|
@@ -38,27 +269,154 @@ declare const validKeyEventTypes: readonly [
|
|
|
38
269
|
"keyup",
|
|
39
270
|
"keypress"
|
|
40
271
|
];
|
|
272
|
+
/**
|
|
273
|
+
* The keyboard event types `useKey` can listen for. See
|
|
274
|
+
* {@link validKeyEventTypes}.
|
|
275
|
+
*/
|
|
41
276
|
export type KeyEventType = (typeof validKeyEventTypes)[number];
|
|
42
|
-
|
|
277
|
+
/**
|
|
278
|
+
* Options shared by both variants of {@link UseKeyOptions}.
|
|
279
|
+
*/
|
|
280
|
+
export interface UseKeyBaseOptions {
|
|
281
|
+
/**
|
|
282
|
+
* Whether the listener is active. Setting this to `false` fully detaches
|
|
283
|
+
* the underlying listener rather than just skipping the check on each
|
|
284
|
+
* keystroke, so there's no runtime cost while disabled.
|
|
285
|
+
*
|
|
286
|
+
* @default true
|
|
287
|
+
*/
|
|
43
288
|
enabled?: boolean;
|
|
44
|
-
|
|
289
|
+
/**
|
|
290
|
+
* The element, ref, `window`, or `document` to attach the listener to.
|
|
291
|
+
*
|
|
292
|
+
* @default window
|
|
293
|
+
*/
|
|
294
|
+
target?: React$1.RefObject<HTMLElement | null> | HTMLElement | Window | Document | null;
|
|
295
|
+
/**
|
|
296
|
+
* Whether to call `event.preventDefault()` when `key` matches. Applied
|
|
297
|
+
* before `handler` is called, so it still takes effect even if `handler`
|
|
298
|
+
* throws.
|
|
299
|
+
*
|
|
300
|
+
* @default true
|
|
301
|
+
*/
|
|
45
302
|
preventDefault?: boolean;
|
|
303
|
+
/**
|
|
304
|
+
* Whether to call `event.stopPropagation()` when `key` matches. Applied
|
|
305
|
+
* before `handler` is called, so it still takes effect even if `handler`
|
|
306
|
+
* throws.
|
|
307
|
+
*
|
|
308
|
+
* @default true
|
|
309
|
+
*/
|
|
46
310
|
stopPropagation?: boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Whether the listener is registered in the capture phase.
|
|
313
|
+
*
|
|
314
|
+
* Unlike `useClickOutside`, this defaults to `false`. Flip it to `true`
|
|
315
|
+
* if a descendant element calling `event.stopPropagation()` is
|
|
316
|
+
* preventing this shortcut from firing.
|
|
317
|
+
*
|
|
318
|
+
* @default false
|
|
319
|
+
*/
|
|
320
|
+
capture?: boolean;
|
|
321
|
+
/**
|
|
322
|
+
* Whether to ignore the keystroke while focus is inside an `<input>`,
|
|
323
|
+
* `<textarea>`, `<select>`, or any `contenteditable` element — so a
|
|
324
|
+
* shortcut like a bare `"s"` doesn't fire while someone is just typing.
|
|
325
|
+
*
|
|
326
|
+
* @default true
|
|
327
|
+
*/
|
|
47
328
|
ignoreWhenFocusedInInputs?: boolean;
|
|
329
|
+
/**
|
|
330
|
+
* Whether the Ctrl key must be held for a match.
|
|
331
|
+
* @default false
|
|
332
|
+
*/
|
|
48
333
|
ctrlKey?: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Whether the Shift key must be held for a match.
|
|
336
|
+
* @default false
|
|
337
|
+
*/
|
|
49
338
|
shiftKey?: boolean;
|
|
339
|
+
/**
|
|
340
|
+
* Whether the Alt key (Option, on Mac) must be held for a match.
|
|
341
|
+
* @default false
|
|
342
|
+
*/
|
|
50
343
|
altKey?: boolean;
|
|
344
|
+
/**
|
|
345
|
+
* Whether the Meta key (Cmd on Mac, the Windows key elsewhere) must be
|
|
346
|
+
* held for a match.
|
|
347
|
+
* @default false
|
|
348
|
+
*/
|
|
51
349
|
metaKey?: boolean;
|
|
52
350
|
}
|
|
53
|
-
|
|
54
|
-
|
|
351
|
+
/**
|
|
352
|
+
* Options accepted by `useKey`.
|
|
353
|
+
*
|
|
354
|
+
* `preventRepeat` is only valid together with `eventType: "keydown"` or
|
|
355
|
+
* `"keypress"` — TypeScript rejects it on `"keyup"`, since a keyup event is
|
|
356
|
+
* never marked as auto-repeating.
|
|
357
|
+
*/
|
|
358
|
+
export type UseKeyOptions = UseKeyBaseOptions & ({
|
|
359
|
+
/**
|
|
360
|
+
* Which keyboard event to listen for.
|
|
361
|
+
* @default "keydown"
|
|
362
|
+
*/
|
|
363
|
+
eventType?: Extract<KeyEventType, "keydown" | "keypress">;
|
|
364
|
+
/**
|
|
365
|
+
* If `true`, ignores auto-repeated events fired while the key is
|
|
366
|
+
* held down (based on the native `KeyboardEvent.repeat` flag), so
|
|
367
|
+
* `handler` only fires once per physical press rather than
|
|
368
|
+
* repeatedly while it's held.
|
|
369
|
+
*
|
|
370
|
+
* @default false
|
|
371
|
+
*/
|
|
55
372
|
preventRepeat?: boolean;
|
|
56
373
|
} | {
|
|
57
|
-
eventType: "keyup"
|
|
374
|
+
eventType: Extract<KeyEventType, "keyup">;
|
|
58
375
|
preventRepeat?: never;
|
|
59
376
|
});
|
|
60
|
-
|
|
61
|
-
|
|
377
|
+
/**
|
|
378
|
+
* A function that detaches the listener registered by `useKey` immediately,
|
|
379
|
+
* without waiting for the component to unmount.
|
|
380
|
+
*
|
|
381
|
+
* Safe to call more than once. Note that this does not permanently disable
|
|
382
|
+
* the hook: if `eventType`, `enabled`, `target`, or `capture` change
|
|
383
|
+
* afterwards, a new listener may be attached again on the next render.
|
|
384
|
+
* Changing `key` — or any of the modifier-matching options — does *not*
|
|
385
|
+
* cause a re-attach; those are picked up fresh on the next keystroke
|
|
386
|
+
* without the underlying listener ever being torn down.
|
|
387
|
+
*/
|
|
388
|
+
export type UseKeyReturn = () => void;
|
|
389
|
+
/**
|
|
390
|
+
* Calls `handler` when `key` is pressed (or released, depending on
|
|
391
|
+
* `eventType`), optionally matching an exact combination of modifier keys.
|
|
392
|
+
*
|
|
393
|
+
* Ignores keystrokes that occur during IME composition (for example, while
|
|
394
|
+
* typing pinyin or romaji before a CJK character is confirmed), so
|
|
395
|
+
* shortcuts don't misfire or interfere with the IME's own confirmation key
|
|
396
|
+
* — often Enter. By default, also ignores keystrokes while focus is inside
|
|
397
|
+
* a text input, textarea, select, or contenteditable element — see
|
|
398
|
+
* `ignoreWhenFocusedInInputs` in {@link UseKeyOptions}.
|
|
399
|
+
*
|
|
400
|
+
* @param key The key to match, compared case-insensitively against
|
|
401
|
+
* `KeyboardEvent.key` (e.g. `"Escape"`, `"a"`, `"Enter"`).
|
|
402
|
+
* @param handler Called with the native event when a match is found. Doesn't need to be
|
|
403
|
+
* memoized.
|
|
404
|
+
* @param options See {@link UseKeyOptions}.
|
|
405
|
+
* @returns A function that detaches the listener on demand.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```tsx
|
|
409
|
+
* useKey("Escape", () => setOpen(false));
|
|
410
|
+
* ```
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* Matching a modifier combination — all four modifier flags are matched
|
|
414
|
+
* exactly, so this only fires for Ctrl+K alone, not Ctrl+Shift+K:
|
|
415
|
+
* ```tsx
|
|
416
|
+
* useKey("k", () => openCommandPalette(), { ctrlKey: true });
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
419
|
+
export declare function useKey(key: string, handler: (event: KeyboardEvent) => void, options?: UseKeyOptions): UseKeyReturn;
|
|
62
420
|
export interface DebounceOptions {
|
|
63
421
|
maxWait?: number;
|
|
64
422
|
leading?: boolean;
|
|
@@ -458,43 +816,295 @@ export interface UseSortReturn<T> {
|
|
|
458
816
|
getSortIndex: (id: string) => number | undefined;
|
|
459
817
|
}
|
|
460
818
|
export declare function useSort<T>(data?: T[], initialSorts?: SortState): UseSortReturn<T>;
|
|
819
|
+
/**
|
|
820
|
+
* Defines how a value of type `T` is converted to and from the string
|
|
821
|
+
* format that `localStorage`/`sessionStorage` can actually store — the Web
|
|
822
|
+
* Storage API only ever stores strings.
|
|
823
|
+
*
|
|
824
|
+
* Implement this to store types the default JSON-based serializer can't
|
|
825
|
+
* round-trip faithfully, e.g. `Map`, `Set`, `Date`, or `bigint` — see
|
|
826
|
+
* `mapSerializer`, `setSerializer`, `dateSerializer`, and
|
|
827
|
+
* `bigIntSerializer` in `serializers.ts` for ready-made ones.
|
|
828
|
+
*
|
|
829
|
+
* @typeParam T - The in-memory value type this serializer handles.
|
|
830
|
+
*/
|
|
461
831
|
export interface StorageSerializer<T> {
|
|
832
|
+
/** Converts an in-memory value into the string that gets stored. */
|
|
462
833
|
serialize: (value: T) => string;
|
|
834
|
+
/**
|
|
835
|
+
* Converts a stored string back into an in-memory value.
|
|
836
|
+
*
|
|
837
|
+
* @throws If the raw string can't be converted back into `T`. The hook
|
|
838
|
+
* catches this, falls back to `initialValue`, and reports the error —
|
|
839
|
+
* see `onError` on {@link BaseStorageOptions}.
|
|
840
|
+
*/
|
|
463
841
|
deserialize: (raw: string) => T;
|
|
464
842
|
}
|
|
843
|
+
/**
|
|
844
|
+
* Options shared by `useLocalStorage` and `useSessionStorage`.
|
|
845
|
+
*
|
|
846
|
+
* @typeParam T - The type of value being stored.
|
|
847
|
+
*/
|
|
465
848
|
export interface BaseStorageOptions<T> {
|
|
849
|
+
/**
|
|
850
|
+
* Custom (de)serializer for values that don't round-trip through
|
|
851
|
+
* `JSON.stringify`/`JSON.parse` cleanly.
|
|
852
|
+
*
|
|
853
|
+
* @defaultValue `defaultSerializer` (plain `JSON.stringify`/`JSON.parse`)
|
|
854
|
+
*/
|
|
466
855
|
serializer?: StorageSerializer<T>;
|
|
856
|
+
/**
|
|
857
|
+
* Whether to synchronously read the existing stored value on mount.
|
|
858
|
+
*
|
|
859
|
+
* - `true` (default): `value` reflects storage from the very first
|
|
860
|
+
* render it's allowed to (see the SSR note below).
|
|
861
|
+
* - `false`: `value` starts as `undefined` and only reflects storage
|
|
862
|
+
* once `isHydrated` becomes `true`, one render after mount. Use this
|
|
863
|
+
* if you'd rather render a loading/skeleton state than briefly show a
|
|
864
|
+
* value that might change right after.
|
|
865
|
+
*
|
|
866
|
+
* Either way, on the server — and during the client's hydration render
|
|
867
|
+
* — `value` is always `initialValue`. This option only affects timing
|
|
868
|
+
* on the client, after that point.
|
|
869
|
+
*
|
|
870
|
+
* @defaultValue `true`
|
|
871
|
+
*/
|
|
467
872
|
initializeWithValue?: boolean;
|
|
873
|
+
/**
|
|
874
|
+
* Whether other instances of this hook watching the *same key* in the
|
|
875
|
+
* *same tab* stay in sync with each other. Implemented via a
|
|
876
|
+
* `CustomEvent` dispatched on `window` — the browser's native `storage`
|
|
877
|
+
* event never fires in the tab that made the change, so without this,
|
|
878
|
+
* two components reading the same key in one tab would drift apart.
|
|
879
|
+
*
|
|
880
|
+
* @defaultValue `true`
|
|
881
|
+
*/
|
|
468
882
|
sameInstanceSync?: boolean;
|
|
883
|
+
/**
|
|
884
|
+
* Called whenever the hook hits an unexpected condition: a failed
|
|
885
|
+
* read, a failed write, a failed cross-instance deserialize, or an
|
|
886
|
+
* attempt to change the storage key at runtime. Fires in every
|
|
887
|
+
* environment, including production — use this for telemetry/error
|
|
888
|
+
* reporting.
|
|
889
|
+
*
|
|
890
|
+
* This is *not* a replacement for the dev-only `console.warn` the hook
|
|
891
|
+
* also emits for the same conditions (visible when
|
|
892
|
+
* `process.env.NODE_ENV !== "production"`) — both fire independently.
|
|
893
|
+
*/
|
|
894
|
+
onError?: (error: Error) => void;
|
|
469
895
|
}
|
|
896
|
+
/**
|
|
897
|
+
* Payload carried by the same-tab `CustomEvent` used for
|
|
898
|
+
* {@link BaseStorageOptions.sameInstanceSync}. Internal — not part of the
|
|
899
|
+
* public hook API, but exported so `useStorageEngine.ts` can import it.
|
|
900
|
+
*/
|
|
470
901
|
export interface StorageCustomEventDetail {
|
|
902
|
+
/** The new serialized value, or `null` if the key was removed. */
|
|
471
903
|
value: string | null;
|
|
904
|
+
/**
|
|
905
|
+
* A per-hook-instance identifier, used so an instance can recognize —
|
|
906
|
+
* and ignore — the event it just dispatched itself.
|
|
907
|
+
*/
|
|
472
908
|
instanceId: symbol;
|
|
473
909
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
910
|
+
/**
|
|
911
|
+
* The shape returned by {@link useStorageEngine} — and, re-exported, by
|
|
912
|
+
* both `useLocalStorage` and `useSessionStorage`.
|
|
913
|
+
*
|
|
914
|
+
* @typeParam T - The type of value being stored.
|
|
915
|
+
*/
|
|
916
|
+
interface UseStorageEngineReturn<T> {
|
|
917
|
+
/**
|
|
918
|
+
* The current value.
|
|
919
|
+
*
|
|
920
|
+
* - `undefined` if nothing is stored yet and no `initialValue` was
|
|
921
|
+
* given, or — when `initializeWithValue: false` — before hydration
|
|
922
|
+
* completes.
|
|
923
|
+
* - On the server, and during the client's hydration render, this is
|
|
924
|
+
* always `initialValue`: real storage can only be read client-side,
|
|
925
|
+
* and reading it any earlier would produce a hydration mismatch.
|
|
926
|
+
*/
|
|
478
927
|
value: T | undefined;
|
|
928
|
+
/**
|
|
929
|
+
* Writes a new value to storage. Accepts either the value directly, or
|
|
930
|
+
* an updater function that receives the current value and returns the
|
|
931
|
+
* next one — the same convention as `useState`'s setter.
|
|
932
|
+
*
|
|
933
|
+
* A no-op if storage isn't available (SSR, or storage access blocked).
|
|
934
|
+
*/
|
|
479
935
|
setValue: (valueOrUpdater: T | ((prev: T | undefined) => T)) => void;
|
|
936
|
+
/**
|
|
937
|
+
* Removes the key from storage entirely and resets `value` back to
|
|
938
|
+
* whatever `initialValue` was passed to the hook.
|
|
939
|
+
*
|
|
940
|
+
* A no-op if storage isn't available (SSR, or storage access blocked).
|
|
941
|
+
*/
|
|
480
942
|
removeValue: () => void;
|
|
943
|
+
/**
|
|
944
|
+
* `true` once the client has mounted and the hook has settled on its
|
|
945
|
+
* real (non-server-snapshot) value. Useful for showing a loading state
|
|
946
|
+
* instead of a value that might change the instant hydration finishes.
|
|
947
|
+
*/
|
|
481
948
|
isHydrated: boolean;
|
|
949
|
+
/**
|
|
950
|
+
* The most recent error the hook encountered — a failed read, write,
|
|
951
|
+
* or cross-instance sync, or an attempted key change — or `null` if
|
|
952
|
+
* nothing has gone wrong (or an error was cleared by a subsequent
|
|
953
|
+
* successful write/remove). See `onError` on {@link BaseStorageOptions}
|
|
954
|
+
* for an imperative alternative to reading this reactively.
|
|
955
|
+
*/
|
|
482
956
|
error: Error | null;
|
|
483
957
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
958
|
+
/**
|
|
959
|
+
* Options accepted by `useLocalStorage`.
|
|
960
|
+
*
|
|
961
|
+
* @typeParam T - The type of value being stored.
|
|
962
|
+
*/
|
|
963
|
+
export interface UseLocalStorageOptions<T> extends BaseStorageOptions<T> {
|
|
964
|
+
/**
|
|
965
|
+
* Whether this hook instance should sync with the same key changing in
|
|
966
|
+
* *other tabs/windows* on the same origin, via the browser's native
|
|
967
|
+
* `storage` event. Has no `sessionStorage` equivalent — sessionStorage
|
|
968
|
+
* isn't shared across tabs, so there's nothing to sync in that case.
|
|
969
|
+
*
|
|
970
|
+
* @defaultValue `true`
|
|
971
|
+
*/
|
|
972
|
+
crossInstanceSync?: boolean;
|
|
492
973
|
}
|
|
493
|
-
|
|
974
|
+
/**
|
|
975
|
+
* Reads and writes a `localStorage` key, kept in sync with React state.
|
|
976
|
+
*
|
|
977
|
+
* - Persists across page reloads and browser restarts (unlike
|
|
978
|
+
* `useSessionStorage`).
|
|
979
|
+
* - Stays in sync with every component in the current tab watching the
|
|
980
|
+
* same key — see {@link UseLocalStorageOptions.sameInstanceSync} — and
|
|
981
|
+
* with other tabs/windows on the same origin — see
|
|
982
|
+
* {@link UseLocalStorageOptions.crossInstanceSync}.
|
|
983
|
+
* - Safe under SSR: on the server, and during the client's hydration
|
|
984
|
+
* render, `value` is always `initialValue`. The real stored value is
|
|
985
|
+
* only read client-side, immediately after hydration.
|
|
986
|
+
*
|
|
987
|
+
* @typeParam T - The type of value being stored. Defaults to `unknown` if
|
|
988
|
+
* omitted — pass an explicit type argument for anything beyond ad-hoc use.
|
|
989
|
+
* @param key - The `localStorage` key to read and write. Changing this on
|
|
990
|
+
* a later render isn't supported; the hook warns (dev console + `onError`)
|
|
991
|
+
* and keeps using the original key if you do.
|
|
992
|
+
* @param initialValue - Used when nothing is stored yet, as the value
|
|
993
|
+
* shown before hydration completes, and as what `removeValue` resets to.
|
|
994
|
+
* @param options - See {@link UseLocalStorageOptions}.
|
|
995
|
+
* @returns `{ value, setValue, removeValue, isHydrated, error }`.
|
|
996
|
+
*
|
|
997
|
+
* @example
|
|
998
|
+
* Basic usage:
|
|
999
|
+
* ```tsx
|
|
1000
|
+
* const { value: theme, setValue: setTheme } = useLocalStorage<"light" | "dark">("theme", "light");
|
|
1001
|
+
*
|
|
1002
|
+
* <button onClick={() => setTheme(prev => (prev === "light" ? "dark" : "light"))}>
|
|
1003
|
+
* Toggle theme
|
|
1004
|
+
* </button>
|
|
1005
|
+
* ```
|
|
1006
|
+
*
|
|
1007
|
+
* @example
|
|
1008
|
+
* With a custom serializer and error reporting:
|
|
1009
|
+
* ```tsx
|
|
1010
|
+
* const { value, setValue, error } = useLocalStorage("lastSeen", new Date(), {
|
|
1011
|
+
* serializer: dateSerializer,
|
|
1012
|
+
* onError: (err) => reportToErrorTracker(err),
|
|
1013
|
+
* });
|
|
1014
|
+
* ```
|
|
1015
|
+
*/
|
|
1016
|
+
export declare function useLocalStorage<T = unknown>(key: string, initialValue?: T, options?: UseLocalStorageOptions<T>): UseStorageEngineReturn<T>;
|
|
1017
|
+
/**
|
|
1018
|
+
* Options accepted by `useSessionStorage`. Identical to
|
|
1019
|
+
* `BaseStorageOptions` — unlike `UseLocalStorageOptions`, there's no
|
|
1020
|
+
* `crossInstanceSync` option here, since sessionStorage isn't shared
|
|
1021
|
+
* across tabs in the first place.
|
|
1022
|
+
*
|
|
1023
|
+
* @typeParam T - The type of value being stored.
|
|
1024
|
+
*/
|
|
1025
|
+
export type UseSessionStorageOptions<T> = BaseStorageOptions<T>;
|
|
1026
|
+
/**
|
|
1027
|
+
* Reads and writes a `sessionStorage` key, kept in sync with React state.
|
|
1028
|
+
*
|
|
1029
|
+
* - Scoped to the current tab: cleared when the tab closes, and not
|
|
1030
|
+
* shared with other tabs (unlike `useLocalStorage`).
|
|
1031
|
+
* - Stays in sync with every component in the current tab watching the
|
|
1032
|
+
* same key — see {@link UseSessionStorageOptions.sameInstanceSync}.
|
|
1033
|
+
* - Safe under SSR: on the server, and during the client's hydration
|
|
1034
|
+
* render, `value` is always `initialValue`. The real stored value is
|
|
1035
|
+
* only read client-side, immediately after hydration.
|
|
1036
|
+
*
|
|
1037
|
+
* @typeParam T - The type of value being stored. Defaults to `unknown` if
|
|
1038
|
+
* omitted — pass an explicit type argument for anything beyond ad-hoc use.
|
|
1039
|
+
* @param key - The `sessionStorage` key to read and write. Changing this
|
|
1040
|
+
* on a later render isn't supported; the hook warns (dev console +
|
|
1041
|
+
* `onError`) and keeps using the original key if you do.
|
|
1042
|
+
* @param initialValue - Used when nothing is stored yet, as the value
|
|
1043
|
+
* shown before hydration completes, and as what `removeValue` resets to.
|
|
1044
|
+
* @param options - See {@link UseSessionStorageOptions}.
|
|
1045
|
+
* @returns `{ value, setValue, removeValue, isHydrated, error }`.
|
|
1046
|
+
*
|
|
1047
|
+
* @example
|
|
1048
|
+
* ```tsx
|
|
1049
|
+
* const { value: draft, setValue: setDraft } = useSessionStorage("draft-comment", "");
|
|
1050
|
+
*
|
|
1051
|
+
* <textarea value={draft ?? ""} onChange={(e) => setDraft(e.target.value)} />
|
|
1052
|
+
* ```
|
|
1053
|
+
*/
|
|
1054
|
+
export declare function useSessionStorage<T = unknown>(key: string, initialValue?: T, options?: UseSessionStorageOptions<T>): UseStorageEngineReturn<T>;
|
|
1055
|
+
/**
|
|
1056
|
+
* The default serializer used when no `serializer` option is passed to
|
|
1057
|
+
* `useLocalStorage`/`useSessionStorage`. Plain `JSON.stringify`/
|
|
1058
|
+
* `JSON.parse` — works for any JSON-safe value (objects, arrays, strings,
|
|
1059
|
+
* numbers, booleans, `null`), but not `Map`, `Set`, `Date`, `bigint`, or
|
|
1060
|
+
* `undefined` (see the other serializers below for those).
|
|
1061
|
+
*/
|
|
494
1062
|
export declare const defaultSerializer: StorageSerializer<unknown>;
|
|
1063
|
+
/**
|
|
1064
|
+
* Serializer for `Map` values. `JSON.stringify` can't handle `Map`
|
|
1065
|
+
* directly, so this round-trips it via an array of `[key, value]` entries.
|
|
1066
|
+
*
|
|
1067
|
+
* @typeParam K - The map's key type.
|
|
1068
|
+
* @typeParam V - The map's value type.
|
|
1069
|
+
*
|
|
1070
|
+
* @example
|
|
1071
|
+
* ```ts
|
|
1072
|
+
* useLocalStorage("tags", new Map<string, number>(), {
|
|
1073
|
+
* serializer: mapSerializer<string, number>(),
|
|
1074
|
+
* });
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
495
1077
|
export declare function mapSerializer<K, V>(): StorageSerializer<Map<K, V>>;
|
|
1078
|
+
/**
|
|
1079
|
+
* Serializer for `Set` values, round-tripped via a plain array.
|
|
1080
|
+
*
|
|
1081
|
+
* @typeParam V - The set's value type.
|
|
1082
|
+
*
|
|
1083
|
+
* @example
|
|
1084
|
+
* ```ts
|
|
1085
|
+
* useLocalStorage("selectedIds", new Set<string>(), {
|
|
1086
|
+
* serializer: setSerializer<string>(),
|
|
1087
|
+
* });
|
|
1088
|
+
* ```
|
|
1089
|
+
*/
|
|
496
1090
|
export declare function setSerializer<V>(): StorageSerializer<Set<V>>;
|
|
1091
|
+
/**
|
|
1092
|
+
* Serializer for `Date` values, stored as an ISO 8601 string
|
|
1093
|
+
* (`Date.prototype.toISOString`).
|
|
1094
|
+
*
|
|
1095
|
+
* @throws During `deserialize`, if the stored string isn't a valid date —
|
|
1096
|
+
* caught by the hook, which falls back to `initialValue` and reports the
|
|
1097
|
+
* error via `onError`/the dev console warning.
|
|
1098
|
+
*/
|
|
497
1099
|
export declare const dateSerializer: StorageSerializer<Date>;
|
|
1100
|
+
/**
|
|
1101
|
+
* Serializer for `bigint` values. `JSON.stringify` throws on `bigint`
|
|
1102
|
+
* values, so this stores them as a plain decimal string instead.
|
|
1103
|
+
*
|
|
1104
|
+
* @throws During `deserialize`, if the stored string can't be converted to
|
|
1105
|
+
* a `bigint` — caught by the hook, which falls back to `initialValue` and
|
|
1106
|
+
* reports the error via `onError`/the dev console warning.
|
|
1107
|
+
*/
|
|
498
1108
|
export declare const bigIntSerializer: StorageSerializer<bigint>;
|
|
499
1109
|
export interface FuzzyHighlighterProps {
|
|
500
1110
|
text: string;
|
|
@@ -590,4 +1200,9 @@ export declare function useVisibility<T = unknown>(options?: {
|
|
|
590
1200
|
initialVisibleIds?: VisibilityId[];
|
|
591
1201
|
}): UseVisibilityReturn<T>;
|
|
592
1202
|
|
|
1203
|
+
export {
|
|
1204
|
+
UseStorageEngineReturn as UseLocalStorageReturn,
|
|
1205
|
+
UseStorageEngineReturn as UseSessionStorageReturn,
|
|
1206
|
+
};
|
|
1207
|
+
|
|
593
1208
|
export {};
|