@workos-inc/widgets 1.7.2 → 1.8.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 (214) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/cjs/api/endpoint.cjs +1 -0
  3. package/dist/cjs/api/endpoint.cjs.map +1 -1
  4. package/dist/cjs/api/endpoint.d.cts +1 -0
  5. package/dist/cjs/index.cjs +5 -2
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/index.d.cts +1 -0
  8. package/dist/cjs/lib/add-mfa-dialog.cjs +133 -61
  9. package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
  10. package/dist/cjs/lib/admin-portal-domain-verification.cjs +41 -5
  11. package/dist/cjs/lib/admin-portal-domain-verification.cjs.map +1 -1
  12. package/dist/cjs/lib/admin-portal-sso-connection.cjs +121 -44
  13. package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
  14. package/dist/cjs/lib/api-keys/api-key-details-card.cjs +25 -3
  15. package/dist/cjs/lib/api-keys/api-key-details-card.cjs.map +1 -1
  16. package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs +25 -3
  17. package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs.map +1 -1
  18. package/dist/cjs/lib/api-keys/api-keys-search.cjs +13 -4
  19. package/dist/cjs/lib/api-keys/api-keys-search.cjs.map +1 -1
  20. package/dist/cjs/lib/api-keys/api-keys-table.cjs +94 -12
  21. package/dist/cjs/lib/api-keys/api-keys-table.cjs.map +1 -1
  22. package/dist/cjs/lib/api-keys/api-keys.cjs +16 -2
  23. package/dist/cjs/lib/api-keys/api-keys.cjs.map +1 -1
  24. package/dist/cjs/lib/api-keys/create-api-key.cjs +172 -20
  25. package/dist/cjs/lib/api-keys/create-api-key.cjs.map +1 -1
  26. package/dist/cjs/lib/api-keys/relative-time.cjs +12 -2
  27. package/dist/cjs/lib/api-keys/relative-time.cjs.map +1 -1
  28. package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs +49 -7
  29. package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs.map +1 -1
  30. package/dist/cjs/lib/change-password-dialog.cjs +122 -16
  31. package/dist/cjs/lib/change-password-dialog.cjs.map +1 -1
  32. package/dist/cjs/lib/copy-button.cjs +14 -2
  33. package/dist/cjs/lib/copy-button.cjs.map +1 -1
  34. package/dist/cjs/lib/copy-button.d.cts +2 -1
  35. package/dist/cjs/lib/delete-domain-dialog.cjs +52 -19
  36. package/dist/cjs/lib/delete-domain-dialog.cjs.map +1 -1
  37. package/dist/cjs/lib/delete-user-dialog.cjs +46 -11
  38. package/dist/cjs/lib/delete-user-dialog.cjs.map +1 -1
  39. package/dist/cjs/lib/delete-user-dialog.d.cts +2 -2
  40. package/dist/cjs/lib/domain-actions.cjs +51 -7
  41. package/dist/cjs/lib/domain-actions.cjs.map +1 -1
  42. package/dist/cjs/lib/domain-item.cjs +42 -8
  43. package/dist/cjs/lib/domain-item.cjs.map +1 -1
  44. package/dist/cjs/lib/edit-user-profile-dialog.cjs +62 -11
  45. package/dist/cjs/lib/edit-user-profile-dialog.cjs.map +1 -1
  46. package/dist/cjs/lib/edit-user-role-dialog.cjs +90 -17
  47. package/dist/cjs/lib/edit-user-role-dialog.cjs.map +1 -1
  48. package/dist/cjs/lib/elements.cjs +14 -3
  49. package/dist/cjs/lib/elements.cjs.map +1 -1
  50. package/dist/cjs/lib/elements.d.cts +5 -2
  51. package/dist/cjs/lib/elevated-access.cjs +78 -18
  52. package/dist/cjs/lib/elevated-access.cjs.map +1 -1
  53. package/dist/cjs/lib/generic-error.cjs +53 -11
  54. package/dist/cjs/lib/generic-error.cjs.map +1 -1
  55. package/dist/cjs/lib/generic-error.d.cts +5 -1
  56. package/dist/cjs/lib/i18n/intl-context.cjs +47 -0
  57. package/dist/cjs/lib/i18n/intl-context.cjs.map +1 -0
  58. package/dist/cjs/lib/i18n/intl-context.d.cts +29 -0
  59. package/dist/cjs/lib/i18n/translation.cjs +67 -0
  60. package/dist/cjs/lib/i18n/translation.cjs.map +1 -0
  61. package/dist/cjs/lib/i18n/translation.d.cts +16 -0
  62. package/dist/cjs/lib/i18n/use-locale.cjs +33 -0
  63. package/dist/cjs/lib/i18n/use-locale.cjs.map +1 -0
  64. package/dist/cjs/lib/i18n/use-locale.d.cts +7 -0
  65. package/dist/cjs/lib/i18n/use-translation.cjs +47 -0
  66. package/dist/cjs/lib/i18n/use-translation.cjs.map +1 -0
  67. package/dist/cjs/lib/i18n/use-translation.d.cts +15 -0
  68. package/dist/cjs/lib/identity-providers.d.cts +1 -1
  69. package/dist/cjs/lib/invite-user-dialog.cjs +69 -14
  70. package/dist/cjs/lib/invite-user-dialog.cjs.map +1 -1
  71. package/dist/cjs/lib/logout-all-sessions-dialog.cjs +33 -4
  72. package/dist/cjs/lib/logout-all-sessions-dialog.cjs.map +1 -1
  73. package/dist/cjs/lib/logout-dialog.cjs +34 -10
  74. package/dist/cjs/lib/logout-dialog.cjs.map +1 -1
  75. package/dist/cjs/lib/organization-switcher.cjs +12 -2
  76. package/dist/cjs/lib/organization-switcher.cjs.map +1 -1
  77. package/dist/cjs/lib/pipes.cjs +175 -36
  78. package/dist/cjs/lib/pipes.cjs.map +1 -1
  79. package/dist/cjs/lib/resend-invite-dialog.cjs +67 -17
  80. package/dist/cjs/lib/resend-invite-dialog.cjs.map +1 -1
  81. package/dist/cjs/lib/reset-mfa-dialog.cjs +50 -7
  82. package/dist/cjs/lib/reset-mfa-dialog.cjs.map +1 -1
  83. package/dist/cjs/lib/revoke-invite-dialog.cjs +42 -10
  84. package/dist/cjs/lib/revoke-invite-dialog.cjs.map +1 -1
  85. package/dist/cjs/lib/save-button.cjs +9 -1
  86. package/dist/cjs/lib/save-button.cjs.map +1 -1
  87. package/dist/cjs/lib/set-password-dialog.cjs +101 -13
  88. package/dist/cjs/lib/set-password-dialog.cjs.map +1 -1
  89. package/dist/cjs/lib/user-actions-dropdown.cjs +54 -6
  90. package/dist/cjs/lib/user-actions-dropdown.cjs.map +1 -1
  91. package/dist/cjs/lib/user-profile.cjs +81 -10
  92. package/dist/cjs/lib/user-profile.cjs.map +1 -1
  93. package/dist/cjs/lib/user-security.cjs +127 -25
  94. package/dist/cjs/lib/user-security.cjs.map +1 -1
  95. package/dist/cjs/lib/user-sessions.cjs +74 -15
  96. package/dist/cjs/lib/user-sessions.cjs.map +1 -1
  97. package/dist/cjs/lib/users-management.cjs +265 -49
  98. package/dist/cjs/lib/users-management.cjs.map +1 -1
  99. package/dist/cjs/lib/users-search.cjs +18 -4
  100. package/dist/cjs/lib/users-search.cjs.map +1 -1
  101. package/dist/cjs/lib/utils.cjs +10 -7
  102. package/dist/cjs/lib/utils.cjs.map +1 -1
  103. package/dist/cjs/lib/utils.d.cts +2 -1
  104. package/dist/cjs/lib/view-dns-record-dialog.cjs +89 -18
  105. package/dist/cjs/lib/view-dns-record-dialog.cjs.map +1 -1
  106. package/dist/cjs/workos-widgets.client.cjs +2 -2
  107. package/dist/cjs/workos-widgets.client.cjs.map +1 -1
  108. package/dist/esm/api/endpoint.d.ts +1 -0
  109. package/dist/esm/api/endpoint.js +1 -0
  110. package/dist/esm/api/endpoint.js.map +1 -1
  111. package/dist/esm/index.d.ts +1 -0
  112. package/dist/esm/index.js +3 -1
  113. package/dist/esm/index.js.map +1 -1
  114. package/dist/esm/lib/add-mfa-dialog.js +133 -61
  115. package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
  116. package/dist/esm/lib/admin-portal-domain-verification.js +41 -5
  117. package/dist/esm/lib/admin-portal-domain-verification.js.map +1 -1
  118. package/dist/esm/lib/admin-portal-sso-connection.js +121 -44
  119. package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
  120. package/dist/esm/lib/api-keys/api-key-details-card.js +25 -3
  121. package/dist/esm/lib/api-keys/api-key-details-card.js.map +1 -1
  122. package/dist/esm/lib/api-keys/api-key-details-dialog.js +25 -3
  123. package/dist/esm/lib/api-keys/api-key-details-dialog.js.map +1 -1
  124. package/dist/esm/lib/api-keys/api-keys-search.js +13 -4
  125. package/dist/esm/lib/api-keys/api-keys-search.js.map +1 -1
  126. package/dist/esm/lib/api-keys/api-keys-table.js +94 -12
  127. package/dist/esm/lib/api-keys/api-keys-table.js.map +1 -1
  128. package/dist/esm/lib/api-keys/api-keys.js +16 -2
  129. package/dist/esm/lib/api-keys/api-keys.js.map +1 -1
  130. package/dist/esm/lib/api-keys/create-api-key.js +172 -20
  131. package/dist/esm/lib/api-keys/create-api-key.js.map +1 -1
  132. package/dist/esm/lib/api-keys/relative-time.js +12 -2
  133. package/dist/esm/lib/api-keys/relative-time.js.map +1 -1
  134. package/dist/esm/lib/api-keys/revoke-api-key-dialog.js +49 -7
  135. package/dist/esm/lib/api-keys/revoke-api-key-dialog.js.map +1 -1
  136. package/dist/esm/lib/change-password-dialog.js +122 -16
  137. package/dist/esm/lib/change-password-dialog.js.map +1 -1
  138. package/dist/esm/lib/copy-button.d.ts +2 -1
  139. package/dist/esm/lib/copy-button.js +14 -2
  140. package/dist/esm/lib/copy-button.js.map +1 -1
  141. package/dist/esm/lib/delete-domain-dialog.js +52 -19
  142. package/dist/esm/lib/delete-domain-dialog.js.map +1 -1
  143. package/dist/esm/lib/delete-user-dialog.d.ts +2 -2
  144. package/dist/esm/lib/delete-user-dialog.js +36 -11
  145. package/dist/esm/lib/delete-user-dialog.js.map +1 -1
  146. package/dist/esm/lib/domain-actions.js +41 -7
  147. package/dist/esm/lib/domain-actions.js.map +1 -1
  148. package/dist/esm/lib/domain-item.js +42 -8
  149. package/dist/esm/lib/domain-item.js.map +1 -1
  150. package/dist/esm/lib/edit-user-profile-dialog.js +62 -11
  151. package/dist/esm/lib/edit-user-profile-dialog.js.map +1 -1
  152. package/dist/esm/lib/edit-user-role-dialog.js +90 -17
  153. package/dist/esm/lib/edit-user-role-dialog.js.map +1 -1
  154. package/dist/esm/lib/elements.d.ts +5 -2
  155. package/dist/esm/lib/elements.js +14 -3
  156. package/dist/esm/lib/elements.js.map +1 -1
  157. package/dist/esm/lib/elevated-access.js +78 -18
  158. package/dist/esm/lib/elevated-access.js.map +1 -1
  159. package/dist/esm/lib/generic-error.d.ts +5 -1
  160. package/dist/esm/lib/generic-error.js +53 -11
  161. package/dist/esm/lib/generic-error.js.map +1 -1
  162. package/dist/esm/lib/i18n/intl-context.d.ts +29 -0
  163. package/dist/esm/lib/i18n/intl-context.js +12 -0
  164. package/dist/esm/lib/i18n/intl-context.js.map +1 -0
  165. package/dist/esm/lib/i18n/translation.d.ts +16 -0
  166. package/dist/esm/lib/i18n/translation.js +45 -0
  167. package/dist/esm/lib/i18n/translation.js.map +1 -0
  168. package/dist/esm/lib/i18n/use-locale.d.ts +7 -0
  169. package/dist/esm/lib/i18n/use-locale.js +9 -0
  170. package/dist/esm/lib/i18n/use-locale.js.map +1 -0
  171. package/dist/esm/lib/i18n/use-translation.d.ts +15 -0
  172. package/dist/esm/lib/i18n/use-translation.js +23 -0
  173. package/dist/esm/lib/i18n/use-translation.js.map +1 -0
  174. package/dist/esm/lib/identity-providers.d.ts +1 -1
  175. package/dist/esm/lib/invite-user-dialog.js +70 -15
  176. package/dist/esm/lib/invite-user-dialog.js.map +1 -1
  177. package/dist/esm/lib/logout-all-sessions-dialog.js +33 -4
  178. package/dist/esm/lib/logout-all-sessions-dialog.js.map +1 -1
  179. package/dist/esm/lib/logout-dialog.js +34 -10
  180. package/dist/esm/lib/logout-dialog.js.map +1 -1
  181. package/dist/esm/lib/organization-switcher.js +12 -2
  182. package/dist/esm/lib/organization-switcher.js.map +1 -1
  183. package/dist/esm/lib/pipes.js +175 -36
  184. package/dist/esm/lib/pipes.js.map +1 -1
  185. package/dist/esm/lib/resend-invite-dialog.js +67 -17
  186. package/dist/esm/lib/resend-invite-dialog.js.map +1 -1
  187. package/dist/esm/lib/reset-mfa-dialog.js +50 -7
  188. package/dist/esm/lib/reset-mfa-dialog.js.map +1 -1
  189. package/dist/esm/lib/revoke-invite-dialog.js +42 -10
  190. package/dist/esm/lib/revoke-invite-dialog.js.map +1 -1
  191. package/dist/esm/lib/save-button.js +9 -1
  192. package/dist/esm/lib/save-button.js.map +1 -1
  193. package/dist/esm/lib/set-password-dialog.js +101 -13
  194. package/dist/esm/lib/set-password-dialog.js.map +1 -1
  195. package/dist/esm/lib/user-actions-dropdown.js +54 -6
  196. package/dist/esm/lib/user-actions-dropdown.js.map +1 -1
  197. package/dist/esm/lib/user-profile.js +81 -10
  198. package/dist/esm/lib/user-profile.js.map +1 -1
  199. package/dist/esm/lib/user-security.js +127 -25
  200. package/dist/esm/lib/user-security.js.map +1 -1
  201. package/dist/esm/lib/user-sessions.js +74 -15
  202. package/dist/esm/lib/user-sessions.js.map +1 -1
  203. package/dist/esm/lib/users-management.js +266 -51
  204. package/dist/esm/lib/users-management.js.map +1 -1
  205. package/dist/esm/lib/users-search.js +18 -4
  206. package/dist/esm/lib/users-search.js.map +1 -1
  207. package/dist/esm/lib/utils.d.ts +2 -1
  208. package/dist/esm/lib/utils.js +10 -7
  209. package/dist/esm/lib/utils.js.map +1 -1
  210. package/dist/esm/lib/view-dns-record-dialog.js +89 -18
  211. package/dist/esm/lib/view-dns-record-dialog.js.map +1 -1
  212. package/dist/esm/workos-widgets.client.js +2 -2
  213. package/dist/esm/workos-widgets.client.js.map +1 -1
  214. package/package.json +11 -2
