@workos-inc/widgets 1.1.4 → 1.2.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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/lib/organization-switcher.d.ts +10 -1
  3. package/dist/cjs/lib/organization-switcher.d.ts.map +1 -1
  4. package/dist/cjs/lib/organization-switcher.js +31 -3
  5. package/dist/cjs/lib/organization-switcher.js.map +1 -1
  6. package/dist/cjs/workos-widgets.client.d.ts +6 -0
  7. package/dist/cjs/workos-widgets.client.d.ts.map +1 -1
  8. package/dist/cjs/workos-widgets.client.js +23 -3
  9. package/dist/cjs/workos-widgets.client.js.map +1 -1
  10. package/dist/esm/lib/organization-switcher.d.ts +10 -1
  11. package/dist/esm/lib/organization-switcher.d.ts.map +1 -1
  12. package/dist/esm/lib/organization-switcher.js +31 -3
  13. package/dist/esm/lib/organization-switcher.js.map +1 -1
  14. package/dist/esm/workos-widgets.client.d.ts +6 -0
  15. package/dist/esm/workos-widgets.client.d.ts.map +1 -1
  16. package/dist/esm/workos-widgets.client.js +25 -5
  17. package/dist/esm/workos-widgets.client.js.map +1 -1
  18. package/package.json +40 -47
  19. package/src/api/api-provider.tsx +0 -158
  20. package/src/api/constants.ts +0 -1
  21. package/src/api/endpoint.ts +0 -3097
  22. package/src/api/errors.ts +0 -48
  23. package/src/api/index.ts +0 -2
  24. package/src/api/utils.ts +0 -42
  25. package/src/api/widgets-api-client.ts +0 -87
  26. package/src/card-list.tsx +0 -26
  27. package/src/index.ts +0 -9
  28. package/src/lib/add-mfa-dialog.tsx +0 -379
  29. package/src/lib/api/config.ts +0 -9
  30. package/src/lib/api/user.ts +0 -98
  31. package/src/lib/change-password-dialog.tsx +0 -290
  32. package/src/lib/constants.ts +0 -3
  33. package/src/lib/copy-button.tsx +0 -53
  34. package/src/lib/delete-user-dialog.tsx +0 -110
  35. package/src/lib/edit-user-profile-dialog.tsx +0 -181
  36. package/src/lib/edit-user-role-dialog.tsx +0 -178
  37. package/src/lib/elements.tsx +0 -428
  38. package/src/lib/elevated-access.tsx +0 -261
  39. package/src/lib/error-boundary.tsx +0 -166
  40. package/src/lib/errors.ts +0 -49
  41. package/src/lib/generic-error.tsx +0 -70
  42. package/src/lib/icon-panel.tsx +0 -26
  43. package/src/lib/icons.tsx +0 -21
  44. package/src/lib/invite-user-dialog.tsx +0 -327
  45. package/src/lib/logout-all-sessions-dialog.tsx +0 -82
  46. package/src/lib/logout-dialog.tsx +0 -85
  47. package/src/lib/marker.tsx +0 -39
  48. package/src/lib/oauth-icons.tsx +0 -138
  49. package/src/lib/organization-switcher.tsx +0 -156
  50. package/src/lib/otp-input.tsx +0 -276
  51. package/src/lib/resend-invite-dialog.tsx +0 -145
  52. package/src/lib/reset-mfa-dialog.tsx +0 -104
  53. package/src/lib/revoke-invite-dialog.tsx +0 -111
  54. package/src/lib/save-button.tsx +0 -113
  55. package/src/lib/search-provider.tsx +0 -51
  56. package/src/lib/set-password-dialog.tsx +0 -204
  57. package/src/lib/use-dialog-close.tsx +0 -19
  58. package/src/lib/use-is-hydrated.ts +0 -13
  59. package/src/lib/use-layout-effect.ts +0 -6
  60. package/src/lib/use-security-settings.tsx +0 -49
  61. package/src/lib/user-actions-dropdown.tsx +0 -157
  62. package/src/lib/user-profile.tsx +0 -227
  63. package/src/lib/user-security.tsx +0 -187
  64. package/src/lib/user-sessions.tsx +0 -204
  65. package/src/lib/users-filter.tsx +0 -62
  66. package/src/lib/users-management-context.tsx +0 -74
  67. package/src/lib/users-management-state.ts +0 -165
  68. package/src/lib/users-management.tsx +0 -594
  69. package/src/lib/users-search.tsx +0 -73
  70. package/src/lib/utils.ts +0 -131
  71. package/src/lib/widgets-context.ts +0 -29
  72. package/src/organization-switcher.client.tsx +0 -81
  73. package/src/user-profile.client.tsx +0 -55
  74. package/src/user-security.client.tsx +0 -55
  75. package/src/user-sessions.client.tsx +0 -100
  76. package/src/users-management.client.tsx +0 -73
  77. package/src/workos-widgets.client.tsx +0 -75
  78. /package/{src → dist/css}/base.css +0 -0
  79. /package/{src → dist/css}/lib/card-list.css +0 -0
  80. /package/{src → dist/css}/lib/marker.css +0 -0
  81. /package/{src → dist/css}/lib/save-button.css +0 -0
  82. /package/{src → dist/css}/styles.css +0 -0
  83. /package/{src → dist/css}/users-management.css +0 -0
