payment-kit 1.21.14 → 1.21.15
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/blocklet.yml +1 -1
- package/package.json +6 -6
- package/src/components/invoice/list.tsx +15 -17
- package/src/components/payment-intent/list.tsx +15 -17
- package/src/components/payouts/list.tsx +15 -17
- package/src/components/refund/list.tsx +15 -17
- package/src/components/subscription/list.tsx +12 -15
- package/src/hooks/cache-state.ts +84 -0
- package/src/pages/admin/overview.tsx +1 -1
package/blocklet.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.15",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"lint": "tsc --noEmit && eslint src api/src --ext .mjs,.js,.jsx,.ts,.tsx",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"@blocklet/error": "^0.2.5",
|
|
57
57
|
"@blocklet/js-sdk": "^1.16.53-beta-20251011-054719-4ed2f6b7",
|
|
58
58
|
"@blocklet/logger": "^1.16.53-beta-20251011-054719-4ed2f6b7",
|
|
59
|
-
"@blocklet/payment-broker-client": "1.21.
|
|
60
|
-
"@blocklet/payment-react": "1.21.
|
|
61
|
-
"@blocklet/payment-vendor": "1.21.
|
|
59
|
+
"@blocklet/payment-broker-client": "1.21.15",
|
|
60
|
+
"@blocklet/payment-react": "1.21.15",
|
|
61
|
+
"@blocklet/payment-vendor": "1.21.15",
|
|
62
62
|
"@blocklet/sdk": "^1.16.53-beta-20251011-054719-4ed2f6b7",
|
|
63
63
|
"@blocklet/ui-react": "^3.1.46",
|
|
64
64
|
"@blocklet/uploader": "^0.2.15",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"devDependencies": {
|
|
129
129
|
"@abtnode/types": "^1.16.53-beta-20251011-054719-4ed2f6b7",
|
|
130
130
|
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
131
|
-
"@blocklet/payment-types": "1.21.
|
|
131
|
+
"@blocklet/payment-types": "1.21.15",
|
|
132
132
|
"@types/cookie-parser": "^1.4.9",
|
|
133
133
|
"@types/cors": "^2.8.19",
|
|
134
134
|
"@types/debug": "^4.1.12",
|
|
@@ -175,5 +175,5 @@
|
|
|
175
175
|
"parser": "typescript"
|
|
176
176
|
}
|
|
177
177
|
},
|
|
178
|
-
"gitHead": "
|
|
178
|
+
"gitHead": "fd48f9233f19514b537e30b013e09a7d9f7a9f48"
|
|
179
179
|
}
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
} from '@blocklet/payment-react';
|
|
14
14
|
import type { TInvoiceExpanded } from '@blocklet/payment-types';
|
|
15
15
|
import { Avatar, CircularProgress, Typography } from '@mui/material';
|
|
16
|
-
import { useLocalStorageState } from 'ahooks';
|
|
17
16
|
import { useEffect, useState } from 'react';
|
|
18
17
|
import { Link, useSearchParams } from 'react-router-dom';
|
|
18
|
+
import { useCacheState } from '../../hooks/cache-state';
|
|
19
19
|
import CustomerLink from '../customer/link';
|
|
20
20
|
import FilterToolbar from '../filter-toolbar';
|
|
21
21
|
import InvoiceActions from './action';
|
|
@@ -129,11 +129,7 @@ export default function InvoiceList({
|
|
|
129
129
|
const { t, locale } = useLocaleContext();
|
|
130
130
|
const defaultPageSize = useDefaultPageSize(20);
|
|
131
131
|
|
|
132
|
-
const
|
|
133
|
-
const urlCurrencyId = searchParams.get('currency_id');
|
|
134
|
-
const urlCustomerId = searchParams.get('customer_id');
|
|
135
|
-
|
|
136
|
-
const [search, setSearch] = useLocalStorageState<
|
|
132
|
+
const [search, setSearch] = useCacheState<
|
|
137
133
|
SearchProps & { ignore_zero?: boolean; include_staking?: boolean; include_return_staking?: boolean }
|
|
138
134
|
>(listKey, {
|
|
139
135
|
defaultValue: {
|
|
@@ -147,19 +143,21 @@ export default function InvoiceList({
|
|
|
147
143
|
include_staking: !!include_staking,
|
|
148
144
|
include_return_staking: !!include_return_staking,
|
|
149
145
|
},
|
|
146
|
+
getUrlParams: () => {
|
|
147
|
+
const params: Record<string, any> = {};
|
|
148
|
+
if (searchParams.has('status')) {
|
|
149
|
+
params.status = searchParams.get('status');
|
|
150
|
+
}
|
|
151
|
+
if (searchParams.has('currency_id')) {
|
|
152
|
+
params.currency_id = searchParams.get('currency_id');
|
|
153
|
+
}
|
|
154
|
+
if (searchParams.has('customer_id')) {
|
|
155
|
+
params.customer_id = searchParams.get('customer_id');
|
|
156
|
+
}
|
|
157
|
+
return params;
|
|
158
|
+
},
|
|
150
159
|
});
|
|
151
160
|
|
|
152
|
-
useEffect(() => {
|
|
153
|
-
if (urlStatus || urlCurrencyId || urlCustomerId) {
|
|
154
|
-
setSearch((prev) => ({
|
|
155
|
-
...prev!,
|
|
156
|
-
...(urlStatus && { status: urlStatus }),
|
|
157
|
-
...(urlCurrencyId && { currency_id: urlCurrencyId }),
|
|
158
|
-
...(urlCustomerId && { customer_id: urlCustomerId }),
|
|
159
|
-
}));
|
|
160
|
-
}
|
|
161
|
-
}, [urlStatus, urlCurrencyId, urlCustomerId, setSearch]);
|
|
162
|
-
|
|
163
161
|
const [data, setData] = useState({}) as any;
|
|
164
162
|
|
|
165
163
|
const refresh = () =>
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
} from '@blocklet/payment-react';
|
|
12
12
|
import type { TPaymentIntentExpanded } from '@blocklet/payment-types';
|
|
13
13
|
import { Avatar, CircularProgress, Typography } from '@mui/material';
|
|
14
|
-
import { useLocalStorageState } from 'ahooks';
|
|
15
14
|
import { useEffect, useState } from 'react';
|
|
16
15
|
import { Link, useSearchParams } from 'react-router-dom';
|
|
17
16
|
|
|
18
17
|
import { debounce } from '../../libs/util';
|
|
18
|
+
import { useCacheState } from '../../hooks/cache-state';
|
|
19
19
|
import CustomerLink from '../customer/link';
|
|
20
20
|
import FilterToolbar from '../filter-toolbar';
|
|
21
21
|
import PaymentIntentActions from './actions';
|
|
@@ -81,11 +81,7 @@ export default function PaymentList({
|
|
|
81
81
|
const listKey = getListKey({ customer_id, invoice_id });
|
|
82
82
|
const defaultPageSize = useDefaultPageSize(20);
|
|
83
83
|
|
|
84
|
-
const
|
|
85
|
-
const urlCurrencyId = searchParams.get('currency_id');
|
|
86
|
-
const urlCustomerId = searchParams.get('customer_id');
|
|
87
|
-
|
|
88
|
-
const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
|
|
84
|
+
const [search, setSearch] = useCacheState<SearchProps>(listKey, {
|
|
89
85
|
defaultValue: {
|
|
90
86
|
status: '',
|
|
91
87
|
customer_id,
|
|
@@ -93,19 +89,21 @@ export default function PaymentList({
|
|
|
93
89
|
pageSize: defaultPageSize,
|
|
94
90
|
page: 1,
|
|
95
91
|
},
|
|
92
|
+
getUrlParams: () => {
|
|
93
|
+
const params: Record<string, any> = {};
|
|
94
|
+
if (searchParams.has('status')) {
|
|
95
|
+
params.status = searchParams.get('status');
|
|
96
|
+
}
|
|
97
|
+
if (searchParams.has('currency_id')) {
|
|
98
|
+
params.currency_id = searchParams.get('currency_id');
|
|
99
|
+
}
|
|
100
|
+
if (searchParams.has('customer_id')) {
|
|
101
|
+
params.customer_id = searchParams.get('customer_id');
|
|
102
|
+
}
|
|
103
|
+
return params;
|
|
104
|
+
},
|
|
96
105
|
});
|
|
97
106
|
|
|
98
|
-
useEffect(() => {
|
|
99
|
-
if (urlStatus || urlCurrencyId || urlCustomerId) {
|
|
100
|
-
setSearch((prev) => ({
|
|
101
|
-
...prev!,
|
|
102
|
-
...(urlStatus && { status: urlStatus }),
|
|
103
|
-
...(urlCurrencyId && { currency_id: urlCurrencyId }),
|
|
104
|
-
...(urlCustomerId && { customer_id: urlCustomerId }),
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
}, [urlStatus, urlCurrencyId, urlCustomerId, setSearch]);
|
|
108
|
-
|
|
109
107
|
const [data, setData] = useState({}) as any;
|
|
110
108
|
|
|
111
109
|
const fetchListData = () => {
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
} from '@blocklet/payment-react';
|
|
12
12
|
import type { TPayoutExpanded } from '@blocklet/payment-types';
|
|
13
13
|
import { Avatar, CircularProgress, Typography } from '@mui/material';
|
|
14
|
-
import { useLocalStorageState } from 'ahooks';
|
|
15
14
|
import { useEffect, useState } from 'react';
|
|
16
15
|
import { Link, useSearchParams } from 'react-router-dom';
|
|
17
16
|
|
|
18
17
|
import DID from '@arcblock/ux/lib/DID';
|
|
19
18
|
import ShortenLabel from '@arcblock/ux/lib/UserCard/Content/shorten-label';
|
|
20
19
|
import { debounce, getAppInfo } from '../../libs/util';
|
|
20
|
+
import { useCacheState } from '../../hooks/cache-state';
|
|
21
21
|
import CustomerLink from '../customer/link';
|
|
22
22
|
import FilterToolbar from '../filter-toolbar';
|
|
23
23
|
import PayoutActions from './actions';
|
|
@@ -86,11 +86,7 @@ export default function PayoutList({
|
|
|
86
86
|
const listKey = getListKey({ customer_id, payment_intent_id });
|
|
87
87
|
const defaultPageSize = useDefaultPageSize(20);
|
|
88
88
|
|
|
89
|
-
const
|
|
90
|
-
const urlCurrencyId = searchParams.get('currency_id');
|
|
91
|
-
const urlCustomerId = searchParams.get('customer_id');
|
|
92
|
-
|
|
93
|
-
const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
|
|
89
|
+
const [search, setSearch] = useCacheState<SearchProps>(listKey, {
|
|
94
90
|
defaultValue: {
|
|
95
91
|
status: status as string,
|
|
96
92
|
customer_id,
|
|
@@ -98,19 +94,21 @@ export default function PayoutList({
|
|
|
98
94
|
pageSize: defaultPageSize,
|
|
99
95
|
page: 1,
|
|
100
96
|
},
|
|
97
|
+
getUrlParams: () => {
|
|
98
|
+
const params: Record<string, any> = {};
|
|
99
|
+
if (searchParams.has('status')) {
|
|
100
|
+
params.status = searchParams.get('status');
|
|
101
|
+
}
|
|
102
|
+
if (searchParams.has('currency_id')) {
|
|
103
|
+
params.currency_id = searchParams.get('currency_id');
|
|
104
|
+
}
|
|
105
|
+
if (searchParams.has('customer_id')) {
|
|
106
|
+
params.customer_id = searchParams.get('customer_id');
|
|
107
|
+
}
|
|
108
|
+
return params;
|
|
109
|
+
},
|
|
101
110
|
});
|
|
102
111
|
|
|
103
|
-
useEffect(() => {
|
|
104
|
-
if (urlStatus || urlCurrencyId || urlCustomerId) {
|
|
105
|
-
setSearch((prev) => ({
|
|
106
|
-
...prev!,
|
|
107
|
-
...(urlStatus && { status: urlStatus }),
|
|
108
|
-
...(urlCurrencyId && { currency_id: urlCurrencyId }),
|
|
109
|
-
...(urlCustomerId && { customer_id: urlCustomerId }),
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
112
|
-
}, [urlStatus, urlCurrencyId, urlCustomerId, setSearch]);
|
|
113
|
-
|
|
114
112
|
const [data, setData] = useState({}) as any;
|
|
115
113
|
|
|
116
114
|
useEffect(() => {
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
} from '@blocklet/payment-react';
|
|
12
12
|
import type { TRefundExpanded } from '@blocklet/payment-types';
|
|
13
13
|
import { Avatar, CircularProgress, Typography } from '@mui/material';
|
|
14
|
-
import { useLocalStorageState } from 'ahooks';
|
|
15
14
|
import { useEffect, useState } from 'react';
|
|
16
15
|
import { Link, useSearchParams } from 'react-router-dom';
|
|
17
16
|
|
|
@@ -19,6 +18,7 @@ import { capitalize, toLower } from 'lodash';
|
|
|
19
18
|
import CustomerLink from '../customer/link';
|
|
20
19
|
import FilterToolbar from '../filter-toolbar';
|
|
21
20
|
import RefundActions from './actions';
|
|
21
|
+
import { useCacheState } from '../../hooks/cache-state';
|
|
22
22
|
|
|
23
23
|
const fetchData = (params: Record<string, any> = {}): Promise<{ list: TRefundExpanded[]; count: number }> => {
|
|
24
24
|
const search = new URLSearchParams();
|
|
@@ -96,11 +96,7 @@ export default function RefundList({
|
|
|
96
96
|
const listKey = getListKey({ customer_id, invoice_id, subscription_id, payment_intent_id });
|
|
97
97
|
const defaultPageSize = useDefaultPageSize(20);
|
|
98
98
|
|
|
99
|
-
const
|
|
100
|
-
const urlCurrencyId = searchParams.get('currency_id');
|
|
101
|
-
const urlCustomerId = searchParams.get('customer_id');
|
|
102
|
-
|
|
103
|
-
const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
|
|
99
|
+
const [search, setSearch] = useCacheState<SearchProps>(listKey, {
|
|
104
100
|
defaultValue: {
|
|
105
101
|
status: status as string,
|
|
106
102
|
customer_id,
|
|
@@ -110,19 +106,21 @@ export default function RefundList({
|
|
|
110
106
|
pageSize: defaultPageSize,
|
|
111
107
|
page: 1,
|
|
112
108
|
},
|
|
109
|
+
getUrlParams: () => {
|
|
110
|
+
const params: Record<string, any> = {};
|
|
111
|
+
if (searchParams.has('status')) {
|
|
112
|
+
params.status = searchParams.get('status');
|
|
113
|
+
}
|
|
114
|
+
if (searchParams.has('currency_id')) {
|
|
115
|
+
params.currency_id = searchParams.get('currency_id');
|
|
116
|
+
}
|
|
117
|
+
if (searchParams.has('customer_id')) {
|
|
118
|
+
params.customer_id = searchParams.get('customer_id');
|
|
119
|
+
}
|
|
120
|
+
return params;
|
|
121
|
+
},
|
|
113
122
|
});
|
|
114
123
|
|
|
115
|
-
useEffect(() => {
|
|
116
|
-
if (urlStatus || urlCurrencyId || urlCustomerId) {
|
|
117
|
-
setSearch((prev) => ({
|
|
118
|
-
...prev!,
|
|
119
|
-
...(urlStatus && { status: urlStatus }),
|
|
120
|
-
...(urlCurrencyId && { currency_id: urlCurrencyId }),
|
|
121
|
-
...(urlCustomerId && { customer_id: urlCustomerId }),
|
|
122
|
-
}));
|
|
123
|
-
}
|
|
124
|
-
}, [urlStatus, urlCurrencyId, urlCustomerId, setSearch]);
|
|
125
|
-
|
|
126
124
|
const [data, setData] = useState({}) as any;
|
|
127
125
|
|
|
128
126
|
const refresh = () =>
|
|
@@ -3,10 +3,10 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
|
3
3
|
import { Status, api, formatTime, Table, useDefaultPageSize } from '@blocklet/payment-react';
|
|
4
4
|
import type { TSubscriptionExpanded } from '@blocklet/payment-types';
|
|
5
5
|
import { CircularProgress } from '@mui/material';
|
|
6
|
-
import { useLocalStorageState } from 'ahooks';
|
|
7
6
|
import { useEffect, useState } from 'react';
|
|
8
7
|
import { Link, useSearchParams } from 'react-router-dom';
|
|
9
8
|
|
|
9
|
+
import { useCacheState } from '../../hooks/cache-state';
|
|
10
10
|
import CustomerLink from '../customer/link';
|
|
11
11
|
import FilterToolbar from '../filter-toolbar';
|
|
12
12
|
import SubscriptionActions from './actions';
|
|
@@ -70,10 +70,7 @@ export default function SubscriptionList({
|
|
|
70
70
|
const { t } = useLocaleContext();
|
|
71
71
|
const defaultPageSize = useDefaultPageSize(20);
|
|
72
72
|
|
|
73
|
-
const
|
|
74
|
-
const urlCustomerId = searchParams.get('customer_id');
|
|
75
|
-
|
|
76
|
-
const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
|
|
73
|
+
const [search, setSearch] = useCacheState<SearchProps>(listKey, {
|
|
77
74
|
defaultValue: {
|
|
78
75
|
status: (status || 'active') as string,
|
|
79
76
|
customer_id,
|
|
@@ -81,18 +78,18 @@ export default function SubscriptionList({
|
|
|
81
78
|
page: 1,
|
|
82
79
|
price_id: '',
|
|
83
80
|
},
|
|
81
|
+
getUrlParams: () => {
|
|
82
|
+
const params: Record<string, any> = {};
|
|
83
|
+
if (searchParams.has('status')) {
|
|
84
|
+
params.status = searchParams.get('status');
|
|
85
|
+
}
|
|
86
|
+
if (searchParams.has('customer_id')) {
|
|
87
|
+
params.customer_id = searchParams.get('customer_id');
|
|
88
|
+
}
|
|
89
|
+
return params;
|
|
90
|
+
},
|
|
84
91
|
});
|
|
85
92
|
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
if (urlStatus || urlCustomerId) {
|
|
88
|
-
setSearch((prev) => ({
|
|
89
|
-
...prev!,
|
|
90
|
-
...(urlStatus && { status: urlStatus }),
|
|
91
|
-
...(urlCustomerId && { customer_id: urlCustomerId }),
|
|
92
|
-
}));
|
|
93
|
-
}
|
|
94
|
-
}, [urlStatus, urlCustomerId, setSearch]);
|
|
95
|
-
|
|
96
93
|
const [data, setData] = useState({}) as any;
|
|
97
94
|
|
|
98
95
|
const refresh = () =>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
type StorageType = 'localStorage' | 'sessionStorage' | 'cookie';
|
|
4
|
+
|
|
5
|
+
interface CacheStateOptions<T> {
|
|
6
|
+
defaultValue: T;
|
|
7
|
+
storage?: StorageType;
|
|
8
|
+
getUrlParams?: () => Partial<T>;
|
|
9
|
+
clearUrlParams?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const getStorageValue = <T>(key: string, storage: StorageType): T | undefined => {
|
|
13
|
+
try {
|
|
14
|
+
if (storage === 'cookie') {
|
|
15
|
+
const matches = document.cookie.match(
|
|
16
|
+
new RegExp(`(?:^|; )${key.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1')}=([^;]*)`)
|
|
17
|
+
);
|
|
18
|
+
return matches?.[1] ? JSON.parse(decodeURIComponent(matches[1])) : undefined;
|
|
19
|
+
}
|
|
20
|
+
const storageObj = storage === 'sessionStorage' ? sessionStorage : localStorage;
|
|
21
|
+
const value = storageObj.getItem(key);
|
|
22
|
+
return value ? JSON.parse(value) : undefined;
|
|
23
|
+
} catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const setStorageValue = <T>(key: string, value: T, storage: StorageType): void => {
|
|
29
|
+
try {
|
|
30
|
+
const serialized = JSON.stringify(value);
|
|
31
|
+
if (storage === 'cookie') {
|
|
32
|
+
document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(serialized)}; path=/`;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const storageObj = storage === 'sessionStorage' ? sessionStorage : localStorage;
|
|
36
|
+
storageObj.setItem(key, serialized);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error(`Failed to set ${storage} value:`, error);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getInitialValue = <T>(
|
|
43
|
+
key: string,
|
|
44
|
+
storage: StorageType,
|
|
45
|
+
defaultValue: T,
|
|
46
|
+
getUrlParams?: () => Partial<T>,
|
|
47
|
+
clearUrlParams?: () => void
|
|
48
|
+
): T => {
|
|
49
|
+
const cachedValue = getStorageValue<T>(key, storage);
|
|
50
|
+
const urlParams = getUrlParams?.();
|
|
51
|
+
|
|
52
|
+
if (urlParams && Object.keys(urlParams).length > 0) {
|
|
53
|
+
const mergedValue = {
|
|
54
|
+
...(cachedValue || defaultValue),
|
|
55
|
+
...urlParams,
|
|
56
|
+
};
|
|
57
|
+
setStorageValue(key, mergedValue, storage);
|
|
58
|
+
clearUrlParams?.();
|
|
59
|
+
return mergedValue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return cachedValue !== undefined ? cachedValue : defaultValue;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const useCacheState = <T = any>(key: string, options: CacheStateOptions<T>) => {
|
|
66
|
+
const { defaultValue, storage = 'localStorage', getUrlParams, clearUrlParams } = options;
|
|
67
|
+
|
|
68
|
+
const [state, setState] = useState<T>(() =>
|
|
69
|
+
getInitialValue(key, storage, defaultValue, getUrlParams, clearUrlParams)
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const setStateAndStorage = useCallback(
|
|
73
|
+
(value: T | ((prev: T) => T)) => {
|
|
74
|
+
setState((prevState) => {
|
|
75
|
+
const nextState = typeof value === 'function' ? (value as (prev: T) => T)(prevState) : value;
|
|
76
|
+
setStorageValue(key, nextState, storage);
|
|
77
|
+
return nextState;
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
[key, storage]
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return [state, setStateAndStorage] as const;
|
|
84
|
+
};
|