@@ -6,6 +6,7 @@ import { useElevatedAccessToken } from "../api/api-provider.js";
6
6
  import { useEffect, useRef, useState } from "react";
7
7
  import { AlertDialog, Dialog, Button } from "./elements.js";
8
8
  import * as Otp from "./otp-input.js";
9
+ import { Translation } from "./i18n/translation.js";
9
10
  function ElevatedAccess({
10
11
  type = "dialog",
11
12
  children,
@@ -65,13 +66,32 @@ function SendVerificationEmailForm({
65
66
  sendVerification.mutate();
66
67
  };
67
68
  return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
68
- /* @__PURE__ */ jsx(Title, { children: hasTokenExpired ? "Your verification token has expired" : "Verify your identity" }),
69
- /* @__PURE__ */ jsxs(Description, { color: "gray", mb: "5", children: [
70
- "To continue, we need to confirm your identity. We'll send a temporary verification code to",
71
- " ",
72
- /* @__PURE__ */ jsx(Text, { weight: "bold", highContrast: true, children: me?.email }),
73
- "."
74
- ] }),
69
+ /* @__PURE__ */ jsx(Title, { children: hasTokenExpired ? /* @__PURE__ */ jsx(
70
+ Translation,
71
+ {
72
+ defaultMessage: "Your verification token has expired",
73
+ id: "lb/AsC",
74
+ description: "Dialog title when verification token has expired"
75
+ }
76
+ ) : /* @__PURE__ */ jsx(
77
+ Translation,
78
+ {
79
+ defaultMessage: "Verify your identity",
80
+ id: "7tGCOh",
81
+ description: "Dialog title for identity verification"
82
+ }
83
+ ) }),
84
+ /* @__PURE__ */ jsx(Description, { color: "gray", mb: "5", children: /* @__PURE__ */ jsx(
85
+ Translation,
86
+ {
87
+ defaultMessage: "To continue, we need to confirm your identity. We'll send a temporary verification code to {email}.",
88
+ id: "FTUSRM",
89
+ description: "Description explaining verification code will be sent",
90
+ values: {
91
+ email: /* @__PURE__ */ jsx(Text, { weight: "bold", highContrast: true, children: me?.email })
92
+ }
93
+ }
94
+ ) }),
75
95
  sendVerification.error && /* @__PURE__ */ jsx(Callout.Root, { color: "red", mt: "-2", mb: "0", children: /* @__PURE__ */ jsx(Callout.Text, { children: getMutationErrorMessage(sendVerification.error) }) }),
76
96
  /* @__PURE__ */ jsxs(Flex, { justify: "end", align: "center", gap: "3", mt: "5", children: [
77
97
  /* @__PURE__ */ jsx(Close, { children: /* @__PURE__ */ jsx(
@@ -80,10 +100,24 @@ function SendVerificationEmailForm({
80
100
  variant: "secondary",
81
101
  type: "button",
82
102
  disabled: sendVerification.isPending,
83
- children: "Cancel"
103
+ children: /* @__PURE__ */ jsx(
104
+ Translation,
105
+ {
106
+ defaultMessage: "Cancel",
107
+ id: "hHNj31",
108
+ description: "Cancel button text"
109
+ }
110
+ )
84
111
  }
85
112
  ) }),
86
- /* @__PURE__ */ jsx(Button, { type: "submit", loading: sendVerification.isPending, children: "Send verification code" })
113
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading: sendVerification.isPending, children: /* @__PURE__ */ jsx(
114
+ Translation,
115
+ {
116
+ defaultMessage: "Send verification code",
117
+ id: "XsTeXJ",
118
+ description: "Button text to send verification code"
119
+ }
120
+ ) })
87
121
  ] })
88
122
  ] });
