@himanshu-sorathiya/react-kit 1.0.26 → 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/index.d.ts +270 -13
- package/dist/storage.d.ts +270 -13
- package/dist/storage2.js +150 -213
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -816,43 +816,295 @@ export interface UseSortReturn<T> {
|
|
|
816
816
|
getSortIndex: (id: string) => number | undefined;
|
|
817
817
|
}
|
|
818
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
|
+
*/
|
|
819
831
|
export interface StorageSerializer<T> {
|
|
832
|
+
/** Converts an in-memory value into the string that gets stored. */
|
|
820
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
|
+
*/
|
|
821
841
|
deserialize: (raw: string) => T;
|
|
822
842
|
}
|
|
843
|
+
/**
|
|
844
|
+
* Options shared by `useLocalStorage` and `useSessionStorage`.
|
|
845
|
+
*
|
|
846
|
+
* @typeParam T - The type of value being stored.
|
|
847
|
+
*/
|
|
823
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
|
+
*/
|
|
824
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
|
+
*/
|
|
825
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
|
+
*/
|
|
826
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;
|
|
827
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
|
+
*/
|
|
828
901
|
export interface StorageCustomEventDetail {
|
|
902
|
+
/** The new serialized value, or `null` if the key was removed. */
|
|
829
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
|
+
*/
|
|
830
908
|
instanceId: symbol;
|
|
831
909
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
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
|
+
*/
|
|
836
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
|
+
*/
|
|
837
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
|
+
*/
|
|
838
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
|
+
*/
|
|
839
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
|
+
*/
|
|
840
956
|
error: Error | null;
|
|
841
957
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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;
|
|
850
973
|
}
|
|
851
|
-
|
|
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
|
+
*/
|
|
852
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
|
+
*/
|
|
853
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
|
+
*/
|
|
854
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
|
+
*/
|
|
855
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
|
+
*/
|
|
856
1108
|
export declare const bigIntSerializer: StorageSerializer<bigint>;
|
|
857
1109
|
export interface FuzzyHighlighterProps {
|
|
858
1110
|
text: string;
|
|
@@ -948,4 +1200,9 @@ export declare function useVisibility<T = unknown>(options?: {
|
|
|
948
1200
|
initialVisibleIds?: VisibilityId[];
|
|
949
1201
|
}): UseVisibilityReturn<T>;
|
|
950
1202
|
|
|
1203
|
+
export {
|
|
1204
|
+
UseStorageEngineReturn as UseLocalStorageReturn,
|
|
1205
|
+
UseStorageEngineReturn as UseSessionStorageReturn,
|
|
1206
|
+
};
|
|
1207
|
+
|
|
951
1208
|
export {};
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,42 +1,299 @@
|
|
|
1
1
|
// Generated by dts-bundle-generator v9.5.1
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Defines how a value of type `T` is converted to and from the string
|
|
5
|
+
* format that `localStorage`/`sessionStorage` can actually store — the Web
|
|
6
|
+
* Storage API only ever stores strings.
|
|
7
|
+
*
|
|
8
|
+
* Implement this to store types the default JSON-based serializer can't
|
|
9
|
+
* round-trip faithfully, e.g. `Map`, `Set`, `Date`, or `bigint` — see
|
|
10
|
+
* `mapSerializer`, `setSerializer`, `dateSerializer`, and
|
|
11
|
+
* `bigIntSerializer` in `serializers.ts` for ready-made ones.
|
|
12
|
+
*
|
|
13
|
+
* @typeParam T - The in-memory value type this serializer handles.
|
|
14
|
+
*/
|
|
3
15
|
export interface StorageSerializer<T> {
|
|
16
|
+
/** Converts an in-memory value into the string that gets stored. */
|
|
4
17
|
serialize: (value: T) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Converts a stored string back into an in-memory value.
|
|
20
|
+
*
|
|
21
|
+
* @throws If the raw string can't be converted back into `T`. The hook
|
|
22
|
+
* catches this, falls back to `initialValue`, and reports the error —
|
|
23
|
+
* see `onError` on {@link BaseStorageOptions}.
|
|
24
|
+
*/
|
|
5
25
|
deserialize: (raw: string) => T;
|
|
6
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Options shared by `useLocalStorage` and `useSessionStorage`.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam T - The type of value being stored.
|
|
31
|
+
*/
|
|
7
32
|
export interface BaseStorageOptions<T> {
|
|
33
|
+
/**
|
|
34
|
+
* Custom (de)serializer for values that don't round-trip through
|
|
35
|
+
* `JSON.stringify`/`JSON.parse` cleanly.
|
|
36
|
+
*
|
|
37
|
+
* @defaultValue `defaultSerializer` (plain `JSON.stringify`/`JSON.parse`)
|
|
38
|
+
*/
|
|
8
39
|
serializer?: StorageSerializer<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to synchronously read the existing stored value on mount.
|
|
42
|
+
*
|
|
43
|
+
* - `true` (default): `value` reflects storage from the very first
|
|
44
|
+
* render it's allowed to (see the SSR note below).
|
|
45
|
+
* - `false`: `value` starts as `undefined` and only reflects storage
|
|
46
|
+
* once `isHydrated` becomes `true`, one render after mount. Use this
|
|
47
|
+
* if you'd rather render a loading/skeleton state than briefly show a
|
|
48
|
+
* value that might change right after.
|
|
49
|
+
*
|
|
50
|
+
* Either way, on the server — and during the client's hydration render
|
|
51
|
+
* — `value` is always `initialValue`. This option only affects timing
|
|
52
|
+
* on the client, after that point.
|
|
53
|
+
*
|
|
54
|
+
* @defaultValue `true`
|
|
55
|
+
*/
|
|
9
56
|
initializeWithValue?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Whether other instances of this hook watching the *same key* in the
|
|
59
|
+
* *same tab* stay in sync with each other. Implemented via a
|
|
60
|
+
* `CustomEvent` dispatched on `window` — the browser's native `storage`
|
|
61
|
+
* event never fires in the tab that made the change, so without this,
|
|
62
|
+
* two components reading the same key in one tab would drift apart.
|
|
63
|
+
*
|
|
64
|
+
* @defaultValue `true`
|
|
65
|
+
*/
|
|
10
66
|
sameInstanceSync?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Called whenever the hook hits an unexpected condition: a failed
|
|
69
|
+
* read, a failed write, a failed cross-instance deserialize, or an
|
|
70
|
+
* attempt to change the storage key at runtime. Fires in every
|
|
71
|
+
* environment, including production — use this for telemetry/error
|
|
72
|
+
* reporting.
|
|
73
|
+
*
|
|
74
|
+
* This is *not* a replacement for the dev-only `console.warn` the hook
|
|
75
|
+
* also emits for the same conditions (visible when
|
|
76
|
+
* `process.env.NODE_ENV !== "production"`) — both fire independently.
|
|
77
|
+
*/
|
|
78
|
+
onError?: (error: Error) => void;
|
|
11
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Payload carried by the same-tab `CustomEvent` used for
|
|
82
|
+
* {@link BaseStorageOptions.sameInstanceSync}. Internal — not part of the
|
|
83
|
+
* public hook API, but exported so `useStorageEngine.ts` can import it.
|
|
84
|
+
*/
|
|
12
85
|
export interface StorageCustomEventDetail {
|
|
86
|
+
/** The new serialized value, or `null` if the key was removed. */
|
|
13
87
|
value: string | null;
|
|
88
|
+
/**
|
|
89
|
+
* A per-hook-instance identifier, used so an instance can recognize —
|
|
90
|
+
* and ignore — the event it just dispatched itself.
|
|
91
|
+
*/
|
|
14
92
|
instanceId: symbol;
|
|
15
93
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
94
|
+
/**
|
|
95
|
+
* The shape returned by {@link useStorageEngine} — and, re-exported, by
|
|
96
|
+
* both `useLocalStorage` and `useSessionStorage`.
|
|
97
|
+
*
|
|
98
|
+
* @typeParam T - The type of value being stored.
|
|
99
|
+
*/
|
|
100
|
+
interface UseStorageEngineReturn<T> {
|
|
101
|
+
/**
|
|
102
|
+
* The current value.
|
|
103
|
+
*
|
|
104
|
+
* - `undefined` if nothing is stored yet and no `initialValue` was
|
|
105
|
+
* given, or — when `initializeWithValue: false` — before hydration
|
|
106
|
+
* completes.
|
|
107
|
+
* - On the server, and during the client's hydration render, this is
|
|
108
|
+
* always `initialValue`: real storage can only be read client-side,
|
|
109
|
+
* and reading it any earlier would produce a hydration mismatch.
|
|
110
|
+
*/
|
|
20
111
|
value: T | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Writes a new value to storage. Accepts either the value directly, or
|
|
114
|
+
* an updater function that receives the current value and returns the
|
|
115
|
+
* next one — the same convention as `useState`'s setter.
|
|
116
|
+
*
|
|
117
|
+
* A no-op if storage isn't available (SSR, or storage access blocked).
|
|
118
|
+
*/
|
|
21
119
|
setValue: (valueOrUpdater: T | ((prev: T | undefined) => T)) => void;
|
|
120
|
+
/**
|
|
121
|
+
* Removes the key from storage entirely and resets `value` back to
|
|
122
|
+
* whatever `initialValue` was passed to the hook.
|
|
123
|
+
*
|
|
124
|
+
* A no-op if storage isn't available (SSR, or storage access blocked).
|
|
125
|
+
*/
|
|
22
126
|
removeValue: () => void;
|
|
127
|
+
/**
|
|
128
|
+
* `true` once the client has mounted and the hook has settled on its
|
|
129
|
+
* real (non-server-snapshot) value. Useful for showing a loading state
|
|
130
|
+
* instead of a value that might change the instant hydration finishes.
|
|
131
|
+
*/
|
|
23
132
|
isHydrated: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* The most recent error the hook encountered — a failed read, write,
|
|
135
|
+
* or cross-instance sync, or an attempted key change — or `null` if
|
|
136
|
+
* nothing has gone wrong (or an error was cleared by a subsequent
|
|
137
|
+
* successful write/remove). See `onError` on {@link BaseStorageOptions}
|
|
138
|
+
* for an imperative alternative to reading this reactively.
|
|
139
|
+
*/
|
|
24
140
|
error: Error | null;
|
|
25
141
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Options accepted by `useLocalStorage`.
|
|
144
|
+
*
|
|
145
|
+
* @typeParam T - The type of value being stored.
|
|
146
|
+
*/
|
|
147
|
+
export interface UseLocalStorageOptions<T> extends BaseStorageOptions<T> {
|
|
148
|
+
/**
|
|
149
|
+
* Whether this hook instance should sync with the same key changing in
|
|
150
|
+
* *other tabs/windows* on the same origin, via the browser's native
|
|
151
|
+
* `storage` event. Has no `sessionStorage` equivalent — sessionStorage
|
|
152
|
+
* isn't shared across tabs, so there's nothing to sync in that case.
|
|
153
|
+
*
|
|
154
|
+
* @defaultValue `true`
|
|
155
|
+
*/
|
|
156
|
+
crossInstanceSync?: boolean;
|
|
34
157
|
}
|
|
35
|
-
|
|
158
|
+
/**
|
|
159
|
+
* Reads and writes a `localStorage` key, kept in sync with React state.
|
|
160
|
+
*
|
|
161
|
+
* - Persists across page reloads and browser restarts (unlike
|
|
162
|
+
* `useSessionStorage`).
|
|
163
|
+
* - Stays in sync with every component in the current tab watching the
|
|
164
|
+
* same key — see {@link UseLocalStorageOptions.sameInstanceSync} — and
|
|
165
|
+
* with other tabs/windows on the same origin — see
|
|
166
|
+
* {@link UseLocalStorageOptions.crossInstanceSync}.
|
|
167
|
+
* - Safe under SSR: on the server, and during the client's hydration
|
|
168
|
+
* render, `value` is always `initialValue`. The real stored value is
|
|
169
|
+
* only read client-side, immediately after hydration.
|
|
170
|
+
*
|
|
171
|
+
* @typeParam T - The type of value being stored. Defaults to `unknown` if
|
|
172
|
+
* omitted — pass an explicit type argument for anything beyond ad-hoc use.
|
|
173
|
+
* @param key - The `localStorage` key to read and write. Changing this on
|
|
174
|
+
* a later render isn't supported; the hook warns (dev console + `onError`)
|
|
175
|
+
* and keeps using the original key if you do.
|
|
176
|
+
* @param initialValue - Used when nothing is stored yet, as the value
|
|
177
|
+
* shown before hydration completes, and as what `removeValue` resets to.
|
|
178
|
+
* @param options - See {@link UseLocalStorageOptions}.
|
|
179
|
+
* @returns `{ value, setValue, removeValue, isHydrated, error }`.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* Basic usage:
|
|
183
|
+
* ```tsx
|
|
184
|
+
* const { value: theme, setValue: setTheme } = useLocalStorage<"light" | "dark">("theme", "light");
|
|
185
|
+
*
|
|
186
|
+
* <button onClick={() => setTheme(prev => (prev === "light" ? "dark" : "light"))}>
|
|
187
|
+
* Toggle theme
|
|
188
|
+
* </button>
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* With a custom serializer and error reporting:
|
|
193
|
+
* ```tsx
|
|
194
|
+
* const { value, setValue, error } = useLocalStorage("lastSeen", new Date(), {
|
|
195
|
+
* serializer: dateSerializer,
|
|
196
|
+
* onError: (err) => reportToErrorTracker(err),
|
|
197
|
+
* });
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
export declare function useLocalStorage<T = unknown>(key: string, initialValue?: T, options?: UseLocalStorageOptions<T>): UseStorageEngineReturn<T>;
|
|
201
|
+
/**
|
|
202
|
+
* Options accepted by `useSessionStorage`. Identical to
|
|
203
|
+
* `BaseStorageOptions` — unlike `UseLocalStorageOptions`, there's no
|
|
204
|
+
* `crossInstanceSync` option here, since sessionStorage isn't shared
|
|
205
|
+
* across tabs in the first place.
|
|
206
|
+
*
|
|
207
|
+
* @typeParam T - The type of value being stored.
|
|
208
|
+
*/
|
|
209
|
+
export type UseSessionStorageOptions<T> = BaseStorageOptions<T>;
|
|
210
|
+
/**
|
|
211
|
+
* Reads and writes a `sessionStorage` key, kept in sync with React state.
|
|
212
|
+
*
|
|
213
|
+
* - Scoped to the current tab: cleared when the tab closes, and not
|
|
214
|
+
* shared with other tabs (unlike `useLocalStorage`).
|
|
215
|
+
* - Stays in sync with every component in the current tab watching the
|
|
216
|
+
* same key — see {@link UseSessionStorageOptions.sameInstanceSync}.
|
|
217
|
+
* - Safe under SSR: on the server, and during the client's hydration
|
|
218
|
+
* render, `value` is always `initialValue`. The real stored value is
|
|
219
|
+
* only read client-side, immediately after hydration.
|
|
220
|
+
*
|
|
221
|
+
* @typeParam T - The type of value being stored. Defaults to `unknown` if
|
|
222
|
+
* omitted — pass an explicit type argument for anything beyond ad-hoc use.
|
|
223
|
+
* @param key - The `sessionStorage` key to read and write. Changing this
|
|
224
|
+
* on a later render isn't supported; the hook warns (dev console +
|
|
225
|
+
* `onError`) and keeps using the original key if you do.
|
|
226
|
+
* @param initialValue - Used when nothing is stored yet, as the value
|
|
227
|
+
* shown before hydration completes, and as what `removeValue` resets to.
|
|
228
|
+
* @param options - See {@link UseSessionStorageOptions}.
|
|
229
|
+
* @returns `{ value, setValue, removeValue, isHydrated, error }`.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```tsx
|
|
233
|
+
* const { value: draft, setValue: setDraft } = useSessionStorage("draft-comment", "");
|
|
234
|
+
*
|
|
235
|
+
* <textarea value={draft ?? ""} onChange={(e) => setDraft(e.target.value)} />
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
export declare function useSessionStorage<T = unknown>(key: string, initialValue?: T, options?: UseSessionStorageOptions<T>): UseStorageEngineReturn<T>;
|
|
239
|
+
/**
|
|
240
|
+
* The default serializer used when no `serializer` option is passed to
|
|
241
|
+
* `useLocalStorage`/`useSessionStorage`. Plain `JSON.stringify`/
|
|
242
|
+
* `JSON.parse` — works for any JSON-safe value (objects, arrays, strings,
|
|
243
|
+
* numbers, booleans, `null`), but not `Map`, `Set`, `Date`, `bigint`, or
|
|
244
|
+
* `undefined` (see the other serializers below for those).
|
|
245
|
+
*/
|
|
36
246
|
export declare const defaultSerializer: StorageSerializer<unknown>;
|
|
247
|
+
/**
|
|
248
|
+
* Serializer for `Map` values. `JSON.stringify` can't handle `Map`
|
|
249
|
+
* directly, so this round-trips it via an array of `[key, value]` entries.
|
|
250
|
+
*
|
|
251
|
+
* @typeParam K - The map's key type.
|
|
252
|
+
* @typeParam V - The map's value type.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* useLocalStorage("tags", new Map<string, number>(), {
|
|
257
|
+
* serializer: mapSerializer<string, number>(),
|
|
258
|
+
* });
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
37
261
|
export declare function mapSerializer<K, V>(): StorageSerializer<Map<K, V>>;
|
|
262
|
+
/**
|
|
263
|
+
* Serializer for `Set` values, round-tripped via a plain array.
|
|
264
|
+
*
|
|
265
|
+
* @typeParam V - The set's value type.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* useLocalStorage("selectedIds", new Set<string>(), {
|
|
270
|
+
* serializer: setSerializer<string>(),
|
|
271
|
+
* });
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
38
274
|
export declare function setSerializer<V>(): StorageSerializer<Set<V>>;
|
|
275
|
+
/**
|
|
276
|
+
* Serializer for `Date` values, stored as an ISO 8601 string
|
|
277
|
+
* (`Date.prototype.toISOString`).
|
|
278
|
+
*
|
|
279
|
+
* @throws During `deserialize`, if the stored string isn't a valid date —
|
|
280
|
+
* caught by the hook, which falls back to `initialValue` and reports the
|
|
281
|
+
* error via `onError`/the dev console warning.
|
|
282
|
+
*/
|
|
39
283
|
export declare const dateSerializer: StorageSerializer<Date>;
|
|
284
|
+
/**
|
|
285
|
+
* Serializer for `bigint` values. `JSON.stringify` throws on `bigint`
|
|
286
|
+
* values, so this stores them as a plain decimal string instead.
|
|
287
|
+
*
|
|
288
|
+
* @throws During `deserialize`, if the stored string can't be converted to
|
|
289
|
+
* a `bigint` — caught by the hook, which falls back to `initialValue` and
|
|
290
|
+
* reports the error via `onError`/the dev console warning.
|
|
291
|
+
*/
|
|
40
292
|
export declare const bigIntSerializer: StorageSerializer<bigint>;
|
|
41
293
|
|
|
294
|
+
export {
|
|
295
|
+
UseStorageEngineReturn as UseLocalStorageReturn,
|
|
296
|
+
UseStorageEngineReturn as UseSessionStorageReturn,
|
|
297
|
+
};
|
|
298
|
+
|
|
42
299
|
export {};
|
package/dist/storage2.js
CHANGED
|
@@ -1,30 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { useCallback as e, useEffect as t, useRef as n, useState as r, useSyncExternalStore as i } from "react";
|
|
2
|
+
//#region src/shared/storageShared/getStorage.ts
|
|
3
|
+
function a(e) {
|
|
4
|
+
return () => {
|
|
5
|
+
if (typeof window > "u") return null;
|
|
6
|
+
try {
|
|
7
|
+
return window[e];
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
3
14
|
//#region src/shared/storageShared/serializers.ts
|
|
4
|
-
var
|
|
15
|
+
var o = {
|
|
5
16
|
serialize: (e) => JSON.stringify(e),
|
|
6
17
|
deserialize: (e) => JSON.parse(e)
|
|
7
18
|
};
|
|
8
|
-
function
|
|
19
|
+
function s() {
|
|
9
20
|
return {
|
|
10
21
|
serialize: (e) => JSON.stringify(Array.from(e.entries())),
|
|
11
22
|
deserialize: (e) => new Map(JSON.parse(e))
|
|
12
23
|
};
|
|
13
24
|
}
|
|
14
|
-
function
|
|
25
|
+
function c() {
|
|
15
26
|
return {
|
|
16
27
|
serialize: (e) => JSON.stringify(Array.from(e.values())),
|
|
17
28
|
deserialize: (e) => new Set(JSON.parse(e))
|
|
18
29
|
};
|
|
19
30
|
}
|
|
20
|
-
var
|
|
31
|
+
var l = {
|
|
21
32
|
serialize: (e) => e.toISOString(),
|
|
22
33
|
deserialize: (e) => {
|
|
23
34
|
let t = new Date(e);
|
|
24
35
|
if (isNaN(t.getTime())) throw Error(`[react-kit] dateSerializer: invalid date string "${e}"`);
|
|
25
36
|
return t;
|
|
26
37
|
}
|
|
27
|
-
},
|
|
38
|
+
}, u = {
|
|
28
39
|
serialize: (e) => e.toString(),
|
|
29
40
|
deserialize: (e) => {
|
|
30
41
|
try {
|
|
@@ -33,229 +44,155 @@ var c = {
|
|
|
33
44
|
throw Error(`[react-kit] bigIntSerializer: cannot convert "${e}" to bigint`);
|
|
34
45
|
}
|
|
35
46
|
}
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
//#region src/storage/useLocalStorage/utils.ts
|
|
39
|
-
function d() {
|
|
40
|
-
if (typeof window > "u") return null;
|
|
47
|
+
}, d = globalThis.process?.env?.NODE_ENV !== "production";
|
|
48
|
+
function f(e, t, n) {
|
|
41
49
|
try {
|
|
42
|
-
return
|
|
50
|
+
return t.deserialize(e);
|
|
43
51
|
} catch {
|
|
44
|
-
return
|
|
52
|
+
return n;
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
function p(a, s, c, l = {}) {
|
|
56
|
+
let { serializer: u = o, initializeWithValue: p = !0, sameInstanceSync: m = !0, crossInstanceSync: h = !0, onError: g } = l, [_] = r(() => s), v = s !== _, [y] = r(() => Symbol()), b = n(u);
|
|
57
|
+
t(() => {
|
|
58
|
+
b.current = u;
|
|
59
|
+
}, [u]);
|
|
60
|
+
let x = n(c);
|
|
61
|
+
t(() => {
|
|
62
|
+
x.current = c;
|
|
63
|
+
}, [c]);
|
|
64
|
+
let S = n(g);
|
|
65
|
+
t(() => {
|
|
66
|
+
S.current = g;
|
|
67
|
+
}, [g]);
|
|
68
|
+
let [C, w] = r(null), T = e((e, t) => {
|
|
69
|
+
d && console.warn(`[${a.hookLabel}] ${e}:`, t.message), S.current?.(t), w(t);
|
|
70
|
+
}, [a.hookLabel]);
|
|
71
|
+
t(() => {
|
|
72
|
+
v && T("Ignoring key change", /* @__PURE__ */ Error(`Changing the storage key at runtime is not supported. Still using original key: "${_}". Received new key: "${s}".`));
|
|
73
|
+
}, [
|
|
74
|
+
s,
|
|
75
|
+
v,
|
|
76
|
+
_,
|
|
77
|
+
T
|
|
78
|
+
]);
|
|
79
|
+
let E = n({
|
|
80
|
+
raw: null,
|
|
81
|
+
parsed: c
|
|
82
|
+
}), D = n(null), O = e(() => {
|
|
83
|
+
let e = a.getStorage();
|
|
84
|
+
if (!e) return x.current;
|
|
85
|
+
let t = e.getItem(_);
|
|
86
|
+
if (E.current.raw === t) return E.current.parsed;
|
|
87
|
+
let n = t === null ? x.current : f(t, b.current, x.current);
|
|
88
|
+
return E.current = {
|
|
89
|
+
raw: t,
|
|
90
|
+
parsed: n
|
|
91
|
+
}, n;
|
|
92
|
+
}, [_]), k = e(() => x.current, []), A = i(e((e) => {
|
|
93
|
+
if (D.current = e, typeof window > "u") return () => {
|
|
94
|
+
D.current = null;
|
|
56
95
|
};
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
|
|
60
|
-
|
|
96
|
+
let t = new AbortController();
|
|
97
|
+
return h && a.nativeStorageEventSupported && window.addEventListener("storage", (t) => {
|
|
98
|
+
t.storageArea === a.getStorage() && (t.key !== null && t.key !== _ || e());
|
|
99
|
+
}, { signal: t.signal }), m && window.addEventListener(`${a.customEventName}:${_}`, (t) => {
|
|
100
|
+
t.detail.instanceId !== y && e();
|
|
101
|
+
}, { signal: t.signal }), () => {
|
|
102
|
+
t.abort(), D.current = null;
|
|
61
103
|
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (!m) return;
|
|
80
|
-
let e = d();
|
|
81
|
-
if (!e) return s;
|
|
82
|
-
let { value: t } = f(e, o, s, l);
|
|
83
|
-
return t;
|
|
84
|
-
}), T = r(C);
|
|
85
|
-
n(() => {
|
|
86
|
-
T.current = C;
|
|
87
|
-
}, [C]);
|
|
88
|
-
let [E, D] = i(m && typeof window < "u"), [O, k] = i(null);
|
|
89
|
-
n(() => {
|
|
90
|
-
if (!y) return;
|
|
91
|
-
let e = /* @__PURE__ */ Error(`[react-kit:use-local-storage] Changing the storage key at runtime is not supported. Still using original key: "${v.current}". Received new key: "${o}".`);
|
|
92
|
-
console.warn(e.message), k(e);
|
|
93
|
-
}, [o, y]), n(() => {
|
|
94
|
-
if (m) return;
|
|
95
|
-
let e = d(), { value: t, error: n } = e === null ? {
|
|
96
|
-
value: s,
|
|
97
|
-
error: null
|
|
98
|
-
} : f(e, v.current, s, S.current);
|
|
99
|
-
n && (console.warn(`[react-kit:use-local-storage] Failed to read key "${v.current}" from localStorage:`, n.message), k(n)), w(t), D(!0);
|
|
100
|
-
}, [m]);
|
|
101
|
-
let A = t((e) => {
|
|
102
|
-
let t = d();
|
|
103
|
-
if (!t) return;
|
|
104
|
-
let n = T.current, r = typeof e == "function" ? e(n) : e;
|
|
105
|
-
try {
|
|
106
|
-
let e = S.current.serialize(r);
|
|
107
|
-
t.setItem(v.current, e), w(r), k(null), h && p(v.current, e, x.current);
|
|
104
|
+
}, [
|
|
105
|
+
_,
|
|
106
|
+
h,
|
|
107
|
+
m,
|
|
108
|
+
a,
|
|
109
|
+
y
|
|
110
|
+
]), O, k), [j, M] = r(!1);
|
|
111
|
+
t(() => {
|
|
112
|
+
M(!0);
|
|
113
|
+
}, []);
|
|
114
|
+
let N = p || j ? A : void 0, P = n(void 0);
|
|
115
|
+
return t(() => {
|
|
116
|
+
let e = a.getStorage();
|
|
117
|
+
if (!e) return;
|
|
118
|
+
let t = e.getItem(_);
|
|
119
|
+
if (t !== P.current && (P.current = t, t !== null)) try {
|
|
120
|
+
b.current.deserialize(t);
|
|
108
121
|
} catch (e) {
|
|
109
|
-
|
|
110
|
-
console.warn(`[react-kit:use-local-storage] Failed to write key "${v.current}" to localStorage:`, t.message), k(t);
|
|
122
|
+
T(`Failed to read key "${_}"`, e instanceof Error ? e : Error(String(e)));
|
|
111
123
|
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (e.newValue === null) {
|
|
119
|
-
w(s), k(null);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
124
|
+
}), {
|
|
125
|
+
value: N,
|
|
126
|
+
setValue: e((e) => {
|
|
127
|
+
let t = a.getStorage();
|
|
128
|
+
if (!t) return;
|
|
129
|
+
let n = O(), r = typeof e == "function" ? e(n) : e;
|
|
122
130
|
try {
|
|
123
|
-
let
|
|
124
|
-
|
|
131
|
+
let e = b.current.serialize(r);
|
|
132
|
+
if (t.setItem(_, e), E.current = {
|
|
133
|
+
raw: e,
|
|
134
|
+
parsed: r
|
|
135
|
+
}, P.current = e, w(null), D.current?.(), m) {
|
|
136
|
+
let t = {
|
|
137
|
+
value: e,
|
|
138
|
+
instanceId: y
|
|
139
|
+
};
|
|
140
|
+
window.dispatchEvent(new CustomEvent(`${a.customEventName}:${_}`, { detail: t }));
|
|
141
|
+
}
|
|
125
142
|
} catch (e) {
|
|
126
|
-
|
|
127
|
-
console.warn(`[react-kit:use-local-storage] Failed to deserialize cross-tab update for key "${v.current}":`, t.message), w(s), k(t);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}), e(b, (e) => {
|
|
131
|
-
if (!h) return;
|
|
132
|
-
let t = e.detail;
|
|
133
|
-
if (t.instanceId !== x.current) {
|
|
134
|
-
if (t.value === null) {
|
|
135
|
-
w(s), k(null);
|
|
136
|
-
return;
|
|
143
|
+
T(`Failed to write key "${_}"`, e instanceof Error ? e : Error(String(e)));
|
|
137
144
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
}, [
|
|
146
|
+
a,
|
|
147
|
+
_,
|
|
148
|
+
m,
|
|
149
|
+
O,
|
|
150
|
+
T,
|
|
151
|
+
y
|
|
152
|
+
]),
|
|
153
|
+
removeValue: e(() => {
|
|
154
|
+
let e = a.getStorage();
|
|
155
|
+
if (e && (e.removeItem(_), E.current = {
|
|
156
|
+
raw: null,
|
|
157
|
+
parsed: x.current
|
|
158
|
+
}, P.current = null, w(null), D.current?.(), m)) {
|
|
159
|
+
let e = {
|
|
160
|
+
value: null,
|
|
161
|
+
instanceId: y
|
|
162
|
+
};
|
|
163
|
+
window.dispatchEvent(new CustomEvent(`${a.customEventName}:${_}`, { detail: e }));
|
|
144
164
|
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
}, [
|
|
166
|
+
a,
|
|
167
|
+
_,
|
|
168
|
+
m,
|
|
169
|
+
y
|
|
170
|
+
]),
|
|
171
|
+
isHydrated: j,
|
|
172
|
+
error: C
|
|
152
173
|
};
|
|
153
174
|
}
|
|
154
175
|
//#endregion
|
|
155
|
-
//#region src/storage/
|
|
156
|
-
var
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
function _(e, t, n, r) {
|
|
168
|
-
try {
|
|
169
|
-
let i = e.getItem(t);
|
|
170
|
-
return i === null ? {
|
|
171
|
-
value: n,
|
|
172
|
-
error: null
|
|
173
|
-
} : {
|
|
174
|
-
value: r.deserialize(i),
|
|
175
|
-
error: null
|
|
176
|
-
};
|
|
177
|
-
} catch (e) {
|
|
178
|
-
return {
|
|
179
|
-
value: n,
|
|
180
|
-
error: e instanceof Error ? e : Error(String(e))
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function v(e, t, n) {
|
|
185
|
-
let r = {
|
|
186
|
-
value: t,
|
|
187
|
-
instanceId: n
|
|
188
|
-
}, i = new CustomEvent(`${h}:${e}`, { detail: r });
|
|
189
|
-
window.dispatchEvent(i);
|
|
176
|
+
//#region src/storage/useLocalStorage/useLocalStorage.ts
|
|
177
|
+
var m = {
|
|
178
|
+
hookLabel: "react-kit:use-local-storage",
|
|
179
|
+
getStorage: a("localStorage"),
|
|
180
|
+
customEventName: "react-kit:use-local-storage",
|
|
181
|
+
nativeStorageEventSupported: !0
|
|
182
|
+
};
|
|
183
|
+
function h(e, t, n = {}) {
|
|
184
|
+
return p(m, e, t, n);
|
|
190
185
|
}
|
|
191
186
|
//#endregion
|
|
192
187
|
//#region src/storage/useSessionStorage/useSessionStorage.ts
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (!e) return s;
|
|
202
|
-
let { value: t } = _(e, o, s, l);
|
|
203
|
-
return t;
|
|
204
|
-
}), w = r(S);
|
|
205
|
-
n(() => {
|
|
206
|
-
w.current = S;
|
|
207
|
-
}, [S]);
|
|
208
|
-
let [T, E] = i(u && typeof window < "u"), [D, O] = i(null);
|
|
209
|
-
n(() => {
|
|
210
|
-
if (!m) return;
|
|
211
|
-
let e = /* @__PURE__ */ Error(`[react-kit:use-session-storage] Changing the storage key at runtime is not supported. Still using original key: "${p.current}". Received new key: "${o}".`);
|
|
212
|
-
console.warn(e.message), O(e);
|
|
213
|
-
}, [o, m]), n(() => {
|
|
214
|
-
if (u) return;
|
|
215
|
-
let e = g(), { value: t, error: n } = e === null ? {
|
|
216
|
-
value: s,
|
|
217
|
-
error: null
|
|
218
|
-
} : _(e, p.current, s, x.current);
|
|
219
|
-
n && (console.warn(`[react-kit:use-session-storage] Failed to read key "${p.current}" from sessionStorage:`, n.message), O(n)), C(t), E(!0);
|
|
220
|
-
}, [u]);
|
|
221
|
-
let k = t((e) => {
|
|
222
|
-
let t = g();
|
|
223
|
-
if (!t) return;
|
|
224
|
-
let n = w.current, r = typeof e == "function" ? e(n) : e;
|
|
225
|
-
try {
|
|
226
|
-
let e = x.current.serialize(r);
|
|
227
|
-
t.setItem(p.current, e), C(r), O(null), d && v(p.current, e, b.current);
|
|
228
|
-
} catch (e) {
|
|
229
|
-
let t = e instanceof Error ? e : Error(String(e));
|
|
230
|
-
console.warn(`[react-kit:use-session-storage] Failed to write key "${p.current}" to sessionStorage:`, t.message), O(t);
|
|
231
|
-
}
|
|
232
|
-
}, [d]), A = t(() => {
|
|
233
|
-
let e = g();
|
|
234
|
-
e && (e.removeItem(p.current), C(s), O(null), d && v(p.current, null, b.current));
|
|
235
|
-
}, [d]);
|
|
236
|
-
return e(y, (e) => {
|
|
237
|
-
if (!d) return;
|
|
238
|
-
let t = e.detail;
|
|
239
|
-
if (t.instanceId !== b.current) {
|
|
240
|
-
if (t.value === null) {
|
|
241
|
-
C(s), O(null);
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
try {
|
|
245
|
-
let e = x.current.deserialize(t.value);
|
|
246
|
-
C(e), O(null);
|
|
247
|
-
} catch (e) {
|
|
248
|
-
let t = e instanceof Error ? e : Error(String(e));
|
|
249
|
-
console.warn(`[react-kit:use-session-storage] Failed to deserialize same-tab update for key "${p.current}":`, t.message), C(s), O(t);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}, { target: typeof window > "u" ? null : window }), {
|
|
253
|
-
value: S,
|
|
254
|
-
setValue: k,
|
|
255
|
-
removeValue: A,
|
|
256
|
-
isHydrated: T,
|
|
257
|
-
error: D
|
|
258
|
-
};
|
|
188
|
+
var g = {
|
|
189
|
+
hookLabel: "react-kit:use-session-storage",
|
|
190
|
+
getStorage: a("sessionStorage"),
|
|
191
|
+
customEventName: "react-kit:use-session-storage",
|
|
192
|
+
nativeStorageEventSupported: !1
|
|
193
|
+
};
|
|
194
|
+
function _(e, t, n = {}) {
|
|
195
|
+
return p(g, e, t, n);
|
|
259
196
|
}
|
|
260
197
|
//#endregion
|
|
261
|
-
export { a,
|
|
198
|
+
export { o as a, l as i, h as n, s as o, u as r, c as s, _ as t };
|