@payloadcms/ui 3.55.0-internal.df60e35 → 3.55.0

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.
Files changed (104) hide show
  1. package/dist/elements/AppHeader/index.scss +1 -0
  2. package/dist/elements/DefaultListViewTabs/index.d.ts +12 -0
  3. package/dist/elements/DefaultListViewTabs/index.d.ts.map +1 -0
  4. package/dist/elements/DefaultListViewTabs/index.js +161 -0
  5. package/dist/elements/DefaultListViewTabs/index.js.map +1 -0
  6. package/dist/elements/{ListHeaderTabs → DefaultListViewTabs}/index.scss +1 -1
  7. package/dist/elements/DocumentDrawer/Provider.d.ts +2 -1
  8. package/dist/elements/DocumentDrawer/Provider.d.ts.map +1 -1
  9. package/dist/elements/DocumentDrawer/Provider.js.map +1 -1
  10. package/dist/elements/FieldSelect/reduceFieldOptions.js +1 -1
  11. package/dist/elements/FieldSelect/reduceFieldOptions.js.map +1 -1
  12. package/dist/elements/ListControls/index.d.ts.map +1 -1
  13. package/dist/elements/ListControls/index.js +69 -78
  14. package/dist/elements/ListControls/index.js.map +1 -1
  15. package/dist/elements/ListControls/index.scss +2 -82
  16. package/dist/elements/SearchBar/index.d.ts +2 -3
  17. package/dist/elements/SearchBar/index.d.ts.map +1 -1
  18. package/dist/elements/SearchBar/index.js +2 -3
  19. package/dist/elements/SearchBar/index.js.map +1 -1
  20. package/dist/elements/SearchBar/index.scss +56 -7
  21. package/dist/elements/SearchFilter/index.d.ts +2 -33
  22. package/dist/elements/SearchFilter/index.d.ts.map +1 -1
  23. package/dist/elements/SearchFilter/index.js +7 -5
  24. package/dist/elements/SearchFilter/index.js.map +1 -1
  25. package/dist/elements/SearchFilter/types.d.ts +33 -0
  26. package/dist/elements/SearchFilter/types.d.ts.map +1 -0
  27. package/dist/elements/SearchFilter/types.js +2 -0
  28. package/dist/elements/SearchFilter/types.js.map +1 -0
  29. package/dist/elements/Status/index.d.ts.map +1 -1
  30. package/dist/elements/Status/index.js +1 -1
  31. package/dist/elements/Status/index.js.map +1 -1
  32. package/dist/exports/client/{CodeEditor-MIIBUJZ4.js → CodeEditor-URFJPG6I.js} +2 -2
  33. package/dist/exports/client/chunk-KPQQ5IUL.js +26 -0
  34. package/dist/exports/client/{chunk-Z6O2JA43.js.map → chunk-KPQQ5IUL.js.map} +3 -3
  35. package/dist/exports/client/index.js +12 -12
  36. package/dist/exports/client/index.js.map +4 -4
  37. package/dist/exports/rsc/index.d.ts +1 -0
  38. package/dist/exports/rsc/index.d.ts.map +1 -1
  39. package/dist/exports/rsc/index.js +1 -0
  40. package/dist/exports/rsc/index.js.map +1 -1
  41. package/dist/fields/Blocks/index.d.ts.map +1 -1
  42. package/dist/fields/Blocks/index.js.map +1 -1
  43. package/dist/fields/Join/index.js +1 -1
  44. package/dist/fields/Join/index.js.map +1 -1
  45. package/dist/forms/Form/types.d.ts +6 -3
  46. package/dist/forms/Form/types.d.ts.map +1 -1
  47. package/dist/forms/Form/types.js.map +1 -1
  48. package/dist/forms/RenderFields/index.d.ts.map +1 -1
  49. package/dist/forms/RenderFields/index.js +1 -1
  50. package/dist/forms/RenderFields/index.js.map +1 -1
  51. package/dist/forms/RowLabel/Context/index.d.ts.map +1 -1
  52. package/dist/forms/RowLabel/Context/index.js +17 -31
  53. package/dist/forms/RowLabel/Context/index.js.map +1 -1
  54. package/dist/providers/Auth/index.d.ts +2 -1
  55. package/dist/providers/Auth/index.d.ts.map +1 -1
  56. package/dist/providers/Auth/index.js +74 -83
  57. package/dist/providers/Auth/index.js.map +1 -1
  58. package/dist/providers/Config/index.d.ts.map +1 -1
  59. package/dist/providers/Config/index.js +6 -3
  60. package/dist/providers/Config/index.js.map +1 -1
  61. package/dist/styles.css +1 -1
  62. package/dist/utilities/buildFormState.js +2 -1
  63. package/dist/utilities/buildFormState.js.map +1 -1
  64. package/dist/utilities/buildTableState.d.ts.map +1 -1
  65. package/dist/utilities/buildTableState.js +12 -4
  66. package/dist/utilities/buildTableState.js.map +1 -1
  67. package/dist/utilities/getClientConfig.d.ts +2 -7
  68. package/dist/utilities/getClientConfig.d.ts.map +1 -1
  69. package/dist/utilities/getClientConfig.js +19 -8
  70. package/dist/utilities/getClientConfig.js.map +1 -1
  71. package/dist/utilities/getColumns.d.ts +10 -0
  72. package/dist/utilities/getColumns.d.ts.map +1 -0
  73. package/dist/utilities/getColumns.js +36 -0
  74. package/dist/utilities/getColumns.js.map +1 -0
  75. package/dist/utilities/renderTable.d.ts +3 -3
  76. package/dist/utilities/renderTable.d.ts.map +1 -1
  77. package/dist/utilities/renderTable.js +2 -11
  78. package/dist/utilities/renderTable.js.map +1 -1
  79. package/dist/views/BrowseByFolder/index.js +1 -1
  80. package/dist/views/BrowseByFolder/index.js.map +1 -1
  81. package/dist/views/CollectionFolder/index.d.ts.map +1 -1
  82. package/dist/views/CollectionFolder/index.js +5 -15
  83. package/dist/views/CollectionFolder/index.js.map +1 -1
  84. package/dist/views/Edit/Auth/index.d.ts.map +1 -1
  85. package/dist/views/Edit/Auth/index.js +1 -1
  86. package/dist/views/Edit/Auth/index.js.map +1 -1
  87. package/dist/views/List/ListHeader/index.d.ts.map +1 -1
  88. package/dist/views/List/ListHeader/index.js +5 -13
  89. package/dist/views/List/ListHeader/index.js.map +1 -1
  90. package/package.json +5 -5
  91. package/dist/elements/ListHeaderTabs/ByFolderPill.d.ts +0 -10
  92. package/dist/elements/ListHeaderTabs/ByFolderPill.d.ts.map +0 -1
  93. package/dist/elements/ListHeaderTabs/ByFolderPill.js +0 -70
  94. package/dist/elements/ListHeaderTabs/ByFolderPill.js.map +0 -1
  95. package/dist/elements/ListHeaderTabs/DefaultListPill.d.ts +0 -9
  96. package/dist/elements/ListHeaderTabs/DefaultListPill.d.ts.map +0 -1
  97. package/dist/elements/ListHeaderTabs/DefaultListPill.js +0 -68
  98. package/dist/elements/ListHeaderTabs/DefaultListPill.js.map +0 -1
  99. package/dist/elements/ListHeaderTabs/TrashPill.d.ts +0 -6
  100. package/dist/elements/ListHeaderTabs/TrashPill.d.ts.map +0 -1
  101. package/dist/elements/ListHeaderTabs/TrashPill.js +0 -53
  102. package/dist/elements/ListHeaderTabs/TrashPill.js.map +0 -1
  103. package/dist/exports/client/chunk-Z6O2JA43.js +0 -26
  104. /package/dist/exports/client/{CodeEditor-MIIBUJZ4.js.map → CodeEditor-URFJPG6I.js.map} +0 -0
