@himanshu-sorathiya/react-kit 1.0.26 → 1.0.28
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/index.d.ts +1153 -43
- package/dist/index.js +5 -5
- package/dist/performance.d.ts +883 -30
- package/dist/performance.js +2 -2
- package/dist/performance2.js +358 -224
- package/dist/storage.d.ts +270 -13
- package/dist/storage2.js +150 -213
- package/package.json +7 -4
package/dist/index.d.ts
CHANGED
|
@@ -417,85 +417,938 @@ export type UseKeyReturn = () => void;
|
|
|
417
417
|
* ```
|
|
418
418
|
*/
|
|
419
419
|
export declare function useKey(key: string, handler: (event: KeyboardEvent) => void, options?: UseKeyOptions): UseKeyReturn;
|
|
420
|
+
/**
|
|
421
|
+
* Adds an optional custom equality comparator to any hook that manages a
|
|
422
|
+
* value and needs to decide whether a "new" value is actually different
|
|
423
|
+
* enough to justify a re-render.
|
|
424
|
+
*
|
|
425
|
+
* Used by the `State` and `Value` variants of debounce/throttle/rate-limit
|
|
426
|
+
* (e.g. `useDebouncedValue`, `useThrottledState`) to avoid committing a
|
|
427
|
+
* value that is deeply/semantically equal to the value already held,
|
|
428
|
+
* which would otherwise trigger a wasted re-render.
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```tsx
|
|
432
|
+
* useDebouncedValue(user, 300, {
|
|
433
|
+
* equalityFn: (previous, next) => previous.id === next.id,
|
|
434
|
+
* });
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
export interface EqualityFnOption<T> {
|
|
438
|
+
/**
|
|
439
|
+
* Called with the currently-held value and the candidate next value.
|
|
440
|
+
* Return `true` if they should be treated as equal (no update should be
|
|
441
|
+
* committed); return `false` to allow the update through.
|
|
442
|
+
*
|
|
443
|
+
* Defaults to `Object.is` when omitted, or when an invalid (non-function)
|
|
444
|
+
* value is provided — see the consuming hook's dev-mode warning.
|
|
445
|
+
*/
|
|
446
|
+
equalityFn?: (previous: T, next: T) => boolean;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Configuration for `useDebouncer` and every hook built on top of it.
|
|
450
|
+
*
|
|
451
|
+
* @remarks
|
|
452
|
+
* `leading` and `trailing` may both be set to `false` at the same time —
|
|
453
|
+
* the hook will not silently correct this for you. That configuration
|
|
454
|
+
* means the debounced function will never run; a dev-mode warning is
|
|
455
|
+
* logged to help catch it early, but the choice itself is respected.
|
|
456
|
+
*/
|
|
420
457
|
export interface DebounceOptions {
|
|
458
|
+
/**
|
|
459
|
+
* A hard ceiling, in milliseconds, on how long invocation can be
|
|
460
|
+
* deferred. If a continuous stream of calls keeps pushing the trailing
|
|
461
|
+
* timer out, `maxWait` forces a synchronous invocation once this many
|
|
462
|
+
* milliseconds have elapsed since the current cycle began — regardless
|
|
463
|
+
* of whether the trailing window has settled yet.
|
|
464
|
+
*
|
|
465
|
+
* Only evaluated at the moment `run()` is called; it is not an
|
|
466
|
+
* independent background timer, so it can't fire while no calls are
|
|
467
|
+
* coming in.
|
|
468
|
+
*
|
|
469
|
+
* @defaultValue `undefined` (no ceiling)
|
|
470
|
+
*/
|
|
421
471
|
maxWait?: number;
|
|
472
|
+
/**
|
|
473
|
+
* When `true`, invokes on the leading edge — immediately, on the first
|
|
474
|
+
* call of a new debounce cycle (i.e. when no cycle is currently active).
|
|
475
|
+
*
|
|
476
|
+
* @defaultValue `false`
|
|
477
|
+
*/
|
|
422
478
|
leading?: boolean;
|
|
479
|
+
/**
|
|
480
|
+
* When `true`, invokes on the trailing edge — once `delay` milliseconds
|
|
481
|
+
* have elapsed with no further calls.
|
|
482
|
+
*
|
|
483
|
+
* Defaults to `true` regardless of `leading`'s value. With
|
|
484
|
+
* `{ leading: true, trailing: true }` (both edges enabled), a single
|
|
485
|
+
* isolated call only fires once (the leading edge) — the trailing edge
|
|
486
|
+
* only fires if at least one more call arrives before the window
|
|
487
|
+
* closes.
|
|
488
|
+
*
|
|
489
|
+
* @defaultValue `true`
|
|
490
|
+
*/
|
|
423
491
|
trailing?: boolean;
|
|
424
492
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
493
|
+
/**
|
|
494
|
+
* Options for `useDebouncedState`: all of {@link DebounceOptions}, plus an
|
|
495
|
+
* optional equality comparator used to skip committing a value equivalent
|
|
496
|
+
* to the one already held.
|
|
497
|
+
*/
|
|
498
|
+
export type UseDebouncedStateOptions<T> = DebounceOptions & EqualityFnOption<T>;
|
|
499
|
+
/**
|
|
500
|
+
* Options for `useDebouncedValue`: all of {@link DebounceOptions}, plus an
|
|
501
|
+
* optional equality comparator used to skip committing a value equivalent
|
|
502
|
+
* to the one already held.
|
|
503
|
+
*/
|
|
504
|
+
export type UseDebouncedValueOptions<T> = DebounceOptions & EqualityFnOption<T>;
|
|
505
|
+
/**
|
|
506
|
+
* The object returned by `useDebouncedCallback`.
|
|
507
|
+
*/
|
|
432
508
|
export interface UseDebouncedCallbackReturn<Args extends unknown[]> {
|
|
509
|
+
/**
|
|
510
|
+
* A stable, debounced wrapper around `func`. Safe to call from any
|
|
511
|
+
* event handler; internally always invokes the most recently rendered
|
|
512
|
+
* `func`, even though `debouncedFunc`'s own identity doesn't change
|
|
513
|
+
* across re-renders.
|
|
514
|
+
*/
|
|
433
515
|
debouncedFunc: (...args: Args) => void;
|
|
516
|
+
/** See {@link UseDebouncerReturn.cancel}. */
|
|
434
517
|
cancel: () => void;
|
|
518
|
+
/** See {@link UseDebouncerReturn.flush}. */
|
|
435
519
|
flush: () => void;
|
|
520
|
+
/** See {@link UseDebouncerReturn.isPending}. */
|
|
436
521
|
isPending: boolean;
|
|
437
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* Debounces a single function.
|
|
525
|
+
*
|
|
526
|
+
* `func` is captured in a ref and refreshed on every render — you can pass
|
|
527
|
+
* a fresh inline closure every time without resetting the pending debounce
|
|
528
|
+
* cycle, and the debounced wrapper always calls the *latest* `func`,
|
|
529
|
+
* closing over whatever props/state were current when it actually fires
|
|
530
|
+
* (never a stale closure from whenever the wrapper was first created).
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```tsx
|
|
534
|
+
* function SearchBox() {
|
|
535
|
+
* const { debouncedFunc: handleSearch, isPending } = useDebouncedCallback(
|
|
536
|
+
* (query: string) => fetchResults(query),
|
|
537
|
+
* 400,
|
|
538
|
+
* );
|
|
539
|
+
*
|
|
540
|
+
* return (
|
|
541
|
+
* <>
|
|
542
|
+
* <input onChange={(e) => handleSearch(e.target.value)} />
|
|
543
|
+
* {isPending && <span>Typing…</span>}
|
|
544
|
+
* </>
|
|
545
|
+
* );
|
|
546
|
+
* }
|
|
547
|
+
* ```
|
|
548
|
+
*
|
|
549
|
+
* @param func - The function to debounce. Safe to pass a new closure on
|
|
550
|
+
* every render.
|
|
551
|
+
* @param delay - See {@link useDebouncer}.
|
|
552
|
+
* @param options - See {@link DebounceOptions}.
|
|
553
|
+
* @returns See {@link UseDebouncedCallbackReturn}.
|
|
554
|
+
*/
|
|
438
555
|
export declare function useDebouncedCallback<Args extends unknown[]>(func: (...args: Args) => void, delay: number, options?: DebounceOptions): UseDebouncedCallbackReturn<Args>;
|
|
556
|
+
/**
|
|
557
|
+
* The tuple returned by `useDebouncedState`, mirroring `useState`'s
|
|
558
|
+
* `[value, setValue]` shape with a third element carrying debounce
|
|
559
|
+
* controls.
|
|
560
|
+
*/
|
|
439
561
|
export type UseDebouncedStateReturn<T> = [
|
|
562
|
+
/** The current, committed state value. */
|
|
440
563
|
T,
|
|
441
|
-
|
|
564
|
+
/**
|
|
565
|
+
* Schedules a debounced update to state. Accepts either a plain value
|
|
566
|
+
* or a `useState`-style functional updater (`(previous) => next`).
|
|
567
|
+
*
|
|
568
|
+
* The functional-updater form composes correctly across multiple rapid
|
|
569
|
+
* calls made before the debounce settles — e.g. calling
|
|
570
|
+
* `setValue((p) => p + 1)` three times in a row schedules a cumulative
|
|
571
|
+
* `+3`, not three competing `+1`s racing to be "the" pending value.
|
|
572
|
+
* `previous` in that case refers to the most recently *scheduled*
|
|
573
|
+
* value, not necessarily the currently-committed state — this matters
|
|
574
|
+
* if you're chaining updates faster than the debounce settles.
|
|
575
|
+
*/
|
|
576
|
+
(value: T | ((previous: T) => T)) => void,
|
|
442
577
|
{
|
|
578
|
+
/** See {@link UseDebouncerReturn.isPending}. */
|
|
443
579
|
isPending: boolean;
|
|
580
|
+
/**
|
|
581
|
+
* Cancels any pending debounced update. Also resyncs the internal
|
|
582
|
+
* "next value to commit" tracking back to the current committed
|
|
583
|
+
* state, so a subsequent functional update starts from the right
|
|
584
|
+
* baseline instead of building on a discarded value.
|
|
585
|
+
*/
|
|
444
586
|
cancel: () => void;
|
|
587
|
+
/** See {@link UseDebouncerReturn.flush}. */
|
|
445
588
|
flush: () => void;
|
|
446
|
-
|
|
589
|
+
/**
|
|
590
|
+
* Bypasses debounce scheduling entirely and applies the value (or
|
|
591
|
+
* updater) immediately. Also cancels any debounced update that was
|
|
592
|
+
* still pending, so it can't land afterward and silently overwrite
|
|
593
|
+
* this forced value.
|
|
594
|
+
*/
|
|
595
|
+
forceSetValue: (value: T | ((previous: T) => T)) => void;
|
|
447
596
|
}
|
|
448
597
|
];
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
598
|
+
/**
|
|
599
|
+
* A `useState`-shaped hook whose setter defers its effect on state until
|
|
600
|
+
* the debounce window settles, instead of applying immediately.
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```tsx
|
|
604
|
+
* function NoteEditor() {
|
|
605
|
+
* const [note, setNote, { isPending, flush, forceSetValue }] =
|
|
606
|
+
* useDebouncedState("", 800);
|
|
607
|
+
*
|
|
608
|
+
* return (
|
|
609
|
+
* <>
|
|
610
|
+
* <textarea onChange={(e) => setNote(e.target.value)} />
|
|
611
|
+
* <p>Committed: {note}</p>
|
|
612
|
+
* {isPending && <span>Unsaved changes…</span>}
|
|
613
|
+
* <button onClick={flush}>Save Now</button>
|
|
614
|
+
* <button onClick={() => forceSetValue("")}>Reset</button>
|
|
615
|
+
* </>
|
|
616
|
+
* );
|
|
617
|
+
* }
|
|
618
|
+
* ```
|
|
619
|
+
*
|
|
620
|
+
* @param initialValue - Initial state value, or a `useState`-style lazy
|
|
621
|
+
* initializer function (`() => T`).
|
|
622
|
+
* @param delay - See {@link useDebouncer}.
|
|
623
|
+
* @param options - See {@link UseDebouncedStateOptions}.
|
|
624
|
+
* @returns See {@link UseDebouncedStateReturn}.
|
|
625
|
+
*/
|
|
626
|
+
export declare function useDebouncedState<T>(initialValue: T | (() => T), delay: number, options?: UseDebouncedStateOptions<T>): UseDebouncedStateReturn<T>;
|
|
627
|
+
/**
|
|
628
|
+
* The tuple returned by `useDebouncedValue`.
|
|
629
|
+
*/
|
|
630
|
+
export type UseDebouncedValueReturn<T> = [
|
|
631
|
+
/** The debounced (lagging) mirror of the source value. */
|
|
632
|
+
T,
|
|
633
|
+
{
|
|
634
|
+
/** See {@link UseDebouncerReturn.isPending}. */
|
|
635
|
+
isPending: boolean;
|
|
636
|
+
/** Cancels the pending sync to the latest source value. */
|
|
637
|
+
cancel: () => void;
|
|
638
|
+
/** Immediately commits the latest source value, bypassing the delay. */
|
|
639
|
+
flush: () => void;
|
|
640
|
+
}
|
|
641
|
+
];
|
|
642
|
+
/**
|
|
643
|
+
* Mirrors `value`, but the mirror only updates `delay` milliseconds after
|
|
644
|
+
* `value` stops changing — a safe, stable dependency for an expensive
|
|
645
|
+
* effect (filtering, fetching) that shouldn't re-run on every keystroke.
|
|
646
|
+
*
|
|
647
|
+
* @example
|
|
648
|
+
* ```tsx
|
|
649
|
+
* function ProductFilterField() {
|
|
650
|
+
* const [query, setQuery] = useState("");
|
|
651
|
+
* const [debouncedQuery] = useDebouncedValue(query, 350);
|
|
652
|
+
*
|
|
653
|
+
* // `debouncedQuery` only updates 350ms after typing stops.
|
|
654
|
+
*
|
|
655
|
+
* return (
|
|
656
|
+
* <input value={query} onChange={(e) => setQuery(e.target.value)} />
|
|
657
|
+
* );
|
|
658
|
+
* }
|
|
659
|
+
* ```
|
|
660
|
+
*
|
|
661
|
+
* @param value - The source value to debounce. Every change re-arms the
|
|
662
|
+
* debounce window.
|
|
663
|
+
* @param delay - See {@link useDebouncer}.
|
|
664
|
+
* @param options - See {@link UseDebouncedValueOptions}.
|
|
665
|
+
* @returns See {@link UseDebouncedValueReturn}.
|
|
666
|
+
*/
|
|
667
|
+
export declare function useDebouncedValue<T>(value: T, delay: number, options?: UseDebouncedValueOptions<T>): UseDebouncedValueReturn<T>;
|
|
668
|
+
/**
|
|
669
|
+
* The object returned by `useDebouncer`.
|
|
670
|
+
*/
|
|
671
|
+
export interface UseDebouncerReturn {
|
|
672
|
+
/**
|
|
673
|
+
* Registers `func` (with `args`) as the function this debounce cycle
|
|
674
|
+
* will invoke, and (re)arms the debounce timer.
|
|
675
|
+
*
|
|
676
|
+
* Each call to `run()` accepts its own function — you are not locked
|
|
677
|
+
* into debouncing a single, fixed callback. If `run()` is called again
|
|
678
|
+
* before the pending timer fires, the previously-registered function
|
|
679
|
+
* and arguments are discarded entirely in favor of the new ones (a
|
|
680
|
+
* "last write wins" swap, not a queue).
|
|
681
|
+
*
|
|
682
|
+
* @example
|
|
683
|
+
* ```ts
|
|
684
|
+
* const { run } = useDebouncer(300);
|
|
685
|
+
*
|
|
686
|
+
* run((query: string) => fetchResults(query), searchTerm);
|
|
687
|
+
* ```
|
|
688
|
+
*/
|
|
689
|
+
run: <Args extends unknown[]>(func: (...args: Args) => void, ...args: Args) => void;
|
|
690
|
+
/**
|
|
691
|
+
* Clears the pending timer and discards whatever function/arguments
|
|
692
|
+
* were registered via `run()`, without invoking anything. Sets
|
|
693
|
+
* `isPending` back to `false`.
|
|
694
|
+
*/
|
|
695
|
+
cancel: () => void;
|
|
696
|
+
/**
|
|
697
|
+
* If a function is currently pending invocation, invokes it immediately
|
|
698
|
+
* (with its most recently registered arguments) and clears the timer.
|
|
699
|
+
* If nothing is pending, this is a no-op.
|
|
700
|
+
*/
|
|
701
|
+
flush: () => void;
|
|
702
|
+
/**
|
|
703
|
+
* `true` whenever a trailing invocation is still scheduled to happen
|
|
704
|
+
* when the current cycle settles. `false` once it's known nothing
|
|
705
|
+
* further will fire — including immediately after a leading-edge
|
|
706
|
+
* invocation if `trailing` is disabled, not merely once the full window
|
|
707
|
+
* elapses.
|
|
708
|
+
*/
|
|
709
|
+
isPending: boolean;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* The debounce engine underlying every hook in this family.
|
|
713
|
+
*
|
|
714
|
+
* `useDebouncer` is a low-level scheduling primitive: a single timer and a
|
|
715
|
+
* single "next function to run" slot. Calling `run(func, ...args)`
|
|
716
|
+
* registers `func` as the occupant of that slot; if `run()` is called
|
|
717
|
+
* again before the timer fires, the new function/arguments replace the old
|
|
718
|
+
* ones outright.
|
|
719
|
+
*
|
|
720
|
+
* Most consumers won't reach for this directly — `useDebouncedCallback`,
|
|
721
|
+
* `useDebouncedState`, and `useDebouncedValue` are thin, purpose-built
|
|
722
|
+
* wrappers around it for the common cases (debouncing one fixed callback,
|
|
723
|
+
* a piece of state, or an incoming value). Use `useDebouncer` directly when
|
|
724
|
+
* you need the "swap, don't queue" behavior across genuinely different
|
|
725
|
+
* functions — see the example below.
|
|
726
|
+
*
|
|
727
|
+
* @example
|
|
728
|
+
* ```tsx
|
|
729
|
+
* function DocumentActionBar() {
|
|
730
|
+
* const { run, isPending } = useDebouncer(1000);
|
|
731
|
+
*
|
|
732
|
+
* const handleSave = () => run(() => saveDocument());
|
|
733
|
+
* const handleCancel = () => run(() => discardChanges());
|
|
734
|
+
*
|
|
735
|
+
* return (
|
|
736
|
+
* <>
|
|
737
|
+
* <button onClick={handleSave}>Save</button>
|
|
738
|
+
* <button onClick={handleCancel}>Cancel</button>
|
|
739
|
+
* {isPending && <span>Pending…</span>}
|
|
740
|
+
* </>
|
|
741
|
+
* );
|
|
742
|
+
* }
|
|
743
|
+
* ```
|
|
744
|
+
*
|
|
745
|
+
* @param delay - Milliseconds to wait before a trailing invocation fires.
|
|
746
|
+
* Coerced to a non-negative number; invalid input falls back to `0` with a
|
|
747
|
+
* dev-mode warning.
|
|
748
|
+
* @param options - See {@link DebounceOptions}.
|
|
749
|
+
* @returns See {@link UseDebouncerReturn}.
|
|
750
|
+
*/
|
|
751
|
+
export declare function useDebouncer(delay: number, options?: DebounceOptions): UseDebouncerReturn;
|
|
752
|
+
/**
|
|
753
|
+
* Configuration for `useRateLimiter` and every hook built on top of it.
|
|
754
|
+
*/
|
|
452
755
|
export interface RateLimitOptions {
|
|
756
|
+
/**
|
|
757
|
+
* Called whenever a call is rejected because no executions remain in
|
|
758
|
+
* the current window.
|
|
759
|
+
*
|
|
760
|
+
* Safe to pass a fresh inline function on every render — it's captured
|
|
761
|
+
* in a ref and refreshed via effect, so it never causes the underlying
|
|
762
|
+
* timers to reset.
|
|
763
|
+
*
|
|
764
|
+
* @defaultValue `undefined`
|
|
765
|
+
*/
|
|
453
766
|
onRateLimitReached?: () => void;
|
|
767
|
+
/**
|
|
768
|
+
* Determines how the allowance replenishes once consumed.
|
|
769
|
+
*
|
|
770
|
+
* - `"burst"` — fixed window. All executions reset to the full `limit`
|
|
771
|
+
* at once, only once the entire `windowMs` duration has elapsed
|
|
772
|
+
* since the window began.
|
|
773
|
+
* - `"gradual"` — trickle refill. Executions return proportionately as
|
|
774
|
+
* time passes (`windowMs / limit` per execution), with no hard reset
|
|
775
|
+
* boundary.
|
|
776
|
+
*
|
|
777
|
+
* @defaultValue `"burst"`
|
|
778
|
+
*/
|
|
454
779
|
refillStrategy?: "burst" | "gradual";
|
|
455
780
|
}
|
|
456
|
-
|
|
457
|
-
|
|
781
|
+
/**
|
|
782
|
+
* Options for `useRateLimitedState`: all of {@link RateLimitOptions}, plus
|
|
783
|
+
* an optional equality comparator used to skip committing a value
|
|
784
|
+
* equivalent to the one already held.
|
|
785
|
+
*/
|
|
786
|
+
export type UseRateLimitedStateOptions<T> = RateLimitOptions & EqualityFnOption<T>;
|
|
787
|
+
/**
|
|
788
|
+
* Options for `useRateLimitedValue`: all of {@link RateLimitOptions}, plus
|
|
789
|
+
* an optional equality comparator used to skip committing a value
|
|
790
|
+
* equivalent to the one already held.
|
|
791
|
+
*/
|
|
792
|
+
export type UseRateLimitedValueOptions<T> = RateLimitOptions & EqualityFnOption<T>;
|
|
793
|
+
/**
|
|
794
|
+
* The object returned by `useRateLimitedCallback`.
|
|
795
|
+
*/
|
|
796
|
+
export interface UseRateLimitedCallbackReturn<Args extends unknown[]> {
|
|
797
|
+
/**
|
|
798
|
+
* A stable, rate-limited wrapper around `func`. Always invokes the
|
|
799
|
+
* most recently rendered `func`, even though `rateLimitedFunc`'s own
|
|
800
|
+
* identity doesn't change across re-renders.
|
|
801
|
+
*
|
|
802
|
+
* @returns `true` if `func` was invoked, `false` if the call was
|
|
803
|
+
* rejected because the allowance is exhausted.
|
|
804
|
+
*/
|
|
805
|
+
rateLimitedFunc: (...args: Args) => boolean;
|
|
806
|
+
/** See {@link UseRateLimiterReturn.reset}. */
|
|
807
|
+
reset: () => void;
|
|
808
|
+
/** See {@link UseRateLimiterReturn.remaining}. */
|
|
458
809
|
remaining: number;
|
|
810
|
+
/** See {@link UseRateLimiterReturn.isRateLimited}. */
|
|
459
811
|
isRateLimited: boolean;
|
|
460
812
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
813
|
+
/**
|
|
814
|
+
* Rate-limits a single function.
|
|
815
|
+
*
|
|
816
|
+
* `func` is captured in a ref and refreshed on every render — you can
|
|
817
|
+
* pass a fresh inline closure every time without resetting the
|
|
818
|
+
* underlying allowance tracking, and the wrapper always calls the
|
|
819
|
+
* *latest* `func`.
|
|
820
|
+
*
|
|
821
|
+
* @example
|
|
822
|
+
* ```tsx
|
|
823
|
+
* function SearchBox() {
|
|
824
|
+
* const { rateLimitedFunc, isRateLimited } = useRateLimitedCallback(
|
|
825
|
+
* (query: string) => fetch(`/api/search?q=${query}`),
|
|
826
|
+
* 10,
|
|
827
|
+
* 60_000,
|
|
828
|
+
* { refillStrategy: "gradual" },
|
|
829
|
+
* );
|
|
830
|
+
*
|
|
831
|
+
* return (
|
|
832
|
+
* <input
|
|
833
|
+
* disabled={isRateLimited}
|
|
834
|
+
* onChange={(e) => rateLimitedFunc(e.target.value)}
|
|
835
|
+
* />
|
|
836
|
+
* );
|
|
837
|
+
* }
|
|
838
|
+
* ```
|
|
839
|
+
*
|
|
840
|
+
* @param func - The function to rate-limit. Safe to pass a new closure
|
|
841
|
+
* on every render.
|
|
842
|
+
* @param limit - See {@link useRateLimiter}.
|
|
843
|
+
* @param windowMs - See {@link useRateLimiter}.
|
|
844
|
+
* @param options - See {@link RateLimitOptions}.
|
|
845
|
+
* @returns See {@link UseRateLimitedCallbackReturn}.
|
|
846
|
+
*/
|
|
847
|
+
export declare function useRateLimitedCallback<Args extends unknown[]>(func: (...args: Args) => void, limit: number, windowMs: number, options?: RateLimitOptions): UseRateLimitedCallbackReturn<Args>;
|
|
848
|
+
/**
|
|
849
|
+
* The tuple returned by `useRateLimitedState`, mirroring `useState`'s
|
|
850
|
+
* `[value, setValue]` shape with a third element carrying rate-limit
|
|
851
|
+
* controls.
|
|
852
|
+
*/
|
|
853
|
+
export type UseRateLimitedStateReturn<T> = [
|
|
854
|
+
/** The current, committed state value. */
|
|
855
|
+
T,
|
|
856
|
+
/**
|
|
857
|
+
* Attempts to update state. Accepts either a plain value or a
|
|
858
|
+
* `useState`-style functional updater (`(previous) => next`).
|
|
859
|
+
*
|
|
860
|
+
* Unlike the debounce/throttle `State` variants, nothing here is ever
|
|
861
|
+
* deferred — the update either applies immediately (against the
|
|
862
|
+
* genuinely current state, via React's own functional `setState`) or
|
|
863
|
+
* is rejected outright and state doesn't change at all. There's no
|
|
864
|
+
* "most recently scheduled value" to reason about, since nothing is
|
|
865
|
+
* ever queued.
|
|
866
|
+
*
|
|
867
|
+
* @returns `true` if the update was applied, `false` if it was
|
|
868
|
+
* rejected because the allowance is exhausted.
|
|
869
|
+
*/
|
|
870
|
+
(value: T | ((previous: T) => T)) => boolean,
|
|
871
|
+
{
|
|
872
|
+
/** See {@link UseRateLimiterReturn.remaining}. */
|
|
873
|
+
remaining: number;
|
|
874
|
+
/** See {@link UseRateLimiterReturn.isRateLimited}. */
|
|
875
|
+
isRateLimited: boolean;
|
|
876
|
+
/** See {@link UseRateLimiterReturn.reset}. */
|
|
877
|
+
reset: () => void;
|
|
878
|
+
/**
|
|
879
|
+
* Bypasses rate-limit enforcement entirely and applies the value
|
|
880
|
+
* (or updater) immediately. Does not consume any of the allowance.
|
|
881
|
+
*/
|
|
882
|
+
forceSetValue: (value: T | ((previous: T) => T)) => void;
|
|
883
|
+
}
|
|
884
|
+
];
|
|
885
|
+
/**
|
|
886
|
+
* A `useState`-shaped hook whose setter can be rejected once the
|
|
887
|
+
* allowance for the current window is exhausted, instead of always
|
|
888
|
+
* applying.
|
|
889
|
+
*
|
|
890
|
+
* @example
|
|
891
|
+
* ```tsx
|
|
892
|
+
* function GenerationDemo() {
|
|
893
|
+
* const [result, generate, { remaining, isRateLimited }] =
|
|
894
|
+
* useRateLimitedState<string | null>(null, 3, 60_000);
|
|
895
|
+
*
|
|
896
|
+
* const handleGenerate = () => {
|
|
897
|
+
* if (!generate(`Result #${Math.random()}`)) {
|
|
898
|
+
* toast("Free limit reached — try again in a minute.");
|
|
899
|
+
* }
|
|
900
|
+
* };
|
|
901
|
+
*
|
|
902
|
+
* return (
|
|
903
|
+
* <>
|
|
904
|
+
* <button onClick={handleGenerate} disabled={isRateLimited}>
|
|
905
|
+
* Generate ({remaining} left)
|
|
906
|
+
* </button>
|
|
907
|
+
* <p>{result}</p>
|
|
908
|
+
* </>
|
|
909
|
+
* );
|
|
910
|
+
* }
|
|
911
|
+
* ```
|
|
912
|
+
*
|
|
913
|
+
* @param initialValue - Initial state value, or a `useState`-style lazy
|
|
914
|
+
* initializer function (`() => T`).
|
|
915
|
+
* @param limit - See {@link useRateLimiter}.
|
|
916
|
+
* @param windowMs - See {@link useRateLimiter}.
|
|
917
|
+
* @param options - See {@link UseRateLimitedStateOptions}.
|
|
918
|
+
* @returns See {@link UseRateLimitedStateReturn}.
|
|
919
|
+
*/
|
|
920
|
+
export declare function useRateLimitedState<T>(initialValue: T | (() => T), limit: number, windowMs: number, options?: UseRateLimitedStateOptions<T>): UseRateLimitedStateReturn<T>;
|
|
921
|
+
/**
|
|
922
|
+
* The tuple returned by `useRateLimitedValue`.
|
|
923
|
+
*/
|
|
924
|
+
export type UseRateLimitedValueReturn<T> = [
|
|
925
|
+
/** The rate-limited mirror of the source value. */
|
|
926
|
+
T,
|
|
927
|
+
{
|
|
928
|
+
/** See {@link UseRateLimiterReturn.remaining}. */
|
|
929
|
+
remaining: number;
|
|
930
|
+
/** See {@link UseRateLimiterReturn.isRateLimited}. */
|
|
931
|
+
isRateLimited: boolean;
|
|
932
|
+
/** See {@link UseRateLimiterReturn.reset}. */
|
|
933
|
+
reset: () => void;
|
|
934
|
+
}
|
|
935
|
+
];
|
|
936
|
+
/**
|
|
937
|
+
* Mirrors `value`, but the mirror updates at most `limit` times per
|
|
938
|
+
* `windowMs` window.
|
|
939
|
+
*
|
|
940
|
+
* @remarks
|
|
941
|
+
* This has a meaningfully weaker guarantee than `useDebouncedValue` /
|
|
942
|
+
* `useThrottledValue`. Those hooks eventually deliver the *latest* value
|
|
943
|
+
* once their window settles, even if intermediate values were skipped.
|
|
944
|
+
* This hook does not — once the allowance is exhausted, incoming changes
|
|
945
|
+
* to `value` are dropped outright until the allowance refills, with no
|
|
946
|
+
* queueing and no catch-up. The mirror simply stays frozen at whatever it
|
|
947
|
+
* last committed until it's allowed to update again.
|
|
948
|
+
*
|
|
949
|
+
* @example
|
|
950
|
+
* ```tsx
|
|
951
|
+
* function NotificationFeed({ latestNotification }: { latestNotification: string }) {
|
|
952
|
+
* const [visibleNotification] = useRateLimitedValue(latestNotification, 3, 10_000);
|
|
953
|
+
*
|
|
954
|
+
* // At most 3 notifications surface per 10s window; any beyond that
|
|
955
|
+
* // are silently dropped rather than queued for later display.
|
|
956
|
+
*
|
|
957
|
+
* return <Toast message={visibleNotification} />;
|
|
958
|
+
* }
|
|
959
|
+
* ```
|
|
960
|
+
*
|
|
961
|
+
* @param value - The source value to rate-limit. Every change is subject
|
|
962
|
+
* to the current allowance.
|
|
963
|
+
* @param limit - See {@link useRateLimiter}.
|
|
964
|
+
* @param windowMs - See {@link useRateLimiter}.
|
|
965
|
+
* @param options - See {@link UseRateLimitedValueOptions}.
|
|
966
|
+
* @returns See {@link UseRateLimitedValueReturn}.
|
|
967
|
+
*/
|
|
968
|
+
export declare function useRateLimitedValue<T>(value: T, limit: number, windowMs: number, options?: UseRateLimitedValueOptions<T>): UseRateLimitedValueReturn<T>;
|
|
969
|
+
/**
|
|
970
|
+
* The object returned by `useRateLimiter`.
|
|
971
|
+
*/
|
|
972
|
+
export interface UseRateLimiterReturn {
|
|
973
|
+
/**
|
|
974
|
+
* Attempts to invoke `func` (with `args`) against the current
|
|
975
|
+
* allowance.
|
|
976
|
+
*
|
|
977
|
+
* Unlike `useDebouncer`/`useThrottler`, nothing here is ever deferred —
|
|
978
|
+
* every call to `run()` resolves synchronously, right now: either an
|
|
979
|
+
* execution is available and `func` runs immediately, or it isn't and
|
|
980
|
+
* `func` doesn't run at all (no queueing, no later catch-up).
|
|
981
|
+
*
|
|
982
|
+
* Each call accepts its own function, so a single `useRateLimiter`
|
|
983
|
+
* instance can gate several different actions against one shared
|
|
984
|
+
* allowance if needed.
|
|
985
|
+
*
|
|
986
|
+
* @returns `true` if `func` was invoked, `false` if the call was
|
|
987
|
+
* rejected because the current window's allowance is exhausted.
|
|
988
|
+
*
|
|
989
|
+
* @example
|
|
990
|
+
* ```ts
|
|
991
|
+
* const { run } = useRateLimiter(3, 10_000);
|
|
992
|
+
*
|
|
993
|
+
* const didFire = run(() => submitForm());
|
|
994
|
+
* if (!didFire) showToast("Too many attempts — please wait.");
|
|
995
|
+
* ```
|
|
996
|
+
*/
|
|
997
|
+
run: <Args extends unknown[]>(func: (...args: Args) => void, ...args: Args) => boolean;
|
|
998
|
+
/**
|
|
999
|
+
* Immediately restores the full allowance and clears any in-progress
|
|
1000
|
+
* background refill, bypassing the normal window/refill timing
|
|
1001
|
+
* entirely. Useful after an unrelated event that should grant a fresh
|
|
1002
|
+
* allowance outright — e.g. a successful CAPTCHA, or a plan upgrade.
|
|
1003
|
+
*/
|
|
1004
|
+
reset: () => void;
|
|
1005
|
+
/**
|
|
1006
|
+
* The number of executions currently available. Kept accurate in real
|
|
1007
|
+
* time — including while idle, with no further calls to `run()` —
|
|
1008
|
+
* by a self-scheduling background timer that mirrors whichever
|
|
1009
|
+
* `refillStrategy` is configured.
|
|
1010
|
+
*/
|
|
464
1011
|
remaining: number;
|
|
1012
|
+
/** Convenience flag, equivalent to `remaining === 0`. */
|
|
465
1013
|
isRateLimited: boolean;
|
|
466
1014
|
}
|
|
467
|
-
|
|
1015
|
+
/**
|
|
1016
|
+
* The rate-limiting engine underlying every hook in this family.
|
|
1017
|
+
*
|
|
1018
|
+
* `useRateLimiter` grants up to `limit` executions per `windowMs` window,
|
|
1019
|
+
* replenished according to `refillStrategy`. Unlike debounce or throttle,
|
|
1020
|
+
* it never delays or reshapes *when* something runs — every call is an
|
|
1021
|
+
* immediate accept-or-reject decision against the current allowance.
|
|
1022
|
+
*
|
|
1023
|
+
* Most consumers won't reach for this directly — `useRateLimitedCallback`,
|
|
1024
|
+
* `useRateLimitedState`, and `useRateLimitedValue` are thin, purpose-built
|
|
1025
|
+
* wrappers around it for the common cases.
|
|
1026
|
+
*
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```tsx
|
|
1029
|
+
* function SubmitButton() {
|
|
1030
|
+
* const { run, remaining, isRateLimited } = useRateLimiter(3, 10_000, {
|
|
1031
|
+
* refillStrategy: "burst",
|
|
1032
|
+
* onRateLimitReached: () => toast("Too many attempts."),
|
|
1033
|
+
* });
|
|
1034
|
+
*
|
|
1035
|
+
* return (
|
|
1036
|
+
* <button onClick={() => run(submitForm)} disabled={isRateLimited}>
|
|
1037
|
+
* Submit ({remaining} left)
|
|
1038
|
+
* </button>
|
|
1039
|
+
* );
|
|
1040
|
+
* }
|
|
1041
|
+
* ```
|
|
1042
|
+
*
|
|
1043
|
+
* @param limit - Maximum executions allowed per window. Coerced to a
|
|
1044
|
+
* non-negative integer with a floor of `1`; invalid input falls back to
|
|
1045
|
+
* `1` with a dev-mode warning.
|
|
1046
|
+
* @param windowMs - Length of the rate-limit window, in milliseconds.
|
|
1047
|
+
* Coerced to a non-negative number; invalid input falls back to `0` with
|
|
1048
|
+
* a dev-mode warning. A value of `0` disables rate limiting entirely
|
|
1049
|
+
* (every call is allowed) rather than causing a division error — also
|
|
1050
|
+
* dev-warned, since it's rarely intentional.
|
|
1051
|
+
* @param options - See {@link RateLimitOptions}.
|
|
1052
|
+
* @returns See {@link UseRateLimiterReturn}.
|
|
1053
|
+
*/
|
|
1054
|
+
export declare function useRateLimiter(limit: number, windowMs: number, options?: RateLimitOptions): UseRateLimiterReturn;
|
|
1055
|
+
/**
|
|
1056
|
+
* Configuration for `useThrottler` and every hook built on top of it.
|
|
1057
|
+
*
|
|
1058
|
+
* @remarks
|
|
1059
|
+
* `leading` and `trailing` may both be set to `false` at the same time —
|
|
1060
|
+
* the hook will not silently correct this for you. That configuration
|
|
1061
|
+
* means the throttled function will never run; a dev-mode warning is
|
|
1062
|
+
* logged to help catch it early, but the choice itself is respected.
|
|
1063
|
+
*/
|
|
468
1064
|
export interface ThrottleOptions {
|
|
1065
|
+
/**
|
|
1066
|
+
* When `true`, invokes immediately on the first call of a new cooldown
|
|
1067
|
+
* window.
|
|
1068
|
+
*
|
|
1069
|
+
* @defaultValue `true`
|
|
1070
|
+
*/
|
|
469
1071
|
leading?: boolean;
|
|
1072
|
+
/**
|
|
1073
|
+
* When `true`, invokes once more at the end of the cooldown window,
|
|
1074
|
+
* using the most recently passed function/arguments — but only if at
|
|
1075
|
+
* least one call arrived after the leading edge fired. A single
|
|
1076
|
+
* isolated call with both edges enabled only fires once.
|
|
1077
|
+
*
|
|
1078
|
+
* @defaultValue `true`
|
|
1079
|
+
*/
|
|
470
1080
|
trailing?: boolean;
|
|
471
1081
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
1082
|
+
/**
|
|
1083
|
+
* Options for `useThrottledState`: all of {@link ThrottleOptions}, plus an
|
|
1084
|
+
* optional equality comparator used to skip committing a value equivalent
|
|
1085
|
+
* to the one already held.
|
|
1086
|
+
*/
|
|
1087
|
+
export type UseThrottledStateOptions<T> = ThrottleOptions & EqualityFnOption<T>;
|
|
1088
|
+
/**
|
|
1089
|
+
* Options for `useThrottledValue`: all of {@link ThrottleOptions}, plus an
|
|
1090
|
+
* optional equality comparator used to skip committing a value equivalent
|
|
1091
|
+
* to the one already held.
|
|
1092
|
+
*/
|
|
1093
|
+
export type UseThrottledValueOptions<T> = ThrottleOptions & EqualityFnOption<T>;
|
|
1094
|
+
/**
|
|
1095
|
+
* The object returned by `useThrottledCallback`.
|
|
1096
|
+
*/
|
|
479
1097
|
export interface UseThrottledCallbackReturn<Args extends unknown[]> {
|
|
1098
|
+
/**
|
|
1099
|
+
* A stable, throttled wrapper around `func`. Safe to attach directly
|
|
1100
|
+
* to an event listener; internally always invokes the most recently
|
|
1101
|
+
* rendered `func`, even though `throttledFunc`'s own identity doesn't
|
|
1102
|
+
* change across re-renders.
|
|
1103
|
+
*/
|
|
480
1104
|
throttledFunc: (...args: Args) => void;
|
|
1105
|
+
/** See {@link UseThrottlerReturn.cancel}. */
|
|
481
1106
|
cancel: () => void;
|
|
1107
|
+
/** See {@link UseThrottlerReturn.flush}. */
|
|
482
1108
|
flush: () => void;
|
|
1109
|
+
/** See {@link UseThrottlerReturn.isPending}. */
|
|
483
1110
|
isPending: boolean;
|
|
484
1111
|
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Throttles a single function.
|
|
1114
|
+
*
|
|
1115
|
+
* `func` is captured in a ref and refreshed on every render — you can pass
|
|
1116
|
+
* a fresh inline closure every time without resetting the running cooldown
|
|
1117
|
+
* window, and the throttled wrapper always calls the *latest* `func`,
|
|
1118
|
+
* closing over whatever props/state were current when it actually fires
|
|
1119
|
+
* (never a stale closure from whenever the wrapper was first created).
|
|
1120
|
+
*
|
|
1121
|
+
* @example
|
|
1122
|
+
* ```tsx
|
|
1123
|
+
* function WindowSizeLogger() {
|
|
1124
|
+
* const { throttledFunc: handleResize } = useThrottledCallback(
|
|
1125
|
+
* () => console.log("width:", window.innerWidth),
|
|
1126
|
+
* 200,
|
|
1127
|
+
* );
|
|
1128
|
+
*
|
|
1129
|
+
* useEffect(() => {
|
|
1130
|
+
* window.addEventListener("resize", handleResize);
|
|
1131
|
+
* return () => window.removeEventListener("resize", handleResize);
|
|
1132
|
+
* }, [handleResize]);
|
|
1133
|
+
*
|
|
1134
|
+
* return null;
|
|
1135
|
+
* }
|
|
1136
|
+
* ```
|
|
1137
|
+
*
|
|
1138
|
+
* @param func - The function to throttle. Safe to pass a new closure on
|
|
1139
|
+
* every render.
|
|
1140
|
+
* @param delay - See {@link useThrottler}.
|
|
1141
|
+
* @param options - See {@link ThrottleOptions}.
|
|
1142
|
+
* @returns See {@link UseThrottledCallbackReturn}.
|
|
1143
|
+
*/
|
|
485
1144
|
export declare function useThrottledCallback<Args extends unknown[]>(func: (...args: Args) => void, delay: number, options?: ThrottleOptions): UseThrottledCallbackReturn<Args>;
|
|
1145
|
+
/**
|
|
1146
|
+
* The tuple returned by `useThrottledState`, mirroring `useState`'s
|
|
1147
|
+
* `[value, setValue]` shape with a third element carrying throttle
|
|
1148
|
+
* controls.
|
|
1149
|
+
*/
|
|
486
1150
|
export type UseThrottledStateReturn<T> = [
|
|
1151
|
+
/** The current (throttled) state value. */
|
|
487
1152
|
T,
|
|
488
|
-
|
|
1153
|
+
/**
|
|
1154
|
+
* Schedules a throttled update to state. Accepts either a plain value
|
|
1155
|
+
* or a `useState`-style functional updater (`(previous) => next`).
|
|
1156
|
+
*
|
|
1157
|
+
* The functional-updater form composes correctly across multiple rapid
|
|
1158
|
+
* calls made before the cooldown window settles — e.g. calling
|
|
1159
|
+
* `setValue((p) => p + 1)` three times in a row schedules a cumulative
|
|
1160
|
+
* `+3`, not three competing `+1`s racing to be "the" pending value.
|
|
1161
|
+
* `previous` in that case refers to the most recently *scheduled*
|
|
1162
|
+
* value, not necessarily the currently-committed state — this matters
|
|
1163
|
+
* if you're chaining updates faster than the window settles.
|
|
1164
|
+
*/
|
|
1165
|
+
(value: T | ((previous: T) => T)) => void,
|
|
489
1166
|
{
|
|
1167
|
+
/** See {@link UseThrottlerReturn.isPending}. */
|
|
490
1168
|
isPending: boolean;
|
|
1169
|
+
/**
|
|
1170
|
+
* Cancels any pending throttled update. Also resyncs the internal
|
|
1171
|
+
* "next value to commit" tracking back to the current committed
|
|
1172
|
+
* state, so a subsequent functional update starts from the right
|
|
1173
|
+
* baseline instead of building on a discarded value.
|
|
1174
|
+
*/
|
|
491
1175
|
cancel: () => void;
|
|
1176
|
+
/** See {@link UseThrottlerReturn.flush}. */
|
|
492
1177
|
flush: () => void;
|
|
493
|
-
|
|
1178
|
+
/**
|
|
1179
|
+
* Bypasses throttle scheduling entirely and applies the value (or
|
|
1180
|
+
* updater) immediately. Also cancels any throttled update that was
|
|
1181
|
+
* still pending, so it can't land afterward and silently overwrite
|
|
1182
|
+
* this forced value.
|
|
1183
|
+
*/
|
|
1184
|
+
forceSetValue: (value: T | ((previous: T) => T)) => void;
|
|
494
1185
|
}
|
|
495
1186
|
];
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
1187
|
+
/**
|
|
1188
|
+
* A `useState`-shaped hook whose setter rate-limits its effect on state
|
|
1189
|
+
* instead of applying immediately.
|
|
1190
|
+
*
|
|
1191
|
+
* @example
|
|
1192
|
+
* ```tsx
|
|
1193
|
+
* function ScoreBoard() {
|
|
1194
|
+
* const [score, setScore, { flush, forceSetValue, isPending }] =
|
|
1195
|
+
* useThrottledState(() => expensiveInitialScore(), 500);
|
|
1196
|
+
*
|
|
1197
|
+
* return (
|
|
1198
|
+
* <>
|
|
1199
|
+
* <p>Score: {score}</p>
|
|
1200
|
+
* <button onClick={() => setScore((s) => s + 1)}>+1 (throttled)</button>
|
|
1201
|
+
* <button onClick={flush}>Flush pending update</button>
|
|
1202
|
+
* <button onClick={() => forceSetValue(0)}>Reset instantly</button>
|
|
1203
|
+
* {isPending && <span>update queued…</span>}
|
|
1204
|
+
* </>
|
|
1205
|
+
* );
|
|
1206
|
+
* }
|
|
1207
|
+
* ```
|
|
1208
|
+
*
|
|
1209
|
+
* @param initialValue - Initial state value, or a `useState`-style lazy
|
|
1210
|
+
* initializer function (`() => T`).
|
|
1211
|
+
* @param delay - See {@link useThrottler}.
|
|
1212
|
+
* @param options - See {@link UseThrottledStateOptions}.
|
|
1213
|
+
* @returns See {@link UseThrottledStateReturn}.
|
|
1214
|
+
*/
|
|
1215
|
+
export declare function useThrottledState<T>(initialValue: T | (() => T), delay: number, options?: UseThrottledStateOptions<T>): UseThrottledStateReturn<T>;
|
|
1216
|
+
/**
|
|
1217
|
+
* The tuple returned by `useThrottledValue`.
|
|
1218
|
+
*/
|
|
1219
|
+
export type UseThrottledValueReturn<T> = [
|
|
1220
|
+
/** The throttled (rate-limited) mirror of the source value. */
|
|
1221
|
+
T,
|
|
1222
|
+
{
|
|
1223
|
+
/** See {@link UseThrottlerReturn.isPending}. */
|
|
1224
|
+
isPending: boolean;
|
|
1225
|
+
/** Cancels the pending sync to the latest source value. */
|
|
1226
|
+
cancel: () => void;
|
|
1227
|
+
/** Immediately commits the latest source value, bypassing the wait. */
|
|
1228
|
+
flush: () => void;
|
|
1229
|
+
}
|
|
1230
|
+
];
|
|
1231
|
+
/**
|
|
1232
|
+
* Mirrors `value`, but the mirror updates at most once every `delay`
|
|
1233
|
+
* milliseconds — a safe, rate-limited dependency for an expensive
|
|
1234
|
+
* downstream render (chart, canvas, map) driven by a fast-changing source
|
|
1235
|
+
* like a slider or live coordinates.
|
|
1236
|
+
*
|
|
1237
|
+
* @remarks
|
|
1238
|
+
* With the default `{ leading: true }`, the mirror updates almost
|
|
1239
|
+
* immediately on the first change — throttle is about limiting *rate*,
|
|
1240
|
+
* not deferring the first response the way debounce does.
|
|
1241
|
+
*
|
|
1242
|
+
* @example
|
|
1243
|
+
* ```tsx
|
|
1244
|
+
* function SliderDemo() {
|
|
1245
|
+
* const [raw, setRaw] = useState(0);
|
|
1246
|
+
* const [throttled] = useThrottledValue(raw, 100);
|
|
1247
|
+
*
|
|
1248
|
+
* return (
|
|
1249
|
+
* <>
|
|
1250
|
+
* <input
|
|
1251
|
+
* type="range"
|
|
1252
|
+
* value={raw}
|
|
1253
|
+
* onChange={(e) => setRaw(Number(e.target.value))}
|
|
1254
|
+
* />
|
|
1255
|
+
* <HeavyPreview value={throttled} />
|
|
1256
|
+
* </>
|
|
1257
|
+
* );
|
|
1258
|
+
* }
|
|
1259
|
+
* ```
|
|
1260
|
+
*
|
|
1261
|
+
* @param value - The source value to throttle. Every change is subject to
|
|
1262
|
+
* the cooldown window.
|
|
1263
|
+
* @param delay - See {@link useThrottler}.
|
|
1264
|
+
* @param options - See {@link UseThrottledValueOptions}.
|
|
1265
|
+
* @returns See {@link UseThrottledValueReturn}.
|
|
1266
|
+
*/
|
|
1267
|
+
export declare function useThrottledValue<T>(value: T, delay: number, options?: UseThrottledValueOptions<T>): UseThrottledValueReturn<T>;
|
|
1268
|
+
/**
|
|
1269
|
+
* The object returned by `useThrottler`.
|
|
1270
|
+
*/
|
|
1271
|
+
export interface UseThrottlerReturn {
|
|
1272
|
+
/**
|
|
1273
|
+
* Registers `func` (with `args`) as the function this cooldown window
|
|
1274
|
+
* will invoke.
|
|
1275
|
+
*
|
|
1276
|
+
* Each call to `run()` accepts its own function — you are not locked
|
|
1277
|
+
* into throttling a single, fixed callback. If a trailing invocation is
|
|
1278
|
+
* still pending when `run()` is called again, the previously-registered
|
|
1279
|
+
* function and arguments are replaced by the new ones — whichever call
|
|
1280
|
+
* was most recent before the window closes is the one that fires (a
|
|
1281
|
+
* "last write wins" swap, not a queue).
|
|
1282
|
+
*
|
|
1283
|
+
* @example
|
|
1284
|
+
* ```ts
|
|
1285
|
+
* const { run } = useThrottler(200);
|
|
1286
|
+
*
|
|
1287
|
+
* run((x: number, y: number) => logPosition(x, y), clientX, clientY);
|
|
1288
|
+
* ```
|
|
1289
|
+
*/
|
|
1290
|
+
run: <Args extends unknown[]>(func: (...args: Args) => void, ...args: Args) => void;
|
|
1291
|
+
/**
|
|
1292
|
+
* Clears any pending trailing invocation and resets the cooldown
|
|
1293
|
+
* window entirely — the next call to `run()` is treated as the start
|
|
1294
|
+
* of a fresh window. Sets `isPending` back to `false`.
|
|
1295
|
+
*/
|
|
1296
|
+
cancel: () => void;
|
|
1297
|
+
/**
|
|
1298
|
+
* If a trailing invocation is currently pending, invokes it
|
|
1299
|
+
* immediately (with its most recently registered arguments) and clears
|
|
1300
|
+
* the timer. If nothing is pending, this is a no-op.
|
|
1301
|
+
*/
|
|
1302
|
+
flush: () => void;
|
|
1303
|
+
/**
|
|
1304
|
+
* `true` whenever a trailing invocation is still scheduled to fire
|
|
1305
|
+
* before the current cooldown window closes. `false` once it's known
|
|
1306
|
+
* nothing further will happen — including right after a leading-edge
|
|
1307
|
+
* invocation with no follow-up call yet, not merely once the whole
|
|
1308
|
+
* window elapses.
|
|
1309
|
+
*/
|
|
1310
|
+
isPending: boolean;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* The throttle engine underlying every hook in this family.
|
|
1314
|
+
*
|
|
1315
|
+
* `useThrottler` is a low-level scheduling primitive: a single cooldown
|
|
1316
|
+
* window and a single "next function to run" slot. Unlike debounce,
|
|
1317
|
+
* additional calls that arrive mid-window do not push the window out
|
|
1318
|
+
* further — they just update which function/arguments will fire when the
|
|
1319
|
+
* *existing* window closes. This is what keeps a continuous stream of
|
|
1320
|
+
* calls (mousemove, scroll, resize) firing at a steady cadence instead of
|
|
1321
|
+
* only ever firing once activity stops.
|
|
1322
|
+
*
|
|
1323
|
+
* Most consumers won't reach for this directly — `useThrottledCallback`,
|
|
1324
|
+
* `useThrottledState`, and `useThrottledValue` are thin, purpose-built
|
|
1325
|
+
* wrappers around it for the common cases. Use `useThrottler` directly
|
|
1326
|
+
* when you need the "swap, don't queue" behavior across genuinely
|
|
1327
|
+
* different functions.
|
|
1328
|
+
*
|
|
1329
|
+
* @example
|
|
1330
|
+
* ```tsx
|
|
1331
|
+
* function ActivityLogger() {
|
|
1332
|
+
* const { run, isPending } = useThrottler(1000);
|
|
1333
|
+
*
|
|
1334
|
+
* return (
|
|
1335
|
+
* <div
|
|
1336
|
+
* onMouseMove={(e) => run(logMouseMove, e.clientX, e.clientY)}
|
|
1337
|
+
* onKeyDown={(e) => run(logKeyPress, e.key)}
|
|
1338
|
+
* >
|
|
1339
|
+
* {isPending ? "Recording…" : "Idle"}
|
|
1340
|
+
* </div>
|
|
1341
|
+
* );
|
|
1342
|
+
* }
|
|
1343
|
+
* ```
|
|
1344
|
+
*
|
|
1345
|
+
* @param delay - Length of the cooldown window, in milliseconds. Coerced
|
|
1346
|
+
* to a non-negative number; invalid input falls back to `0` with a
|
|
1347
|
+
* dev-mode warning.
|
|
1348
|
+
* @param options - See {@link ThrottleOptions}.
|
|
1349
|
+
* @returns See {@link UseThrottlerReturn}.
|
|
1350
|
+
*/
|
|
1351
|
+
export declare function useThrottler(delay: number, options?: ThrottleOptions): UseThrottlerReturn;
|
|
499
1352
|
export type ScrollAlign = "start" | "center" | "end" | "auto";
|
|
500
1353
|
export type Axis = "vertical" | "horizontal";
|
|
501
1354
|
export interface ScrollToOffsetOptions {
|
|
@@ -816,43 +1669,295 @@ export interface UseSortReturn<T> {
|
|
|
816
1669
|
getSortIndex: (id: string) => number | undefined;
|
|
817
1670
|
}
|
|
818
1671
|
export declare function useSort<T>(data?: T[], initialSorts?: SortState): UseSortReturn<T>;
|
|
1672
|
+
/**
|
|
1673
|
+
* Defines how a value of type `T` is converted to and from the string
|
|
1674
|
+
* format that `localStorage`/`sessionStorage` can actually store — the Web
|
|
1675
|
+
* Storage API only ever stores strings.
|
|
1676
|
+
*
|
|
1677
|
+
* Implement this to store types the default JSON-based serializer can't
|
|
1678
|
+
* round-trip faithfully, e.g. `Map`, `Set`, `Date`, or `bigint` — see
|
|
1679
|
+
* `mapSerializer`, `setSerializer`, `dateSerializer`, and
|
|
1680
|
+
* `bigIntSerializer` in `serializers.ts` for ready-made ones.
|
|
1681
|
+
*
|
|
1682
|
+
* @typeParam T - The in-memory value type this serializer handles.
|
|
1683
|
+
*/
|
|
819
1684
|
export interface StorageSerializer<T> {
|
|
1685
|
+
/** Converts an in-memory value into the string that gets stored. */
|
|
820
1686
|
serialize: (value: T) => string;
|
|
1687
|
+
/**
|
|
1688
|
+
* Converts a stored string back into an in-memory value.
|
|
1689
|
+
*
|
|
1690
|
+
* @throws If the raw string can't be converted back into `T`. The hook
|
|
1691
|
+
* catches this, falls back to `initialValue`, and reports the error —
|
|
1692
|
+
* see `onError` on {@link BaseStorageOptions}.
|
|
1693
|
+
*/
|
|
821
1694
|
deserialize: (raw: string) => T;
|
|
822
1695
|
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Options shared by `useLocalStorage` and `useSessionStorage`.
|
|
1698
|
+
*
|
|
1699
|
+
* @typeParam T - The type of value being stored.
|
|
1700
|
+
*/
|
|
823
1701
|
export interface BaseStorageOptions<T> {
|
|
1702
|
+
/**
|
|
1703
|
+
* Custom (de)serializer for values that don't round-trip through
|
|
1704
|
+
* `JSON.stringify`/`JSON.parse` cleanly.
|
|
1705
|
+
*
|
|
1706
|
+
* @defaultValue `defaultSerializer` (plain `JSON.stringify`/`JSON.parse`)
|
|
1707
|
+
*/
|
|
824
1708
|
serializer?: StorageSerializer<T>;
|
|
1709
|
+
/**
|
|
1710
|
+
* Whether to synchronously read the existing stored value on mount.
|
|
1711
|
+
*
|
|
1712
|
+
* - `true` (default): `value` reflects storage from the very first
|
|
1713
|
+
* render it's allowed to (see the SSR note below).
|
|
1714
|
+
* - `false`: `value` starts as `undefined` and only reflects storage
|
|
1715
|
+
* once `isHydrated` becomes `true`, one render after mount. Use this
|
|
1716
|
+
* if you'd rather render a loading/skeleton state than briefly show a
|
|
1717
|
+
* value that might change right after.
|
|
1718
|
+
*
|
|
1719
|
+
* Either way, on the server — and during the client's hydration render
|
|
1720
|
+
* — `value` is always `initialValue`. This option only affects timing
|
|
1721
|
+
* on the client, after that point.
|
|
1722
|
+
*
|
|
1723
|
+
* @defaultValue `true`
|
|
1724
|
+
*/
|
|
825
1725
|
initializeWithValue?: boolean;
|
|
1726
|
+
/**
|
|
1727
|
+
* Whether other instances of this hook watching the *same key* in the
|
|
1728
|
+
* *same tab* stay in sync with each other. Implemented via a
|
|
1729
|
+
* `CustomEvent` dispatched on `window` — the browser's native `storage`
|
|
1730
|
+
* event never fires in the tab that made the change, so without this,
|
|
1731
|
+
* two components reading the same key in one tab would drift apart.
|
|
1732
|
+
*
|
|
1733
|
+
* @defaultValue `true`
|
|
1734
|
+
*/
|
|
826
1735
|
sameInstanceSync?: boolean;
|
|
1736
|
+
/**
|
|
1737
|
+
* Called whenever the hook hits an unexpected condition: a failed
|
|
1738
|
+
* read, a failed write, a failed cross-instance deserialize, or an
|
|
1739
|
+
* attempt to change the storage key at runtime. Fires in every
|
|
1740
|
+
* environment, including production — use this for telemetry/error
|
|
1741
|
+
* reporting.
|
|
1742
|
+
*
|
|
1743
|
+
* This is *not* a replacement for the dev-only `console.warn` the hook
|
|
1744
|
+
* also emits for the same conditions (visible when
|
|
1745
|
+
* `process.env.NODE_ENV !== "production"`) — both fire independently.
|
|
1746
|
+
*/
|
|
1747
|
+
onError?: (error: Error) => void;
|
|
827
1748
|
}
|
|
1749
|
+
/**
|
|
1750
|
+
* Payload carried by the same-tab `CustomEvent` used for
|
|
1751
|
+
* {@link BaseStorageOptions.sameInstanceSync}. Internal — not part of the
|
|
1752
|
+
* public hook API, but exported so `useStorageEngine.ts` can import it.
|
|
1753
|
+
*/
|
|
828
1754
|
export interface StorageCustomEventDetail {
|
|
1755
|
+
/** The new serialized value, or `null` if the key was removed. */
|
|
829
1756
|
value: string | null;
|
|
1757
|
+
/**
|
|
1758
|
+
* A per-hook-instance identifier, used so an instance can recognize —
|
|
1759
|
+
* and ignore — the event it just dispatched itself.
|
|
1760
|
+
*/
|
|
830
1761
|
instanceId: symbol;
|
|
831
1762
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
1763
|
+
/**
|
|
1764
|
+
* The shape returned by {@link useStorageEngine} — and, re-exported, by
|
|
1765
|
+
* both `useLocalStorage` and `useSessionStorage`.
|
|
1766
|
+
*
|
|
1767
|
+
* @typeParam T - The type of value being stored.
|
|
1768
|
+
*/
|
|
1769
|
+
interface UseStorageEngineReturn<T> {
|
|
1770
|
+
/**
|
|
1771
|
+
* The current value.
|
|
1772
|
+
*
|
|
1773
|
+
* - `undefined` if nothing is stored yet and no `initialValue` was
|
|
1774
|
+
* given, or — when `initializeWithValue: false` — before hydration
|
|
1775
|
+
* completes.
|
|
1776
|
+
* - On the server, and during the client's hydration render, this is
|
|
1777
|
+
* always `initialValue`: real storage can only be read client-side,
|
|
1778
|
+
* and reading it any earlier would produce a hydration mismatch.
|
|
1779
|
+
*/
|
|
836
1780
|
value: T | undefined;
|
|
1781
|
+
/**
|
|
1782
|
+
* Writes a new value to storage. Accepts either the value directly, or
|
|
1783
|
+
* an updater function that receives the current value and returns the
|
|
1784
|
+
* next one — the same convention as `useState`'s setter.
|
|
1785
|
+
*
|
|
1786
|
+
* A no-op if storage isn't available (SSR, or storage access blocked).
|
|
1787
|
+
*/
|
|
837
1788
|
setValue: (valueOrUpdater: T | ((prev: T | undefined) => T)) => void;
|
|
1789
|
+
/**
|
|
1790
|
+
* Removes the key from storage entirely and resets `value` back to
|
|
1791
|
+
* whatever `initialValue` was passed to the hook.
|
|
1792
|
+
*
|
|
1793
|
+
* A no-op if storage isn't available (SSR, or storage access blocked).
|
|
1794
|
+
*/
|
|
838
1795
|
removeValue: () => void;
|
|
1796
|
+
/**
|
|
1797
|
+
* `true` once the client has mounted and the hook has settled on its
|
|
1798
|
+
* real (non-server-snapshot) value. Useful for showing a loading state
|
|
1799
|
+
* instead of a value that might change the instant hydration finishes.
|
|
1800
|
+
*/
|
|
839
1801
|
isHydrated: boolean;
|
|
1802
|
+
/**
|
|
1803
|
+
* The most recent error the hook encountered — a failed read, write,
|
|
1804
|
+
* or cross-instance sync, or an attempted key change — or `null` if
|
|
1805
|
+
* nothing has gone wrong (or an error was cleared by a subsequent
|
|
1806
|
+
* successful write/remove). See `onError` on {@link BaseStorageOptions}
|
|
1807
|
+
* for an imperative alternative to reading this reactively.
|
|
1808
|
+
*/
|
|
840
1809
|
error: Error | null;
|
|
841
1810
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
1811
|
+
/**
|
|
1812
|
+
* Options accepted by `useLocalStorage`.
|
|
1813
|
+
*
|
|
1814
|
+
* @typeParam T - The type of value being stored.
|
|
1815
|
+
*/
|
|
1816
|
+
export interface UseLocalStorageOptions<T> extends BaseStorageOptions<T> {
|
|
1817
|
+
/**
|
|
1818
|
+
* Whether this hook instance should sync with the same key changing in
|
|
1819
|
+
* *other tabs/windows* on the same origin, via the browser's native
|
|
1820
|
+
* `storage` event. Has no `sessionStorage` equivalent — sessionStorage
|
|
1821
|
+
* isn't shared across tabs, so there's nothing to sync in that case.
|
|
1822
|
+
*
|
|
1823
|
+
* @defaultValue `true`
|
|
1824
|
+
*/
|
|
1825
|
+
crossInstanceSync?: boolean;
|
|
850
1826
|
}
|
|
851
|
-
|
|
1827
|
+
/**
|
|
1828
|
+
* Reads and writes a `localStorage` key, kept in sync with React state.
|
|
1829
|
+
*
|
|
1830
|
+
* - Persists across page reloads and browser restarts (unlike
|
|
1831
|
+
* `useSessionStorage`).
|
|
1832
|
+
* - Stays in sync with every component in the current tab watching the
|
|
1833
|
+
* same key — see {@link UseLocalStorageOptions.sameInstanceSync} — and
|
|
1834
|
+
* with other tabs/windows on the same origin — see
|
|
1835
|
+
* {@link UseLocalStorageOptions.crossInstanceSync}.
|
|
1836
|
+
* - Safe under SSR: on the server, and during the client's hydration
|
|
1837
|
+
* render, `value` is always `initialValue`. The real stored value is
|
|
1838
|
+
* only read client-side, immediately after hydration.
|
|
1839
|
+
*
|
|
1840
|
+
* @typeParam T - The type of value being stored. Defaults to `unknown` if
|
|
1841
|
+
* omitted — pass an explicit type argument for anything beyond ad-hoc use.
|
|
1842
|
+
* @param key - The `localStorage` key to read and write. Changing this on
|
|
1843
|
+
* a later render isn't supported; the hook warns (dev console + `onError`)
|
|
1844
|
+
* and keeps using the original key if you do.
|
|
1845
|
+
* @param initialValue - Used when nothing is stored yet, as the value
|
|
1846
|
+
* shown before hydration completes, and as what `removeValue` resets to.
|
|
1847
|
+
* @param options - See {@link UseLocalStorageOptions}.
|
|
1848
|
+
* @returns `{ value, setValue, removeValue, isHydrated, error }`.
|
|
1849
|
+
*
|
|
1850
|
+
* @example
|
|
1851
|
+
* Basic usage:
|
|
1852
|
+
* ```tsx
|
|
1853
|
+
* const { value: theme, setValue: setTheme } = useLocalStorage<"light" | "dark">("theme", "light");
|
|
1854
|
+
*
|
|
1855
|
+
* <button onClick={() => setTheme(prev => (prev === "light" ? "dark" : "light"))}>
|
|
1856
|
+
* Toggle theme
|
|
1857
|
+
* </button>
|
|
1858
|
+
* ```
|
|
1859
|
+
*
|
|
1860
|
+
* @example
|
|
1861
|
+
* With a custom serializer and error reporting:
|
|
1862
|
+
* ```tsx
|
|
1863
|
+
* const { value, setValue, error } = useLocalStorage("lastSeen", new Date(), {
|
|
1864
|
+
* serializer: dateSerializer,
|
|
1865
|
+
* onError: (err) => reportToErrorTracker(err),
|
|
1866
|
+
* });
|
|
1867
|
+
* ```
|
|
1868
|
+
*/
|
|
1869
|
+
export declare function useLocalStorage<T = unknown>(key: string, initialValue?: T, options?: UseLocalStorageOptions<T>): UseStorageEngineReturn<T>;
|
|
1870
|
+
/**
|
|
1871
|
+
* Options accepted by `useSessionStorage`. Identical to
|
|
1872
|
+
* `BaseStorageOptions` — unlike `UseLocalStorageOptions`, there's no
|
|
1873
|
+
* `crossInstanceSync` option here, since sessionStorage isn't shared
|
|
1874
|
+
* across tabs in the first place.
|
|
1875
|
+
*
|
|
1876
|
+
* @typeParam T - The type of value being stored.
|
|
1877
|
+
*/
|
|
1878
|
+
export type UseSessionStorageOptions<T> = BaseStorageOptions<T>;
|
|
1879
|
+
/**
|
|
1880
|
+
* Reads and writes a `sessionStorage` key, kept in sync with React state.
|
|
1881
|
+
*
|
|
1882
|
+
* - Scoped to the current tab: cleared when the tab closes, and not
|
|
1883
|
+
* shared with other tabs (unlike `useLocalStorage`).
|
|
1884
|
+
* - Stays in sync with every component in the current tab watching the
|
|
1885
|
+
* same key — see {@link UseSessionStorageOptions.sameInstanceSync}.
|
|
1886
|
+
* - Safe under SSR: on the server, and during the client's hydration
|
|
1887
|
+
* render, `value` is always `initialValue`. The real stored value is
|
|
1888
|
+
* only read client-side, immediately after hydration.
|
|
1889
|
+
*
|
|
1890
|
+
* @typeParam T - The type of value being stored. Defaults to `unknown` if
|
|
1891
|
+
* omitted — pass an explicit type argument for anything beyond ad-hoc use.
|
|
1892
|
+
* @param key - The `sessionStorage` key to read and write. Changing this
|
|
1893
|
+
* on a later render isn't supported; the hook warns (dev console +
|
|
1894
|
+
* `onError`) and keeps using the original key if you do.
|
|
1895
|
+
* @param initialValue - Used when nothing is stored yet, as the value
|
|
1896
|
+
* shown before hydration completes, and as what `removeValue` resets to.
|
|
1897
|
+
* @param options - See {@link UseSessionStorageOptions}.
|
|
1898
|
+
* @returns `{ value, setValue, removeValue, isHydrated, error }`.
|
|
1899
|
+
*
|
|
1900
|
+
* @example
|
|
1901
|
+
* ```tsx
|
|
1902
|
+
* const { value: draft, setValue: setDraft } = useSessionStorage("draft-comment", "");
|
|
1903
|
+
*
|
|
1904
|
+
* <textarea value={draft ?? ""} onChange={(e) => setDraft(e.target.value)} />
|
|
1905
|
+
* ```
|
|
1906
|
+
*/
|
|
1907
|
+
export declare function useSessionStorage<T = unknown>(key: string, initialValue?: T, options?: UseSessionStorageOptions<T>): UseStorageEngineReturn<T>;
|
|
1908
|
+
/**
|
|
1909
|
+
* The default serializer used when no `serializer` option is passed to
|
|
1910
|
+
* `useLocalStorage`/`useSessionStorage`. Plain `JSON.stringify`/
|
|
1911
|
+
* `JSON.parse` — works for any JSON-safe value (objects, arrays, strings,
|
|
1912
|
+
* numbers, booleans, `null`), but not `Map`, `Set`, `Date`, `bigint`, or
|
|
1913
|
+
* `undefined` (see the other serializers below for those).
|
|
1914
|
+
*/
|
|
852
1915
|
export declare const defaultSerializer: StorageSerializer<unknown>;
|
|
1916
|
+
/**
|
|
1917
|
+
* Serializer for `Map` values. `JSON.stringify` can't handle `Map`
|
|
1918
|
+
* directly, so this round-trips it via an array of `[key, value]` entries.
|
|
1919
|
+
*
|
|
1920
|
+
* @typeParam K - The map's key type.
|
|
1921
|
+
* @typeParam V - The map's value type.
|
|
1922
|
+
*
|
|
1923
|
+
* @example
|
|
1924
|
+
* ```ts
|
|
1925
|
+
* useLocalStorage("tags", new Map<string, number>(), {
|
|
1926
|
+
* serializer: mapSerializer<string, number>(),
|
|
1927
|
+
* });
|
|
1928
|
+
* ```
|
|
1929
|
+
*/
|
|
853
1930
|
export declare function mapSerializer<K, V>(): StorageSerializer<Map<K, V>>;
|
|
1931
|
+
/**
|
|
1932
|
+
* Serializer for `Set` values, round-tripped via a plain array.
|
|
1933
|
+
*
|
|
1934
|
+
* @typeParam V - The set's value type.
|
|
1935
|
+
*
|
|
1936
|
+
* @example
|
|
1937
|
+
* ```ts
|
|
1938
|
+
* useLocalStorage("selectedIds", new Set<string>(), {
|
|
1939
|
+
* serializer: setSerializer<string>(),
|
|
1940
|
+
* });
|
|
1941
|
+
* ```
|
|
1942
|
+
*/
|
|
854
1943
|
export declare function setSerializer<V>(): StorageSerializer<Set<V>>;
|
|
1944
|
+
/**
|
|
1945
|
+
* Serializer for `Date` values, stored as an ISO 8601 string
|
|
1946
|
+
* (`Date.prototype.toISOString`).
|
|
1947
|
+
*
|
|
1948
|
+
* @throws During `deserialize`, if the stored string isn't a valid date —
|
|
1949
|
+
* caught by the hook, which falls back to `initialValue` and reports the
|
|
1950
|
+
* error via `onError`/the dev console warning.
|
|
1951
|
+
*/
|
|
855
1952
|
export declare const dateSerializer: StorageSerializer<Date>;
|
|
1953
|
+
/**
|
|
1954
|
+
* Serializer for `bigint` values. `JSON.stringify` throws on `bigint`
|
|
1955
|
+
* values, so this stores them as a plain decimal string instead.
|
|
1956
|
+
*
|
|
1957
|
+
* @throws During `deserialize`, if the stored string can't be converted to
|
|
1958
|
+
* a `bigint` — caught by the hook, which falls back to `initialValue` and
|
|
1959
|
+
* reports the error via `onError`/the dev console warning.
|
|
1960
|
+
*/
|
|
856
1961
|
export declare const bigIntSerializer: StorageSerializer<bigint>;
|
|
857
1962
|
export interface FuzzyHighlighterProps {
|
|
858
1963
|
text: string;
|
|
@@ -948,4 +2053,9 @@ export declare function useVisibility<T = unknown>(options?: {
|
|
|
948
2053
|
initialVisibleIds?: VisibilityId[];
|
|
949
2054
|
}): UseVisibilityReturn<T>;
|
|
950
2055
|
|
|
2056
|
+
export {
|
|
2057
|
+
UseStorageEngineReturn as UseLocalStorageReturn,
|
|
2058
|
+
UseStorageEngineReturn as UseSessionStorageReturn,
|
|
2059
|
+
};
|
|
2060
|
+
|
|
951
2061
|
export {};
|