89
123
  }
@@ -127,13 +161,25 @@ function VerificationIdentityForm({
127
161
  setIsSubmitting(false);
128
162
  };
129
163
  return /* @__PURE__ */ jsxs(Form.Root, { onSubmit: handleSubmit, children: [
130
- /* @__PURE__ */ jsx(Title, { children: "Verify your identity" }),
131
- /* @__PURE__ */ jsxs(Description, { color: "gray", children: [
132
- "A verification code was sent to",
133
- " ",
134
- /* @__PURE__ */ jsx(Text, { weight: "bold", highContrast: true, children: me?.email }),
135
- ". Please enter it below."
136
- ] }),
164
+ /* @__PURE__ */ jsx(Title, { children: /* @__PURE__ */ jsx(
165
+ Translation,
166
+ {
167
+ defaultMessage: "Verify your identity",
168
+ id: "7tGCOh",
169
+ description: "Dialog title for identity verification"
170
+ }
171
+ ) }),
172
+ /* @__PURE__ */ jsx(Description, { color: "gray", children: /* @__PURE__ */ jsx(
173
+ Translation,
174
+ {
175
+ defaultMessage: "A verification code was sent to {email}. Please enter it below.",
176
+ id: "kvxE0S",
177
+ description: "Description explaining where verification code was sent",
178
+ values: {
179
+ email: /* @__PURE__ */ jsx(Text, { weight: "bold", highContrast: true, children: me?.email })
180
+ }
181
+ }
182
+ ) }),
137
183
  /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", mt: "5", mx: "auto", width: "fit-content", children: [
138
184
  /* @__PURE__ */ jsxs(
139
185
  Otp.Root,
@@ -159,8 +205,22 @@ function VerificationIdentityForm({
159
205
  verifyIdentity.error && /* @__PURE__ */ jsx(Text, { color: "red", size: "2", as: "p", children: getMutationErrorMessage(verifyIdentity.error) })
160
206
  ] }),
161
207
  /* @__PURE__ */ jsxs(Flex, { justify: "end", align: "center", gap: "3", mt: "5", children: [
162
- /* @__PURE__ */ jsx(Close, { children: /* @__PURE__ */ jsx(Button, { variant: "secondary", type: "button", children: "Cancel" }) }),
163
- /* @__PURE__ */ jsx(Button, { type: "submit", loading: isSubmitting, children: "Confirm" })
208
+ /* @__PURE__ */ jsx(Close, { children: /* @__PURE__ */ jsx(Button, { variant: "secondary", type: "button", children: /* @__PURE__ */ jsx(
209
+ Translation,
210
+ {
211
+ defaultMessage: "Cancel",
212
+ id: "hHNj31",
213
+ description: "Cancel button text"
214
+ }
215
+ ) }) }),
216
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading: isSubmitting, children: /* @__PURE__ */ jsx(
217
+ Translation,
218
+ {
219
+ defaultMessage: "Confirm",
220
+ id: "EmYENK",
221
+ description: "Confirm button text for verification"
222
+ }
223
+ ) })
164
224
  ] })
165
225
  ] });
