@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
@@ -1,157 +0,0 @@
1
- "use client";
2
-
3
- import { DropdownMenu } from "@radix-ui/themes";
4
- import * as React from "react";
5
- import { Member } from "../api";
6
- import { DeleteUserDialog } from "./delete-user-dialog";
7
- import { EditUserRoleDialog } from "./edit-user-role-dialog";
8
- import {
9
- DestructiveMenuItem,
10
- DropdownMenuContent,
11
- PrimaryMenuItem,
12
- } from "./elements";
13
- import { ResendInviteDialog } from "./resend-invite-dialog";
14
- import { RevokeInviteDialog } from "./revoke-invite-dialog";
15
- import { useRoles } from "../api";
16
-
17
- interface UserActionsDropdownProps {
18
- user: Member;
19
- children: React.ReactNode;
20
- }
21
-
22
- type UserActionDialog =
23
- | "revoke-membership"
24
- | "revoke-invite"
25
- | "resend-invite"
26
- | "edit-role";
27
-
28
- export const UserActionsDropdown = ({
29
- user,
30
- children,
31
- }: UserActionsDropdownProps) => {
32
- const rolesQuery = useRoles({
33
- query: {
34
- initialData: [],
35
- },
36
- });
37
- const [openDialog, setOpenDialog] = React.useState<UserActionDialog | null>(
38
- null,
39
- );
40
-
41
- /**
42
- * Assigns a key for each dialog based on its open state to ensure its
43
- * internal state is cleared when it is closed.
44
- */
45
- function getDialogKey(dialog: UserActionDialog) {
46
- return `${dialog}-${openDialog === dialog}-${user.id}`;
47
- }
48
-
49
- const { actions, items } = React.useMemo(() => {
50
- const actions = new Set(user.actions);
51
- const items: React.ReactElement[] = [];
52
- if (actions.has("edit-role")) {
53
- items.push(
54
- <PrimaryMenuItem
55
- key="edit-role"
56
- onSelect={() => setOpenDialog("edit-role")}
57
- disabled={
58
- rolesQuery.isLoading ||
59
- (rolesQuery.isSuccess && rolesQuery.data.length <= 1)
60
- }
61
- title={
62
- rolesQuery.isSuccess && rolesQuery.data.length <= 1
63
- ? "You cannot update the role for this user as there is only one role available."
64
- : undefined
65
- }
66
- >
67
- Edit role
68
- </PrimaryMenuItem>,
69
- );
70
- }
71
- if (actions.has("resend-invite")) {
72
- items.push(
73
- <PrimaryMenuItem
74
- key="resend-invite"
75
- onSelect={() => setOpenDialog("resend-invite")}
76
- >
77
- Resend invitation
78
- </PrimaryMenuItem>,
79
- );
80
- }
81
- if (actions.has("revoke-invite")) {
82
- items.push(
83
- <DestructiveMenuItem
84
- key="revoke-invite"
85
- onSelect={() => setOpenDialog("revoke-invite")}
86
- >
87
- Revoke invitation
88
- </DestructiveMenuItem>,
89
- );
90
- }
91
- if (actions.has("revoke-membership")) {
92
- items.push(
93
- <DestructiveMenuItem
94
- key="revoke-membership"
95
- onSelect={() => setOpenDialog("revoke-membership")}
96
- >
97
- Remove user
98
- </DestructiveMenuItem>,
99
- );
100
- }
101
- return {
102
- actions,
103
- items,
104
- };
105
- }, [rolesQuery, user.actions]);
106
-
107
- if (user.isLoggedInUser || items.length === 0) {
108
- return null;
109
- }
110
-
111
- return (
112
- <>
113
- <DropdownMenu.Root>
114
- <DropdownMenu.Trigger>{children}</DropdownMenu.Trigger>
115
- <DropdownMenuContent size="2" align="end">
116
- {items}
117
- </DropdownMenuContent>
118
- </DropdownMenu.Root>
119
-
120
- {actions.has("edit-role") && (
121
- <EditUserRoleDialog
122
- key={getDialogKey("edit-role")}
123
- user={user}
124
- open={openDialog === "edit-role"}
125
- onOpenChange={(open) => !open && setOpenDialog(null)}
126
- />
127
- )}
128
-
129
- {actions.has("revoke-membership") && (
130
- <DeleteUserDialog
131
- key={getDialogKey("revoke-membership")}
132
- user={user}
133
- open={openDialog === "revoke-membership"}
134
- onOpenChange={(open) => !open && setOpenDialog(null)}
135
- />
136
- )}
137
-
138
- {actions.has("revoke-invite") && (
139
- <RevokeInviteDialog
140
- key={getDialogKey("revoke-invite")}
141
- user={user}
142
- open={openDialog === "revoke-invite"}
143
- onOpenChange={(open) => !open && setOpenDialog(null)}
144
- />
145
- )}
146
-
147
- {actions.has("resend-invite") && (
148
- <ResendInviteDialog
149
- key={getDialogKey("resend-invite")}
150
- user={user}
151
- open={openDialog === "resend-invite"}
152
- onOpenChange={(open) => !open && setOpenDialog(null)}
153
- />
154
- )}
155
- </>
156
- );
157
- };
@@ -1,227 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- Box,
5
- Card,
6
- DataList,
7
- Flex,
8
- Inset,
9
- Separator,
10
- Strong,
11
- Text,
12
- } from "@radix-ui/themes";
13
- import clsx from "clsx";
14
- import { Avatar, SecondaryButton, Skeleton } from "./elements";
15
- import { Me } from "../api";
16
- import { EditUserProfileDialog } from "./edit-user-profile-dialog";
17
- import { getBestName } from "./utils";
18
- import { getOAuthIcon, getOAuthName } from "./oauth-icons";
19
- import { GenericError } from "./generic-error";
20
-
21
- interface UserProfileProps {
22
- userData: Me;
23
- }
24
-
25
- export const UserProfile = ({ userData: user }: UserProfileProps) => {
26
- const oauthAccounts = Object.entries(user.oauthProfiles || {});
27
-
28
- return (
29
- <Card
30
- className={clsx("woswidgets-widget")}
31
- data-woswidgets-widget-id="user-profile"
32
- size="2"
33
- >
34
- <DataList.Root>
35
- {user.profilePictureUrl && (
36
- <>
37
- <DataList.Item align="center">
38
- <DataList.Label minWidth="220px" highContrast>
39
- <Strong>Profile picture</Strong>
40
- </DataList.Label>
41
- <DataList.Value>
42
- <Avatar
43
- size="2"
44
- fallback={<FallbackUserIcon />}
45
- src={user.profilePictureUrl}
46
- />
47
- </DataList.Value>
48
- </DataList.Item>
49
-
50
- <ListSeparator />
51
- </>
52
- )}
53
-
54
- <DataList.Item align="center">
55
- <DataList.Label highContrast>
56
- <Strong>Full name</Strong>
57
- </DataList.Label>
58
- <DataList.Value>
59
- <Flex
60
- align="center"
61
- justify="between"
62
- width="100%"
63
- minHeight="var(--space-6)"
64
- >
65
- <Text size="2">
66
- {getBestName(user) || (
67
- <Text
68
- color="gray"
69
- style={{ color: "var(--gray-10)", cursor: "default" }}
70
- >
71
- Not set
72
- </Text>
73
- )}
74
- </Text>
75
-
76
- <EditUserProfileDialog user={user}>
77
- <SecondaryButton>Edit</SecondaryButton>
78
- </EditUserProfileDialog>
79
- </Flex>
80
- </DataList.Value>
81
- </DataList.Item>
82
-
83
- <ListSeparator />
84
-
85
- <DataList.Item align="center">
86
- <DataList.Label highContrast>
87
- <Strong>Email address</Strong>
88
- </DataList.Label>
89
- <DataList.Value>
90
- <Flex align="center" minHeight="var(--space-6)">
91
- <Text size="2">{user.email}</Text>
92
- </Flex>
93
- </DataList.Value>
94
- </DataList.Item>
95
-
96
- {oauthAccounts.length > 0 && (
97
- <>
98
- <ListSeparator />
99
-
100
- <DataList.Item>
101
- <DataList.Label highContrast>
102
- <Strong>Connected accounts</Strong>
103
- </DataList.Label>
104
- <DataList.Value>
105
- <Flex direction="column" gap="2">
106
- {oauthAccounts.map(([account, data]) => (
107
- <OAuthAccount
108
- key={account}
109
- account={account}
110
- email={data?.email}
111
- />
112
- ))}
113
- </Flex>
114
- </DataList.Value>
115
- </DataList.Item>
116
- </>
117
- )}
118
- </DataList.Root>
119
- </Card>
120
- );
121
- };
122
-
123
- export function UserProfileLoading() {
124
- return (
125
- <Card size="2">
126
- <DataList.Root>
127
- <DataList.Item align="center">
128
- <DataList.Label minWidth="220px" highContrast>
129
- <Strong>
130
- <Skeleton>Full name</Skeleton>
131
- </Strong>
132
- </DataList.Label>
133
- <DataList.Value>
134
- <Flex
135
- align="center"
136
- justify="between"
137
- width="100%"
138
- minHeight="var(--space-6)"
139
- >
140
- <Text size="2">
141
- <Skeleton>Full name</Skeleton>
142
- </Text>
143
- </Flex>
144
- </DataList.Value>
145
- </DataList.Item>
146
-
147
- <ListSeparator />
148
-
149
- <DataList.Item align="center">
150
- <DataList.Label highContrast>
151
- <Strong>
152
- <Skeleton>Email address</Skeleton>
153
- </Strong>
154
- </DataList.Label>
155
- <DataList.Value>
156
- <Flex align="center" minHeight="var(--space-6)">
157
- <Text size="2">
158
- <Skeleton>Email address</Skeleton>
159
- </Text>
160
- </Flex>
161
- </DataList.Value>
162
- </DataList.Item>
163
- </DataList.Root>
164
- </Card>
165
- );
166
- }
167
-
168
- export function UserProfileError({ error }: { error: unknown }) {
169
- return (
170
- <Card size="2">
171
- <GenericError error={error} />
172
- </Card>
173
- );
174
- }
175
-
176
- const ListSeparator = () => (
177
- <Box asChild gridColumn="span 2">
178
- <Inset side="x">
179
- <Separator size="4" />
180
- </Inset>
181
- </Box>
182
- );
183
-
184
- const OAuthAccount = ({
185
- account,
186
- email,
187
- }: {
188
- account: string;
189
- email?: string | null;
190
- }) => {
191
- const Icon = getOAuthIcon(account);
192
- const name = getOAuthName(account);
193
-
194
- return (
195
- <Flex align="center" gap="1">
196
- <Icon />
197
-
198
- <Text size="2" ml="1">
199
- {name}
200
- </Text>
201
-
202
- {email && (
203
- <Box display={{ initial: "none", sm: "contents" }}>
204
- <Text size="2" color="gray">
205
-
206
- </Text>
207
- <Text size="2" color="gray">
208
- {email}
209
- </Text>
210
- </Box>
211
- )}
212
- </Flex>
213
- );
214
- };
215
-
216
- const FallbackUserIcon = () => (
217
- <svg
218
- xmlns="http://www.w3.org/2000/svg"
219
- width="20"
220
- height="20"
221
- fill="currentColor"
222
- viewBox="0 0 256 256"
223
- >
224
- <title>User icon</title>
225
- <path d="M229.19,213c-15.81-27.32-40.63-46.49-69.47-54.62a70,70,0,1,0-63.44,0C67.44,166.5,42.62,185.67,26.81,213a6,6,0,1,0,10.38,6C56.4,185.81,90.34,166,128,166s71.6,19.81,90.81,53a6,6,0,1,0,10.38-6ZM70,96a58,58,0,1,1,58,58A58.07,58.07,0,0,1,70,96Z" />
226
- </svg>
227
- );
@@ -1,187 +0,0 @@
1
- "use client";
2
-
3
- import { Card, Flex, Grid, Text } from "@radix-ui/themes";
4
- import clsx from "clsx";
5
- import { SecondaryButton, Skeleton } from "./elements";
6
- import { IconPanel } from "./icon-panel";
7
- import { ButtonIcon, LockClosedIcon } from "@radix-ui/react-icons";
8
- import { SetPasswordDialog } from "./set-password-dialog";
9
- import { ChangePasswordDialog } from "./change-password-dialog";
10
- import { AddMfaDialog } from "./add-mfa-dialog";
11
- import type {
12
- AuthenticationInformationResponseData as AuthenticationSettings,
13
- AuthenticationInformationResponseDataVerificationMethodsPassword as PasswordVerificationMethod,
14
- AuthenticationInformationResponseDataVerificationMethodsMfa as MfaVerificationMethod,
15
- } from "../api";
16
- import { ResetMfaDialog } from "./reset-mfa-dialog";
17
- import * as CardList from "../card-list";
18
- import { GenericError } from "./generic-error";
19
- import { getComparativeReadableDate } from "./utils";
20
-
21
- interface UserSecurityProps {
22
- settings: AuthenticationSettings;
23
- }
24
-
25
- export const UserSecurity = ({ settings }: UserSecurityProps) => {
26
- const passwordSettings = settings.verificationMethods.Password;
27
- const mfaSettings = settings.verificationMethods.Mfa;
28
-
29
- return (
30
- <CardList.Root
31
- className={clsx("woswidgets-widget")}
32
- data-woswidgets-widget-id="user-security"
33
- >
34
- {passwordSettings && (
35
- <CardList.Item>
36
- <PasswordSettings settings={passwordSettings} />
37
- </CardList.Item>
38
- )}
39
-
40
- {mfaSettings && (
41
- <CardList.Item>
42
- <MfaSettings
43
- settings={mfaSettings}
44
- isPasswordSet={!!passwordSettings?.isSetUp}
45
- />
46
- </CardList.Item>
47
- )}
48
- </CardList.Root>
49
- );
50
- };
51
-
52
- export function UserSecurityError({ error }: { error: unknown }) {
53
- return (
54
- <Card size="2">
55
- <GenericError error={error} />
56
- </Card>
57
- );
58
- }
59
-
60
- export function UserSecurityLoading() {
61
- return (
62
- <Card size="2">
63
- <Grid columns="auto 1fr auto" align="center" gap="4">
64
- <Skeleton>
65
- <IconPanel />
66
- </Skeleton>
67
-
68
- <Flex direction="column">
69
- <Text size="2" highContrast weight="bold" as="p" mb="-2px">
70
- <Skeleton>Password</Skeleton>
71
- </Text>
72
- <Text as="p" size="2" color="gray">
73
- <Skeleton>Set a password to access your account</Skeleton>
74
- </Text>
75
- </Flex>
76
-
77
- <ChangePasswordDialog>
78
- <Skeleton>
79
- <SecondaryButton>Change</SecondaryButton>
80
- </Skeleton>
81
- </ChangePasswordDialog>
82
- </Grid>
83
- </Card>
84
- );
85
- }
86
-
87
- function PasswordSettings({
88
- settings,
89
- }: {
90
- settings: NonNullable<PasswordVerificationMethod>;
91
- }) {
92
- return (
93
- <Grid columns="auto 1fr auto" align="center" gap="4">
94
- <IconPanel>
95
- <LockClosedIcon />
96
- </IconPanel>
97
-
98
- <Flex direction="column">
99
- <Text size="2" highContrast weight="bold" as="p" mb="-2px">
100
- Password
101
- </Text>
102
-
103
- {settings.isSetUp ? (
104
- settings.lastUsed && (
105
- <Text size="2" color="gray">
106
- Last used{" "}
107
- {getComparativeReadableDate(
108
- new Date(),
109
- new Date(settings.lastUsed),
110
- )}
111
- </Text>
112
- )
113
- ) : (
114
- <Text as="p" size="2" color="gray">
115
- Set a password to access your account
116
- </Text>
117
- )}
118
- </Flex>
119
-
120
- {settings.isSetUp ? (
121
- <ChangePasswordDialog>
122
- <SecondaryButton>Change</SecondaryButton>
123
- </ChangePasswordDialog>
124
- ) : (
125
- <SetPasswordDialog>
126
- <SecondaryButton>Set a password</SecondaryButton>
127
- </SetPasswordDialog>
128
- )}
129
- </Grid>
130
- );
131
- }
132
-
133
- function MfaSettings({
134
- settings,
135
- isPasswordSet,
136
- }: {
137
- settings: NonNullable<MfaVerificationMethod>;
138
- isPasswordSet: boolean;
139
- }) {
140
- return (
141
- <Grid columns="auto 1fr auto" align="center" gap="4">
142
- <IconPanel>
143
- <ButtonIcon />
144
- </IconPanel>
145
-
146
- <Flex direction="column">
147
- <Text size="2" highContrast weight="bold" as="p" mb="-2px">
148
- Multi-factor authentication
149
- </Text>
150
-
151
- {settings.isSetUp ? (
152
- <Text size="2">
153
- Authenticator app
154
- {settings.lastUsed && (
155
- <>
156
- <Text size="2" color="gray" mx="1">
157
-
158
- </Text>
159
- <Text size="2" color="gray">
160
- Last used{" "}
161
- {getComparativeReadableDate(
162
- new Date(),
163
- new Date(settings.lastUsed),
164
- )}
165
- </Text>
166
- </>
167
- )}
168
- </Text>
169
- ) : (
170
- <Text as="p" size="2" color="gray">
171
- Secure your account with an extra verification step
172
- </Text>
173
- )}
174
- </Flex>
175
-
176
- {settings.isSetUp ? (
177
- <ResetMfaDialog isPasswordSet={isPasswordSet}>
178
- <SecondaryButton>Disable</SecondaryButton>
179
- </ResetMfaDialog>
180
- ) : (
181
- <AddMfaDialog>
182
- <SecondaryButton>Set up authenticator app</SecondaryButton>
183
- </AddMfaDialog>
184
- )}
185
- </Grid>
186
- );
187
- }