@workos-inc/widgets 1.1.5 → 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.
- package/dist/cjs/lib/organization-switcher.d.ts +10 -1
- package/dist/cjs/lib/organization-switcher.d.ts.map +1 -1
- package/dist/cjs/lib/organization-switcher.js +31 -3
- package/dist/cjs/lib/organization-switcher.js.map +1 -1
- package/dist/cjs/workos-widgets.client.d.ts +6 -0
- package/dist/cjs/workos-widgets.client.d.ts.map +1 -1
- package/dist/cjs/workos-widgets.client.js +23 -3
- package/dist/cjs/workos-widgets.client.js.map +1 -1
- package/dist/esm/lib/organization-switcher.d.ts +10 -1
- package/dist/esm/lib/organization-switcher.d.ts.map +1 -1
- package/dist/esm/lib/organization-switcher.js +31 -3
- package/dist/esm/lib/organization-switcher.js.map +1 -1
- package/dist/esm/workos-widgets.client.d.ts +6 -0
- package/dist/esm/workos-widgets.client.d.ts.map +1 -1
- package/dist/esm/workos-widgets.client.js +25 -5
- package/dist/esm/workos-widgets.client.js.map +1 -1
- package/package.json +8 -9
- package/src/api/api-provider.tsx +0 -158
- package/src/api/constants.ts +0 -1
- package/src/api/endpoint.ts +0 -3097
- package/src/api/errors.ts +0 -48
- package/src/api/index.ts +0 -2
- package/src/api/utils.ts +0 -42
- package/src/api/widgets-api-client.ts +0 -87
- package/src/card-list.tsx +0 -26
- package/src/index.ts +0 -9
- package/src/lib/add-mfa-dialog.tsx +0 -379
- package/src/lib/api/config.ts +0 -9
- package/src/lib/api/user.ts +0 -98
- package/src/lib/change-password-dialog.tsx +0 -290
- package/src/lib/constants.ts +0 -3
- package/src/lib/copy-button.tsx +0 -53
- package/src/lib/delete-user-dialog.tsx +0 -110
- package/src/lib/edit-user-profile-dialog.tsx +0 -181
- package/src/lib/edit-user-role-dialog.tsx +0 -178
- package/src/lib/elements.tsx +0 -428
- package/src/lib/elevated-access.tsx +0 -261
- package/src/lib/error-boundary.tsx +0 -166
- package/src/lib/errors.ts +0 -49
- package/src/lib/generic-error.tsx +0 -70
- package/src/lib/icon-panel.tsx +0 -26
- package/src/lib/icons.tsx +0 -21
- package/src/lib/invite-user-dialog.tsx +0 -327
- package/src/lib/logout-all-sessions-dialog.tsx +0 -82
- package/src/lib/logout-dialog.tsx +0 -85
- package/src/lib/marker.tsx +0 -39
- package/src/lib/oauth-icons.tsx +0 -138
- package/src/lib/organization-switcher.tsx +0 -156
- package/src/lib/otp-input.tsx +0 -276
- package/src/lib/resend-invite-dialog.tsx +0 -145
- package/src/lib/reset-mfa-dialog.tsx +0 -104
- package/src/lib/revoke-invite-dialog.tsx +0 -111
- package/src/lib/save-button.tsx +0 -113
- package/src/lib/search-provider.tsx +0 -51
- package/src/lib/set-password-dialog.tsx +0 -204
- package/src/lib/use-dialog-close.tsx +0 -19
- package/src/lib/use-is-hydrated.ts +0 -13
- package/src/lib/use-layout-effect.ts +0 -6
- package/src/lib/use-security-settings.tsx +0 -49
- package/src/lib/user-actions-dropdown.tsx +0 -157
- package/src/lib/user-profile.tsx +0 -227
- package/src/lib/user-security.tsx +0 -187
- package/src/lib/user-sessions.tsx +0 -204
- package/src/lib/users-filter.tsx +0 -62
- package/src/lib/users-management-context.tsx +0 -74
- package/src/lib/users-management-state.ts +0 -165
- package/src/lib/users-management.tsx +0 -594
- package/src/lib/users-search.tsx +0 -73
- package/src/lib/utils.ts +0 -131
- package/src/lib/widgets-context.ts +0 -29
- package/src/organization-switcher.client.tsx +0 -81
- package/src/user-profile.client.tsx +0 -55
- package/src/user-security.client.tsx +0 -55
- package/src/user-sessions.client.tsx +0 -100
- package/src/users-management.client.tsx +0 -73
- package/src/workos-widgets.client.tsx +0 -75
- /package/{src → dist/css}/base.css +0 -0
- /package/{src → dist/css}/lib/card-list.css +0 -0
- /package/{src → dist/css}/lib/marker.css +0 -0
- /package/{src → dist/css}/lib/save-button.css +0 -0
- /package/{src → dist/css}/styles.css +0 -0
- /package/{src → dist/css}/users-management.css +0 -0
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import * as Form from "@radix-ui/react-form";
|
|
2
|
-
import { AlertDialog, Callout, Dialog, Flex, Text } from "@radix-ui/themes";
|
|
3
|
-
import {
|
|
4
|
-
useElevatedAccessToken,
|
|
5
|
-
useMe,
|
|
6
|
-
useSendVerification,
|
|
7
|
-
useVerify,
|
|
8
|
-
} from "../api";
|
|
9
|
-
import { PropsWithChildren, useEffect, useRef, useState } from "react";
|
|
10
|
-
import { PrimaryButton, SecondaryButton } from "./elements";
|
|
11
|
-
import * as Otp from "./otp-input";
|
|
12
|
-
|
|
13
|
-
interface ElevatedAccessProps extends PropsWithChildren {
|
|
14
|
-
onVerified?: () => Promise<unknown>;
|
|
15
|
-
type?: "dialog" | "alert";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function ElevatedAccess({
|
|
19
|
-
type = "dialog",
|
|
20
|
-
children,
|
|
21
|
-
onVerified,
|
|
22
|
-
}: ElevatedAccessProps) {
|
|
23
|
-
const { elevatedAccess } = useElevatedAccessToken();
|
|
24
|
-
const [authenticationChallengeId, setAuthenticationChallengeId] =
|
|
25
|
-
useState<string>();
|
|
26
|
-
|
|
27
|
-
const prevAccessToken = useRef(elevatedAccess);
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
prevAccessToken.current = elevatedAccess;
|
|
31
|
-
}, [elevatedAccess]);
|
|
32
|
-
|
|
33
|
-
if (elevatedAccess) {
|
|
34
|
-
return <>{children}</>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (!authenticationChallengeId) {
|
|
38
|
-
const hasTokenExpired = !!prevAccessToken.current;
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<SendVerificationEmailForm
|
|
42
|
-
type={type}
|
|
43
|
-
hasTokenExpired={hasTokenExpired}
|
|
44
|
-
onSuccess={(challengeId) => {
|
|
45
|
-
setAuthenticationChallengeId(challengeId);
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (authenticationChallengeId) {
|
|
52
|
-
return (
|
|
53
|
-
<VerificationIdentityForm
|
|
54
|
-
type={type}
|
|
55
|
-
authenticationChallengeId={authenticationChallengeId}
|
|
56
|
-
onSuccess={() => {
|
|
57
|
-
// Reset the challenge id
|
|
58
|
-
setAuthenticationChallengeId(undefined);
|
|
59
|
-
|
|
60
|
-
return onVerified?.();
|
|
61
|
-
}}
|
|
62
|
-
/>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface SendVerificationEmailFormProps {
|
|
70
|
-
onSuccess: (challengeId: string) => unknown | Promise<unknown>;
|
|
71
|
-
type: "dialog" | "alert";
|
|
72
|
-
hasTokenExpired: boolean;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function SendVerificationEmailForm({
|
|
76
|
-
onSuccess,
|
|
77
|
-
type,
|
|
78
|
-
hasTokenExpired,
|
|
79
|
-
}: SendVerificationEmailFormProps) {
|
|
80
|
-
const { data: me } = useMe();
|
|
81
|
-
const sendVerification = useSendVerification({
|
|
82
|
-
mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const Title = type === "dialog" ? Dialog.Title : AlertDialog.Title;
|
|
86
|
-
const Description =
|
|
87
|
-
type === "dialog" ? Dialog.Description : AlertDialog.Description;
|
|
88
|
-
const Close = type === "dialog" ? Dialog.Close : AlertDialog.Cancel;
|
|
89
|
-
|
|
90
|
-
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
|
91
|
-
event.preventDefault();
|
|
92
|
-
|
|
93
|
-
sendVerification.mutate();
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<form onSubmit={handleSubmit}>
|
|
98
|
-
<Title>
|
|
99
|
-
{hasTokenExpired
|
|
100
|
-
? "Your verification token has expired"
|
|
101
|
-
: "Verify your identity"}
|
|
102
|
-
</Title>
|
|
103
|
-
|
|
104
|
-
<Description color="gray" mb="5">
|
|
105
|
-
To continue, we need to confirm your identity. We'll send a temporary
|
|
106
|
-
verification code to{" "}
|
|
107
|
-
<Text weight="bold" highContrast>
|
|
108
|
-
{me?.email}
|
|
109
|
-
</Text>
|
|
110
|
-
.
|
|
111
|
-
</Description>
|
|
112
|
-
|
|
113
|
-
{sendVerification.error && (
|
|
114
|
-
<Callout.Root color="red" mt="-2" mb="0">
|
|
115
|
-
<Callout.Text>
|
|
116
|
-
{getMutationErrorMessage(sendVerification.error)}
|
|
117
|
-
</Callout.Text>
|
|
118
|
-
</Callout.Root>
|
|
119
|
-
)}
|
|
120
|
-
|
|
121
|
-
<Flex justify="end" align="center" gap="3" mt="5">
|
|
122
|
-
<Close>
|
|
123
|
-
<SecondaryButton type="button" disabled={sendVerification.isPending}>
|
|
124
|
-
Cancel
|
|
125
|
-
</SecondaryButton>
|
|
126
|
-
</Close>
|
|
127
|
-
<PrimaryButton type="submit" loading={sendVerification.isPending}>
|
|
128
|
-
Send verification code
|
|
129
|
-
</PrimaryButton>
|
|
130
|
-
</Flex>
|
|
131
|
-
</form>
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
interface VerificationIdentityFormProps {
|
|
136
|
-
onSuccess?: () => unknown | Promise<unknown>;
|
|
137
|
-
authenticationChallengeId: string;
|
|
138
|
-
type: "dialog" | "alert";
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function VerificationIdentityForm({
|
|
142
|
-
onSuccess,
|
|
143
|
-
authenticationChallengeId,
|
|
144
|
-
type,
|
|
145
|
-
}: VerificationIdentityFormProps) {
|
|
146
|
-
const { data: me } = useMe();
|
|
147
|
-
const { setElevatedAccess } = useElevatedAccessToken();
|
|
148
|
-
const verifyIdentity = useVerify();
|
|
149
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
150
|
-
|
|
151
|
-
const Title = type === "dialog" ? Dialog.Title : AlertDialog.Title;
|
|
152
|
-
const Description =
|
|
153
|
-
type === "dialog" ? Dialog.Description : AlertDialog.Description;
|
|
154
|
-
const Close = type === "dialog" ? Dialog.Close : AlertDialog.Cancel;
|
|
155
|
-
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
|
156
|
-
event.preventDefault();
|
|
157
|
-
|
|
158
|
-
const formData = new FormData(event.currentTarget);
|
|
159
|
-
const code = formData.get("otp-code")?.toString() ?? "";
|
|
160
|
-
|
|
161
|
-
setIsSubmitting(true);
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
// Mutate async so we can wait for the onSuccess callback as well
|
|
165
|
-
const newAuthState = await verifyIdentity.mutateAsync({
|
|
166
|
-
data: {
|
|
167
|
-
code,
|
|
168
|
-
authenticationChallengeId,
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
const in10Seconds = new Date(Date.now() + 5 * 1000);
|
|
173
|
-
|
|
174
|
-
setElevatedAccess({
|
|
175
|
-
token: newAuthState.elevatedAccessToken,
|
|
176
|
-
// expiresAt: newAuthState.expiresAt,
|
|
177
|
-
expiresAt: in10Seconds.toISOString(),
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
if (onSuccess) {
|
|
181
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
182
|
-
await onSuccess();
|
|
183
|
-
}
|
|
184
|
-
} catch (error) {
|
|
185
|
-
console.error(error);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
setIsSubmitting(false);
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
return (
|
|
192
|
-
<Form.Root onSubmit={handleSubmit}>
|
|
193
|
-
<Title>Verify your identity</Title>
|
|
194
|
-
|
|
195
|
-
<Description color="gray">
|
|
196
|
-
A verification code was sent to{" "}
|
|
197
|
-
<Text weight="bold" highContrast>
|
|
198
|
-
{me?.email}
|
|
199
|
-
</Text>
|
|
200
|
-
. Please enter it below.
|
|
201
|
-
</Description>
|
|
202
|
-
|
|
203
|
-
<Flex direction="column" gap="2" mt="5" mx="auto" width="fit-content">
|
|
204
|
-
<Otp.Root
|
|
205
|
-
autoSubmit
|
|
206
|
-
gap="2"
|
|
207
|
-
justify="center"
|
|
208
|
-
columns="repeat(6, 48px)"
|
|
209
|
-
width="fit-content"
|
|
210
|
-
rows="48px"
|
|
211
|
-
name="otp-code"
|
|
212
|
-
readOnly={isSubmitting}
|
|
213
|
-
>
|
|
214
|
-
<Otp.Input required autoFocus autoComplete="off" />
|
|
215
|
-
<Otp.Input required />
|
|
216
|
-
<Otp.Input required />
|
|
217
|
-
<Otp.Input required />
|
|
218
|
-
<Otp.Input required />
|
|
219
|
-
<Otp.Input required />
|
|
220
|
-
</Otp.Root>
|
|
221
|
-
|
|
222
|
-
{verifyIdentity.error && (
|
|
223
|
-
<Text color="red" size="2" as="p">
|
|
224
|
-
{getMutationErrorMessage(verifyIdentity.error)}
|
|
225
|
-
</Text>
|
|
226
|
-
)}
|
|
227
|
-
</Flex>
|
|
228
|
-
|
|
229
|
-
<Flex justify="end" align="center" gap="3" mt="5">
|
|
230
|
-
<Close>
|
|
231
|
-
<SecondaryButton type="button">Cancel</SecondaryButton>
|
|
232
|
-
</Close>
|
|
233
|
-
|
|
234
|
-
<PrimaryButton type="submit" loading={isSubmitting}>
|
|
235
|
-
Confirm
|
|
236
|
-
</PrimaryButton>
|
|
237
|
-
</Flex>
|
|
238
|
-
</Form.Root>
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function getMutationErrorMessage(error: unknown) {
|
|
243
|
-
let message = typeof error === "string" ? error : "";
|
|
244
|
-
|
|
245
|
-
if (error instanceof Error) {
|
|
246
|
-
message = error.message;
|
|
247
|
-
} else if (
|
|
248
|
-
typeof error === "object" &&
|
|
249
|
-
error !== null &&
|
|
250
|
-
"message" in error &&
|
|
251
|
-
typeof error.message === "string"
|
|
252
|
-
) {
|
|
253
|
-
message = error.message;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (!message || message === "Bad Request") {
|
|
257
|
-
message = "Invalid code, please try again.";
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return message;
|
|
261
|
-
}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
// Modified from https://github.com/bvaughn/react-error-boundary
|
|
2
|
-
// Copyright (c) 2020 Brian Vaughn, MIT License
|
|
3
|
-
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
|
|
6
|
-
type ErrorBoundaryState =
|
|
7
|
-
| { didCatch: true; error: any }
|
|
8
|
-
| { didCatch: false; error: null };
|
|
9
|
-
|
|
10
|
-
export interface ErrorBoundaryContextValue {
|
|
11
|
-
didCatch: boolean;
|
|
12
|
-
error: any;
|
|
13
|
-
resetErrorBoundary: (...args: any[]) => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const ErrorBoundaryContext =
|
|
17
|
-
React.createContext<ErrorBoundaryContextValue | null>(null);
|
|
18
|
-
ErrorBoundaryContext.displayName = "ErrorBoundaryContext";
|
|
19
|
-
|
|
20
|
-
const initialState: ErrorBoundaryState = {
|
|
21
|
-
didCatch: false,
|
|
22
|
-
error: null,
|
|
23
|
-
} satisfies ErrorBoundaryState;
|
|
24
|
-
|
|
25
|
-
export class ErrorBoundary extends React.Component<
|
|
26
|
-
ErrorBoundaryProps,
|
|
27
|
-
ErrorBoundaryState
|
|
28
|
-
> {
|
|
29
|
-
constructor(props: ErrorBoundaryProps) {
|
|
30
|
-
super(props);
|
|
31
|
-
|
|
32
|
-
this.resetErrorBoundary = this.resetErrorBoundary.bind(this);
|
|
33
|
-
this.state = initialState;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
static getDerivedStateFromError(error: Error) {
|
|
37
|
-
return { didCatch: true, error };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
resetErrorBoundary(...args: any[]) {
|
|
41
|
-
const { error } = this.state;
|
|
42
|
-
|
|
43
|
-
if (error !== null) {
|
|
44
|
-
this.props.onReset?.({
|
|
45
|
-
args,
|
|
46
|
-
reason: "imperative-api",
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
this.setState(initialState);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
componentDidCatch(error: Error, info: React.ErrorInfo) {
|
|
54
|
-
this.props.onError?.(error, info);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
componentDidUpdate(
|
|
58
|
-
prevProps: ErrorBoundaryProps,
|
|
59
|
-
prevState: ErrorBoundaryState,
|
|
60
|
-
) {
|
|
61
|
-
const { didCatch } = this.state;
|
|
62
|
-
const { resetKeys } = this.props;
|
|
63
|
-
|
|
64
|
-
// There's an edge case where if the thing that triggered the error happens
|
|
65
|
-
// to *also* be in the resetKeys array, we'd end up resetting the error
|
|
66
|
-
// boundary immediately.
|
|
67
|
-
//
|
|
68
|
-
// This would likely trigger a second error to be thrown. So we make sure
|
|
69
|
-
// that we don't check the resetKeys on the first call of cDU after the
|
|
70
|
-
// error is set.
|
|
71
|
-
if (
|
|
72
|
-
didCatch &&
|
|
73
|
-
prevState.error !== null &&
|
|
74
|
-
hasArrayChanged(prevProps.resetKeys, resetKeys)
|
|
75
|
-
) {
|
|
76
|
-
this.props.onReset?.({
|
|
77
|
-
next: resetKeys,
|
|
78
|
-
prev: prevProps.resetKeys,
|
|
79
|
-
reason: "keys",
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
this.setState(initialState);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
render() {
|
|
87
|
-
const { children, fallbackRender, FallbackComponent, fallback } =
|
|
88
|
-
this.props;
|
|
89
|
-
const { didCatch, error } = this.state;
|
|
90
|
-
|
|
91
|
-
let childToRender = children;
|
|
92
|
-
|
|
93
|
-
if (didCatch) {
|
|
94
|
-
const props: FallbackProps = {
|
|
95
|
-
error,
|
|
96
|
-
resetErrorBoundary: this.resetErrorBoundary,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
if (typeof fallbackRender === "function") {
|
|
100
|
-
childToRender = fallbackRender(props);
|
|
101
|
-
} else if (FallbackComponent) {
|
|
102
|
-
childToRender = React.createElement(FallbackComponent, props);
|
|
103
|
-
} else if (fallback !== undefined) {
|
|
104
|
-
childToRender = fallback;
|
|
105
|
-
} else {
|
|
106
|
-
throw error;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<ErrorBoundaryContext.Provider
|
|
112
|
-
value={{
|
|
113
|
-
didCatch,
|
|
114
|
-
error,
|
|
115
|
-
resetErrorBoundary: this.resetErrorBoundary,
|
|
116
|
-
}}
|
|
117
|
-
>
|
|
118
|
-
{childToRender}
|
|
119
|
-
</ErrorBoundaryContext.Provider>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function hasArrayChanged(a: any[] = [], b: any[] = []) {
|
|
125
|
-
return (
|
|
126
|
-
a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]))
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export type FallbackProps = {
|
|
131
|
-
error: any;
|
|
132
|
-
resetErrorBoundary: (...args: any[]) => void;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
type ErrorBoundarySharedProps = React.PropsWithChildren<{
|
|
136
|
-
onError?: (error: Error, info: React.ErrorInfo) => void;
|
|
137
|
-
onReset?: (
|
|
138
|
-
details:
|
|
139
|
-
| { reason: "imperative-api"; args: any[] }
|
|
140
|
-
| { reason: "keys"; prev: any[] | undefined; next: any[] | undefined },
|
|
141
|
-
) => void;
|
|
142
|
-
resetKeys?: any[];
|
|
143
|
-
}>;
|
|
144
|
-
|
|
145
|
-
export type ErrorBoundaryPropsWithComponent = ErrorBoundarySharedProps & {
|
|
146
|
-
fallback?: never;
|
|
147
|
-
FallbackComponent: React.ComponentType<FallbackProps>;
|
|
148
|
-
fallbackRender?: never;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
export type ErrorBoundaryPropsWithRender = ErrorBoundarySharedProps & {
|
|
152
|
-
fallback?: never;
|
|
153
|
-
FallbackComponent?: never;
|
|
154
|
-
fallbackRender: (props: FallbackProps) => React.ReactNode;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
export type ErrorBoundaryPropsWithFallback = ErrorBoundarySharedProps & {
|
|
158
|
-
fallback: React.ReactNode;
|
|
159
|
-
FallbackComponent?: never;
|
|
160
|
-
fallbackRender?: never;
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
export type ErrorBoundaryProps =
|
|
164
|
-
| ErrorBoundaryPropsWithFallback
|
|
165
|
-
| ErrorBoundaryPropsWithComponent
|
|
166
|
-
| ErrorBoundaryPropsWithRender;
|
package/src/lib/errors.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
type QueryType = "query" | "mutation";
|
|
2
|
-
type RecordType = "users" | "roles";
|
|
3
|
-
|
|
4
|
-
export class FetchError extends Error {
|
|
5
|
-
queryType: QueryType;
|
|
6
|
-
recordType: RecordType;
|
|
7
|
-
context: unknown;
|
|
8
|
-
constructor(args: {
|
|
9
|
-
message: string;
|
|
10
|
-
queryType: QueryType;
|
|
11
|
-
recordType: RecordType;
|
|
12
|
-
context?: unknown;
|
|
13
|
-
}) {
|
|
14
|
-
super(args.message);
|
|
15
|
-
this.name = "FetchError";
|
|
16
|
-
this.queryType = args.queryType;
|
|
17
|
-
this.recordType = args.recordType;
|
|
18
|
-
this.context = args.context;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class ApiError extends Error {
|
|
23
|
-
status: number;
|
|
24
|
-
queryType: QueryType;
|
|
25
|
-
recordType: RecordType;
|
|
26
|
-
context: unknown;
|
|
27
|
-
constructor(args: {
|
|
28
|
-
message: string;
|
|
29
|
-
queryType: QueryType;
|
|
30
|
-
recordType: RecordType;
|
|
31
|
-
status: number;
|
|
32
|
-
context?: unknown;
|
|
33
|
-
}) {
|
|
34
|
-
super(args.message);
|
|
35
|
-
this.name = "ApiError";
|
|
36
|
-
this.status = args.status;
|
|
37
|
-
this.queryType = args.queryType;
|
|
38
|
-
this.recordType = args.recordType;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export class NoAuthTokenError extends Error {
|
|
43
|
-
context: unknown;
|
|
44
|
-
constructor(args?: { context?: unknown }) {
|
|
45
|
-
super("No auth token provided");
|
|
46
|
-
this.name = "NoAuthTokenError";
|
|
47
|
-
this.context = args?.context;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Flex, Heading, Text } from "@radix-ui/themes";
|
|
3
|
-
import { ApiError, FetchError, NoAuthTokenError } from "./errors";
|
|
4
|
-
import { Cross2Icon } from "@radix-ui/react-icons";
|
|
5
|
-
|
|
6
|
-
export function GenericError({ error }: { error: unknown }) {
|
|
7
|
-
React.useEffect(() => {
|
|
8
|
-
console.error(error);
|
|
9
|
-
}, [error]);
|
|
10
|
-
|
|
11
|
-
const render = (heading: string, message: React.ReactNode) => (
|
|
12
|
-
<Flex p="6" justify="center" align="center" direction="column">
|
|
13
|
-
<Flex
|
|
14
|
-
align="center"
|
|
15
|
-
justify="center"
|
|
16
|
-
width="32px"
|
|
17
|
-
height="32px"
|
|
18
|
-
mb="2"
|
|
19
|
-
style={{
|
|
20
|
-
borderRadius: "9999px",
|
|
21
|
-
backgroundColor: "var(--red-a4)",
|
|
22
|
-
color: "var(--red-a11)",
|
|
23
|
-
}}
|
|
24
|
-
>
|
|
25
|
-
<Cross2Icon width="24px" height="24px" />
|
|
26
|
-
</Flex>
|
|
27
|
-
|
|
28
|
-
<Flex direction="column" gap="1" maxWidth="420px">
|
|
29
|
-
<Heading size="5" align="center" mb="1" wrap="balance" as="h3">
|
|
30
|
-
{heading}
|
|
31
|
-
</Heading>
|
|
32
|
-
|
|
33
|
-
<Text as="p" align="center" wrap="balance" color="gray">
|
|
34
|
-
{message}
|
|
35
|
-
</Text>
|
|
36
|
-
</Flex>
|
|
37
|
-
</Flex>
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
if (error instanceof FetchError) {
|
|
41
|
-
return render(
|
|
42
|
-
"Error fetching data",
|
|
43
|
-
"An error occurred. You may need to configure CORS in the WorkOS Dashboard. " +
|
|
44
|
-
"Contact your organization admin for support.",
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (error instanceof NoAuthTokenError) {
|
|
49
|
-
return render(
|
|
50
|
-
"Error fetching data",
|
|
51
|
-
"Authorization error. You likely forgot to provide an authorization " +
|
|
52
|
-
"token to the Users Management Widget.",
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (error instanceof ApiError && error.status === 404) {
|
|
57
|
-
// The widgets API treats all authorization errors as 404s. If there is a
|
|
58
|
-
// legitimate 404, it's a bug on our end but there's currently no way to
|
|
59
|
-
// distinguish between the two.
|
|
60
|
-
return render(
|
|
61
|
-
"Error fetching data",
|
|
62
|
-
"Authorization error. Contact your organization admin for support.",
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return render(
|
|
67
|
-
"Error fetching data",
|
|
68
|
-
"An unknown error occurred. If the problem continues, contact the site owner.",
|
|
69
|
-
);
|
|
70
|
-
}
|
package/src/lib/icon-panel.tsx
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Flex, FlexProps } from "@radix-ui/themes";
|
|
2
|
-
import { forwardRef } from "react";
|
|
3
|
-
|
|
4
|
-
export const IconPanel = forwardRef<HTMLDivElement, FlexProps>(
|
|
5
|
-
function IconPanel({ children, ...props }, ref) {
|
|
6
|
-
return (
|
|
7
|
-
<Flex
|
|
8
|
-
ref={ref}
|
|
9
|
-
width="32px"
|
|
10
|
-
height="32px"
|
|
11
|
-
align="center"
|
|
12
|
-
justify="center"
|
|
13
|
-
style={{
|
|
14
|
-
borderWidth: 1,
|
|
15
|
-
borderStyle: "solid",
|
|
16
|
-
borderColor: "var(--gray-4)",
|
|
17
|
-
borderRadius: "var(--radius-3)",
|
|
18
|
-
backgroundColor: "var(--gray-2)",
|
|
19
|
-
}}
|
|
20
|
-
{...props}
|
|
21
|
-
>
|
|
22
|
-
{children}
|
|
23
|
-
</Flex>
|
|
24
|
-
);
|
|
25
|
-
},
|
|
26
|
-
);
|
package/src/lib/icons.tsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { SVGProps } from "react";
|
|
2
|
-
|
|
3
|
-
export function PasskeyIcon(props: SVGProps<SVGSVGElement>) {
|
|
4
|
-
return (
|
|
5
|
-
<svg
|
|
6
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
-
width={16}
|
|
8
|
-
height={16}
|
|
9
|
-
viewBox="0 0 16 16"
|
|
10
|
-
fill="none"
|
|
11
|
-
{...props}
|
|
12
|
-
>
|
|
13
|
-
<path
|
|
14
|
-
fill="currentColor"
|
|
15
|
-
fillRule="evenodd"
|
|
16
|
-
d="M5.86 1.005a2.86 2.86 0 1 0 0 5.719 2.86 2.86 0 0 0 0-5.72ZM2 3.865a3.86 3.86 0 1 1 4.899 3.717c.974.166 1.699.58 2.368 1.196a.5.5 0 1 1-.678.735C7.882 8.862 7.136 8.5 5.859 8.5c-2.036 0-3.195.693-3.867 1.613-.602.824-.86 1.893-.917 2.986h8.618a.5.5 0 0 1 0 1H.563a.5.5 0 0 1-.5-.5c0-1.356.248-2.88 1.121-4.076.743-1.018 1.897-1.741 3.582-1.957A3.861 3.861 0 0 1 2 3.864Zm12.185 6.509a2.892 2.892 0 1 0-2.212-.024v4.428L13.197 16l2.036-2.037-1.271-1.27 1.271-1.272-1.046-1.047Zm-.212-3.423a.847.847 0 1 1-1.695 0 .847.847 0 0 1 1.695 0Z"
|
|
17
|
-
clipRule="evenodd"
|
|
18
|
-
/>
|
|
19
|
-
</svg>
|
|
20
|
-
);
|
|
21
|
-
}
|