166
226
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/elevated-access.tsx"],"sourcesContent":["import * as Form from \"@radix-ui/react-form\";\nimport { Callout, Flex, Text } from \"@radix-ui/themes\";\nimport { useMe, useSendVerification, useVerify } from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { PropsWithChildren, useEffect, useRef, useState } from \"react\";\nimport { AlertDialog, Dialog, Button } from \"./elements.js\";\nimport * as Otp from \"./otp-input.js\";\n\ninterface ElevatedAccessProps extends PropsWithChildren {\n onVerified?: () => Promise<unknown>;\n type?: \"dialog\" | \"alert\";\n}\n\nexport function ElevatedAccess({\n type = \"dialog\",\n children,\n onVerified,\n}: ElevatedAccessProps) {\n const { elevatedAccess } = useElevatedAccessToken();\n const [authenticationChallengeId, setAuthenticationChallengeId] =\n useState<string>();\n\n const prevAccessToken = useRef(elevatedAccess);\n\n useEffect(() => {\n prevAccessToken.current = elevatedAccess;\n }, [elevatedAccess]);\n\n if (elevatedAccess) {\n return <>{children}</>;\n }\n\n if (!authenticationChallengeId) {\n // FIXME: This should be refactored\n // eslint-disable-next-line react-hooks/refs\n const hasTokenExpired = !!prevAccessToken.current;\n\n return (\n <SendVerificationEmailForm\n type={type}\n hasTokenExpired={hasTokenExpired}\n onSuccess={(challengeId) => {\n setAuthenticationChallengeId(challengeId);\n }}\n />\n );\n }\n\n if (authenticationChallengeId) {\n return (\n <VerificationIdentityForm\n type={type}\n authenticationChallengeId={authenticationChallengeId}\n onSuccess={() => {\n // Reset the challenge id\n setAuthenticationChallengeId(undefined);\n\n return onVerified?.();\n }}\n />\n );\n }\n\n return null;\n}\n\ninterface SendVerificationEmailFormProps {\n onSuccess: (challengeId: string) => unknown | Promise<unknown>;\n type: \"dialog\" | \"alert\";\n hasTokenExpired: boolean;\n}\n\nfunction SendVerificationEmailForm({\n onSuccess,\n type,\n hasTokenExpired,\n}: SendVerificationEmailFormProps) {\n const { data: me } = useMe();\n const sendVerification = useSendVerification({\n mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },\n });\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n sendVerification.mutate();\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Title>\n {hasTokenExpired\n ? \"Your verification token has expired\"\n : \"Verify your identity\"}\n </Title>\n\n <Description color=\"gray\" mb=\"5\">\n To continue, we need to confirm your identity. We'll send a temporary\n verification code to{\" \"}\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n .\n </Description>\n\n {sendVerification.error && (\n <Callout.Root color=\"red\" mt=\"-2\" mb=\"0\">\n <Callout.Text>\n {getMutationErrorMessage(sendVerification.error)}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={sendVerification.isPending}\n >\n Cancel\n </Button>\n </Close>\n <Button type=\"submit\" loading={sendVerification.isPending}>\n Send verification code\n </Button>\n </Flex>\n </form>\n );\n}\n\ninterface VerificationIdentityFormProps {\n onSuccess?: () => unknown | Promise<unknown>;\n authenticationChallengeId: string;\n type: \"dialog\" | \"alert\";\n}\n\nfunction VerificationIdentityForm({\n onSuccess,\n authenticationChallengeId,\n type,\n}: VerificationIdentityFormProps) {\n const { data: me } = useMe();\n const { setElevatedAccess } = useElevatedAccessToken();\n const verifyIdentity = useVerify();\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const code = formData.get(\"otp-code\")?.toString() ?? \"\";\n\n setIsSubmitting(true);\n\n try {\n // Mutate async so we can wait for the onSuccess callback as well\n const newAuthState = await verifyIdentity.mutateAsync({\n data: {\n code,\n authenticationChallengeId,\n },\n });\n\n const in10Seconds = new Date(Date.now() + 5 * 1000);\n\n setElevatedAccess({\n token: newAuthState.elevatedAccessToken,\n // expiresAt: newAuthState.expiresAt,\n expiresAt: in10Seconds.toISOString(),\n });\n\n if (onSuccess) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n await onSuccess();\n }\n } catch (error) {\n console.error(error);\n }\n\n setIsSubmitting(false);\n };\n\n return (\n <Form.Root onSubmit={handleSubmit}>\n <Title>Verify your identity</Title>\n\n <Description color=\"gray\">\n A verification code was sent to{\" \"}\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n . Please enter it below.\n </Description>\n\n <Flex direction=\"column\" gap=\"2\" mt=\"5\" mx=\"auto\" width=\"fit-content\">\n <Otp.Root\n autoSubmit\n gap=\"2\"\n justify=\"center\"\n columns=\"repeat(6, 48px)\"\n width=\"fit-content\"\n rows=\"48px\"\n name=\"otp-code\"\n readOnly={isSubmitting}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {verifyIdentity.error && (\n <Text color=\"red\" size=\"2\" as=\"p\">\n {getMutationErrorMessage(verifyIdentity.error)}\n </Text>\n )}\n </Flex>\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button variant=\"secondary\" type=\"button\">\n Cancel\n </Button>\n </Close>\n <Button type=\"submit\" loading={isSubmitting}>\n Confirm\n </Button>\n </Flex>\n </Form.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = typeof error === \"string\" ? error : \"\";\n\n if (error instanceof Error) {\n message = error.message;\n } else if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (!message || message === \"Bad Request\") {\n message = \"Invalid code, please try again.\";\n }\n\n return message;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/elevated-access.tsx"],"sourcesContent":["import * as Form from \"@radix-ui/react-form\";\nimport { Callout, Flex, Text } from \"@radix-ui/themes\";\nimport { useMe, useSendVerification, useVerify } from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { PropsWithChildren, useEffect, useRef, useState } from \"react\";\nimport { AlertDialog, Dialog, Button } from \"./elements.js\";\nimport * as Otp from \"./otp-input.js\";\nimport { Translation } from \"./i18n/translation.js\";\n\ninterface ElevatedAccessProps extends PropsWithChildren {\n onVerified?: () => Promise<unknown>;\n type?: \"dialog\" | \"alert\";\n}\n\nexport function ElevatedAccess({\n type = \"dialog\",\n children,\n onVerified,\n}: ElevatedAccessProps) {\n const { elevatedAccess } = useElevatedAccessToken();\n const [authenticationChallengeId, setAuthenticationChallengeId] =\n useState<string>();\n\n const prevAccessToken = useRef(elevatedAccess);\n\n useEffect(() => {\n prevAccessToken.current = elevatedAccess;\n }, [elevatedAccess]);\n\n if (elevatedAccess) {\n return <>{children}</>;\n }\n\n if (!authenticationChallengeId) {\n // FIXME: This should be refactored\n // eslint-disable-next-line react-hooks/refs\n const hasTokenExpired = !!prevAccessToken.current;\n\n return (\n <SendVerificationEmailForm\n type={type}\n hasTokenExpired={hasTokenExpired}\n onSuccess={(challengeId) => {\n setAuthenticationChallengeId(challengeId);\n }}\n />\n );\n }\n\n if (authenticationChallengeId) {\n return (\n <VerificationIdentityForm\n type={type}\n authenticationChallengeId={authenticationChallengeId}\n onSuccess={() => {\n // Reset the challenge id\n setAuthenticationChallengeId(undefined);\n\n return onVerified?.();\n }}\n />\n );\n }\n\n return null;\n}\n\ninterface SendVerificationEmailFormProps {\n onSuccess: (challengeId: string) => unknown | Promise<unknown>;\n type: \"dialog\" | \"alert\";\n hasTokenExpired: boolean;\n}\n\nfunction SendVerificationEmailForm({\n onSuccess,\n type,\n hasTokenExpired,\n}: SendVerificationEmailFormProps) {\n const { data: me } = useMe();\n const sendVerification = useSendVerification({\n mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },\n });\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n sendVerification.mutate();\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Title>\n {hasTokenExpired ? (\n <Translation\n defaultMessage=\"Your verification token has expired\"\n id=\"lb/AsC\"\n description=\"Dialog title when verification token has expired\"\n />\n ) : (\n <Translation\n defaultMessage=\"Verify your identity\"\n id=\"7tGCOh\"\n description=\"Dialog title for identity verification\"\n />\n )}\n </Title>\n\n <Description color=\"gray\" mb=\"5\">\n <Translation\n defaultMessage=\"To continue, we need to confirm your identity. We'll send a temporary verification code to {email}.\"\n id=\"FTUSRM\"\n description=\"Description explaining verification code will be sent\"\n values={{\n email: (\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n ),\n }}\n />\n </Description>\n\n {sendVerification.error && (\n <Callout.Root color=\"red\" mt=\"-2\" mb=\"0\">\n <Callout.Text>\n {getMutationErrorMessage(sendVerification.error)}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={sendVerification.isPending}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Close>\n <Button type=\"submit\" loading={sendVerification.isPending}>\n <Translation\n defaultMessage=\"Send verification code\"\n id=\"XsTeXJ\"\n description=\"Button text to send verification code\"\n />\n </Button>\n </Flex>\n </form>\n );\n}\n\ninterface VerificationIdentityFormProps {\n onSuccess?: () => unknown | Promise<unknown>;\n authenticationChallengeId: string;\n type: \"dialog\" | \"alert\";\n}\n\nfunction VerificationIdentityForm({\n onSuccess,\n authenticationChallengeId,\n type,\n}: VerificationIdentityFormProps) {\n const { data: me } = useMe();\n const { setElevatedAccess } = useElevatedAccessToken();\n const verifyIdentity = useVerify();\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const code = formData.get(\"otp-code\")?.toString() ?? \"\";\n\n setIsSubmitting(true);\n\n try {\n // Mutate async so we can wait for the onSuccess callback as well\n const newAuthState = await verifyIdentity.mutateAsync({\n data: {\n code,\n authenticationChallengeId,\n },\n });\n\n const in10Seconds = new Date(Date.now() + 5 * 1000);\n\n setElevatedAccess({\n token: newAuthState.elevatedAccessToken,\n // expiresAt: newAuthState.expiresAt,\n expiresAt: in10Seconds.toISOString(),\n });\n\n if (onSuccess) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n await onSuccess();\n }\n } catch (error) {\n console.error(error);\n }\n\n setIsSubmitting(false);\n };\n\n return (\n <Form.Root onSubmit={handleSubmit}>\n <Title>\n <Translation\n defaultMessage=\"Verify your identity\"\n id=\"7tGCOh\"\n description=\"Dialog title for identity verification\"\n />\n </Title>\n\n <Description color=\"gray\">\n <Translation\n defaultMessage=\"A verification code was sent to {email}. Please enter it below.\"\n id=\"kvxE0S\"\n description=\"Description explaining where verification code was sent\"\n values={{\n email: (\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n ),\n }}\n />\n </Description>\n\n <Flex direction=\"column\" gap=\"2\" mt=\"5\" mx=\"auto\" width=\"fit-content\">\n <Otp.Root\n autoSubmit\n gap=\"2\"\n justify=\"center\"\n columns=\"repeat(6, 48px)\"\n width=\"fit-content\"\n rows=\"48px\"\n name=\"otp-code\"\n readOnly={isSubmitting}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {verifyIdentity.error && (\n <Text color=\"red\" size=\"2\" as=\"p\">\n {getMutationErrorMessage(verifyIdentity.error)}\n </Text>\n )}\n </Flex>\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button variant=\"secondary\" type=\"button\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Close>\n <Button type=\"submit\" loading={isSubmitting}>\n <Translation\n defaultMessage=\"Confirm\"\n id=\"EmYENK\"\n description=\"Confirm button text for verification\"\n />\n </Button>\n </Flex>\n </Form.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = typeof error === \"string\" ? error : \"\";\n\n if (error instanceof Error) {\n message = error.message;\n } else if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (!message || message === \"Bad Request\") {\n message = \"Invalid code, please try again.\";\n }\n\n return message;\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they are displayed dynamically\n"],"mappings":"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","names":[]}
@@ -6,7 +6,11 @@ type GenericErrorProps = React.ComponentProps<typeof Flex> & {
6
6
  error: unknown;
7
7
  };
8
8
  declare function GenericError({ error, ...domProps }: GenericErrorProps): react_jsx_runtime.JSX.Element;