@@ -8,22 +8,18 @@ import * as qs from 'qs-esm';
8
8
  import React, { createContext, use, useCallback, useEffect, useState } from 'react';
9
9
  import { toast } from 'sonner';
10
10
  import { stayLoggedInModalSlug } from '../../elements/StayLoggedIn/index.js';
11
- import { useDebounce } from '../../hooks/useDebounce.js';
12
11
  import { useEffectEvent } from '../../hooks/useEffectEvent.js';
13
12
  import { useTranslation } from '../../providers/Translation/index.js';
14
13
  import { requests } from '../../utilities/api.js';
15
14
  import { useConfig } from '../Config/index.js';
16
15
  import { useRouteTransition } from '../RouteTransition/index.js';
17
16
  const Context = /*#__PURE__*/createContext({});
18
- const maxTimeoutTime = 2147483647;
17
+ const maxTimeoutMs = 2147483647;
19
18
  export function AuthProvider({
20
19
  children,
21
20
  permissions: initialPermissions,
22
21
  user: initialUser
23
22
  }) {
24
- const [user, setUserInMemory] = useState(initialUser);
25
- const [tokenInMemory, setTokenInMemory] = useState();
26
- const [tokenExpiration, setTokenExpiration] = useState();
27
23
  const pathname = usePathname();
28
24
  const router = useRouter();
29
25
  const {
@@ -31,6 +27,7 @@ export function AuthProvider({
31
27
  } = useConfig();
32
28
  const {
33
29
  admin: {
30
+ autoRefresh,
34
31
  routes: {
35
32
  inactivity: logoutInactivityRoute
36
33
  },
@@ -42,7 +39,6 @@ export function AuthProvider({
42
39
  },
43
40
  serverURL
44
41
  } = config;
45
- const [permissions, setPermissions] = useState(initialPermissions);
46
42
  const {
47
43
  i18n
48
44
  } = useTranslation();
@@ -50,12 +46,18 @@ export function AuthProvider({
50
46
  closeAllModals,
51
47
  openModal
52
48
  } = useModal();
53
- const [lastLocationChange, setLastLocationChange] = useState(0);
54
- const debouncedLocationChange = useDebounce(lastLocationChange, 10000);
55
- const refreshTokenTimeoutRef = React.useRef(null);
56
49
  const {
57
50
  startRouteTransition
58
51
  } = useRouteTransition();
52
+ const [user, setUserInMemory] = useState(initialUser);
53
+ const [tokenInMemory, setTokenInMemory] = useState();
54
+ const [tokenExpirationMs, setTokenExpirationMs] = useState();
55
+ const [permissions, setPermissions] = useState(initialPermissions);
56
+ const [forceLogoutBufferMs, setForceLogoutBufferMs] = useState(120_000);
57
+ const [fetchedUserOnMount, setFetchedUserOnMount] = useState(false);
58
+ const refreshTokenTimeoutRef = React.useRef(null);
59
+ const reminderTimeoutRef = React.useRef(null);
60
+ const forceLogOutTimeoutRef = React.useRef(null);
59
61
  const id = user?.id;
60
62
  const redirectToInactivityRoute = useCallback(() => {
61
63
  startRouteTransition(() => router.replace(formatAdminURL({
@@ -65,50 +67,65 @@ export function AuthProvider({
65
67
  closeAllModals();
66
68
  }, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition]);
67
69
  const revokeTokenAndExpire = useCallback(() => {
70
+ setUserInMemory(null);
68
71
  setTokenInMemory(undefined);
69
- setTokenExpiration(undefined);
72
+ setTokenExpirationMs(undefined);
70
73
  clearTimeout(refreshTokenTimeoutRef.current);
71
74
  }, []);
72
75
  const setNewUser = useCallback(userResponse => {
76
+ clearTimeout(reminderTimeoutRef.current);
77
+ clearTimeout(forceLogOutTimeoutRef.current);
73
78
  if (userResponse?.user) {
74
79
  setUserInMemory(userResponse.user);
75
80
  setTokenInMemory(userResponse.token);
76
- setTokenExpiration(userResponse.exp);
81
+ setTokenExpirationMs(userResponse.exp * 1000);
82
+ const expiresInMs = Math.max(0, Math.min((userResponse.exp ?? 0) * 1000 - Date.now(), maxTimeoutMs));
83
+ if (expiresInMs) {
84
+ const nextForceLogoutBufferMs = Math.min(60_000, expiresInMs / 2);
85
+ setForceLogoutBufferMs(nextForceLogoutBufferMs);
86
+ reminderTimeoutRef.current = setTimeout(() => {
87
+ if (autoRefresh) {
88
+ refreshCookieEvent();
89
+ } else {
90
+ openModal(stayLoggedInModalSlug);
91
+ }
92
+ }, Math.max(expiresInMs - nextForceLogoutBufferMs, 0));
93
+ forceLogOutTimeoutRef.current = setTimeout(() => {
94
+ revokeTokenAndExpire();
95
+ redirectToInactivityRoute();
96
+ }, expiresInMs);
97
+ }
77
98
  } else {
78
- setUserInMemory(null);
79
99
  revokeTokenAndExpire();
80
100
  }
81
- }, [revokeTokenAndExpire]);
101
+ }, [autoRefresh, redirectToInactivityRoute, revokeTokenAndExpire, openModal]);
82
102
  const refreshCookie = useCallback(forceRefresh => {
83
- const now = Math.round(new Date().getTime() / 1000);
84
- const remainingTime = (typeof tokenExpiration === 'number' ? tokenExpiration : 0) - now;
85
- if (forceRefresh || tokenExpiration && remainingTime < 120) {
86
- refreshTokenTimeoutRef.current = setTimeout(() => {
87
- async function refresh() {
88
- try {
89
- const request = await requests.post(`${serverURL}${apiRoute}/${userSlug}/refresh-token?refresh`, {
90
- headers: {
91
- 'Accept-Language': i18n.language
92
- }
93
- });
94
- if (request.status === 200) {
95
- const json = await request.json();
96
- setNewUser(json);
97
- } else {
98
- setNewUser(null);
99
- redirectToInactivityRoute();
103
+ if (!id) {
104
+ return;
105
+ }
106
+ const expiresInMs_0 = Math.max(0, (tokenExpirationMs ?? 0) - Date.now());
107
+ if (forceRefresh || tokenExpirationMs && expiresInMs_0 < forceLogoutBufferMs * 2) {
108
+ clearTimeout(refreshTokenTimeoutRef.current);
109
+ refreshTokenTimeoutRef.current = setTimeout(async () => {
110
+ try {
111
+ const request = await requests.post(`${serverURL}${apiRoute}/${userSlug}/refresh-token?refresh`, {
112
+ headers: {
113
+ 'Accept-Language': i18n.language
100
114
  }
101
- } catch (e) {
102
- toast.error(e.message);
115
+ });
116
+ if (request.status === 200) {
117
+ const json = await request.json();
118
+ setNewUser(json);
119
+ } else {
120
+ setNewUser(null);
121
+ redirectToInactivityRoute();
103
122
  }
123
+ } catch (e) {
124
+ toast.error(e.message);
104
125
  }
105
- void refresh();
106
126
  }, 1000);
107
127
  }
108
- return () => {
109
- clearTimeout(refreshTokenTimeoutRef.current);
110
- };
111
- }, [apiRoute, i18n.language, redirectToInactivityRoute, serverURL, setNewUser, tokenExpiration, userSlug]);
128
+ }, [apiRoute, i18n.language, redirectToInactivityRoute, serverURL, setNewUser, tokenExpirationMs, userSlug, forceLogoutBufferMs, id]);
112
129
  const refreshCookieAsync = useCallback(async skipSetUser => {
113
130
  try {
114
131
  const request_0 = await requests.post(`${serverURL}${apiRoute}/${userSlug}/refresh-token`, {
@@ -127,11 +144,10 @@ export function AuthProvider({
127
144
  setNewUser(null);
128
145
  redirectToInactivityRoute();
129
146
  }
130
- return null;
131
147
  } catch (e_0) {
132
148
  toast.error(`Refreshing token failed: ${e_0.message}`);
133
- return null;
134
149
  }
150
+ return null;
135
151
  }, [apiRoute, i18n.language, redirectToInactivityRoute, serverURL, setNewUser, userSlug, user]);
136
152
  const logOut = useCallback(async () => {
137
153
  try {
@@ -178,62 +194,36 @@ export function AuthProvider({
178
194
  });
179
195
  if (request_2.status === 200) {
180
196
  const json_2 = await request_2.json();
181
- const user_0 = null;
182
197
  setNewUser(json_2);
183
- return user_0;
198
+ return json_2?.user || null;
184
199
  }
185
200
  } catch (e_2) {
186
201
  toast.error(`Fetching user failed: ${e_2.message}`);
187
202
  }
188
203
  return null;
189
204
  }, [serverURL, apiRoute, userSlug, i18n.language, setNewUser]);
190
- const fetchFullUserEvent = useEffectEvent(fetchFullUser);
191
- // On mount, get user and set
192
- useEffect(() => {
193
- void fetchFullUserEvent();
194
- }, []);
195
- const refreshCookieEvent = useEffectEvent(() => {
196
- if (id) {
197
- refreshCookie();
198
- }
199
- });
200
- // When location changes, refresh cookie
205
+ const refreshCookieEvent = useEffectEvent(refreshCookie);
201
206
  useEffect(() => {
207
+ // when location changes, refresh cookie
202
208
  refreshCookieEvent();
203
- }, [debouncedLocationChange]);
204
- useEffect(() => {
205
- setLastLocationChange(Date.now());
206
209
  }, [pathname]);
210
+ const fetchFullUserEvent = useEffectEvent(fetchFullUser);
207
211
  useEffect(() => {
208
- let reminder;
209
- let forceLogOut;
210
- const now_0 = Math.round(new Date().getTime() / 1000);
211
- const remainingTime_0 = typeof tokenExpiration === 'number' ? tokenExpiration - now_0 : 0;
212
- const remindInTimeFromNow = Math.max(Math.min((remainingTime_0 - 60) * 1000, maxTimeoutTime), 0);
213
- const forceLogOutInTimeFromNow = Math.max(Math.min(remainingTime_0 * 1000, maxTimeoutTime), 0);
214
- if (!user) {
215
- clearTimeout(reminder);
216
- clearTimeout(forceLogOut);
217
- return;
218
- }
219
- if (remainingTime_0 > 0) {
220
- reminder = setTimeout(() => {
221
- openModal(stayLoggedInModalSlug);
222
- }, remindInTimeFromNow);
223
- forceLogOut = setTimeout(() => {
224
- setNewUser(null);
225
- redirectToInactivityRoute();
226
- }, forceLogOutInTimeFromNow);
212
+ async function fetchUserOnMount() {
213
+ await fetchFullUserEvent();
214
+ setFetchedUserOnMount(true);
227
215
  }
228
- return () => {
229
- if (reminder) {
230
- clearTimeout(reminder);
231
- }
232
- if (forceLogOut) {
233
- clearTimeout(forceLogOut);
234
- }
235
- };
236
- }, [tokenExpiration, openModal, i18n, setNewUser, user, redirectToInactivityRoute]);
216
+ void fetchUserOnMount();
217
+ }, []);
218
+ useEffect(() => () => {
219
+ // remove all timeouts on unmount
220
+ clearTimeout(refreshTokenTimeoutRef.current);
221
+ clearTimeout(reminderTimeoutRef.current);
222
+ clearTimeout(forceLogOutTimeoutRef.current);
223
+ }, []);
224
+ if (!user && !fetchedUserOnMount) {
225
+ return null;
226
+ }
237
227
  return /*#__PURE__*/_jsx(Context, {
238
228
  value: {
239
229
  fetchFullUser,
@@ -245,6 +235,7 @@ export function AuthProvider({
245
235
  setPermissions,
246
236
  setUser: setNewUser,
247
237
  token: tokenInMemory,
238
+ tokenExpirationMs,
248
239
  user
249
240
  },
250
241
  children: children
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useModal","usePathname","useRouter","formatAdminURL","qs","React","createContext","use","useCallback","useEffect","useState","toast","stayLoggedInModalSlug","useDebounce","useEffectEvent","useTranslation","requests","useConfig","useRouteTransition","Context","maxTimeoutTime","AuthProvider","children","permissions","initialPermissions","user","initialUser","setUserInMemory","tokenInMemory","setTokenInMemory","tokenExpiration","setTokenExpiration","pathname","router","config","admin","routes","inactivity","logoutInactivityRoute","userSlug","adminRoute","api","apiRoute","serverURL","setPermissions","i18n","closeAllModals","openModal","lastLocationChange","setLastLocationChange","debouncedLocationChange","refreshTokenTimeoutRef","useRef","startRouteTransition","id","redirectToInactivityRoute","replace","path","window","location","startsWith","encodeURIComponent","revokeTokenAndExpire","undefined","clearTimeout","current","setNewUser","userResponse","token","exp","refreshCookie","forceRefresh","now","Math","round","Date","getTime","remainingTime","setTimeout","refresh","request","post","headers","language","status","json","e","error","message","refreshCookieAsync","skipSetUser","logOut","collection","_","refreshPermissions","locale","params","stringify","addQueryPrefix","get","Error","fetchFullUser","credentials","fetchFullUserEvent","refreshCookieEvent","reminder","forceLogOut","remindInTimeFromNow","max","min","forceLogOutInTimeFromNow","_jsx","value","setUser","useAuth"],"sources":["../../../src/providers/Auth/index.tsx"],"sourcesContent":["'use client'\nimport type { ClientUser, SanitizedPermissions, TypedUser } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\nimport { usePathname, useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React, { createContext, use, useCallback, useEffect, useState } from 'react'\nimport { toast } from 'sonner'\n\nimport { stayLoggedInModalSlug } from '../../elements/StayLoggedIn/index.js'\nimport { useDebounce } from '../../hooks/useDebounce.js'\nimport { useEffectEvent } from '../../hooks/useEffectEvent.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { requests } from '../../utilities/api.js'\nimport { useConfig } from '../Config/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\n\nexport type UserWithToken<T = ClientUser> = {\n exp: number\n token: string\n user: T\n}\n\nexport type AuthContext<T = ClientUser> = {\n fetchFullUser: () => Promise<null | TypedUser>\n logOut: () => Promise<boolean>\n permissions?: SanitizedPermissions\n refreshCookie: (forceRefresh?: boolean) => void\n refreshCookieAsync: () => Promise<ClientUser>\n refreshPermissions: () => Promise<void>\n setPermissions: (permissions: SanitizedPermissions) => void\n setUser: (user: null | UserWithToken<T>) => void\n strategy?: string\n token?: string\n tokenExpiration?: number\n user?: null | T\n}\n\nconst Context = createContext({} as AuthContext)\n\nconst maxTimeoutTime = 2147483647\n\ntype Props = {\n children: React.ReactNode\n permissions?: SanitizedPermissions\n user?: ClientUser | null\n}\n\nexport function AuthProvider({\n children,\n permissions: initialPermissions,\n user: initialUser,\n}: Props) {\n const [user, setUserInMemory] = useState<ClientUser | null>(initialUser)\n const [tokenInMemory, setTokenInMemory] = useState<string>()\n const [tokenExpiration, setTokenExpiration] = useState<number>()\n const pathname = usePathname()\n const router = useRouter()\n\n const { config } = useConfig()\n\n const {\n admin: {\n routes: { inactivity: logoutInactivityRoute },\n user: userSlug,\n },\n routes: { admin: adminRoute, api: apiRoute },\n serverURL,\n } = config\n\n const [permissions, setPermissions] = useState<SanitizedPermissions>(initialPermissions)\n\n const { i18n } = useTranslation()\n const { closeAllModals, openModal } = useModal()\n const [lastLocationChange, setLastLocationChange] = useState(0)\n const debouncedLocationChange = useDebounce(lastLocationChange, 10000)\n const refreshTokenTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n const { startRouteTransition } = useRouteTransition()\n\n const id = user?.id\n\n const redirectToInactivityRoute = useCallback(() => {\n startRouteTransition(() =>\n router.replace(\n formatAdminURL({\n adminRoute,\n path: `${logoutInactivityRoute}${window.location.pathname.startsWith(adminRoute) ? `?redirect=${encodeURIComponent(window.location.pathname)}` : ''}`,\n }),\n ),\n )\n\n closeAllModals()\n }, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition])\n\n const revokeTokenAndExpire = useCallback(() => {\n setTokenInMemory(undefined)\n setTokenExpiration(undefined)\n clearTimeout(refreshTokenTimeoutRef.current)\n }, [])\n\n const setNewUser = useCallback(\n (userResponse: null | UserWithToken) => {\n if (userResponse?.user) {\n setUserInMemory(userResponse.user)\n setTokenInMemory(userResponse.token)\n setTokenExpiration(userResponse.exp)\n } else {\n setUserInMemory(null)\n revokeTokenAndExpire()\n }\n },\n [revokeTokenAndExpire],\n )\n\n const refreshCookie = useCallback(\n (forceRefresh?: boolean) => {\n const now = Math.round(new Date().getTime() / 1000)\n const remainingTime = (typeof tokenExpiration === 'number' ? tokenExpiration : 0) - now\n\n if (forceRefresh || (tokenExpiration && remainingTime < 120)) {\n refreshTokenTimeoutRef.current = setTimeout(() => {\n async function refresh() {\n try {\n const request = await requests.post(\n `${serverURL}${apiRoute}/${userSlug}/refresh-token?refresh`,\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json = await request.json()\n setNewUser(json)\n } else {\n setNewUser(null)\n redirectToInactivityRoute()\n }\n } catch (e) {\n toast.error(e.message)\n }\n }\n\n void refresh()\n }, 1000)\n }\n\n return () => {\n clearTimeout(refreshTokenTimeoutRef.current)\n }\n },\n [\n apiRoute,\n i18n.language,\n redirectToInactivityRoute,\n serverURL,\n setNewUser,\n tokenExpiration,\n userSlug,\n ],\n )\n\n const refreshCookieAsync = useCallback(\n async (skipSetUser?: boolean): Promise<ClientUser> => {\n try {\n const request = await requests.post(`${serverURL}${apiRoute}/${userSlug}/refresh-token`, {\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n if (request.status === 200) {\n const json = await request.json()\n if (!skipSetUser) {\n setNewUser(json)\n }\n return json.user\n }\n\n if (user) {\n setNewUser(null)\n redirectToInactivityRoute()\n }\n return null\n } catch (e) {\n toast.error(`Refreshing token failed: ${e.message}`)\n return null\n }\n },\n [apiRoute, i18n.language, redirectToInactivityRoute, serverURL, setNewUser, userSlug, user],\n )\n\n const logOut = useCallback(async () => {\n try {\n if (user && user.collection) {\n setNewUser(null)\n await requests.post(`${serverURL}${apiRoute}/${user.collection}/logout`)\n }\n } catch (_) {\n // fail silently and log the user out in state\n }\n\n return true\n }, [apiRoute, serverURL, setNewUser, user])\n\n const refreshPermissions = useCallback(\n async ({ locale }: { locale?: string } = {}) => {\n const params = qs.stringify(\n {\n locale,\n },\n {\n addQueryPrefix: true,\n },\n )\n\n try {\n const request = await requests.get(`${serverURL}${apiRoute}/access${params}`, {\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n if (request.status === 200) {\n const json: SanitizedPermissions = await request.json()\n setPermissions(json)\n } else {\n throw new Error(`Fetching permissions failed with status code ${request.status}`)\n }\n } catch (e) {\n toast.error(`Refreshing permissions failed: ${e.message}`)\n }\n },\n [serverURL, apiRoute, i18n],\n )\n\n const fetchFullUser = React.useCallback(async () => {\n try {\n const request = await requests.get(`${serverURL}${apiRoute}/${userSlug}/me`, {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n const user = null\n\n setNewUser(json)\n return user\n }\n } catch (e) {\n toast.error(`Fetching user failed: ${e.message}`)\n }\n\n return null\n }, [serverURL, apiRoute, userSlug, i18n.language, setNewUser])\n\n const fetchFullUserEvent = useEffectEvent(fetchFullUser)\n\n // On mount, get user and set\n useEffect(() => {\n void fetchFullUserEvent()\n }, [])\n\n const refreshCookieEvent = useEffectEvent(() => {\n if (id) {\n refreshCookie()\n }\n })\n\n // When location changes, refresh cookie\n useEffect(() => {\n refreshCookieEvent()\n }, [debouncedLocationChange])\n\n useEffect(() => {\n setLastLocationChange(Date.now())\n }, [pathname])\n\n useEffect(() => {\n let reminder: ReturnType<typeof setTimeout>\n let forceLogOut: ReturnType<typeof setTimeout>\n const now = Math.round(new Date().getTime() / 1000)\n const remainingTime = typeof tokenExpiration === 'number' ? tokenExpiration - now : 0\n const remindInTimeFromNow = Math.max(Math.min((remainingTime - 60) * 1000, maxTimeoutTime), 0)\n const forceLogOutInTimeFromNow = Math.max(Math.min(remainingTime * 1000, maxTimeoutTime), 0)\n\n if (!user) {\n clearTimeout(reminder)\n clearTimeout(forceLogOut)\n return\n }\n\n if (remainingTime > 0) {\n reminder = setTimeout(() => {\n openModal(stayLoggedInModalSlug)\n }, remindInTimeFromNow)\n\n forceLogOut = setTimeout(() => {\n setNewUser(null)\n redirectToInactivityRoute()\n }, forceLogOutInTimeFromNow)\n }\n\n return () => {\n if (reminder) {\n clearTimeout(reminder)\n }\n if (forceLogOut) {\n clearTimeout(forceLogOut)\n }\n }\n }, [tokenExpiration, openModal, i18n, setNewUser, user, redirectToInactivityRoute])\n\n return (\n <Context\n value={{\n fetchFullUser,\n logOut,\n permissions,\n refreshCookie,\n refreshCookieAsync,\n refreshPermissions,\n setPermissions,\n setUser: setNewUser,\n token: tokenInMemory,\n user,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport const useAuth = <T = ClientUser,>(): AuthContext<T> => use(Context) as AuthContext<T>\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useModal","usePathname","useRouter","formatAdminURL","qs","React","createContext","use","useCallback","useEffect","useState","toast","stayLoggedInModalSlug","useEffectEvent","useTranslation","requests","useConfig","useRouteTransition","Context","maxTimeoutMs","AuthProvider","children","permissions","initialPermissions","user","initialUser","pathname","router","config","admin","autoRefresh","routes","inactivity","logoutInactivityRoute","userSlug","adminRoute","api","apiRoute","serverURL","i18n","closeAllModals","openModal","startRouteTransition","setUserInMemory","tokenInMemory","setTokenInMemory","tokenExpirationMs","setTokenExpirationMs","setPermissions","forceLogoutBufferMs","setForceLogoutBufferMs","fetchedUserOnMount","setFetchedUserOnMount","refreshTokenTimeoutRef","useRef","reminderTimeoutRef","forceLogOutTimeoutRef","id","redirectToInactivityRoute","replace","path","window","location","startsWith","encodeURIComponent","revokeTokenAndExpire","undefined","clearTimeout","current","setNewUser","userResponse","token","exp","expiresInMs","Math","max","min","Date","now","nextForceLogoutBufferMs","setTimeout","refreshCookieEvent","refreshCookie","forceRefresh","request","post","headers","language","status","json","e","error","message","refreshCookieAsync","skipSetUser","logOut","collection","_","refreshPermissions","locale","params","stringify","addQueryPrefix","get","Error","fetchFullUser","credentials","fetchFullUserEvent","fetchUserOnMount","_jsx","value","setUser","useAuth"],"sources":["../../../src/providers/Auth/index.tsx"],"sourcesContent":["'use client'\nimport type { ClientUser, SanitizedPermissions, TypedUser } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\nimport { usePathname, useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React, { createContext, use, useCallback, useEffect, useState } from 'react'\nimport { toast } from 'sonner'\n\nimport { stayLoggedInModalSlug } from '../../elements/StayLoggedIn/index.js'\nimport { useEffectEvent } from '../../hooks/useEffectEvent.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { requests } from '../../utilities/api.js'\nimport { useConfig } from '../Config/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\n\nexport type UserWithToken<T = ClientUser> = {\n /** seconds until expiration */\n exp: number\n token: string\n user: T\n}\n\nexport type AuthContext<T = ClientUser> = {\n fetchFullUser: () => Promise<null | TypedUser>\n logOut: () => Promise<boolean>\n permissions?: SanitizedPermissions\n refreshCookie: (forceRefresh?: boolean) => void\n refreshCookieAsync: () => Promise<ClientUser>\n refreshPermissions: () => Promise<void>\n setPermissions: (permissions: SanitizedPermissions) => void\n setUser: (user: null | UserWithToken<T>) => void\n strategy?: string\n token?: string\n tokenExpirationMs?: number\n user?: null | T\n}\n\nconst Context = createContext({} as AuthContext)\n\nconst maxTimeoutMs = 2147483647\n\ntype Props = {\n children: React.ReactNode\n permissions?: SanitizedPermissions\n user?: ClientUser | null\n}\n\nexport function AuthProvider({\n children,\n permissions: initialPermissions,\n user: initialUser,\n}: Props) {\n const pathname = usePathname()\n const router = useRouter()\n\n const { config } = useConfig()\n\n const {\n admin: {\n autoRefresh,\n routes: { inactivity: logoutInactivityRoute },\n user: userSlug,\n },\n routes: { admin: adminRoute, api: apiRoute },\n serverURL,\n } = config\n\n const { i18n } = useTranslation()\n const { closeAllModals, openModal } = useModal()\n const { startRouteTransition } = useRouteTransition()\n\n const [user, setUserInMemory] = useState<ClientUser | null>(initialUser)\n const [tokenInMemory, setTokenInMemory] = useState<string>()\n const [tokenExpirationMs, setTokenExpirationMs] = useState<number>()\n const [permissions, setPermissions] = useState<SanitizedPermissions>(initialPermissions)\n const [forceLogoutBufferMs, setForceLogoutBufferMs] = useState<number>(120_000)\n const [fetchedUserOnMount, setFetchedUserOnMount] = useState(false)\n\n const refreshTokenTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n const reminderTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n const forceLogOutTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n\n const id = user?.id\n\n const redirectToInactivityRoute = useCallback(() => {\n startRouteTransition(() =>\n router.replace(\n formatAdminURL({\n adminRoute,\n path: `${logoutInactivityRoute}${window.location.pathname.startsWith(adminRoute) ? `?redirect=${encodeURIComponent(window.location.pathname)}` : ''}`,\n }),\n ),\n )\n\n closeAllModals()\n }, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition])\n\n const revokeTokenAndExpire = useCallback(() => {\n setUserInMemory(null)\n setTokenInMemory(undefined)\n setTokenExpirationMs(undefined)\n clearTimeout(refreshTokenTimeoutRef.current)\n }, [])\n\n const setNewUser = useCallback(\n (userResponse: null | UserWithToken) => {\n clearTimeout(reminderTimeoutRef.current)\n clearTimeout(forceLogOutTimeoutRef.current)\n\n if (userResponse?.user) {\n setUserInMemory(userResponse.user)\n setTokenInMemory(userResponse.token)\n setTokenExpirationMs(userResponse.exp * 1000)\n\n const expiresInMs = Math.max(\n 0,\n Math.min((userResponse.exp ?? 0) * 1000 - Date.now(), maxTimeoutMs),\n )\n\n if (expiresInMs) {\n const nextForceLogoutBufferMs = Math.min(60_000, expiresInMs / 2)\n setForceLogoutBufferMs(nextForceLogoutBufferMs)\n\n reminderTimeoutRef.current = setTimeout(\n () => {\n if (autoRefresh) {\n refreshCookieEvent()\n } else {\n openModal(stayLoggedInModalSlug)\n }\n },\n Math.max(expiresInMs - nextForceLogoutBufferMs, 0),\n )\n\n forceLogOutTimeoutRef.current = setTimeout(() => {\n revokeTokenAndExpire()\n redirectToInactivityRoute()\n }, expiresInMs)\n }\n } else {\n revokeTokenAndExpire()\n }\n },\n [autoRefresh, redirectToInactivityRoute, revokeTokenAndExpire, openModal],\n )\n\n const refreshCookie = useCallback(\n (forceRefresh?: boolean) => {\n if (!id) {\n return\n }\n\n const expiresInMs = Math.max(0, (tokenExpirationMs ?? 0) - Date.now())\n\n if (forceRefresh || (tokenExpirationMs && expiresInMs < forceLogoutBufferMs * 2)) {\n clearTimeout(refreshTokenTimeoutRef.current)\n refreshTokenTimeoutRef.current = setTimeout(async () => {\n try {\n const request = await requests.post(\n `${serverURL}${apiRoute}/${userSlug}/refresh-token?refresh`,\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n setNewUser(json)\n } else {\n setNewUser(null)\n redirectToInactivityRoute()\n }\n } catch (e) {\n toast.error(e.message)\n }\n }, 1000)\n }\n },\n [\n apiRoute,\n i18n.language,\n redirectToInactivityRoute,\n serverURL,\n setNewUser,\n tokenExpirationMs,\n userSlug,\n forceLogoutBufferMs,\n id,\n ],\n )\n\n const refreshCookieAsync = useCallback(\n async (skipSetUser?: boolean): Promise<ClientUser> => {\n try {\n const request = await requests.post(`${serverURL}${apiRoute}/${userSlug}/refresh-token`, {\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n if (!skipSetUser) {\n setNewUser(json)\n }\n return json.user\n }\n\n if (user) {\n setNewUser(null)\n redirectToInactivityRoute()\n }\n } catch (e) {\n toast.error(`Refreshing token failed: ${e.message}`)\n }\n return null\n },\n [apiRoute, i18n.language, redirectToInactivityRoute, serverURL, setNewUser, userSlug, user],\n )\n\n const logOut = useCallback(async () => {\n try {\n if (user && user.collection) {\n setNewUser(null)\n await requests.post(`${serverURL}${apiRoute}/${user.collection}/logout`)\n }\n } catch (_) {\n // fail silently and log the user out in state\n }\n\n return true\n }, [apiRoute, serverURL, setNewUser, user])\n\n const refreshPermissions = useCallback(\n async ({ locale }: { locale?: string } = {}) => {\n const params = qs.stringify(\n {\n locale,\n },\n {\n addQueryPrefix: true,\n },\n )\n\n try {\n const request = await requests.get(`${serverURL}${apiRoute}/access${params}`, {\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n if (request.status === 200) {\n const json: SanitizedPermissions = await request.json()\n setPermissions(json)\n } else {\n throw new Error(`Fetching permissions failed with status code ${request.status}`)\n }\n } catch (e) {\n toast.error(`Refreshing permissions failed: ${e.message}`)\n }\n },\n [serverURL, apiRoute, i18n],\n )\n\n const fetchFullUser = React.useCallback(async () => {\n try {\n const request = await requests.get(`${serverURL}${apiRoute}/${userSlug}/me`, {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n setNewUser(json)\n return json?.user || null\n }\n } catch (e) {\n toast.error(`Fetching user failed: ${e.message}`)\n }\n\n return null\n }, [serverURL, apiRoute, userSlug, i18n.language, setNewUser])\n\n const refreshCookieEvent = useEffectEvent(refreshCookie)\n useEffect(() => {\n // when location changes, refresh cookie\n refreshCookieEvent()\n }, [pathname])\n\n const fetchFullUserEvent = useEffectEvent(fetchFullUser)\n useEffect(() => {\n async function fetchUserOnMount() {\n await fetchFullUserEvent()\n setFetchedUserOnMount(true)\n }\n\n void fetchUserOnMount()\n }, [])\n\n useEffect(\n () => () => {\n // remove all timeouts on unmount\n clearTimeout(refreshTokenTimeoutRef.current)\n clearTimeout(reminderTimeoutRef.current)\n clearTimeout(forceLogOutTimeoutRef.current)\n },\n [],\n )\n\n if (!user && !fetchedUserOnMount) {\n return null\n }\n\n return (\n <Context\n value={{\n fetchFullUser,\n logOut,\n permissions,\n refreshCookie,\n refreshCookieAsync,\n refreshPermissions,\n setPermissions,\n setUser: setNewUser,\n token: tokenInMemory,\n tokenExpirationMs,\n user,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport const useAuth = <T = ClientUser,>(): AuthContext<T> => use(Context) as AuthContext<T>\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/Config/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,uBAAuB,EACxB,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAgF,MAAM,OAAO,CAAA;AAEpG,KAAK,iBAAiB,GAAG;IAGvB,CAAC,IAAI,EAAE;QAAE,cAAc,EAAE,EAAE,GAAG,cAAc,CAAC;QAAC,UAAU,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,sBAAsB,CAAA;IAI3F,CAAC,IAAI,EAAE;QAAE,cAAc,CAAC,EAAE,KAAK,CAAC;QAAC,UAAU,EAAE,EAAE,GAAG,UAAU,CAAA;KAAE,GAAG,kBAAkB,CAAA;IAGnF,CAAC,IAAI,EAAE;QACL,cAAc,CAAC,EAAE,EAAE,GAAG,cAAc,CAAA;QACpC,UAAU,CAAC,EAAE,EAAE,GAAG,UAAU,CAAA;KAC7B,GAAG,sBAAsB,GAAG,kBAAkB,GAAG,IAAI,CAAA;CACvD,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,YAAY,CAAA;IACpB;;;;OAIG;IACH,eAAe,EAAE,iBAAiB,CAAA;IAClC,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;CAC1C,CAAA;AAsBD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,uBAAuB,CAAA;CACxD,CA8CA,CAAA;AAED,eAAO,MAAM,SAAS,QAAO,mBAA6C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/Config/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,uBAAuB,EACxB,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAgF,MAAM,OAAO,CAAA;AAEpG,KAAK,iBAAiB,GAAG;IAGvB,CAAC,IAAI,EAAE;QAAE,cAAc,EAAE,EAAE,GAAG,cAAc,CAAC;QAAC,UAAU,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,sBAAsB,CAAA;IAI3F,CAAC,IAAI,EAAE;QAAE,cAAc,CAAC,EAAE,KAAK,CAAC;QAAC,UAAU,EAAE,EAAE,GAAG,UAAU,CAAA;KAAE,GAAG,kBAAkB,CAAA;IAGnF,CAAC,IAAI,EAAE;QACL,cAAc,CAAC,EAAE,EAAE,GAAG,cAAc,CAAA;QACpC,UAAU,CAAC,EAAE,EAAE,GAAG,UAAU,CAAA;KAC7B,GAAG,sBAAsB,GAAG,kBAAkB,GAAG,IAAI,CAAA;CACvD,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,YAAY,CAAA;IACpB;;;;OAIG;IACH,eAAe,EAAE,iBAAiB,CAAA;IAClC,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;CAC1C,CAAA;AAsBD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,uBAAuB,CAAA;CACxD,CAsDA,CAAA;AAED,eAAO,MAAM,SAAS,QAAO,mBAA6C,CAAA"}
@@ -23,8 +23,11 @@ export const ConfigProvider = ({
23
23
  children,
24
24
  config: configFromProps
25
25
  }) => {
26
- const [config, setConfig] = useState(() => sanitizeClientConfig(configFromProps));
26
+ const [config, setConfigFn] = useState(() => sanitizeClientConfig(configFromProps));
27
27
  const isFirstRenderRef = useRef(true);
28
+ const setConfig = useCallback(newConfig => {
29
+ setConfigFn(sanitizeClientConfig(newConfig));
30
+ }, []);
28
31
  // Need to update local config state if config from props changes, for HMR.
29
32
  // That way, config changes will be updated in the UI immediately without needing a refresh.
30
33
  useEffect(() => {
@@ -32,8 +35,8 @@ export const ConfigProvider = ({
32
35
  isFirstRenderRef.current = false;
33
36
  return;
34
37
  }
35
- setConfig(sanitizeClientConfig(configFromProps));
36
- }, [configFromProps]);
38
+ setConfig(configFromProps);
39
+ }, [configFromProps, setConfig]);
37
40
  // Build lookup maps for collections and globals so we can do O(1) lookups by slug
38
41
  const {
39
42
  collectionsBySlug: collectionsBySlug_0,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["React","createContext","use","useCallback","useEffect","useMemo","useRef","useState","RootConfigContext","undefined","sanitizeClientConfig","unSanitizedConfig","blocks","length","blocksMap","sanitizedConfig","block","slug","ConfigProvider","children","config","configFromProps","setConfig","isFirstRenderRef","current","collectionsBySlug","globalsBySlug","collection","collections","global","globals","getEntityConfig","args","collectionSlug","globalSlug","value","_jsx","useConfig"],"sources":["../../../src/providers/Config/index.tsx"],"sourcesContent":["/* eslint-disable perfectionist/sort-object-types */ // Need to disable this rule because the order of the overloads is important\n'use client'\nimport type {\n ClientCollectionConfig,\n ClientConfig,\n ClientGlobalConfig,\n CollectionSlug,\n GlobalSlug,\n UnsanitizedClientConfig,\n} from 'payload'\n\nimport React, { createContext, use, useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\ntype GetEntityConfigFn = {\n // Overload #1: collectionSlug only\n // @todo remove \"{} |\" in 4.0, which would be a breaking change\n (args: { collectionSlug: {} | CollectionSlug; globalSlug?: never }): ClientCollectionConfig\n\n // Overload #2: globalSlug only\n // @todo remove \"{} |\" in 4.0, which would be a breaking change\n (args: { collectionSlug?: never; globalSlug: {} | GlobalSlug }): ClientGlobalConfig\n\n // Overload #3: both/none (fall back to union | null)\n (args: {\n collectionSlug?: {} | CollectionSlug\n globalSlug?: {} | GlobalSlug\n }): ClientCollectionConfig | ClientGlobalConfig | null\n}\n\nexport type ClientConfigContext = {\n config: ClientConfig\n /**\n * Get a collection or global config by its slug. This is preferred over\n * using `config.collections.find` or `config.globals.find`, because\n * getEntityConfig uses a lookup map for O(1) lookups.\n */\n getEntityConfig: GetEntityConfigFn\n setConfig: (config: ClientConfig) => void\n}\n\nconst RootConfigContext = createContext<ClientConfigContext | undefined>(undefined)\n\nfunction sanitizeClientConfig(\n unSanitizedConfig: ClientConfig | UnsanitizedClientConfig,\n): ClientConfig {\n if (!unSanitizedConfig?.blocks?.length || (unSanitizedConfig as ClientConfig).blocksMap) {\n ;(unSanitizedConfig as ClientConfig).blocksMap = {}\n return unSanitizedConfig as ClientConfig\n }\n const sanitizedConfig: ClientConfig = { ...unSanitizedConfig } as ClientConfig\n\n sanitizedConfig.blocksMap = {}\n\n for (const block of unSanitizedConfig.blocks) {\n sanitizedConfig.blocksMap[block.slug] = block\n }\n\n return sanitizedConfig\n}\n\nexport const ConfigProvider: React.FC<{\n readonly children: React.ReactNode\n readonly config: ClientConfig | UnsanitizedClientConfig\n}> = ({ children, config: configFromProps }) => {\n const [config, setConfig] = useState<ClientConfig>(() => sanitizeClientConfig(configFromProps))\n\n const isFirstRenderRef = useRef(true)\n\n // Need to update local config state if config from props changes, for HMR.\n // That way, config changes will be updated in the UI immediately without needing a refresh.\n useEffect(() => {\n if (isFirstRenderRef.current) {\n isFirstRenderRef.current = false\n return\n }\n setConfig(sanitizeClientConfig(configFromProps))\n }, [configFromProps])\n\n // Build lookup maps for collections and globals so we can do O(1) lookups by slug\n const { collectionsBySlug, globalsBySlug } = useMemo(() => {\n const collectionsBySlug: Record<string, ClientCollectionConfig> = {}\n const globalsBySlug: Record<string, ClientGlobalConfig> = {}\n\n for (const collection of config.collections) {\n collectionsBySlug[collection.slug] = collection\n }\n for (const global of config.globals) {\n globalsBySlug[global.slug] = global\n }\n\n return { collectionsBySlug, globalsBySlug }\n }, [config])\n\n const getEntityConfig = useCallback<GetEntityConfigFn>(\n (args) => {\n if ('collectionSlug' in args) {\n return collectionsBySlug[args.collectionSlug] ?? null\n }\n if ('globalSlug' in args) {\n return globalsBySlug[args.globalSlug] ?? null\n }\n return null as any\n },\n [collectionsBySlug, globalsBySlug],\n )\n\n const value = useMemo(() => ({ config, getEntityConfig, setConfig }), [config, getEntityConfig])\n\n return <RootConfigContext value={value}>{children}</RootConfigContext>\n}\n\nexport const useConfig = (): ClientConfigContext => use(RootConfigContext)\n"],"mappings":"AAAA,sDAAsD;AACtD;;;AAUA,OAAOA,KAAA,IAASC,aAAa,EAAEC,GAAG,EAAEC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ;AA6B7F,MAAMC,iBAAA,gBAAoBP,aAAA,CAA+CQ,SAAA;AAEzE,SAASC,qBACPC,iBAAyD;EAEzD,IAAI,CAACA,iBAAA,EAAmBC,MAAA,EAAQC,MAAA,IAAUF,iBAAC,CAAmCG,SAAS,EAAE;;IACrFH,iBAAA,CAAmCG,SAAS,GAAG,CAAC;IAClD,OAAOH,iBAAA;EACT;EACA,MAAMI,eAAA,GAAgC;IAAE,GAAGJ;EAAkB;EAE7DI,eAAA,CAAgBD,SAAS,GAAG,CAAC;EAE7B,KAAK,MAAME,KAAA,IAASL,iBAAA,CAAkBC,MAAM,EAAE;IAC5CG,eAAA,CAAgBD,SAAS,CAACE,KAAA,CAAMC,IAAI,CAAC,GAAGD,KAAA;EAC1C;EAEA,OAAOD,eAAA;AACT;AAEA,OAAO,MAAMG,cAAA,GAGRA,CAAC;EAAEC,QAAQ;EAAEC,MAAA,EAAQC;AAAe,CAAE;EACzC,MAAM,CAACD,MAAA,EAAQE,SAAA,CAAU,GAAGf,QAAA,CAAuB,MAAMG,oBAAA,CAAqBW,eAAA;EAE9E,MAAME,gBAAA,GAAmBjB,MAAA,CAAO;EAEhC;EACA;EACAF,SAAA,CAAU;IACR,IAAImB,gBAAA,CAAiBC,OAAO,EAAE;MAC5BD,gBAAA,CAAiBC,OAAO,GAAG;MAC3B;IACF;IACAF,SAAA,CAAUZ,oBAAA,CAAqBW,eAAA;EACjC,GAAG,CAACA,eAAA,CAAgB;EAEpB;EACA,MAAM;IAAEI,iBAAiB,EAAjBA,mBAAiB;IAAEC,aAAa,EAAbA;EAAa,CAAE,GAAGrB,OAAA,CAAQ;IACnD,MAAMoB,iBAAA,GAA4D,CAAC;IACnE,MAAMC,aAAA,GAAoD,CAAC;IAE3D,KAAK,MAAMC,UAAA,IAAcP,MAAA,CAAOQ,WAAW,EAAE;MAC3CH,iBAAiB,CAACE,UAAA,CAAWV,IAAI,CAAC,GAAGU,UAAA;IACvC;IACA,KAAK,MAAME,MAAA,IAAUT,MAAA,CAAOU,OAAO,EAAE;MACnCJ,aAAa,CAACG,MAAA,CAAOZ,IAAI,CAAC,GAAGY,MAAA;IAC/B;IAEA,OAAO;MAAEJ,iBAAA;MAAmBC;IAAc;EAC5C,GAAG,CAACN,MAAA,CAAO;EAEX,MAAMW,eAAA,GAAkB5B,WAAA,CACrB6B,IAAA;IACC,IAAI,oBAAoBA,IAAA,EAAM;MAC5B,OAAOP,mBAAiB,CAACO,IAAA,CAAKC,cAAc,CAAC,IAAI;IACnD;IACA,IAAI,gBAAgBD,IAAA,EAAM;MACxB,OAAON,eAAa,CAACM,IAAA,CAAKE,UAAU,CAAC,IAAI;IAC3C;IACA,OAAO;EACT,GACA,CAACT,mBAAA,EAAmBC,eAAA,CAAc;EAGpC,MAAMS,KAAA,GAAQ9B,OAAA,CAAQ,OAAO;IAAEe,MAAA;IAAQW,eAAA;IAAiBT;EAAU,IAAI,CAACF,MAAA,EAAQW,eAAA,CAAgB;EAE/F,oBAAOK,IAAA,CAAC5B,iBAAA;IAAkB2B,KAAA,EAAOA,KAAA;cAAQhB;;AAC3C;AAEA,OAAO,MAAMkB,SAAA,GAAYA,CAAA,KAA2BnC,GAAA,CAAIM,iBAAA","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["React","createContext","use","useCallback","useEffect","useMemo","useRef","useState","RootConfigContext","undefined","sanitizeClientConfig","unSanitizedConfig","blocks","length","blocksMap","sanitizedConfig","block","slug","ConfigProvider","children","config","configFromProps","setConfigFn","isFirstRenderRef","setConfig","newConfig","current","collectionsBySlug","globalsBySlug","collection","collections","global","globals","getEntityConfig","args","collectionSlug","globalSlug","value","_jsx","useConfig"],"sources":["../../../src/providers/Config/index.tsx"],"sourcesContent":["/* eslint-disable perfectionist/sort-object-types */ // Need to disable this rule because the order of the overloads is important\n'use client'\nimport type {\n ClientCollectionConfig,\n ClientConfig,\n ClientGlobalConfig,\n CollectionSlug,\n GlobalSlug,\n UnsanitizedClientConfig,\n} from 'payload'\n\nimport React, { createContext, use, useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\ntype GetEntityConfigFn = {\n // Overload #1: collectionSlug only\n // @todo remove \"{} |\" in 4.0, which would be a breaking change\n (args: { collectionSlug: {} | CollectionSlug; globalSlug?: never }): ClientCollectionConfig\n\n // Overload #2: globalSlug only\n // @todo remove \"{} |\" in 4.0, which would be a breaking change\n (args: { collectionSlug?: never; globalSlug: {} | GlobalSlug }): ClientGlobalConfig\n\n // Overload #3: both/none (fall back to union | null)\n (args: {\n collectionSlug?: {} | CollectionSlug\n globalSlug?: {} | GlobalSlug\n }): ClientCollectionConfig | ClientGlobalConfig | null\n}\n\nexport type ClientConfigContext = {\n config: ClientConfig\n /**\n * Get a collection or global config by its slug. This is preferred over\n * using `config.collections.find` or `config.globals.find`, because\n * getEntityConfig uses a lookup map for O(1) lookups.\n */\n getEntityConfig: GetEntityConfigFn\n setConfig: (config: ClientConfig) => void\n}\n\nconst RootConfigContext = createContext<ClientConfigContext | undefined>(undefined)\n\nfunction sanitizeClientConfig(\n unSanitizedConfig: ClientConfig | UnsanitizedClientConfig,\n): ClientConfig {\n if (!unSanitizedConfig?.blocks?.length || (unSanitizedConfig as ClientConfig).blocksMap) {\n ;(unSanitizedConfig as ClientConfig).blocksMap = {}\n return unSanitizedConfig as ClientConfig\n }\n const sanitizedConfig: ClientConfig = { ...unSanitizedConfig } as ClientConfig\n\n sanitizedConfig.blocksMap = {}\n\n for (const block of unSanitizedConfig.blocks) {\n sanitizedConfig.blocksMap[block.slug] = block\n }\n\n return sanitizedConfig\n}\n\nexport const ConfigProvider: React.FC<{\n readonly children: React.ReactNode\n readonly config: ClientConfig | UnsanitizedClientConfig\n}> = ({ children, config: configFromProps }) => {\n const [config, setConfigFn] = useState<ClientConfig>(() => sanitizeClientConfig(configFromProps))\n\n const isFirstRenderRef = useRef(true)\n\n const setConfig = useCallback((newConfig: ClientConfig | UnsanitizedClientConfig) => {\n setConfigFn(sanitizeClientConfig(newConfig))\n }, [])\n\n // Need to update local config state if config from props changes, for HMR.\n // That way, config changes will be updated in the UI immediately without needing a refresh.\n useEffect(() => {\n if (isFirstRenderRef.current) {\n isFirstRenderRef.current = false\n return\n }\n\n setConfig(configFromProps)\n }, [configFromProps, setConfig])\n\n // Build lookup maps for collections and globals so we can do O(1) lookups by slug\n const { collectionsBySlug, globalsBySlug } = useMemo(() => {\n const collectionsBySlug: Record<string, ClientCollectionConfig> = {}\n const globalsBySlug: Record<string, ClientGlobalConfig> = {}\n\n for (const collection of config.collections) {\n collectionsBySlug[collection.slug] = collection\n }\n\n for (const global of config.globals) {\n globalsBySlug[global.slug] = global\n }\n\n return { collectionsBySlug, globalsBySlug }\n }, [config])\n\n const getEntityConfig = useCallback<GetEntityConfigFn>(\n (args) => {\n if ('collectionSlug' in args) {\n return collectionsBySlug[args.collectionSlug] ?? null\n }\n\n if ('globalSlug' in args) {\n return globalsBySlug[args.globalSlug] ?? null\n }\n\n return null as any\n },\n [collectionsBySlug, globalsBySlug],\n )\n\n const value = useMemo(() => ({ config, getEntityConfig, setConfig }), [config, getEntityConfig])\n\n return <RootConfigContext value={value}>{children}</RootConfigContext>\n}\n\nexport const useConfig = (): ClientConfigContext => use(RootConfigContext)\n"],"mappings":"AAAA,sDAAsD;AACtD;;;AAUA,OAAOA,KAAA,IAASC,aAAa,EAAEC,GAAG,EAAEC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ;AA6B7F,MAAMC,iBAAA,gBAAoBP,aAAA,CAA+CQ,SAAA;AAEzE,SAASC,qBACPC,iBAAyD;EAEzD,IAAI,CAACA,iBAAA,EAAmBC,MAAA,EAAQC,MAAA,IAAUF,iBAAC,CAAmCG,SAAS,EAAE;;IACrFH,iBAAA,CAAmCG,SAAS,GAAG,CAAC;IAClD,OAAOH,iBAAA;EACT;EACA,MAAMI,eAAA,GAAgC;IAAE,GAAGJ;EAAkB;EAE7DI,eAAA,CAAgBD,SAAS,GAAG,CAAC;EAE7B,KAAK,MAAME,KAAA,IAASL,iBAAA,CAAkBC,MAAM,EAAE;IAC5CG,eAAA,CAAgBD,SAAS,CAACE,KAAA,CAAMC,IAAI,CAAC,GAAGD,KAAA;EAC1C;EAEA,OAAOD,eAAA;AACT;AAEA,OAAO,MAAMG,cAAA,GAGRA,CAAC;EAAEC,QAAQ;EAAEC,MAAA,EAAQC;AAAe,CAAE;EACzC,MAAM,CAACD,MAAA,EAAQE,WAAA,CAAY,GAAGf,QAAA,CAAuB,MAAMG,oBAAA,CAAqBW,eAAA;EAEhF,MAAME,gBAAA,GAAmBjB,MAAA,CAAO;EAEhC,MAAMkB,SAAA,GAAYrB,WAAA,CAAasB,SAAA;IAC7BH,WAAA,CAAYZ,oBAAA,CAAqBe,SAAA;EACnC,GAAG,EAAE;EAEL;EACA;EACArB,SAAA,CAAU;IACR,IAAImB,gBAAA,CAAiBG,OAAO,EAAE;MAC5BH,gBAAA,CAAiBG,OAAO,GAAG;MAC3B;IACF;IAEAF,SAAA,CAAUH,eAAA;EACZ,GAAG,CAACA,eAAA,EAAiBG,SAAA,CAAU;EAE/B;EACA,MAAM;IAAEG,iBAAiB,EAAjBA,mBAAiB;IAAEC,aAAa,EAAbA;EAAa,CAAE,GAAGvB,OAAA,CAAQ;IACnD,MAAMsB,iBAAA,GAA4D,CAAC;IACnE,MAAMC,aAAA,GAAoD,CAAC;IAE3D,KAAK,MAAMC,UAAA,IAAcT,MAAA,CAAOU,WAAW,EAAE;MAC3CH,iBAAiB,CAACE,UAAA,CAAWZ,IAAI,CAAC,GAAGY,UAAA;IACvC;IAEA,KAAK,MAAME,MAAA,IAAUX,MAAA,CAAOY,OAAO,EAAE;MACnCJ,aAAa,CAACG,MAAA,CAAOd,IAAI,CAAC,GAAGc,MAAA;IAC/B;IAEA,OAAO;MAAEJ,iBAAA;MAAmBC;IAAc;EAC5C,GAAG,CAACR,MAAA,CAAO;EAEX,MAAMa,eAAA,GAAkB9B,WAAA,CACrB+B,IAAA;IACC,IAAI,oBAAoBA,IAAA,EAAM;MAC5B,OAAOP,mBAAiB,CAACO,IAAA,CAAKC,cAAc,CAAC,IAAI;IACnD;IAEA,IAAI,gBAAgBD,IAAA,EAAM;MACxB,OAAON,eAAa,CAACM,IAAA,CAAKE,UAAU,CAAC,IAAI;IAC3C;IAEA,OAAO;EACT,GACA,CAACT,mBAAA,EAAmBC,eAAA,CAAc;EAGpC,MAAMS,KAAA,GAAQhC,OAAA,CAAQ,OAAO;IAAEe,MAAA;IAAQa,eAAA;IAAiBT;EAAU,IAAI,CAACJ,MAAA,EAAQa,eAAA,CAAgB;EAE/F,oBAAOK,IAAA,CAAC9B,iBAAA;IAAkB6B,KAAA,EAAOA,KAAA;cAAQlB;;AAC3C;AAEA,OAAO,MAAMoB,SAAA,GAAYA,CAAA,KAA2BrC,GAAA,CAAIM,iBAAA","ignoreList":[]}