@mui/utils 5.15.13 → 5.15.20

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.
@@ -23,11 +23,9 @@ export default function deepmerge(target, source, options = {
23
23
  const output = options.clone ? _extends({}, target) : target;
24
24
  if (isPlainObject(target) && isPlainObject(source)) {
25
25
  Object.keys(source).forEach(key => {
26
+ if (isPlainObject(source[key]) &&
26
27
  // Avoid prototype pollution
27
- if (key === '__proto__') {
28
- return;
29
- }
30
- if (isPlainObject(source[key]) && key in target && isPlainObject(target[key])) {
28
+ Object.prototype.hasOwnProperty.call(target, key) && isPlainObject(target[key])) {
31
29
  // Since `output` is a clone of `target` and we have narrowed `target` in this block we can cast to the same type.
32
30
  output[key] = deepmerge(target[key], source[key], options);
33
31
  } else if (options.clone) {
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v5.15.13
2
+ * @mui/utils v5.15.20
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -25,11 +25,9 @@ export default function deepmerge(target, source) {
25
25
  var output = options.clone ? _extends({}, target) : target;
26
26
  if (isPlainObject(target) && isPlainObject(source)) {
27
27
  Object.keys(source).forEach(function (key) {
28
+ if (isPlainObject(source[key]) &&
28
29
  // Avoid prototype pollution
29
- if (key === '__proto__') {
30
- return;
31
- }
32
- if (isPlainObject(source[key]) && key in target && isPlainObject(target[key])) {
30
+ Object.prototype.hasOwnProperty.call(target, key) && isPlainObject(target[key])) {
33
31
  // Since `output` is a clone of `target` and we have narrowed `target` in this block we can cast to the same type.
34
32
  output[key] = deepmerge(target[key], source[key], options);
35
33
  } else if (options.clone) {
package/legacy/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v5.15.13
2
+ * @mui/utils v5.15.20
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -24,7 +24,7 @@ export default function useControlled(_ref) {
24
24
  var _React$useRef2 = React.useRef(defaultProp),
25
25
  defaultValue = _React$useRef2.current;
26
26
  React.useEffect(function () {
27
- if (!isControlled && defaultValue !== defaultProp) {
27
+ if (!isControlled && !Object.is(defaultValue, defaultProp)) {
28
28
  console.error(["MUI: A component is changing the default ".concat(state, " state of an uncontrolled ").concat(name, " after being initialized. ") + "To suppress this warning opt to use a controlled ".concat(name, ".")].join('\n'));
29
29
  }
30
30
  }, [JSON.stringify(defaultProp)]);
@@ -0,0 +1 @@
1
+ export { default } from './useLocalStorageState';
@@ -0,0 +1,121 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+
5
+ // storage events only work across tabs, we'll use an event emitter to announce within the current tab
6
+ var currentTabChangeListeners = new Map();
7
+ function onCurrentTabStorageChange(key, handler) {
8
+ var listeners = currentTabChangeListeners.get(key);
9
+ if (!listeners) {
10
+ listeners = new Set();
11
+ currentTabChangeListeners.set(key, listeners);
12
+ }
13
+ listeners.add(handler);
14
+ }
15
+ function offCurrentTabStorageChange(key, handler) {
16
+ var listeners = currentTabChangeListeners.get(key);
17
+ if (!listeners) {
18
+ return;
19
+ }
20
+ listeners.delete(handler);
21
+ if (listeners.size === 0) {
22
+ currentTabChangeListeners.delete(key);
23
+ }
24
+ }
25
+ function emitCurrentTabStorageChange(key) {
26
+ var listeners = currentTabChangeListeners.get(key);
27
+ if (listeners) {
28
+ listeners.forEach(function (listener) {
29
+ return listener();
30
+ });
31
+ }
32
+ }
33
+ function subscribe(area, key, callbark) {
34
+ if (!key) {
35
+ return function () {};
36
+ }
37
+ var storageHandler = function storageHandler(event) {
38
+ if (event.storageArea === area && event.key === key) {
39
+ callbark();
40
+ }
41
+ };
42
+ window.addEventListener('storage', storageHandler);
43
+ onCurrentTabStorageChange(key, callbark);
44
+ return function () {
45
+ window.removeEventListener('storage', storageHandler);
46
+ offCurrentTabStorageChange(key, callbark);
47
+ };
48
+ }
49
+ function getSnapshot(area, key) {
50
+ if (!key) {
51
+ return null;
52
+ }
53
+ try {
54
+ return area.getItem(key);
55
+ } catch (_unused) {
56
+ // ignore
57
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
58
+ return null;
59
+ }
60
+ }
61
+ function setValue(area, key, value) {
62
+ if (!key) {
63
+ return;
64
+ }
65
+ try {
66
+ if (value === null) {
67
+ area.removeItem(key);
68
+ } else {
69
+ area.setItem(key, String(value));
70
+ }
71
+ } catch (_unused2) {
72
+ // ignore
73
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
74
+ return;
75
+ }
76
+ emitCurrentTabStorageChange(key);
77
+ }
78
+ var serverValue = [null, function () {}];
79
+ function useLocalStorageStateServer() {
80
+ return serverValue;
81
+ }
82
+
83
+ /**
84
+ * Sync state to local storage so that it persists through a page refresh. Usage is
85
+ * similar to useState except we pass in a storage key so that we can default
86
+ * to that value on page load instead of the specified initial value.
87
+ *
88
+ * Since the storage API isn't available in server-rendering environments, we
89
+ * return null during SSR and hydration.
90
+ */
91
+ function useLocalStorageStateBrowser(key) {
92
+ var initializer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
93
+ var _React$useState = React.useState(initializer),
94
+ initialValue = _React$useState[0];
95
+ var area = window.localStorage;
96
+ var subscribeKey = React.useCallback(function (callbark) {
97
+ return subscribe(area, key, callbark);
98
+ }, [area, key]);
99
+ var getKeySnapshot = React.useCallback(function () {
100
+ var _getSnapshot;
101
+ return (_getSnapshot = getSnapshot(area, key)) != null ? _getSnapshot : initialValue;
102
+ }, [area, initialValue, key]);
103
+
104
+ // Start with null for the hydration, and then switch to the actual value.
105
+ var getKeyServerSnapshot = function getKeyServerSnapshot() {
106
+ return null;
107
+ };
108
+ var storedValue = React.useSyncExternalStore(subscribeKey, getKeySnapshot, getKeyServerSnapshot);
109
+ var setStoredValue = React.useCallback(function (value) {
110
+ var valueToStore = value instanceof Function ? value(storedValue) : value;
111
+ setValue(area, key, valueToStore);
112
+ }, [area, key, storedValue]);
113
+ var _React$useState2 = React.useState(initialValue),
114
+ nonStoredValue = _React$useState2[0],
115
+ setNonStoredValue = _React$useState2[1];
116
+ if (!key) {
117
+ return [nonStoredValue, setNonStoredValue];
118
+ }
119
+ return [storedValue, setStoredValue];
120
+ }
121
+ export default typeof window === 'undefined' ? useLocalStorageStateServer : useLocalStorageStateBrowser;
@@ -23,11 +23,9 @@ export default function deepmerge(target, source, options = {
23
23
  const output = options.clone ? _extends({}, target) : target;
24
24
  if (isPlainObject(target) && isPlainObject(source)) {
25
25
  Object.keys(source).forEach(key => {
26
+ if (isPlainObject(source[key]) &&
26
27
  // Avoid prototype pollution
27
- if (key === '__proto__') {
28
- return;
29
- }
30
- if (isPlainObject(source[key]) && key in target && isPlainObject(target[key])) {
28
+ Object.prototype.hasOwnProperty.call(target, key) && isPlainObject(target[key])) {
31
29
  // Since `output` is a clone of `target` and we have narrowed `target` in this block we can cast to the same type.
32
30
  output[key] = deepmerge(target[key], source[key], options);
33
31
  } else if (options.clone) {
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v5.15.13
2
+ * @mui/utils v5.15.20
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -24,7 +24,7 @@ export default function useControlled({
24
24
  current: defaultValue
25
25
  } = React.useRef(defaultProp);
26
26
  React.useEffect(() => {
27
- if (!isControlled && defaultValue !== defaultProp) {
27
+ if (!isControlled && !Object.is(defaultValue, defaultProp)) {
28
28
  console.error([`MUI: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` + `To suppress this warning opt to use a controlled ${name}.`].join('\n'));
29
29
  }
30
30
  }, [JSON.stringify(defaultProp)]);
@@ -0,0 +1 @@
1
+ export { default } from './useLocalStorageState';
@@ -0,0 +1,108 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+
5
+ // storage events only work across tabs, we'll use an event emitter to announce within the current tab
6
+ const currentTabChangeListeners = new Map();
7
+ function onCurrentTabStorageChange(key, handler) {
8
+ let listeners = currentTabChangeListeners.get(key);
9
+ if (!listeners) {
10
+ listeners = new Set();
11
+ currentTabChangeListeners.set(key, listeners);
12
+ }
13
+ listeners.add(handler);
14
+ }
15
+ function offCurrentTabStorageChange(key, handler) {
16
+ const listeners = currentTabChangeListeners.get(key);
17
+ if (!listeners) {
18
+ return;
19
+ }
20
+ listeners.delete(handler);
21
+ if (listeners.size === 0) {
22
+ currentTabChangeListeners.delete(key);
23
+ }
24
+ }
25
+ function emitCurrentTabStorageChange(key) {
26
+ const listeners = currentTabChangeListeners.get(key);
27
+ if (listeners) {
28
+ listeners.forEach(listener => listener());
29
+ }
30
+ }
31
+ function subscribe(area, key, callbark) {
32
+ if (!key) {
33
+ return () => {};
34
+ }
35
+ const storageHandler = event => {
36
+ if (event.storageArea === area && event.key === key) {
37
+ callbark();
38
+ }
39
+ };
40
+ window.addEventListener('storage', storageHandler);
41
+ onCurrentTabStorageChange(key, callbark);
42
+ return () => {
43
+ window.removeEventListener('storage', storageHandler);
44
+ offCurrentTabStorageChange(key, callbark);
45
+ };
46
+ }
47
+ function getSnapshot(area, key) {
48
+ if (!key) {
49
+ return null;
50
+ }
51
+ try {
52
+ return area.getItem(key);
53
+ } catch {
54
+ // ignore
55
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
56
+ return null;
57
+ }
58
+ }
59
+ function setValue(area, key, value) {
60
+ if (!key) {
61
+ return;
62
+ }
63
+ try {
64
+ if (value === null) {
65
+ area.removeItem(key);
66
+ } else {
67
+ area.setItem(key, String(value));
68
+ }
69
+ } catch {
70
+ // ignore
71
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
72
+ return;
73
+ }
74
+ emitCurrentTabStorageChange(key);
75
+ }
76
+ const serverValue = [null, () => {}];
77
+ function useLocalStorageStateServer() {
78
+ return serverValue;
79
+ }
80
+
81
+ /**
82
+ * Sync state to local storage so that it persists through a page refresh. Usage is
83
+ * similar to useState except we pass in a storage key so that we can default
84
+ * to that value on page load instead of the specified initial value.
85
+ *
86
+ * Since the storage API isn't available in server-rendering environments, we
87
+ * return null during SSR and hydration.
88
+ */
89
+ function useLocalStorageStateBrowser(key, initializer = null) {
90
+ const [initialValue] = React.useState(initializer);
91
+ const area = window.localStorage;
92
+ const subscribeKey = React.useCallback(callbark => subscribe(area, key, callbark), [area, key]);
93
+ const getKeySnapshot = React.useCallback(() => getSnapshot(area, key) ?? initialValue, [area, initialValue, key]);
94
+
95
+ // Start with null for the hydration, and then switch to the actual value.
96
+ const getKeyServerSnapshot = () => null;
97
+ const storedValue = React.useSyncExternalStore(subscribeKey, getKeySnapshot, getKeyServerSnapshot);
98
+ const setStoredValue = React.useCallback(value => {
99
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
100
+ setValue(area, key, valueToStore);
101
+ }, [area, key, storedValue]);
102
+ const [nonStoredValue, setNonStoredValue] = React.useState(initialValue);
103
+ if (!key) {
104
+ return [nonStoredValue, setNonStoredValue];
105
+ }
106
+ return [storedValue, setStoredValue];
107
+ }
108
+ export default typeof window === 'undefined' ? useLocalStorageStateServer : useLocalStorageStateBrowser;
@@ -31,11 +31,9 @@ function deepmerge(target, source, options = {
31
31
  const output = options.clone ? (0, _extends2.default)({}, target) : target;
32
32
  if (isPlainObject(target) && isPlainObject(source)) {
33
33
  Object.keys(source).forEach(key => {
34
+ if (isPlainObject(source[key]) &&
34
35
  // Avoid prototype pollution
35
- if (key === '__proto__') {
36
- return;
37
- }
38
- if (isPlainObject(source[key]) && key in target && isPlainObject(target[key])) {
36
+ Object.prototype.hasOwnProperty.call(target, key) && isPlainObject(target[key])) {
39
37
  // Since `output` is a clone of `target` and we have narrowed `target` in this block we can cast to the same type.
40
38
  output[key] = deepmerge(target[key], source[key], options);
41
39
  } else if (options.clone) {
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v5.15.13
2
+ * @mui/utils v5.15.20
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -31,7 +31,7 @@ function useControlled({
31
31
  current: defaultValue
32
32
  } = React.useRef(defaultProp);
33
33
  React.useEffect(() => {
34
- if (!isControlled && defaultValue !== defaultProp) {
34
+ if (!isControlled && !Object.is(defaultValue, defaultProp)) {
35
35
  console.error([`MUI: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` + `To suppress this warning opt to use a controlled ${name}.`].join('\n'));
36
36
  }
37
37
  }, [JSON.stringify(defaultProp)]);
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ Object.defineProperty(exports, "default", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _useLocalStorageState.default;
11
+ }
12
+ });
13
+ var _useLocalStorageState = _interopRequireDefault(require("./useLocalStorageState"));
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var React = _interopRequireWildcard(require("react"));
9
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
10
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
11
+ // storage events only work across tabs, we'll use an event emitter to announce within the current tab
12
+ const currentTabChangeListeners = new Map();
13
+ function onCurrentTabStorageChange(key, handler) {
14
+ let listeners = currentTabChangeListeners.get(key);
15
+ if (!listeners) {
16
+ listeners = new Set();
17
+ currentTabChangeListeners.set(key, listeners);
18
+ }
19
+ listeners.add(handler);
20
+ }
21
+ function offCurrentTabStorageChange(key, handler) {
22
+ const listeners = currentTabChangeListeners.get(key);
23
+ if (!listeners) {
24
+ return;
25
+ }
26
+ listeners.delete(handler);
27
+ if (listeners.size === 0) {
28
+ currentTabChangeListeners.delete(key);
29
+ }
30
+ }
31
+ function emitCurrentTabStorageChange(key) {
32
+ const listeners = currentTabChangeListeners.get(key);
33
+ if (listeners) {
34
+ listeners.forEach(listener => listener());
35
+ }
36
+ }
37
+ function subscribe(area, key, callbark) {
38
+ if (!key) {
39
+ return () => {};
40
+ }
41
+ const storageHandler = event => {
42
+ if (event.storageArea === area && event.key === key) {
43
+ callbark();
44
+ }
45
+ };
46
+ window.addEventListener('storage', storageHandler);
47
+ onCurrentTabStorageChange(key, callbark);
48
+ return () => {
49
+ window.removeEventListener('storage', storageHandler);
50
+ offCurrentTabStorageChange(key, callbark);
51
+ };
52
+ }
53
+ function getSnapshot(area, key) {
54
+ if (!key) {
55
+ return null;
56
+ }
57
+ try {
58
+ return area.getItem(key);
59
+ } catch {
60
+ // ignore
61
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
62
+ return null;
63
+ }
64
+ }
65
+ function setValue(area, key, value) {
66
+ if (!key) {
67
+ return;
68
+ }
69
+ try {
70
+ if (value === null) {
71
+ area.removeItem(key);
72
+ } else {
73
+ area.setItem(key, String(value));
74
+ }
75
+ } catch {
76
+ // ignore
77
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
78
+ return;
79
+ }
80
+ emitCurrentTabStorageChange(key);
81
+ }
82
+ const serverValue = [null, () => {}];
83
+ function useLocalStorageStateServer() {
84
+ return serverValue;
85
+ }
86
+
87
+ /**
88
+ * Sync state to local storage so that it persists through a page refresh. Usage is
89
+ * similar to useState except we pass in a storage key so that we can default
90
+ * to that value on page load instead of the specified initial value.
91
+ *
92
+ * Since the storage API isn't available in server-rendering environments, we
93
+ * return null during SSR and hydration.
94
+ */
95
+ function useLocalStorageStateBrowser(key, initializer = null) {
96
+ const [initialValue] = React.useState(initializer);
97
+ const area = window.localStorage;
98
+ const subscribeKey = React.useCallback(callbark => subscribe(area, key, callbark), [area, key]);
99
+ const getKeySnapshot = React.useCallback(() => {
100
+ var _getSnapshot;
101
+ return (_getSnapshot = getSnapshot(area, key)) != null ? _getSnapshot : initialValue;
102
+ }, [area, initialValue, key]);
103
+
104
+ // Start with null for the hydration, and then switch to the actual value.
105
+ const getKeyServerSnapshot = () => null;
106
+ const storedValue = React.useSyncExternalStore(subscribeKey, getKeySnapshot, getKeyServerSnapshot);
107
+ const setStoredValue = React.useCallback(value => {
108
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
109
+ setValue(area, key, valueToStore);
110
+ }, [area, key, storedValue]);
111
+ const [nonStoredValue, setNonStoredValue] = React.useState(initialValue);
112
+ if (!key) {
113
+ return [nonStoredValue, setNonStoredValue];
114
+ }
115
+ return [storedValue, setStoredValue];
116
+ }
117
+ var _default = exports.default = typeof window === 'undefined' ? useLocalStorageStateServer : useLocalStorageStateBrowser;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/utils",
3
- "version": "5.15.13",
3
+ "version": "5.15.20",
4
4
  "private": false,
5
5
  "author": "MUI Team",
6
6
  "description": "Utility functions for React components.",
@@ -24,7 +24,7 @@ export default function useControlled({
24
24
  current: defaultValue
25
25
  } = React.useRef(defaultProp);
26
26
  React.useEffect(() => {
27
- if (!isControlled && defaultValue !== defaultProp) {
27
+ if (!isControlled && !Object.is(defaultValue, defaultProp)) {
28
28
  console.error([`MUI: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` + `To suppress this warning opt to use a controlled ${name}.`].join('\n'));
29
29
  }
30
30
  }, [JSON.stringify(defaultProp)]);
@@ -0,0 +1 @@
1
+ export { default } from './useLocalStorageState';
@@ -0,0 +1 @@
1
+ export { default } from './useLocalStorageState';
@@ -0,0 +1,6 @@
1
+ {
2
+ "sideEffects": false,
3
+ "module": "./index.js",
4
+ "main": "../node/useLocalStorageState/index.js",
5
+ "types": "./index.d.ts"
6
+ }
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ type Initializer = () => string | null;
3
+ type UseStorageStateHookResult = [
4
+ string | null,
5
+ React.Dispatch<React.SetStateAction<string | null>>
6
+ ];
7
+ /**
8
+ * Sync state to local storage so that it persists through a page refresh. Usage is
9
+ * similar to useState except we pass in a storage key so that we can default
10
+ * to that value on page load instead of the specified initial value.
11
+ *
12
+ * Since the storage API isn't available in server-rendering environments, we
13
+ * return null during SSR and hydration.
14
+ */
15
+ declare function useLocalStorageStateBrowser(key: string | null, initializer?: string | null | Initializer): UseStorageStateHookResult;
16
+ declare const _default: typeof useLocalStorageStateBrowser;
17
+ export default _default;
@@ -0,0 +1,111 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+
5
+ // storage events only work across tabs, we'll use an event emitter to announce within the current tab
6
+ const currentTabChangeListeners = new Map();
7
+ function onCurrentTabStorageChange(key, handler) {
8
+ let listeners = currentTabChangeListeners.get(key);
9
+ if (!listeners) {
10
+ listeners = new Set();
11
+ currentTabChangeListeners.set(key, listeners);
12
+ }
13
+ listeners.add(handler);
14
+ }
15
+ function offCurrentTabStorageChange(key, handler) {
16
+ const listeners = currentTabChangeListeners.get(key);
17
+ if (!listeners) {
18
+ return;
19
+ }
20
+ listeners.delete(handler);
21
+ if (listeners.size === 0) {
22
+ currentTabChangeListeners.delete(key);
23
+ }
24
+ }
25
+ function emitCurrentTabStorageChange(key) {
26
+ const listeners = currentTabChangeListeners.get(key);
27
+ if (listeners) {
28
+ listeners.forEach(listener => listener());
29
+ }
30
+ }
31
+ function subscribe(area, key, callbark) {
32
+ if (!key) {
33
+ return () => {};
34
+ }
35
+ const storageHandler = event => {
36
+ if (event.storageArea === area && event.key === key) {
37
+ callbark();
38
+ }
39
+ };
40
+ window.addEventListener('storage', storageHandler);
41
+ onCurrentTabStorageChange(key, callbark);
42
+ return () => {
43
+ window.removeEventListener('storage', storageHandler);
44
+ offCurrentTabStorageChange(key, callbark);
45
+ };
46
+ }
47
+ function getSnapshot(area, key) {
48
+ if (!key) {
49
+ return null;
50
+ }
51
+ try {
52
+ return area.getItem(key);
53
+ } catch {
54
+ // ignore
55
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
56
+ return null;
57
+ }
58
+ }
59
+ function setValue(area, key, value) {
60
+ if (!key) {
61
+ return;
62
+ }
63
+ try {
64
+ if (value === null) {
65
+ area.removeItem(key);
66
+ } else {
67
+ area.setItem(key, String(value));
68
+ }
69
+ } catch {
70
+ // ignore
71
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
72
+ return;
73
+ }
74
+ emitCurrentTabStorageChange(key);
75
+ }
76
+ const serverValue = [null, () => {}];
77
+ function useLocalStorageStateServer() {
78
+ return serverValue;
79
+ }
80
+
81
+ /**
82
+ * Sync state to local storage so that it persists through a page refresh. Usage is
83
+ * similar to useState except we pass in a storage key so that we can default
84
+ * to that value on page load instead of the specified initial value.
85
+ *
86
+ * Since the storage API isn't available in server-rendering environments, we
87
+ * return null during SSR and hydration.
88
+ */
89
+ function useLocalStorageStateBrowser(key, initializer = null) {
90
+ const [initialValue] = React.useState(initializer);
91
+ const area = window.localStorage;
92
+ const subscribeKey = React.useCallback(callbark => subscribe(area, key, callbark), [area, key]);
93
+ const getKeySnapshot = React.useCallback(() => {
94
+ var _getSnapshot;
95
+ return (_getSnapshot = getSnapshot(area, key)) != null ? _getSnapshot : initialValue;
96
+ }, [area, initialValue, key]);
97
+
98
+ // Start with null for the hydration, and then switch to the actual value.
99
+ const getKeyServerSnapshot = () => null;
100
+ const storedValue = React.useSyncExternalStore(subscribeKey, getKeySnapshot, getKeyServerSnapshot);
101
+ const setStoredValue = React.useCallback(value => {
102
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
103
+ setValue(area, key, valueToStore);
104
+ }, [area, key, storedValue]);
105
+ const [nonStoredValue, setNonStoredValue] = React.useState(initialValue);
106
+ if (!key) {
107
+ return [nonStoredValue, setNonStoredValue];
108
+ }
109
+ return [storedValue, setStoredValue];
110
+ }
111
+ export default typeof window === 'undefined' ? useLocalStorageStateServer : useLocalStorageStateBrowser;