9
- declare function getErrorMessage(error: unknown): {
9
+ declare function getErrorMessage(error: unknown, translate: ({ defaultMessage, description, id, }: {
10
+ defaultMessage: string;
11
+ description: string;
12
+ id: string;
13
+ }) => string): {
10
14
  heading: string;
11
15
  message: string;
12
16
  };
@@ -7,11 +7,14 @@ import {
7
7
  NoAuthTokenError
8
8
  } from "./errors.js";
9
9
  import { Cross2Icon } from "@radix-ui/react-icons";
10
+ import { Translation } from "./i18n/translation.js";
11
+ import { useTranslation } from "./i18n/use-translation.js";
10
12
  function GenericError({ error, ...domProps }) {
13
+ const translate = useTranslation();
11
14
  React.useEffect(() => {
12
15
  console.error(error);
13
16
  }, [error]);
14
- const { heading, message } = getErrorMessage(error);
17
+ const { message } = getErrorMessage(error, translate);
15
18
  return /* @__PURE__ */ jsxs(
16
19
  Flex,
17
20
  {
@@ -38,35 +41,74 @@ function GenericError({ error, ...domProps }) {
38
41
  }
39
42
  ),
40
43
  /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "1", maxWidth: "420px", children: [
41
- /* @__PURE__ */ jsx(Heading, { size: "5", align: "center", mb: "1", wrap: "balance", as: "h3", children: heading }),
44
+ /* @__PURE__ */ jsx(Heading, { size: "5", align: "center", mb: "1", wrap: "balance", as: "h3", children: /* @__PURE__ */ jsx(
45
+ Translation,
46
+ {
47
+ defaultMessage: "Error fetching data",
48
+ id: "mjZ9vq",
49
+ description: "Error heading shown when there is a network or authorization error"
50
+ }
51
+ ) }),
42
52
  /* @__PURE__ */ jsx(Text, { as: "p", align: "center", wrap: "balance", color: "gray", children: message })
43
53
  ] })
44
54
  ]
45
55
  }
46
56
  );
47
57
  }