package/src/api/errors.ts DELETED
@@ -1,48 +0,0 @@
1
- type QueryType = "query" | "mutation";
2
-
3
- export class FetchError extends Error {
4
- queryType: QueryType;
5
- recordType?: string;
6
- context: unknown;
7
- constructor(args: {
8
- message: string;
9
- queryType: QueryType;
10
- recordType?: string;
11
- context?: unknown;
12
- }) {
13
- super(args.message);
14
- this.name = "FetchError";
15
- this.queryType = args.queryType;
16
- this.recordType = args.recordType;
17
- this.context = args.context;
18
- }
19
- }
20
-
21
- export class ApiError extends Error {
22
- status: number;
23
- queryType: QueryType;
24
- recordType?: string;
25
- context: unknown;
26
- constructor(args: {
27
- message: string;
28
- queryType: QueryType;
29
- recordType?: string;
30
- status: number;
31
- context?: unknown;
32
- }) {
33
- super(args.message);
34
- this.name = "ApiError";
35
- this.status = args.status;
36
- this.queryType = args.queryType;
37
- this.recordType = args.recordType;
38
- }
39
- }
40
-
41
- export class NoAuthTokenError extends Error {
42
- context: unknown;
43
- constructor(args?: { context?: unknown }) {
44
- super("No auth token provided");
45
- this.name = "NoAuthTokenError";
46
- this.context = args?.context;
47
- }
48
- }
package/src/api/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./endpoint";
2
- export * from "./api-provider";
package/src/api/utils.ts DELETED
@@ -1,42 +0,0 @@
1
- import { WIDGETS_API_VERSION } from "./constants";
2
-
3
- export function getAuthHeaders(authToken: string): HeadersInit {
4
- return {
5
- Authorization: `Bearer ${authToken}`,
6
- "WorkOS-Widgets-Version": WIDGETS_API_VERSION,
7
- };
8
- }
9
-
10
- export function isObjectLike(value: unknown): value is Record<string, unknown> {
11
- return typeof value === "object" && value !== null;
12
- }
13
-
14
- export function isErrorLike(
15
- value: unknown,
16
- ): value is Record<string, unknown> & { message: string } {
17
- return isObjectLike(value) && typeof value.message === "string";
18
- }
19
-
20
- export async function parseErrorResponse(
21
- response: Response,
22
- ): Promise<{ message: string; status: number }> {
23
- try {
24
- const json = await response.json();
25
- if (!isObjectLike(json) || typeof json.message !== "string") {
26
- return {
27
- status: response.status,
28
- message: response.statusText,
29
- };
30
- }
31
- return {
32
- ...json,
33
- status: response.status,
34
- message: json.message || response.statusText,
35
- };
36
- } catch {
37
- return {
38
- status: response.status,
39
- message: response.statusText,
40
- };
41
- }
42
- }
@@ -1,87 +0,0 @@
1
- import { QueryKey } from "@tanstack/react-query";
2
- import { useApi } from "./api-provider";
3
- import { ApiError, FetchError } from "./errors";
4
- import { getAuthHeaders, parseErrorResponse } from "./utils";
5
-
6
- type WidgetsApiClient<T> = (data: {
7
- url: string;
8
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
9
- params?: Record<string, any>;
10
- headers?: Record<string, any>;
11
- data?: BodyType<unknown>;
12
- signal?: AbortSignal;
13
- }) => Promise<T>;
14
-
15
- export const useWidgetsApiClient = <T>(): WidgetsApiClient<T> => {
16
- const { authToken, baseUrl, elevatedAccess, widgetType } = useApi();
17
-
18
- return async ({ url: pathname, method, params, data }) => {
19
- const url = new URL(baseUrl);
20
- url.pathname = pathname;
21
-
22
- if (params) {
23
- const cleanParams = Object.fromEntries(
24
- Object.entries(params).filter(([_, value]) => value !== undefined),
25
- );
26
- url.search = new URLSearchParams(cleanParams).toString();
27
- }
28
-
29
- const queryType = method.toLowerCase() === "get" ? "query" : "mutation";
30
- const headers = {
31
- ...getAuthHeaders(await Promise.resolve(authToken)),
32
- ...(elevatedAccess && queryType === "mutation"
33
- ? { "x-elevated-access-token": elevatedAccess.token }
34
- : {}),
35
- "WorkOS-Widgets-Type": widgetType,
36
- "Content-Type": "application/json",
37
- };
38
-
39
- const response = await fetch(url, {
40
- method,
41
- cache: "no-store",
42
- headers,
43
- ...(data ? { body: JSON.stringify(data) } : {}),
44
- }).catch((error) => {
45
- throw new FetchError({
46
- message: `Failed to ${method} ${url.toString()}`,
47
- queryType,
48
- context: { error },
49
- });
50
- });
51
-
52
- if (!response.ok) {
53
- const { message, status } = await parseErrorResponse(response);
54
-
55
- throw new ApiError({
56
- message,
57
- status,
58
- queryType: method.toLowerCase() === "get" ? "query" : "mutation",
59
- });
60
- }
61
-
62
- return response.json();
63
- };
64
- };
65
-
66
- export type ErrorType<ErrorData> = ErrorData;
67
-
68
- export type BodyType<BodyData> = BodyData & { headers?: any };
69
-
70
- export const useWidgetsApiQueryOptions = <
71
- QueryOptions extends { queryKey: QK },
72
- QK extends QueryKey,
73
- >(
74
- queryOptions: QueryOptions,
75
- ) => {
76
- const { authTokenQueryKey, baseUrl } = useApi();
77
- const queryKey = [
78
- // initial query key needs to go first to allow invalidation of the query name to work
79
- ...queryOptions.queryKey,
80
- { authTokenQueryKey, baseUrl },
81
- ] as unknown as QK;
82
-
83
- return {
84
- ...queryOptions,
85
- queryKey: queryKey as QK,
86
- };
87
- };
package/src/card-list.tsx DELETED
@@ -1,26 +0,0 @@
1
- import { Box, Card, CardProps, Inset } from "@radix-ui/themes";
2
-
3
- export function Root({ children, ...props }: CardProps) {
4
- return (
5
- <Card size="2" {...props} className="woswidgets-card-list">
6
- <Inset side="all" clip="padding-box">
7
- {children}
8
- </Inset>
9
- </Card>
10
- );
11
- }
12
-
13
- export function Item({ children }: { children: React.ReactNode }) {
14
- return (
15
- <Inset
16
- side="x"
17
- px="current"
18
- className="woswidgets-card-list-item"
19
- clip="padding-box"
20
- >
21
- <Box px="4" py="4">
22
- {children}
23
- </Box>
24
- </Inset>
25
- );
26
- }
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export {
2
- WorkOsWidgets,
3
- type WorkOsWidgetsProps,
4
- } from "./workos-widgets.client";
5
- export { OrganizationSwitcher } from "./organization-switcher.client";
6
- export { UserProfile } from "./user-profile.client";
7
- export { UserSecurity } from "./user-security.client";
8
- export { UserSessions } from "./user-sessions.client";
9
- export { UsersManagement } from "./users-management.client";
@@ -1,379 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- Box,
5
- Code,
6
- Dialog,
7
- Flex,
8
- Grid,
9
- Link,
10
- Separator,
11
- Text,
12
- VisuallyHidden,
13
- } from "@radix-ui/themes";
14
- import * as React from "react";
15
- import { type ReactNode } from "react";
16
- import * as Otp from "./otp-input";
17
- import { DialogContent, PrimaryButton, SecondaryButton } from "./elements";
18
- import {
19
- CreateTotpFactorResponse,
20
- CreateTotpFactorResponseAuthenticationFactorAllOfTotpAnyOf,
21
- useCreateTotpFactor,
22
- useElevatedAccessToken,
23
- useVerifyTotpFactor,
24
- } from "../api";
25
- import * as Form from "@radix-ui/react-form";
26
- import { Marker } from "./marker";
27
- import { CopyButton } from "./copy-button";
28
- import { useSecuritySettings } from "./use-security-settings";
29
- import { ElevatedAccess } from "./elevated-access";
30
- import { SaveButton } from "./save-button";
31
- import { useDialogClose } from "./use-dialog-close";
32
-
33
- interface AddMfaDialogProps extends Dialog.RootProps {
34
- children?: ReactNode;
35
- onSuccess?: () => void;
36
- }
37
-
38
- export function AddMfaDialog({
39
- children,
40
- onSuccess,
41
- ...props
42
- }: AddMfaDialogProps) {
43
- const [open, setOpen] = React.useState(false);
44
- const [manuallyTriggered, setManuallyTriggered] = React.useState(false);
45
- const { elevatedAccess } = useElevatedAccessToken();
46
- const createAuthFactor = useCreateTotpFactor();
47
-
48
- const handleVerified = async () => {
49
- await createAuthFactor.mutateAsync(undefined);
50
- };
51
-
52
- const onTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {
53
- if (elevatedAccess && !createAuthFactor.data) {
54
- event.preventDefault();
55
- setManuallyTriggered(true);
56
- createAuthFactor.mutate(undefined, {
57
- onSuccess: () => {
58
- setOpen(true);
59
- },
60
- });
61
- } else {
62
- setManuallyTriggered(false);
63
- }
64
- };
65
-
66
- const handleClose = React.useCallback(() => {
67
- setOpen(false);
68
- }, []);
69
-
70
- return (
71
- <Dialog.Root
72
- {...props}
73
- open={props.open || open}
74
- onOpenChange={props.onOpenChange || setOpen}
75
- >
76
- <Dialog.Trigger
77
- onClick={onTriggerClick}
78
- // @ts-ignore I've to find a way to pass the loading state to the trigger
79
- loading={manuallyTriggered && createAuthFactor.isPending}
80
- >
81
- {children}
82
- </Dialog.Trigger>
83
-
84
- <DialogContent maxWidth="480px">
85
- <ElevatedAccess onVerified={handleVerified}>
86
- <Content onClose={handleClose} totpFactor={createAuthFactor.data} />
87
- </ElevatedAccess>
88
- </DialogContent>
89
- </Dialog.Root>
90
- );
91
- }
92
-
93
- interface ContentProps {
94
- totpFactor?: CreateTotpFactorResponse;
95
- onClose?: () => void;
96
- }
97
-
98
- function Content({ onClose, totpFactor }: ContentProps) {
99
- const securitySettings = useSecuritySettings();
100
-
101
- const [customError, setCustomError] = React.useState<string | null>(null);
102
- const totp = hasQrCode(totpFactor)
103
- ? totpFactor.authenticationFactor.totp
104
- : undefined;
105
-
106
- const verifyTotp = useVerifyTotpFactor({
107
- mutation: {
108
- onSuccess: ({ success }) => {
109
- if (!success) {
110
- setCustomError("Invalid passcode");
111
- }
112
- },
113
- },
114
- });
115
-
116
- const serverError = verifyTotp.error || customError;
117
- const isSuccess = verifyTotp.isSuccess && !serverError;
118
-
119
- const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
120
- event.preventDefault();
121
- setCustomError(null);
122
-
123
- const formData = new FormData(event.currentTarget);
124
- const otpCode = formData.get("otp-code")?.toString();
125
-
126
- verifyTotp.mutate({
127
- data: {
128
- authenticationChallengeId: totpFactor?.authenticationChallenge.id ?? "",
129
- code: otpCode ?? "",
130
- },
131
- });
132
- };
133
-
134
- useDialogClose(isSuccess, () => {
135
- securitySettings.update("Mfa", true);
136
- });
137
-
138
- return (
139
- <>
140
- <Dialog.Title mb="5">Set up an authenticator app</Dialog.Title>
141
-
142
- <Form.Root onSubmit={handleSubmit}>
143
- <Grid columns="auto 1fr" rows="repeat(4, auto)" gapX="3" gapY="1">
144
- <Grid
145
- rows="subgrid"
146
- gridRow="span 4"
147
- style={{ placeItems: "center" }}
148
- >
149
- <Marker>1</Marker>
150
- <Separator
151
- orientation="vertical"
152
- size="4"
153
- style={{ width: "2px" }}
154
- />
155
- <Marker>2</Marker>
156
- <div />
157
- </Grid>
158
-
159
- <Grid rows="subgrid" gridRow="span 4">
160
- <Text as="p" size="3" weight="bold">
161
- Scan the QR code
162
- </Text>
163
- <Flex direction="column" gap="1">
164
- <Text as="p" size="2">
165
- Use an authenticator app like{" "}
166
- <Link
167
- href="https://1password.com/"
168
- rel="noopener noreferrer"
169
- target="_blank"
170
- >
171
- 1Password
172
- </Link>
173
- ,{" "}
174
- <Link
175
- href="https://apps.apple.com/us/app/google-authenticator/id388497605"
176
- rel="noopener noreferrer"
177
- target="_blank"
178
- >
179
- Google Authenticator
180
- </Link>
181
- ,{" "}
182
- <Link
183
- href="https://authy.com/"
184
- rel="noopener noreferrer"
185
- target="_blank"
186
- >
187
- Authy
188
- </Link>
189
- , or{" "}
190
- <Link
191
- href="https://www.microsoft.com/en-gb/security/mobile-authenticator-app"
192
- rel="noopener noreferrer"
193
- target="_blank"
194
- >
195
- Microsoft Authenticator
196
- </Link>{" "}
197
- to scan the QR code below.
198
- </Text>
199
- <Flex align="center" gap="5" my="5">
200
- <Grid
201
- position="relative"
202
- width="160px"
203
- height="160px"
204
- p="2"
205
- style={{
206
- border: "1px solid var(--gray-7)",
207
- borderRadius: "var(--radius-4)",
208
- background: "var(--gray-2)",
209
- overflow: "hidden",
210
- }}
211
- >
212
- {totp?.qr_code && (
213
- <Box asChild width="100%" height="auto">
214
- <img
215
- alt="Scan this QR code to enroll"
216
- aria-describedby="secret-note"
217
- height="160"
218
- src={totp.qr_code}
219
- style={{ userSelect: "none", background: "white" }}
220
- width="160"
221
- />
222
- </Box>
223
- )}
224
- </Grid>
225
-
226
- <Flex direction="column" gap="1" align="start">
227
- <Text color="gray" id="secret-note" size="2">
228
- Can‘t scan the code?{" "}
229
- </Text>
230
-
231
- <SecretDialog setupKey={totp?.secret ?? ""}>
232
- <SecondaryButton
233
- size="1"
234
- disabled={verifyTotp.isPending || isSuccess}
235
- >
236
- View setup key
237
- </SecondaryButton>
238
- </SecretDialog>
239
- </Flex>
240
- </Flex>
241
- </Flex>
242
- <Text as="p" size="3" weight="bold">
243
- Get verification passcode
244
- </Text>
245
- <Flex direction="column" gap="4">
246
- <Text as="p" size="2">
247
- Enter the 6-digit passcode from your authenticator app.
248
- </Text>
249
-
250
- <Flex direction="column" gap="2">
251
- <Otp.Root
252
- autoSubmit
253
- gap="3"
254
- justify="start"
255
- name="otp-code"
256
- rows="48px"
257
- columns="repeat(6, 48px)"
258
- readOnly={verifyTotp.isPending || isSuccess}
259
- >
260
- <Otp.Input required autoFocus autoComplete="off" />
261
- <Otp.Input required />
262
- <Otp.Input required />
263
- <Otp.Input required />
264
- <Otp.Input required />
265
- <Otp.Input required />
266
- </Otp.Root>
267
-
268
- {serverError && (
269
- <Text size="2" color="red">
270
- {getMutationErrorMessage(serverError)}
271
- </Text>
272
- )}
273
- </Flex>
274
- </Flex>
275
- </Grid>
276
- </Grid>
277
-
278
- <Flex mt="5" gap="3" justify="end">
279
- <Dialog.Close>
280
- <SecondaryButton disabled={verifyTotp.isPending || isSuccess}>
281
- Cancel
282
- </SecondaryButton>
283
- </Dialog.Close>
284
-
285
- <SaveButton
286
- asChild
287
- loading={verifyTotp.isPending}
288
- done={isSuccess}
289
- onDone={onClose}
290
- >
291
- <PrimaryButton type="submit">Confirm</PrimaryButton>
292
- </SaveButton>
293
- </Flex>
294
- </Form.Root>
295
-
296
- {/* mirror errors in a live region */}
297
- <VisuallyHidden asChild>
298
- <section aria-live="polite">
299
- {getMutationErrorMessage(serverError)}
300
- </section>
301
- </VisuallyHidden>
302
- </>
303
- );
304
- }
305
-
306
- interface SecretDialogProps extends React.PropsWithChildren {
307
- setupKey: string;
308
- }
309
-
310
- function SecretDialog({ children, setupKey }: SecretDialogProps) {
311
- return (
312
- <Dialog.Root>
313
- <Dialog.Trigger>{children}</Dialog.Trigger>
314
- <Dialog.Content
315
- maxWidth="90vw"
316
- size={{ initial: "3", sm: "4" }}
317
- minWidth="300px"
318
- width="fit-content"
319
- >
320
- <Dialog.Title size="2" weight="regular">
321
- Your setup key
322
- </Dialog.Title>
323
- <Dialog.Description>
324
- <Text size="6">
325
- <Code variant="ghost" style={{ letterSpacing: "0.15rem" }}>
326
- {setupKey}
327
- </Code>
328
- </Text>
329
- </Dialog.Description>
330
-
331
- <Flex align="center" gap="3" justify="end" mt="5">
332
- <Dialog.Close>
333
- <CopyButton asChild value={setupKey}>
334
- <PrimaryButton>Copy and close</PrimaryButton>
335
- </CopyButton>
336
- </Dialog.Close>
337
- </Flex>
338
- </Dialog.Content>
339
- </Dialog.Root>
340
- );
341
- }
342
-
343
- function getMutationErrorMessage(error: unknown) {
344
- let message = "Something went wrong, please try again";
345
-
346
- if (typeof error === "string") {
347
- message = error;
348
- }
349
-
350
- if (error instanceof Error) {
351
- message = error.message;
352
- }
353
-
354
- if (
355
- typeof error === "object" &&
356
- error !== null &&
357
- "message" in error &&
358
- typeof error.message === "string"
359
- ) {
360
- message = error.message;
361
- }
362
-
363
- if (message === "Invalid passcode") {
364
- message = "Invalid passcode, please try again";
365
- }
366
-
367
- return message;
368
- }
369
-
370
- function hasQrCode(
371
- response?: CreateTotpFactorResponse,
372
- ): response is CreateTotpFactorResponse & {
373
- authenticationFactor: {
374
- totp: NonNullable<CreateTotpFactorResponseAuthenticationFactorAllOfTotpAnyOf>;
375
- };
376
- } {
377
- const totp = response?.authenticationFactor.totp;
378
- return totp != null && "qr_code" in totp;
379
- }
@@ -1,9 +0,0 @@
1
- export const DEFAULT_API_HOSTNAME = "api.workos.com";
2
- export const API_ENDPOINTS = {
3
- USERS: "_widgets/UserManagement/members",
4
- USER_ROLES: "_widgets/UserManagement/roles",
5
- USER_INVITE: "_widgets/UserManagement/invite-user",
6
- USER_INVITES: "_widgets/UserManagement/invites",
7
- USER_INVITES_RESEND: (userId: string) =>
8
- `_widgets/UserManagement/invites/${userId}/resend`,
9
- };
@@ -1,98 +0,0 @@
1
- import {
2
- getMembersQueryKey,
3
- useInviteMember,
4
- useMembers,
5
- useRemoveMember,
6
- useResendInvite,
7
- useRevokeInvite,
8
- useUpdateMember,
9
- } from "../../api";
10
- import { keepPreviousData, useQueryClient } from "@tanstack/react-query";
11
- import { USER_ROW_LIMIT } from "../constants";
12
- import {
13
- useUsersManagementContext,
14
- type UsersManagementContextType,
15
- } from "../users-management-context";
16
-
17
- export const useUsers = (context?: UsersManagementContextType) => {
18
- const {
19
- state: { pagination, role, searchQuery },
20
- } = useUsersManagementContext(context);
21
- const limit = USER_ROW_LIMIT;
22
- const { before, after } = pagination || {};
23
-
24
- return useMembers(
25
- {
26
- after: after ?? undefined,
27
- before: before ?? undefined,
28
- limit: limit.toString(),
29
- role: role ?? undefined,
30
- search: searchQuery ?? undefined,
31
- },
32
- {
33
- query: {
34
- placeholderData: keepPreviousData,
35
- },
36
- },
37
- );
38
- };
39
-
40
- export const useUpdateUserRole: typeof useUpdateMember = () => {
41
- const queryClient = useQueryClient();
42
-
43
- return useUpdateMember({
44
- mutation: {
45
- onSuccess: () => {
46
- queryClient.invalidateQueries({ queryKey: getMembersQueryKey() });
47
- },
48
- },
49
- });
50
- };
51
-
52
- export const useInviteUser: typeof useInviteMember = () => {
53
- const queryClient = useQueryClient();
54
-
55
- return useInviteMember({
56
- mutation: {
57
- onSuccess: () => {
58
- queryClient.invalidateQueries({ queryKey: getMembersQueryKey() });
59
- },
60
- },
61
- });
62
- };
63
-
64
- export const useDeleteUser = () => {
65
- const queryClient = useQueryClient();
66
-
67
- return useRemoveMember({
68
- mutation: {
69
- onSuccess: () => {
70
- queryClient.invalidateQueries({ queryKey: getMembersQueryKey() });
71
- },
72
- },
73
- });
74
- };
75
-
76
- export const useRevokeUserInvite = () => {
77
- const queryClient = useQueryClient();
78
-
79
- return useRevokeInvite({
80
- mutation: {
81
- onSuccess: () => {
82
- queryClient.invalidateQueries({ queryKey: getMembersQueryKey() });
83
- },
84
- },
85
- });
86
- };
87
-
88
- export const useResendUserInvite = () => {
89
- const queryClient = useQueryClient();
90
-
91
- return useResendInvite({
92
- mutation: {
93
- onSuccess: () => {
94
- queryClient.invalidateQueries({ queryKey: getMembersQueryKey() });
95
- },
96
- },
97
- });
98
- };