48
- function getErrorMessage(error) {
58
+ function getErrorMessage(error, translate) {
49
59
  if (error instanceof FetchError) {
50
60
  return {
51
- heading: "Error fetching data",
52
- message: "An error occurred. You may need to configure CORS in the WorkOS Dashboard."
61
+ heading: translate({
62
+ defaultMessage: "Error fetching data",
63
+ description: "Error message heading",
64
+ id: "5QzKdW"
65
+ }),
66
+ message: translate({
67
+ defaultMessage: "An error occurred. You may need to configure CORS in the WorkOS Dashboard.",
68
+ description: "Error message details",
69
+ id: "63rRud"
70
+ })
53
71
  };
54
72
  }
55
73
  if (error instanceof NoAuthTokenError) {
56
74
  return {
57
- heading: "Authorization error",
58
- message: "You likely forgot to provide an authorization token to the widget."
75
+ heading: translate({
76
+ defaultMessage: "Authorization error",
77
+ description: "Error message heading",
78
+ id: "s/dQVI"
79
+ }),
80
+ message: translate({
81
+ defaultMessage: "You likely forgot to provide an authorization token to the widget.",
82
+ description: "Error message details",
83
+ id: "d7mvgq"
84
+ })
59
85
  };
60
86
  }
61
87
  if (error instanceof IncorrectPermissionsError) {
62
88
  return {
63
- heading: "Incorrect permissions",
64
- message: "Check that the correct permissions have been assigned."
89
+ heading: translate({
90
+ defaultMessage: "Incorrect permissions",
91
+ description: "Error message heading",
92
+ id: "dFmPj3"
93
+ }),
94
+ message: translate({
95
+ defaultMessage: "Check that the correct permissions have been assigned.",
96
+ description: "Error message details",
97
+ id: "hd/Llp"
98
+ })
65
99
  };
66
100
  }
67
101
  return {
68
- heading: "Error fetching data",
69
- message: "An unexpected error occurred. Check your network connection or try refreshing the page."
102
+ heading: translate({
103
+ defaultMessage: "Error fetching data",
104
+ description: "Error message heading",
105
+ id: "5QzKdW"
106
+ }),
107
+ message: translate({
108
+ defaultMessage: "An unexpected error occurred. Check your network connection or try refreshing the page.",
109
+ description: "Error message details",
110
+ id: "t+CDVJ"
111
+ })
70
112
  };
71
113
  }
72
114
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/generic-error.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Flex, Heading, Text } from \"@radix-ui/themes\";\nimport {\n FetchError,\n IncorrectPermissionsError,\n NoAuthTokenError,\n} from \"./errors.js\";\nimport { Cross2Icon } from \"@radix-ui/react-icons\";\n\ntype GenericErrorProps = React.ComponentProps<typeof Flex> & {\n error: unknown;\n};\n\nexport function GenericError({ error, ...domProps }: GenericErrorProps) {\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const { heading, message } = getErrorMessage(error);\n return (\n <Flex\n p=\"6\"\n justify=\"center\"\n align=\"center\"\n direction=\"column\"\n {...domProps}\n >\n <Flex\n align=\"center\"\n justify=\"center\"\n width=\"32px\"\n height=\"32px\"\n mb=\"2\"\n style={{\n borderRadius: \"9999px\",\n backgroundColor: \"var(--red-a4)\",\n color: \"var(--red-a11)\",\n }}\n >\n <Cross2Icon width=\"24px\" height=\"24px\" />\n </Flex>\n\n <Flex direction=\"column\" gap=\"1\" maxWidth=\"420px\">\n <Heading size=\"5\" align=\"center\" mb=\"1\" wrap=\"balance\" as=\"h3\">\n {heading}\n </Heading>\n <Text as=\"p\" align=\"center\" wrap=\"balance\" color=\"gray\">\n {message}\n </Text>\n </Flex>\n </Flex>\n );\n}\n\nexport function getErrorMessage(error: unknown) {\n if (error instanceof FetchError) {\n return {\n heading: \"Error fetching data\",\n message:\n \"An error occurred. You may need to configure CORS in the WorkOS Dashboard.\",\n };\n }\n\n if (error instanceof NoAuthTokenError) {\n return {\n heading: \"Authorization error\",\n message:\n \"You likely forgot to provide an authorization token to the widget.\",\n };\n }\n\n if (error instanceof IncorrectPermissionsError) {\n return {\n heading: \"Incorrect permissions\",\n message: \"Check that the correct permissions have been assigned.\",\n };\n }\n\n return {\n heading: \"Error fetching data\",\n message:\n \"An unexpected error occurred. Check your network connection or try refreshing the page.\",\n };\n}\n"],"mappings":"AAuCQ,cAGF,YAHE;AAvCR,YAAY,WAAW;AACvB,SAAS,MAAM,SAAS,YAAY;AACpC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAMpB,SAAS,aAAa,EAAE,OAAO,GAAG,SAAS,GAAsB;AACtE,QAAM,UAAU,MAAM;AACpB,YAAQ,MAAM,KAAK;AAAA,EACrB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,EAAE,SAAS,QAAQ,IAAI,gBAAgB,KAAK;AAClD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,GAAE;AAAA,MACF,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,WAAU;AAAA,MACT,GAAG;AAAA,MAEJ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,SAAQ;AAAA,YACR,OAAM;AAAA,YACN,QAAO;AAAA,YACP,IAAG;AAAA,YACH,OAAO;AAAA,cACL,cAAc;AAAA,cACd,iBAAiB;AAAA,cACjB,OAAO;AAAA,YACT;AAAA,YAEA,8BAAC,cAAW,OAAM,QAAO,QAAO,QAAO;AAAA;AAAA,QACzC;AAAA,QAEA,qBAAC,QAAK,WAAU,UAAS,KAAI,KAAI,UAAS,SACxC;AAAA,8BAAC,WAAQ,MAAK,KAAI,OAAM,UAAS,IAAG,KAAI,MAAK,WAAU,IAAG,MACvD,mBACH;AAAA,UACA,oBAAC,QAAK,IAAG,KAAI,OAAM,UAAS,MAAK,WAAU,OAAM,QAC9C,mBACH;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,gBAAgB,OAAgB;AAC9C,MAAI,iBAAiB,YAAY;AAC/B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SACE;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,iBAAiB,kBAAkB;AACrC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SACE;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,iBAAiB,2BAA2B;AAC9C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SACE;AAAA,EACJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/generic-error.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Flex, Heading, Text } from \"@radix-ui/themes\";\nimport {\n FetchError,\n IncorrectPermissionsError,\n NoAuthTokenError,\n} from \"./errors.js\";\nimport { Cross2Icon } from \"@radix-ui/react-icons\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ntype GenericErrorProps = React.ComponentProps<typeof Flex> & {\n error: unknown;\n};\n\nexport function GenericError({ error, ...domProps }: GenericErrorProps) {\n const translate = useTranslation();\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const { message } = getErrorMessage(error, translate);\n return (\n <Flex\n p=\"6\"\n justify=\"center\"\n align=\"center\"\n direction=\"column\"\n {...domProps}\n >\n <Flex\n align=\"center\"\n justify=\"center\"\n width=\"32px\"\n height=\"32px\"\n mb=\"2\"\n style={{\n borderRadius: \"9999px\",\n backgroundColor: \"var(--red-a4)\",\n color: \"var(--red-a11)\",\n }}\n >\n <Cross2Icon width=\"24px\" height=\"24px\" />\n </Flex>\n\n <Flex direction=\"column\" gap=\"1\" maxWidth=\"420px\">\n <Heading size=\"5\" align=\"center\" mb=\"1\" wrap=\"balance\" as=\"h3\">\n <Translation\n defaultMessage=\"Error fetching data\"\n id=\"mjZ9vq\"\n description=\"Error heading shown when there is a network or authorization error\"\n />\n </Heading>\n <Text as=\"p\" align=\"center\" wrap=\"balance\" color=\"gray\">\n {message}\n </Text>\n </Flex>\n </Flex>\n );\n}\n\nexport function getErrorMessage(\n error: unknown,\n translate: ({\n defaultMessage,\n description,\n id,\n }: {\n defaultMessage: string;\n description: string;\n id: string;\n }) => string,\n) {\n if (error instanceof FetchError) {\n return {\n heading: translate({\n defaultMessage: \"Error fetching data\",\n description: \"Error message heading\",\n id: \"5QzKdW\",\n }),\n message: translate({\n defaultMessage:\n \"An error occurred. You may need to configure CORS in the WorkOS Dashboard.\",\n description: \"Error message details\",\n id: \"63rRud\",\n }),\n };\n }\n\n if (error instanceof NoAuthTokenError) {\n return {\n heading: translate({\n defaultMessage: \"Authorization error\",\n description: \"Error message heading\",\n id: \"s/dQVI\",\n }),\n message: translate({\n defaultMessage:\n \"You likely forgot to provide an authorization token to the widget.\",\n description: \"Error message details\",\n id: \"d7mvgq\",\n }),\n };\n }\n\n if (error instanceof IncorrectPermissionsError) {\n return {\n heading: translate({\n defaultMessage: \"Incorrect permissions\",\n description: \"Error message heading\",\n id: \"dFmPj3\",\n }),\n message: translate({\n defaultMessage:\n \"Check that the correct permissions have been assigned.\",\n description: \"Error message details\",\n id: \"hd/Llp\",\n }),\n };\n }\n\n return {\n heading: translate({\n defaultMessage: \"Error fetching data\",\n description: \"Error message heading\",\n id: \"5QzKdW\",\n }),\n message: translate({\n defaultMessage:\n \"An unexpected error occurred. Check your network connection or try refreshing the page.\",\n description: \"Error message details\",\n id: \"t+CDVJ\",\n }),\n };\n}\n"],"mappings":"AA0CQ,cAGF,YAHE;AA1CR,YAAY,WAAW;AACvB,SAAS,MAAM,SAAS,YAAY;AACpC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAMxB,SAAS,aAAa,EAAE,OAAO,GAAG,SAAS,GAAsB;AACtE,QAAM,YAAY,eAAe;AACjC,QAAM,UAAU,MAAM;AACpB,YAAQ,MAAM,KAAK;AAAA,EACrB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,EAAE,QAAQ,IAAI,gBAAgB,OAAO,SAAS;AACpD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,GAAE;AAAA,MACF,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,WAAU;AAAA,MACT,GAAG;AAAA,MAEJ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,SAAQ;AAAA,YACR,OAAM;AAAA,YACN,QAAO;AAAA,YACP,IAAG;AAAA,YACH,OAAO;AAAA,cACL,cAAc;AAAA,cACd,iBAAiB;AAAA,cACjB,OAAO;AAAA,YACT;AAAA,YAEA,8BAAC,cAAW,OAAM,QAAO,QAAO,QAAO;AAAA;AAAA,QACzC;AAAA,QAEA,qBAAC,QAAK,WAAU,UAAS,KAAI,KAAI,UAAS,SACxC;AAAA,8BAAC,WAAQ,MAAK,KAAI,OAAM,UAAS,IAAG,KAAI,MAAK,WAAU,IAAG,MACxD;AAAA,YAAC;AAAA;AAAA,cACC,gBAAe;AAAA,cACf,IAAG;AAAA,cACH,aAAY;AAAA;AAAA,UACd,GACF;AAAA,UACA,oBAAC,QAAK,IAAG,KAAI,OAAM,UAAS,MAAK,WAAU,OAAM,QAC9C,mBACH;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,gBACd,OACA,WASA;AACA,MAAI,iBAAiB,YAAY;AAC/B,WAAO;AAAA,MACL,SAAS,UAAU;AAAA,QACjB,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,IAAI;AAAA,MACN,CAAC;AAAA,MACD,SAAS,UAAU;AAAA,QACjB,gBACE;AAAA,QACF,aAAa;AAAA,QACb,IAAI;AAAA,MACN,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,iBAAiB,kBAAkB;AACrC,WAAO;AAAA,MACL,SAAS,UAAU;AAAA,QACjB,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,IAAI;AAAA,MACN,CAAC;AAAA,MACD,SAAS,UAAU;AAAA,QACjB,gBACE;AAAA,QACF,aAAa;AAAA,QACb,IAAI;AAAA,MACN,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,iBAAiB,2BAA2B;AAC9C,WAAO;AAAA,MACL,SAAS,UAAU;AAAA,QACjB,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,IAAI;AAAA,MACN,CAAC;AAAA,MACD,SAAS,UAAU;AAAA,QACjB,gBACE;AAAA,QACF,aAAa;AAAA,QACb,IAAI;AAAA,MACN,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,UAAU;AAAA,MACjB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,IAAI;AAAA,IACN,CAAC;AAAA,IACD,SAAS,UAAU;AAAA,MACjB,gBACE;AAAA,MACF,aAAa;AAAA,MACb,IAAI;AAAA,IACN,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+
3
+ type MessageDescriptor = {
4
+ id: string;
5
+ defaultMessage: string;
6
+ description: string;
7
+ };
8
+ type MessageValues = Record<string, string | React.ReactNode>;
9
+ /**
10
+ * Shape of the i18n context value.
11
+ * This mirrors the essential parts of react-intl's IntlShape without importing it.
12
+ */
13
+ interface IntlContextValue {
14
+ locale: string;
15
+ formatMessage(descriptor: MessageDescriptor, values?: MessageValues): string | React.ReactNode[];
16
+ }
17
+ /**
18
+ * Context for optional i18n support.
19
+ * When this context has a value, translations will use react-intl.
20
+ * When this context is null/undefined, translations will fall back to defaultMessage.
21
+ */
22
+ declare const IntlContext: React.Context<IntlContextValue | null>;
23
+ /**
24
+ * Hook to access the i18n context.
25
+ * Returns null if no IntlProvider is present in the component tree.
26
+ */
27
+ declare function useIntl(): IntlContextValue | null;
28
+
29
+ export { IntlContext, type IntlContextValue, type MessageDescriptor, type MessageValues, useIntl };
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ const IntlContext = React.createContext(null);
4
+ IntlContext.displayName = "IntlContext";
5
+ function useIntl() {
6
+ return React.useContext(IntlContext);
7
+ }
8
+ export {
9
+ IntlContext,
10
+ useIntl
11
+ };
12
+ //# sourceMappingURL=intl-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/i18n/intl-context.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nexport type MessageDescriptor = {\n id: string;\n defaultMessage: string;\n description: string;\n};\n\nexport type MessageValues = Record<string, string | React.ReactNode>;\n\n/**\n * Shape of the i18n context value.\n * This mirrors the essential parts of react-intl's IntlShape without importing it.\n */\nexport interface IntlContextValue {\n locale: string;\n formatMessage(\n descriptor: MessageDescriptor,\n values?: MessageValues,\n ): string | React.ReactNode[];\n}\n\n/**\n * Context for optional i18n support.\n * When this context has a value, translations will use react-intl.\n * When this context is null/undefined, translations will fall back to defaultMessage.\n */\nexport const IntlContext = React.createContext<IntlContextValue | null>(null);\nIntlContext.displayName = \"IntlContext\";\n\n/**\n * Hook to access the i18n context.\n * Returns null if no IntlProvider is present in the component tree.\n */\nexport function useIntl(): IntlContextValue | null {\n return React.useContext(IntlContext);\n}\n"],"mappings":";AAEA,YAAY,WAAW;AA2BhB,MAAM,cAAc,MAAM,cAAuC,IAAI;AAC5E,YAAY,cAAc;AAMnB,SAAS,UAAmC;AACjD,SAAO,MAAM,WAAW,WAAW;AACrC;","names":[]}
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import { MessageDescriptor, MessageValues } from './intl-context.js';
3
+
4
+ type TranslationProps = MessageDescriptor & {
5
+ trailingSpace?: boolean;
6
+ values?: MessageValues;
7
+ };
8
+ /**
9
+ * Translation component that gracefully degrades when no I18nProvider is present.
10
+ *
11
+ * - With I18nProvider: Uses react-intl for full i18n support (react-intl will be bundled)
12
+ * - Without I18nProvider: Renders the defaultMessage with simple value interpolation (no react-intl bundled)
13
+ */
14
+ declare const Translation: React.FC<TranslationProps>;
15
+
16
+ export { Translation };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { Fragment, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ useIntl
5
+ } from "./intl-context.js";
6
+ const Translation = (props) => {
7
+ const { defaultMessage, id, description, trailingSpace, values } = props;
8
+ const i18n = useIntl();
9
+ if (i18n) {
10
+ const str = i18n.formatMessage({ id, defaultMessage, description }, values);
11
+ return trailingSpace ? /* @__PURE__ */ jsxs(Fragment, { children: [
12
+ str,
13
+ " "
14
+ ] }) : str;
15
+ }
16
+ if (!values) {
17
+ return trailingSpace ? /* @__PURE__ */ jsxs(Fragment, { children: [
18
+ defaultMessage,
19
+ " "
20
+ ] }) : defaultMessage;
21
+ }
22
+ const parts = [];
23
+ let lastIndex = 0;
24
+ const regex = /\{(\w+)\}/g;
25
+ let match;
26
+ while ((match = regex.exec(defaultMessage)) !== null) {
27
+ const [placeholder, key] = match;
28
+ if (match.index > lastIndex) {
29
+ parts.push(defaultMessage.substring(lastIndex, match.index));
30
+ }
31
+ parts.push(values[key] ?? placeholder);
32
+ lastIndex = match.index + placeholder.length;
33
+ }
34
+ if (lastIndex < defaultMessage.length) {
35
+ parts.push(defaultMessage.substring(lastIndex));
36
+ }
37
+ return trailingSpace ? /* @__PURE__ */ jsxs(Fragment, { children: [
38
+ parts,
39
+ " "
40
+ ] }) : parts;
41
+ };
42
+ export {
43
+ Translation
44
+ };
45
+ //# sourceMappingURL=translation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/i18n/translation.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n useIntl,\n type MessageDescriptor,\n type MessageValues,\n} from \"./intl-context.js\";\n\ntype TranslationProps = MessageDescriptor & {\n trailingSpace?: boolean;\n values?: MessageValues;\n};\n\n/**\n * Translation component that gracefully degrades when no I18nProvider is present.\n *\n * - With I18nProvider: Uses react-intl for full i18n support (react-intl will be bundled)\n * - Without I18nProvider: Renders the defaultMessage with simple value interpolation (no react-intl bundled)\n */\nexport const Translation: React.FC<TranslationProps> = (props) => {\n const { defaultMessage, id, description, trailingSpace, values } = props;\n const i18n = useIntl();\n\n // If I18nProvider is present, use react-intl's formatting\n if (i18n) {\n const str = i18n.formatMessage({ id, defaultMessage, description }, values);\n return trailingSpace ? <>{str} </> : str;\n }\n\n // If no I18nProvider is present, render the defaultMessage with simple interpolation\n if (!values) {\n return trailingSpace ? <>{defaultMessage} </> : defaultMessage;\n }\n\n // Simple interpolation: split by placeholders and interleave with values\n const parts: React.ReactNode[] = [];\n let lastIndex = 0;\n const regex = /\\{(\\w+)\\}/g;\n let match;\n\n while ((match = regex.exec(defaultMessage)) !== null) {\n const [placeholder, key] = match;\n\n // Add text before the placeholder\n if (match.index > lastIndex) {\n parts.push(defaultMessage.substring(lastIndex, match.index));\n }\n\n // Add the interpolated value or placeholder if not found\n parts.push(values[key] ?? placeholder);\n lastIndex = match.index + placeholder.length;\n }\n\n // Add remaining text\n if (lastIndex < defaultMessage.length) {\n parts.push(defaultMessage.substring(lastIndex));\n }\n\n return trailingSpace ? <>{parts} </> : parts;\n};\n"],"mappings":";AA2B2B;AAxB3B;AAAA,EACE;AAAA,OAGK;AAaA,MAAM,cAA0C,CAAC,UAAU;AAChE,QAAM,EAAE,gBAAgB,IAAI,aAAa,eAAe,OAAO,IAAI;AACnE,QAAM,OAAO,QAAQ;AAGrB,MAAI,MAAM;AACR,UAAM,MAAM,KAAK,cAAc,EAAE,IAAI,gBAAgB,YAAY,GAAG,MAAM;AAC1E,WAAO,gBAAgB,iCAAG;AAAA;AAAA,MAAI;AAAA,OAAC,IAAM;AAAA,EACvC;AAGA,MAAI,CAAC,QAAQ;AACX,WAAO,gBAAgB,iCAAG;AAAA;AAAA,MAAe;AAAA,OAAC,IAAM;AAAA,EAClD;AAGA,QAAM,QAA2B,CAAC;AAClC,MAAI,YAAY;AAChB,QAAM,QAAQ;AACd,MAAI;AAEJ,UAAQ,QAAQ,MAAM,KAAK,cAAc,OAAO,MAAM;AACpD,UAAM,CAAC,aAAa,GAAG,IAAI;AAG3B,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,KAAK,eAAe,UAAU,WAAW,MAAM,KAAK,CAAC;AAAA,IAC7D;AAGA,UAAM,KAAK,OAAO,GAAG,KAAK,WAAW;AACrC,gBAAY,MAAM,QAAQ,YAAY;AAAA,EACxC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,KAAK,eAAe,UAAU,SAAS,CAAC;AAAA,EAChD;AAEA,SAAO,gBAAgB,iCAAG;AAAA;AAAA,IAAM;AAAA,KAAC,IAAM;AACzC;","names":[]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Hook to get the current locale.
3
+ * Returns the locale from IntlContext if available, otherwise falls back to "en-US".
4
+ */
5
+ declare function useLocale(): string;
6
+
7
+ export { useLocale };
@@ -0,0 +1,9 @@
1
+ import { useIntl } from "./intl-context.js";
2
+ function useLocale() {
3
+ const intl = useIntl();
4
+ return intl?.locale ?? "en-US";
5
+ }
6
+ export {
7
+ useLocale
8
+ };
9
+ //# sourceMappingURL=use-locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/i18n/use-locale.ts"],"sourcesContent":["import { useIntl } from \"./intl-context.js\";\n\n/**\n * Hook to get the current locale.\n * Returns the locale from IntlContext if available, otherwise falls back to \"en-US\".\n */\nexport function useLocale(): string {\n const intl = useIntl();\n return intl?.locale ?? \"en-US\";\n}\n"],"mappings":"AAAA,SAAS,eAAe;AAMjB,SAAS,YAAoB;AAClC,QAAM,OAAO,QAAQ;AACrB,SAAO,MAAM,UAAU;AACzB;","names":[]}
@@ -0,0 +1,15 @@
1
+ import { MessageDescriptor } from './intl-context.js';
2
+ import 'react';
3
+
4
+ type TranslationParams = MessageDescriptor & {
5
+ values?: Record<string, string>;
6
+ };
7
+ /**
8
+ * Translation hook that gracefully degrades when no I18nProvider is present.
9
+ *
10
+ * - With I18nProvider: Uses react-intl's formatMessage for full i18n support (react-intl will be bundled)
11
+ * - Without I18nProvider: Returns the defaultMessage with simple string interpolation (no react-intl bundled)
12
+ */
13
+ declare function useTranslation(): (params: TranslationParams) => string;
14
+
15
+ export { useTranslation };
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { useIntl } from "./intl-context.js";
3
+ function useTranslation() {
4
+ const i18n = useIntl();
5
+ return (params) => {
6
+ const { defaultMessage, description, id, values } = params;
7
+ if (i18n) {
8
+ return String(
9
+ i18n.formatMessage({ id, defaultMessage, description }, values)
10
+ );
11
+ }
12
+ if (!values) {
13
+ return defaultMessage;
14
+ }
15
+ return defaultMessage.replace(/\{(\w+)\}/g, (match, key) => {
16
+ return key in values ? String(values[key]) : match;
17
+ });
18
+ };
19
+ }
20
+ export {
21
+ useTranslation
22
+ };
23
+ //# sourceMappingURL=use-translation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/i18n/use-translation.ts"],"sourcesContent":["\"use client\";\n\nimport { useIntl, type MessageDescriptor } from \"./intl-context.js\";\n\ntype TranslationParams = MessageDescriptor & {\n values?: Record<string, string>;\n};\n\n/**\n * Translation hook that gracefully degrades when no I18nProvider is present.\n *\n * - With I18nProvider: Uses react-intl's formatMessage for full i18n support (react-intl will be bundled)\n * - Without I18nProvider: Returns the defaultMessage with simple string interpolation (no react-intl bundled)\n */\nexport function useTranslation() {\n const i18n = useIntl();\n\n return (params: TranslationParams): string => {\n const { defaultMessage, description, id, values } = params;\n\n // If I18nProvider is present, use react-intl's formatMessage\n if (i18n) {\n // TODO: Do we really want to cast this to a string?\n return String(\n i18n.formatMessage({ id, defaultMessage, description }, values),\n );\n }\n\n // If no I18nProvider is present, return defaultMessage with simple interpolation\n if (!values) {\n return defaultMessage;\n }\n\n // Simple string interpolation for values\n return defaultMessage.replace(/\\{(\\w+)\\}/g, (match, key) => {\n return key in values ? String(values[key]) : match;\n });\n };\n}\n"],"mappings":";AAEA,SAAS,eAAuC;AAYzC,SAAS,iBAAiB;AAC/B,QAAM,OAAO,QAAQ;AAErB,SAAO,CAAC,WAAsC;AAC5C,UAAM,EAAE,gBAAgB,aAAa,IAAI,OAAO,IAAI;AAGpD,QAAI,MAAM;AAER,aAAO;AAAA,QACL,KAAK,cAAc,EAAE,IAAI,gBAAgB,YAAY,GAAG,MAAM;AAAA,MAChE;AAAA,IACF;AAGA,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAGA,WAAO,eAAe,QAAQ,cAAc,CAAC,OAAO,QAAQ;AAC1D,aAAO,OAAO,SAAS,OAAO,OAAO,GAAG,CAAC,IAAI;AAAA,IAC/C,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -1,4 +1,4 @@
1
- declare const IDENTITY_PROVIDER_DICT: Map<"asana" | "box" | "dropbox" | "github" | "gitlab" | "google" | "google-calendar" | "google-drive" | "hubspot" | "intercom" | "linear" | "microsoft" | "notion" | "salesforce" | "slack" | "stripe" | "zendesk" | "azure" | "access-people-hr" | "adp" | "apple" | "auth0" | "aws" | "bamboohr" | "bamboo-hr" | "bitbucket" | "breathe-hr" | "bubble" | "cas" | "cezanne-hr" | "classlink" | "clerk" | "cloudflare" | "cyberark" | "datadog" | "duo" | "firebase" | "fourth" | "generic-saml" | "generic-oidc" | "godaddy" | "google-analytics" | "google-mail" | "google-cloud" | "hibob" | "intuit" | "jumpcloud" | "keycloak" | "lastpass" | "linkedin" | "login-gov" | "miniorange" | "net-iq" | "next-auth" | "okta" | "onelogin" | "oracle" | "personio" | "ping-identity" | "react-native-expo" | "rippling" | "segment" | "shibboleth" | "simple-saml-php" | "splunk" | "supabase" | "vercel" | "vmware" | "workday" | "workos" | "xero" | "test-idp" | "discord" | "clever", "GoDaddy" | "Access People HR" | "ADP" | "Apple" | "Asana" | "Auth0" | "Azure" | "AWS" | "BambooHR" | "Bitbucket" | "Box" | "BreatheHR" | "Bubble" | "CAS" | "Cezanne HR" | "Classlink" | "Clerk" | "Cloudflare" | "CyberArk" | "Datadog" | "Dropbox" | "Duo" | "Firebase" | "Fourth" | "Generic SAML" | "Generic OIDC" | "GitHub" | "GitLab" | "Google" | "Google Analytics" | "Google Calendar" | "Google Drive" | "Google Mail" | "Google Cloud" | "Hibob" | "Hubspot" | "Intercom" | "Intuit" | "JumpCloud" | "Keycloak" | "LastPass" | "Linear" | "LinkedIn" | "Login.gov" | "Microsoft" | "Miniorange" | "NetIQ" | "NextAuth" | "Notion" | "Okta" | "OneLogin" | "Oracle" | "Personio" | "Ping Identity" | "React Native Expo" | "Rippling" | "Salesforce" | "Segment" | "Shibboleth" | "Simple SAML PHP" | "Slack" | "Splunk" | "Stripe" | "Supabase" | "Vercel" | "VMware" | "Workday" | "WorkOS" | "Xero" | "Zendesk" | "Test IDP" | "Discord" | "Clever">;
1
+ declare const IDENTITY_PROVIDER_DICT: Map<"asana" | "box" | "dropbox" | "github" | "gitlab" | "google" | "google-calendar" | "google-drive" | "hubspot" | "intercom" | "linear" | "microsoft" | "notion" | "salesforce" | "slack" | "stripe" | "xero" | "zendesk" | "azure" | "access-people-hr" | "adp" | "apple" | "auth0" | "aws" | "bamboohr" | "bamboo-hr" | "bitbucket" | "breathe-hr" | "bubble" | "cas" | "cezanne-hr" | "classlink" | "clerk" | "cloudflare" | "cyberark" | "datadog" | "duo" | "firebase" | "fourth" | "generic-saml" | "generic-oidc" | "godaddy" | "google-analytics" | "google-mail" | "google-cloud" | "hibob" | "intuit" | "jumpcloud" | "keycloak" | "lastpass" | "linkedin" | "login-gov" | "miniorange" | "net-iq" | "next-auth" | "okta" | "onelogin" | "oracle" | "personio" | "ping-identity" | "react-native-expo" | "rippling" | "segment" | "shibboleth" | "simple-saml-php" | "splunk" | "supabase" | "vercel" | "vmware" | "workday" | "workos" | "test-idp" | "discord" | "clever", "GoDaddy" | "Access People HR" | "ADP" | "Apple" | "Asana" | "Auth0" | "Azure" | "AWS" | "BambooHR" | "Bitbucket" | "Box" | "BreatheHR" | "Bubble" | "CAS" | "Cezanne HR" | "Classlink" | "Clerk" | "Cloudflare" | "CyberArk" | "Datadog" | "Dropbox" | "Duo" | "Firebase" | "Fourth" | "Generic SAML" | "Generic OIDC" | "GitHub" | "GitLab" | "Google" | "Google Analytics" | "Google Calendar" | "Google Drive" | "Google Mail" | "Google Cloud" | "Hibob" | "Hubspot" | "Intercom" | "Intuit" | "JumpCloud" | "Keycloak" | "LastPass" | "Linear" | "LinkedIn" | "Login.gov" | "Microsoft" | "Miniorange" | "NetIQ" | "NextAuth" | "Notion" | "Okta" | "OneLogin" | "Oracle" | "Personio" | "Ping Identity" | "React Native Expo" | "Rippling" | "Salesforce" | "Segment" | "Shibboleth" | "Simple SAML PHP" | "Slack" | "Splunk" | "Stripe" | "Supabase" | "Vercel" | "VMware" | "Workday" | "WorkOS" | "Xero" | "Zendesk" | "Test IDP" | "Discord" | "Clever">;
2
2
  type MapKey<T extends Map<unknown, unknown>> = T extends Map<infer K, unknown> ? K : never;
3
3
  type IdentityProvider = MapKey<typeof IDENTITY_PROVIDER_DICT>;
4
4
  declare function getIdentityProviderName(provider: IdentityProvider): "GoDaddy" | "Access People HR" | "ADP" | "Apple" | "Asana" | "Auth0" | "Azure" | "AWS" | "BambooHR" | "Bitbucket" | "Box" | "BreatheHR" | "Bubble" | "CAS" | "Cezanne HR" | "Classlink" | "Clerk" | "Cloudflare" | "CyberArk" | "Datadog" | "Dropbox" | "Duo" | "Firebase" | "Fourth" | "Generic SAML" | "Generic OIDC" | "GitHub" | "GitLab" | "Google" | "Google Analytics" | "Google Calendar" | "Google Drive" | "Google Mail" | "Google Cloud" | "Hibob" | "Hubspot" | "Intercom" | "Intuit" | "JumpCloud" | "Keycloak" | "LastPass" | "Linear" | "LinkedIn" | "Login.gov" | "Microsoft" | "Miniorange" | "NetIQ" | "NextAuth" | "Notion" | "Okta" | "OneLogin" | "Oracle" | "Personio" | "Ping Identity" | "React Native Expo" | "Rippling" | "Salesforce" | "Segment" | "Shibboleth" | "Simple SAML PHP" | "Slack" | "Splunk" | "Stripe" | "Supabase" | "Vercel" | "VMware" | "Workday" | "WorkOS" | "Xero" | "Zendesk" | "Test IDP" | "Discord" | "Clever" | undefined;