@workos-inc/widgets 1.8.2 → 1.9.1

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 (113) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/cjs/admin-portal-domain-verification.client.cjs.map +1 -1
  3. package/dist/cjs/admin-portal-sso-connection.client.cjs +4 -7
  4. package/dist/cjs/admin-portal-sso-connection.client.cjs.map +1 -1
  5. package/dist/cjs/api/api-provider.cjs.map +1 -1
  6. package/dist/cjs/api/api-provider.d.cts +1 -1
  7. package/dist/cjs/api/endpoint.cjs +741 -771
  8. package/dist/cjs/api/endpoint.cjs.map +1 -1
  9. package/dist/cjs/api/endpoint.d.cts +860 -813
  10. package/dist/cjs/directory-sync.client.cjs +156 -0
  11. package/dist/cjs/directory-sync.client.cjs.map +1 -0
  12. package/dist/cjs/directory-sync.client.d.cts +26 -0
  13. package/dist/cjs/experimental/api/fetch.cjs +327 -411
  14. package/dist/cjs/experimental/api/fetch.cjs.map +1 -1
  15. package/dist/cjs/experimental/api/fetch.d.cts +832 -798
  16. package/dist/cjs/experimental/api/react-query.cjs +747 -777
  17. package/dist/cjs/experimental/api/react-query.cjs.map +1 -1
  18. package/dist/cjs/experimental/api/react-query.d.cts +1378 -1263
  19. package/dist/cjs/experimental/api/swr.cjs +720 -742
  20. package/dist/cjs/experimental/api/swr.cjs.map +1 -1
  21. package/dist/cjs/experimental/api/swr.d.cts +1218 -1175
  22. package/dist/cjs/index.cjs +5 -0
  23. package/dist/cjs/index.cjs.map +1 -1
  24. package/dist/cjs/index.d.cts +2 -0
  25. package/dist/cjs/lib/add-mfa-dialog.cjs +18 -16
  26. package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
  27. package/dist/cjs/lib/admin-portal-sso-connection.cjs +0 -8
  28. package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
  29. package/dist/cjs/lib/admin-portal-sso-connection.d.cts +1 -2
  30. package/dist/cjs/lib/api-keys/api-keys-context.cjs +1 -1
  31. package/dist/cjs/lib/api-keys/api-keys-context.cjs.map +1 -1
  32. package/dist/cjs/lib/api-keys/api-keys-table.cjs +7 -5
  33. package/dist/cjs/lib/api-keys/api-keys-table.cjs.map +1 -1
  34. package/dist/cjs/lib/directory-sync.cjs +288 -0
  35. package/dist/cjs/lib/directory-sync.cjs.map +1 -0
  36. package/dist/cjs/lib/directory-sync.d.cts +72 -0
  37. package/dist/cjs/lib/identity-providers.cjs +57 -1
  38. package/dist/cjs/lib/identity-providers.cjs.map +1 -1
  39. package/dist/cjs/lib/identity-providers.d.cts +5 -3
  40. package/dist/cjs/lib/pipes.cjs +9 -9
  41. package/dist/cjs/lib/pipes.cjs.map +1 -1
  42. package/dist/cjs/lib/provider-icon.cjs.map +1 -1
  43. package/dist/cjs/lib/provider-icon.d.cts +2 -2
  44. package/dist/cjs/lib/reset-mfa-dialog.cjs +2 -1
  45. package/dist/cjs/lib/reset-mfa-dialog.cjs.map +1 -1
  46. package/dist/cjs/lib/use-permissions.cjs.map +1 -1
  47. package/dist/cjs/lib/use-permissions.d.cts +1 -1
  48. package/dist/cjs/lib/users-management-context.cjs +1 -1
  49. package/dist/cjs/lib/users-management-context.cjs.map +1 -1
  50. package/dist/cjs/lib/users-management.cjs +3 -3
  51. package/dist/cjs/lib/users-management.cjs.map +1 -1
  52. package/dist/cjs/lib/utils.cjs +9 -0
  53. package/dist/cjs/lib/utils.cjs.map +1 -1
  54. package/dist/cjs/lib/utils.d.cts +16 -2
  55. package/dist/cjs/workos-widgets.client.cjs +13 -1
  56. package/dist/cjs/workos-widgets.client.cjs.map +1 -1
  57. package/dist/esm/admin-portal-domain-verification.client.js +2 -2
  58. package/dist/esm/admin-portal-domain-verification.client.js.map +1 -1
  59. package/dist/esm/admin-portal-sso-connection.client.js +6 -9
  60. package/dist/esm/admin-portal-sso-connection.client.js.map +1 -1
  61. package/dist/esm/api/api-provider.d.ts +1 -1
  62. package/dist/esm/api/api-provider.js.map +1 -1
  63. package/dist/esm/api/endpoint.d.ts +860 -813
  64. package/dist/esm/api/endpoint.js +727 -751
  65. package/dist/esm/api/endpoint.js.map +1 -1
  66. package/dist/esm/directory-sync.client.d.ts +26 -0
  67. package/dist/esm/directory-sync.client.js +134 -0
  68. package/dist/esm/directory-sync.client.js.map +1 -0
  69. package/dist/esm/experimental/api/fetch.d.ts +832 -798
  70. package/dist/esm/experimental/api/fetch.js +319 -391
  71. package/dist/esm/experimental/api/fetch.js.map +1 -1
  72. package/dist/esm/experimental/api/react-query.d.ts +1378 -1263
  73. package/dist/esm/experimental/api/react-query.js +730 -757
  74. package/dist/esm/experimental/api/react-query.js.map +1 -1
  75. package/dist/esm/experimental/api/swr.d.ts +1218 -1175
  76. package/dist/esm/experimental/api/swr.js +706 -722
  77. package/dist/esm/experimental/api/swr.js.map +1 -1
  78. package/dist/esm/index.d.ts +2 -0
  79. package/dist/esm/index.js +6 -0
  80. package/dist/esm/index.js.map +1 -1
  81. package/dist/esm/lib/add-mfa-dialog.js +18 -16
  82. package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
  83. package/dist/esm/lib/admin-portal-sso-connection.d.ts +1 -2
  84. package/dist/esm/lib/admin-portal-sso-connection.js +0 -8
  85. package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
  86. package/dist/esm/lib/api-keys/api-keys-context.js +1 -1
  87. package/dist/esm/lib/api-keys/api-keys-context.js.map +1 -1
  88. package/dist/esm/lib/api-keys/api-keys-table.js +7 -5
  89. package/dist/esm/lib/api-keys/api-keys-table.js.map +1 -1
  90. package/dist/esm/lib/directory-sync.d.ts +72 -0
  91. package/dist/esm/lib/directory-sync.js +259 -0
  92. package/dist/esm/lib/directory-sync.js.map +1 -0
  93. package/dist/esm/lib/identity-providers.d.ts +5 -3
  94. package/dist/esm/lib/identity-providers.js +55 -1
  95. package/dist/esm/lib/identity-providers.js.map +1 -1
  96. package/dist/esm/lib/pipes.js +9 -10
  97. package/dist/esm/lib/pipes.js.map +1 -1
  98. package/dist/esm/lib/provider-icon.d.ts +2 -2
  99. package/dist/esm/lib/provider-icon.js.map +1 -1
  100. package/dist/esm/lib/reset-mfa-dialog.js +2 -1
  101. package/dist/esm/lib/reset-mfa-dialog.js.map +1 -1
  102. package/dist/esm/lib/use-permissions.d.ts +1 -1
  103. package/dist/esm/lib/use-permissions.js.map +1 -1
  104. package/dist/esm/lib/users-management-context.js +1 -1
  105. package/dist/esm/lib/users-management-context.js.map +1 -1
  106. package/dist/esm/lib/users-management.js +5 -4
  107. package/dist/esm/lib/users-management.js.map +1 -1
  108. package/dist/esm/lib/utils.d.ts +16 -2
  109. package/dist/esm/lib/utils.js +8 -0
  110. package/dist/esm/lib/utils.js.map +1 -1
  111. package/dist/esm/workos-widgets.client.js +13 -1
  112. package/dist/esm/workos-widgets.client.js.map +1 -1
  113. package/package.json +2 -2
@@ -8,6 +8,7 @@ export { UsersManagement, UsersManagementProps } from './users-management.client
8
8
  export { AdminPortalDomainVerification, AdminPortalDomainVerificationProps } from './admin-portal-domain-verification.client.js';
9
9
  export { ApiKeys, ApiKeysProps } from './api-keys.client.js';
10
10
  export { Pipes, PipesProps } from './pipes.client.js';
11
+ export { DirectorySync, DirectorySyncProps } from './directory-sync.client.js';
11
12
  export { IntlContext as internal_IntlContext } from './lib/i18n/intl-context.js';
12
13
  export { OrganizationSwitcherLoading } from './lib/organization-switcher.js';
13
14
  export { AdminPortalSsoConnectionLoading } from './lib/admin-portal-sso-connection.js';
@@ -18,6 +19,7 @@ export { UsersManagementLoading } from './lib/users-management.js';
18
19
  export { AdminPortalDomainVerificationLoading } from './lib/admin-portal-domain-verification.js';
19
20
  export { ApiKeysLoading } from './lib/api-keys/api-keys.js';
20
21
  export { PipesLoading } from './lib/pipes.js';
22
+ export { DirectorySyncLoading } from './lib/directory-sync.js';
21
23
  import '@radix-ui/themes/props';
22
24
  import '@tanstack/react-query';
23
25
  import 'react';
package/dist/esm/index.js CHANGED
@@ -34,6 +34,10 @@ import {
34
34
  ApiKeysLoading
35
35
  } from "./api-keys.client.js";
36
36
  import { Pipes, PipesLoading } from "./pipes.client.js";
37
+ import {
38
+ DirectorySync,
39
+ DirectorySyncLoading
40
+ } from "./directory-sync.client.js";
37
41
  import { IntlContext } from "./lib/i18n/intl-context.js";
38
42
  export {
39
43
  AdminPortalDomainVerification,
@@ -42,6 +46,8 @@ export {
42
46
  AdminPortalSsoConnectionLoading,
43
47
  ApiKeys,
44
48
  ApiKeysLoading,
49
+ DirectorySync,
50
+ DirectorySyncLoading,
45
51
  OrganizationSwitcher,
46
52
  OrganizationSwitcherLoading,
47
53
  Pipes,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export {\n WorkOsWidgets,\n type WorkOsWidgetsProps,\n} from \"./workos-widgets.client.js\";\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n type OrganizationSwitcherProps,\n} from \"./organization-switcher.client.js\";\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n type AdminPortalSsoConnectionProps,\n} from \"./admin-portal-sso-connection.client.js\";\nexport {\n UserProfile,\n UserProfileLoading,\n type UserProfileProps,\n} from \"./user-profile.client.js\";\nexport {\n UserSecurity,\n UserSecurityLoading,\n type UserSecurityProps,\n} from \"./user-security.client.js\";\nexport {\n UserSessions,\n UserSessionsLoading,\n type UserSessionsProps,\n} from \"./user-sessions.client.js\";\nexport {\n UsersManagement,\n UsersManagementLoading,\n type UsersManagementProps,\n} from \"./users-management.client.js\";\nexport {\n AdminPortalDomainVerification,\n AdminPortalDomainVerificationLoading,\n type AdminPortalDomainVerificationProps,\n} from \"./admin-portal-domain-verification.client.js\";\nexport {\n ApiKeys,\n ApiKeysLoading,\n type ApiKeysProps,\n} from \"./api-keys.client.js\";\nexport { Pipes, PipesLoading, type PipesProps } from \"./pipes.client.js\";\nexport { IntlContext as internal_IntlContext } from \"./lib/i18n/intl-context.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,OAAO,oBAAqC;AACrD,SAAwB,mBAA4B;","names":[]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export {\n WorkOsWidgets,\n type WorkOsWidgetsProps,\n} from \"./workos-widgets.client.js\";\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n type OrganizationSwitcherProps,\n} from \"./organization-switcher.client.js\";\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n type AdminPortalSsoConnectionProps,\n} from \"./admin-portal-sso-connection.client.js\";\nexport {\n UserProfile,\n UserProfileLoading,\n type UserProfileProps,\n} from \"./user-profile.client.js\";\nexport {\n UserSecurity,\n UserSecurityLoading,\n type UserSecurityProps,\n} from \"./user-security.client.js\";\nexport {\n UserSessions,\n UserSessionsLoading,\n type UserSessionsProps,\n} from \"./user-sessions.client.js\";\nexport {\n UsersManagement,\n UsersManagementLoading,\n type UsersManagementProps,\n} from \"./users-management.client.js\";\nexport {\n AdminPortalDomainVerification,\n AdminPortalDomainVerificationLoading,\n type AdminPortalDomainVerificationProps,\n} from \"./admin-portal-domain-verification.client.js\";\nexport {\n ApiKeys,\n ApiKeysLoading,\n type ApiKeysProps,\n} from \"./api-keys.client.js\";\nexport { Pipes, PipesLoading, type PipesProps } from \"./pipes.client.js\";\nexport {\n DirectorySync,\n DirectorySyncLoading,\n type DirectorySyncProps,\n} from \"./directory-sync.client.js\";\nexport { IntlContext as internal_IntlContext } from \"./lib/i18n/intl-context.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,OAAO,oBAAqC;AACrD;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAwB,mBAA4B;","names":[]}
@@ -79,7 +79,7 @@ function Content({ onClose, totpFactor }) {
79
79
  const securitySettings = useSecuritySettings();
80
80
  const translate = useTranslation();
81
81
  const [customError, setCustomError] = React.useState(null);
82
- const totp = hasQrCode(totpFactor) ? totpFactor.authenticationFactor.totp : void 0;
82
+ const totp = totpFactor?.authenticationFactor.totp != null && "qr_code" in totpFactor.authenticationFactor.totp ? totpFactor.authenticationFactor.totp : void 0;
83
83
  const verifyTotp = useVerifyTotpFactor({
84
84
  mutation: {
85
85
  onSuccess: ({ success }) => {
@@ -208,7 +208,7 @@ function Content({ onClose, totpFactor }) {
208
208
  background: "var(--gray-2)",
209
209
  overflow: "hidden"
210
210
  },
211
- children: totp?.qr_code && /* @__PURE__ */ jsx(Box, { asChild: true, width: "100%", height: "auto", children: /* @__PURE__ */ jsx(
211
+ children: !!totp?.qr_code && /* @__PURE__ */ jsx(Box, { asChild: true, width: "100%", height: "auto", children: /* @__PURE__ */ jsx(
212
212
  "img",
213
213
  {
214
214
  alt: translate({
@@ -234,22 +234,28 @@ function Content({ onClose, totpFactor }) {
234
234
  description: "Question asking if user is unable to scan the QR code"
235
235
  }
236
236
  ) }),
237
- /* @__PURE__ */ jsx(SecretDialog, { setupKey: totp?.secret ?? "", children: /* @__PURE__ */ jsx(
238
- Button,
237
+ /* @__PURE__ */ jsx(
238
+ SecretDialog,
239
239
  {
240
- variant: "secondary",
241
- size: "1",
242
- disabled: verifyTotp.isPending || isSuccess,
240
+ setupKey: totp && "secret" in totp ? totp.secret : "",
243
241
  children: /* @__PURE__ */ jsx(
244
- Translation,
242
+ Button,
245
243
  {
246
- defaultMessage: "View setup key",
247
- id: "q3eZjH",
248
- description: "Button text to view the manual setup key"
244
+ variant: "secondary",
245
+ size: "1",
246
+ disabled: verifyTotp.isPending || isSuccess,
247
+ children: /* @__PURE__ */ jsx(
248
+ Translation,
249
+ {
250
+ defaultMessage: "View setup key",
251
+ id: "q3eZjH",
252
+ description: "Button text to view the manual setup key"
253
+ }
254
+ )
249
255
  }
250
256
  )
251
257
  }
252
- ) })
258
+ )
253
259
  ] })
254
260
  ] })
255
261
  ] }),
@@ -383,10 +389,6 @@ function getMutationErrorMessage(error) {
383
389
  }
384
390
  return message;
385
391
  }
386
- function hasQrCode(response) {
387
- const totp = response?.authenticationFactor.totp;
388
- return totp != null && "qr_code" in totp;
389
- }
390
392
  export {
391
393
  AddMfaDialog
392
394
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/add-mfa-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Box,\n Code,\n Flex,\n Grid,\n Link,\n Separator,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport * as Otp from \"./otp-input.js\";\nimport { Dialog, Button } from \"./elements.js\";\nimport {\n CreateTotpFactorResponse,\n CreateTotpFactorResponseAuthenticationFactorAllOfTotpAnyOf,\n useCreateTotpFactor,\n useVerifyTotpFactor,\n} from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { Form } from \"radix-ui\";\nimport { Marker } from \"./marker.js\";\nimport { CopyButton } from \"./copy-button.js\";\nimport { useSecuritySettings } from \"./use-security-settings.js\";\nimport { ElevatedAccess } from \"./elevated-access.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { useDialogClose } from \"./use-dialog-close.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface AddMfaDialogProps extends Dialog.RootProps {\n children?: ReactNode;\n onSuccess?: () => void;\n}\n\nexport function AddMfaDialog({\n children,\n onSuccess,\n ...props\n}: AddMfaDialogProps) {\n const [open, setOpen] = React.useState(false);\n const [manuallyTriggered, setManuallyTriggered] = React.useState(false);\n const { elevatedAccess } = useElevatedAccessToken();\n const createAuthFactor = useCreateTotpFactor();\n\n const handleVerified = async () => {\n await createAuthFactor.mutateAsync(undefined);\n };\n\n const onTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (elevatedAccess && !createAuthFactor.data) {\n event.preventDefault();\n setManuallyTriggered(true);\n createAuthFactor.mutate(undefined, {\n onSuccess: () => {\n setOpen(true);\n },\n });\n } else {\n setManuallyTriggered(false);\n }\n };\n\n const handleClose = React.useCallback(() => {\n setOpen(false);\n }, []);\n\n return (\n <Dialog.Root\n {...props}\n open={props.open || open}\n onOpenChange={props.onOpenChange || setOpen}\n >\n <Dialog.Trigger\n onClick={onTriggerClick}\n // @ts-ignore I've to find a way to pass the loading state to the trigger\n loading={manuallyTriggered && createAuthFactor.isPending}\n >\n {children}\n </Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <ElevatedAccess onVerified={handleVerified}>\n <Content onClose={handleClose} totpFactor={createAuthFactor.data} />\n </ElevatedAccess>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps {\n totpFactor?: CreateTotpFactorResponse;\n onClose?: () => void;\n}\n\nfunction Content({ onClose, totpFactor }: ContentProps) {\n const securitySettings = useSecuritySettings();\n const translate = useTranslation();\n\n const [customError, setCustomError] = React.useState<string | null>(null);\n const totp = hasQrCode(totpFactor)\n ? totpFactor.authenticationFactor.totp\n : undefined;\n\n const verifyTotp = useVerifyTotpFactor({\n mutation: {\n onSuccess: ({ success }) => {\n if (!success) {\n setCustomError(\"Invalid passcode\");\n }\n },\n },\n });\n\n const serverError = verifyTotp.error || customError;\n const isSuccess = verifyTotp.isSuccess && !serverError;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setCustomError(null);\n\n const formData = new FormData(event.currentTarget);\n const otpCode = formData.get(\"otp-code\")?.toString();\n\n verifyTotp.mutate({\n data: {\n authenticationChallengeId: totpFactor?.authenticationChallenge.id ?? \"\",\n code: otpCode ?? \"\",\n },\n });\n };\n\n useDialogClose(isSuccess, () => {\n securitySettings.update(\"Mfa\", true);\n });\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Set up an authenticator app\"\n id=\"Eu+kuO\"\n description=\"Title for setting up two-factor authentication\"\n />\n </Dialog.Title>\n\n <Form.Root onSubmit={handleSubmit}>\n <Grid columns=\"auto 1fr\" rows=\"repeat(4, auto)\" gapX=\"3\" gapY=\"1\">\n <Grid\n rows=\"subgrid\"\n gridRow=\"span 4\"\n style={{ placeItems: \"center\" }}\n >\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>1</Marker>\n <Separator\n orientation=\"vertical\"\n size=\"4\"\n style={{ width: \"2px\" }}\n />\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>2</Marker>\n <div />\n </Grid>\n\n <Grid rows=\"subgrid\" gridRow=\"span 4\">\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Scan the QR code\"\n id=\"fTSp5u\"\n description=\"Heading for the QR code scanning step in MFA setup\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"1\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Use an authenticator app like {onep}, {google}, {authy}, or {microsoft} to scan the QR code below.\"\n id=\"8xwdwI\"\n description=\"Instructions for scanning the QR code with authenticator apps\"\n values={{\n onep: (\n <Link\n href=\"https://1password.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n 1Password\n </Link>\n ),\n google: (\n <Link\n href=\"https://apps.apple.com/us/app/google-authenticator/id388497605\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Google Authenticator\n </Link>\n ),\n authy: (\n <Link\n href=\"https://authy.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Authy\n </Link>\n ),\n microsoft: (\n <Link\n href=\"https://www.microsoft.com/en-gb/security/mobile-authenticator-app\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Microsoft Authenticator\n </Link>\n ),\n }}\n />\n </Text>\n <Flex align=\"center\" gap=\"5\" my=\"5\">\n <Grid\n position=\"relative\"\n width=\"160px\"\n height=\"160px\"\n p=\"2\"\n style={{\n border: \"1px solid var(--gray-7)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--gray-2)\",\n overflow: \"hidden\",\n }}\n >\n {totp?.qr_code && (\n <Box asChild width=\"100%\" height=\"auto\">\n <img\n alt={translate({\n defaultMessage: \"Scan this QR code to enroll\",\n description: \"Alt text for QR code image\",\n id: \"wpbqFJ\",\n })}\n aria-describedby=\"secret-note\"\n height=\"160\"\n src={totp.qr_code}\n style={{ userSelect: \"none\", background: \"white\" }}\n width=\"160\"\n />\n </Box>\n )}\n </Grid>\n\n <Flex direction=\"column\" gap=\"1\" align=\"start\">\n <Text color=\"gray\" id=\"secret-note\" size=\"2\">\n <Translation\n defaultMessage=\"Can't scan the code?\"\n id=\"6/cdcS\"\n description=\"Question asking if user is unable to scan the QR code\"\n />\n </Text>\n\n <SecretDialog setupKey={totp?.secret ?? \"\"}>\n <Button\n variant=\"secondary\"\n size=\"1\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"View setup key\"\n id=\"q3eZjH\"\n description=\"Button text to view the manual setup key\"\n />\n </Button>\n </SecretDialog>\n </Flex>\n </Flex>\n </Flex>\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Get verification passcode\"\n id=\"1kRd2b\"\n description=\"Heading for entering the verification code step\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"4\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Enter the 6-digit passcode from your authenticator app.\"\n id=\"4/66bS\"\n description=\"Instructions for entering the verification passcode\"\n />\n </Text>\n\n <Flex direction=\"column\" gap=\"2\">\n <Otp.Root\n autoSubmit\n gap=\"3\"\n justify=\"start\"\n name=\"otp-code\"\n rows=\"48px\"\n columns=\"repeat(6, 48px)\"\n readOnly={verifyTotp.isPending || isSuccess}\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 {serverError && (\n <Text size=\"2\" color=\"red\">\n {getMutationErrorMessage(serverError)}\n </Text>\n )}\n </Flex>\n </Flex>\n </Grid>\n </Grid>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"84pAvU\"\n description=\"Button text to cancel MFA setup\"\n />\n </Button>\n </Dialog.Close>\n\n <SaveButton\n type=\"submit\"\n loading={verifyTotp.isPending}\n done={isSuccess}\n onDone={onClose}\n >\n <Translation\n defaultMessage=\"Confirm\"\n id=\"WHthZi\"\n description=\"Button text to confirm MFA setup\"\n />\n </SaveButton>\n </Flex>\n </Form.Root>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">\n {getMutationErrorMessage(serverError)}\n </section>\n </VisuallyHidden>\n </>\n );\n}\n\ninterface SecretDialogProps extends React.PropsWithChildren {\n setupKey: string;\n}\n\nfunction SecretDialog({ children, setupKey }: SecretDialogProps) {\n return (\n <Dialog.Root>\n <Dialog.Trigger>{children}</Dialog.Trigger>\n <Dialog.Content\n maxWidth=\"90vw\"\n size={{ initial: \"3\", sm: \"4\" }}\n minWidth=\"300px\"\n width=\"fit-content\"\n >\n <Dialog.Title size=\"2\" weight=\"regular\">\n <Translation\n defaultMessage=\"Your setup key\"\n id=\"LleqNP\"\n description=\"Title for dialog showing the manual setup key\"\n />\n </Dialog.Title>\n <Dialog.Description>\n <Text size=\"6\">\n <Code variant=\"ghost\" style={{ letterSpacing: \"0.15rem\" }}>\n {setupKey}\n </Code>\n </Text>\n </Dialog.Description>\n\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <CopyButton value={setupKey}>\n <Translation\n defaultMessage=\"Copy and close\"\n id=\"EyjGir\"\n description=\"Button text to copy setup key and close dialog\"\n />\n </CopyButton>\n </Dialog.Close>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = \"Something went wrong, please try again\";\n\n if (typeof error === \"string\") {\n message = error;\n }\n\n if (error instanceof Error) {\n message = error.message;\n }\n\n 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 === \"Invalid passcode\") {\n message = \"Invalid passcode, please try again\";\n }\n\n return message;\n}\n\nfunction hasQrCode(\n response?: CreateTotpFactorResponse,\n): response is CreateTotpFactorResponse & {\n authenticationFactor: {\n totp: NonNullable<CreateTotpFactorResponseAuthenticationFactorAllOfTotpAnyOf>;\n };\n} {\n const totp = response?.authenticationFactor.totp;\n return totp != null && \"qr_code\" in totp;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/add-mfa-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Box,\n Code,\n Flex,\n Grid,\n Link,\n Separator,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport * as Otp from \"./otp-input.js\";\nimport { Dialog, Button } from \"./elements.js\";\nimport {\n CreateTotpFactorResponse,\n useCreateTotpFactor,\n useVerifyTotpFactor,\n} from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { Form } from \"radix-ui\";\nimport { Marker } from \"./marker.js\";\nimport { CopyButton } from \"./copy-button.js\";\nimport { useSecuritySettings } from \"./use-security-settings.js\";\nimport { ElevatedAccess } from \"./elevated-access.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { useDialogClose } from \"./use-dialog-close.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface AddMfaDialogProps extends Dialog.RootProps {\n children?: ReactNode;\n onSuccess?: () => void;\n}\n\nexport function AddMfaDialog({\n children,\n onSuccess,\n ...props\n}: AddMfaDialogProps) {\n const [open, setOpen] = React.useState(false);\n const [manuallyTriggered, setManuallyTriggered] = React.useState(false);\n const { elevatedAccess } = useElevatedAccessToken();\n const createAuthFactor = useCreateTotpFactor();\n\n const handleVerified = async () => {\n await createAuthFactor.mutateAsync(undefined);\n };\n\n const onTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (elevatedAccess && !createAuthFactor.data) {\n event.preventDefault();\n setManuallyTriggered(true);\n createAuthFactor.mutate(undefined, {\n onSuccess: () => {\n setOpen(true);\n },\n });\n } else {\n setManuallyTriggered(false);\n }\n };\n\n const handleClose = React.useCallback(() => {\n setOpen(false);\n }, []);\n\n return (\n <Dialog.Root\n {...props}\n open={props.open || open}\n onOpenChange={props.onOpenChange || setOpen}\n >\n <Dialog.Trigger\n onClick={onTriggerClick}\n // @ts-ignore I've to find a way to pass the loading state to the trigger\n loading={manuallyTriggered && createAuthFactor.isPending}\n >\n {children}\n </Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <ElevatedAccess onVerified={handleVerified}>\n <Content onClose={handleClose} totpFactor={createAuthFactor.data} />\n </ElevatedAccess>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps {\n totpFactor?: CreateTotpFactorResponse;\n onClose?: () => void;\n}\n\nfunction Content({ onClose, totpFactor }: ContentProps) {\n const securitySettings = useSecuritySettings();\n const translate = useTranslation();\n\n const [customError, setCustomError] = React.useState<string | null>(null);\n const totp =\n totpFactor?.authenticationFactor.totp != null &&\n \"qr_code\" in totpFactor.authenticationFactor.totp\n ? totpFactor.authenticationFactor.totp\n : undefined;\n\n const verifyTotp = useVerifyTotpFactor({\n mutation: {\n onSuccess: ({ success }) => {\n if (!success) {\n setCustomError(\"Invalid passcode\");\n }\n },\n },\n });\n\n const serverError = verifyTotp.error || customError;\n const isSuccess = verifyTotp.isSuccess && !serverError;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setCustomError(null);\n\n const formData = new FormData(event.currentTarget);\n const otpCode = formData.get(\"otp-code\")?.toString();\n\n verifyTotp.mutate({\n data: {\n authenticationChallengeId: totpFactor?.authenticationChallenge.id ?? \"\",\n code: otpCode ?? \"\",\n },\n });\n };\n\n useDialogClose(isSuccess, () => {\n securitySettings.update(\"Mfa\", true);\n });\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Set up an authenticator app\"\n id=\"Eu+kuO\"\n description=\"Title for setting up two-factor authentication\"\n />\n </Dialog.Title>\n\n <Form.Root onSubmit={handleSubmit}>\n <Grid columns=\"auto 1fr\" rows=\"repeat(4, auto)\" gapX=\"3\" gapY=\"1\">\n <Grid\n rows=\"subgrid\"\n gridRow=\"span 4\"\n style={{ placeItems: \"center\" }}\n >\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>1</Marker>\n <Separator\n orientation=\"vertical\"\n size=\"4\"\n style={{ width: \"2px\" }}\n />\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>2</Marker>\n <div />\n </Grid>\n\n <Grid rows=\"subgrid\" gridRow=\"span 4\">\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Scan the QR code\"\n id=\"fTSp5u\"\n description=\"Heading for the QR code scanning step in MFA setup\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"1\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Use an authenticator app like {onep}, {google}, {authy}, or {microsoft} to scan the QR code below.\"\n id=\"8xwdwI\"\n description=\"Instructions for scanning the QR code with authenticator apps\"\n values={{\n onep: (\n <Link\n href=\"https://1password.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n 1Password\n </Link>\n ),\n google: (\n <Link\n href=\"https://apps.apple.com/us/app/google-authenticator/id388497605\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Google Authenticator\n </Link>\n ),\n authy: (\n <Link\n href=\"https://authy.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Authy\n </Link>\n ),\n microsoft: (\n <Link\n href=\"https://www.microsoft.com/en-gb/security/mobile-authenticator-app\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Microsoft Authenticator\n </Link>\n ),\n }}\n />\n </Text>\n <Flex align=\"center\" gap=\"5\" my=\"5\">\n <Grid\n position=\"relative\"\n width=\"160px\"\n height=\"160px\"\n p=\"2\"\n style={{\n border: \"1px solid var(--gray-7)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--gray-2)\",\n overflow: \"hidden\",\n }}\n >\n {!!totp?.qr_code && (\n <Box asChild width=\"100%\" height=\"auto\">\n <img\n alt={translate({\n defaultMessage: \"Scan this QR code to enroll\",\n description: \"Alt text for QR code image\",\n id: \"wpbqFJ\",\n })}\n aria-describedby=\"secret-note\"\n height=\"160\"\n src={totp.qr_code}\n style={{ userSelect: \"none\", background: \"white\" }}\n width=\"160\"\n />\n </Box>\n )}\n </Grid>\n\n <Flex direction=\"column\" gap=\"1\" align=\"start\">\n <Text color=\"gray\" id=\"secret-note\" size=\"2\">\n <Translation\n defaultMessage=\"Can't scan the code?\"\n id=\"6/cdcS\"\n description=\"Question asking if user is unable to scan the QR code\"\n />\n </Text>\n\n <SecretDialog\n setupKey={totp && \"secret\" in totp ? totp.secret : \"\"}\n >\n <Button\n variant=\"secondary\"\n size=\"1\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"View setup key\"\n id=\"q3eZjH\"\n description=\"Button text to view the manual setup key\"\n />\n </Button>\n </SecretDialog>\n </Flex>\n </Flex>\n </Flex>\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Get verification passcode\"\n id=\"1kRd2b\"\n description=\"Heading for entering the verification code step\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"4\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Enter the 6-digit passcode from your authenticator app.\"\n id=\"4/66bS\"\n description=\"Instructions for entering the verification passcode\"\n />\n </Text>\n\n <Flex direction=\"column\" gap=\"2\">\n <Otp.Root\n autoSubmit\n gap=\"3\"\n justify=\"start\"\n name=\"otp-code\"\n rows=\"48px\"\n columns=\"repeat(6, 48px)\"\n readOnly={verifyTotp.isPending || isSuccess}\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 {serverError && (\n <Text size=\"2\" color=\"red\">\n {getMutationErrorMessage(serverError)}\n </Text>\n )}\n </Flex>\n </Flex>\n </Grid>\n </Grid>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"84pAvU\"\n description=\"Button text to cancel MFA setup\"\n />\n </Button>\n </Dialog.Close>\n\n <SaveButton\n type=\"submit\"\n loading={verifyTotp.isPending}\n done={isSuccess}\n onDone={onClose}\n >\n <Translation\n defaultMessage=\"Confirm\"\n id=\"WHthZi\"\n description=\"Button text to confirm MFA setup\"\n />\n </SaveButton>\n </Flex>\n </Form.Root>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">\n {getMutationErrorMessage(serverError)}\n </section>\n </VisuallyHidden>\n </>\n );\n}\n\ninterface SecretDialogProps extends React.PropsWithChildren {\n setupKey: string;\n}\n\nfunction SecretDialog({ children, setupKey }: SecretDialogProps) {\n return (\n <Dialog.Root>\n <Dialog.Trigger>{children}</Dialog.Trigger>\n <Dialog.Content\n maxWidth=\"90vw\"\n size={{ initial: \"3\", sm: \"4\" }}\n minWidth=\"300px\"\n width=\"fit-content\"\n >\n <Dialog.Title size=\"2\" weight=\"regular\">\n <Translation\n defaultMessage=\"Your setup key\"\n id=\"LleqNP\"\n description=\"Title for dialog showing the manual setup key\"\n />\n </Dialog.Title>\n <Dialog.Description>\n <Text size=\"6\">\n <Code variant=\"ghost\" style={{ letterSpacing: \"0.15rem\" }}>\n {setupKey}\n </Code>\n </Text>\n </Dialog.Description>\n\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <CopyButton value={setupKey}>\n <Translation\n defaultMessage=\"Copy and close\"\n id=\"EyjGir\"\n description=\"Button text to copy setup key and close dialog\"\n />\n </CopyButton>\n </Dialog.Close>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = \"Something went wrong, please try again\";\n\n if (typeof error === \"string\") {\n message = error;\n }\n\n if (error instanceof Error) {\n message = error.message;\n }\n\n 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 === \"Invalid passcode\") {\n message = \"Invalid passcode, please try again\";\n }\n\n return message;\n}\n"],"mappings":"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","names":[]}
@@ -44,9 +44,8 @@ type AdminPortalSsoConnectionProps = WidgetRootDomProps & AdminPortalSsoConnecti
44
44
  adminPortalOpenButton: React.ReactNode;
45
45
  };
46
46
  declare const AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps>;
47
- declare function AdminPortalOpenButton({ isPending, href, initConfig, }: {
47
+ declare function AdminPortalOpenButton({ isPending, initConfig, }: {
48
48
  isPending: boolean;
49
- href: string | null;
50
49
  initConfig: () => void;
51
50
  }): react_jsx_runtime.JSX.Element;
52
51
  interface AdminPortalSsoConnectionLoadingProps extends WidgetRootDomProps {
@@ -206,7 +206,6 @@ function SessionInfo({
206
206
  }
207
207
  function AdminPortalOpenButton({
208
208
  isPending,
209
- href,
210
209
  initConfig
211
210
  }) {
212
211
  const { connectionStatus } = useAdminPortalSsoConnectionContext();
@@ -245,13 +244,6 @@ function AdminPortalOpenButton({
245
244
  return unreachable(connectionStatus);
246
245
  }
247
246
  })();
248
- if (href) {
249
- return /* @__PURE__ */ jsx(Button, { variant: "secondary", asChild: true, children: /* @__PURE__ */ jsxs("a", { href, target: "_blank", rel: "noopener noreferrer", children: [
250
- label,
251
- " ",
252
- /* @__PURE__ */ jsx(ExternalLinkIcon, { "aria-hidden": true })
253
- ] }) });
254
- }
255
247
  return /* @__PURE__ */ jsxs(
256
248
  Button,
257
249
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/admin-portal-sso-connection.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Box, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { Button, Skeleton } from \"./elements.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport {\n ExternalLinkIcon,\n InfoCircledIcon,\n Cross2Icon,\n} from \"@radix-ui/react-icons\";\nimport * as CardList from \"./card-list.js\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport {\n getIdentityProviderName,\n type IdentityProvider,\n} from \"./identity-providers.js\";\nimport { Status } from \"./status.js\";\nimport {\n getDomProps,\n unreachable,\n type WidgetRootState,\n type WidgetRootDomProps,\n} from \"./utils.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\n\ninterface NotConfiguredProps {\n connectionStatus: \"NotConfigured\";\n identityProvider?: never;\n expiryDate?: never;\n}\n\ninterface InactiveProps {\n connectionStatus: \"Inactive\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface ActiveProps {\n connectionStatus: \"Active\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface RequiresActionProps {\n connectionStatus: \"Expired\" | \"Expiring\";\n identityProvider: IdentityProvider;\n expiryDate: Date | null;\n}\n\nexport type AdminPortalSsoConnectionStatusProps =\n | NotConfiguredProps\n | InactiveProps\n | ActiveProps\n | RequiresActionProps;\n\ntype AdminPortalSsoConnectionProps = WidgetRootDomProps &\n AdminPortalSsoConnectionStatusProps & {\n currentDate: Date | null;\n lastSession: Date | null;\n adminPortalOpenButton: React.ReactNode;\n };\n\ninterface AdminPortalSsoConnectionContextValue {\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}\n\nconst AdminPortalSsoConnectionContext =\n React.createContext<AdminPortalSsoConnectionContextValue | null>(null);\nAdminPortalSsoConnectionContext.displayName = \"AdminPortalSsoConnectionContext\";\n\nfunction useAdminPortalSsoConnectionContext() {\n const context = React.useContext(AdminPortalSsoConnectionContext);\n if (!context) {\n throw new Error(\n \"useAdminPortalSsoConnectionContext must be used within a AdminPortalSsoConnectionContext provider\",\n );\n }\n return context;\n}\n\nconst AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps> = ({\n currentDate,\n connectionStatus,\n identityProvider,\n expiryDate,\n lastSession,\n adminPortalOpenButton,\n ...domProps\n}) => {\n return (\n <CardList.Root size=\"2\" {...getWidgetRootDomProps(\"resolved\", domProps)}>\n <AdminPortalSsoConnectionContext.Provider value={{ connectionStatus }}>\n <CardList.Item>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n {(() => {\n if (connectionStatus === \"NotConfigured\") {\n return (\n <>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"You haven't set up Single Sign-On yet.\"\n id=\"KDs1Ib\"\n description=\"Empty state message when SSO is not configured\"\n />\n </Text>\n {adminPortalOpenButton}\n </>\n );\n }\n\n return (\n <>\n <SessionInfo\n connectionStatus={connectionStatus}\n identityProvider={identityProvider}\n lastSession={lastSession}\n currentDate={currentDate}\n />\n <Flex gap=\"5\" align=\"center\">\n <SsoStatus status={connectionStatus} />\n {adminPortalOpenButton}\n </Flex>\n </>\n );\n })()}\n </Flex>\n </CardList.Item>\n {connectionStatus === \"Expired\" && (\n <CardList.Item>\n <Flex align=\"start\" gap=\"2\">\n <Box asChild mt=\"2px\" flexShrink=\"0\">\n <InfoCircledIcon color=\"gray\" />\n </Box>\n {(() => {\n if (connectionStatus === \"Expired\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate has expired. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"5tX19v\"\n description=\"Error message when SAML certificate has expired (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate expired on {expiryDate}. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"vmTW/h\"\n description=\"Error message when SAML certificate has expired with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n\n if (connectionStatus === \"Expiring\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate is expiring soon. When expired, users won't be able to sign-in.\"\n id=\"3dgA5f\"\n description=\"Warning message when SAML certificate is expiring soon (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate will expire on {expiryDate}. When expired, users won't be able to sign-in.\"\n id=\"xT9Exy\"\n description=\"Warning message when SAML certificate is expiring with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n })()}\n </Flex>\n </CardList.Item>\n )}\n </AdminPortalSsoConnectionContext.Provider>\n </CardList.Root>\n );\n};\n\nfunction SsoStatus({\n status,\n}: {\n status: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n if (status === \"NotConfigured\") {\n return null;\n }\n\n if (status === \"Inactive\") {\n return (\n <Status state=\"waiting\">\n <Translation\n defaultMessage=\"Setup in progress\"\n id=\"MQR5mR\"\n description=\"Status label when SSO setup is incomplete\"\n />\n </Status>\n );\n }\n\n if (status === \"Expired\") {\n return (\n <Status state=\"error\">\n <Translation\n defaultMessage=\"Requires action\"\n id=\"Yo2vHC\"\n description=\"Status label when SSO requires attention\"\n />\n </Status>\n );\n }\n\n if (status === \"Active\" || status === \"Expiring\") {\n return (\n <Status state=\"success\">\n <Translation\n defaultMessage=\"Connected\"\n id=\"8S+Cyw\"\n description=\"Status label when SSO is active\"\n />\n </Status>\n );\n }\n\n return unreachable(status);\n}\n\nfunction SessionInfo({\n currentDate,\n identityProvider,\n lastSession,\n connectionStatus,\n}: {\n identityProvider: IdentityProvider;\n lastSession: Date | null;\n currentDate: Date | null;\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n const relativeTimeString = React.useMemo(() => {\n if (\n !lastSession ||\n !currentDate ||\n connectionStatus === \"NotConfigured\" ||\n connectionStatus === \"Inactive\"\n ) {\n return null;\n }\n\n return getRelativeTimeString(currentDate, lastSession);\n }, [lastSession, currentDate, connectionStatus]);\n\n return (\n <Flex gap=\"4\" align=\"center\">\n <IconPanel color=\"panel\">\n <ProviderIcon provider={identityProvider} size=\"2\" />\n </IconPanel>\n {lastSession ? (\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n {relativeTimeString ? (\n <Text color=\"gray\" size=\"2\">\n <Translation\n defaultMessage=\"Last session {relativeTime}\"\n id=\"yN72Gc\"\n description=\"Label showing when the last SSO session occurred\"\n values={{ relativeTime: relativeTimeString }}\n />\n </Text>\n ) : null}\n </Flex>\n ) : (\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n )}\n </Flex>\n );\n}\n\nfunction AdminPortalOpenButton({\n isPending,\n href,\n initConfig,\n}: {\n isPending: boolean;\n href: string | null;\n initConfig: () => void;\n}) {\n const { connectionStatus } = useAdminPortalSsoConnectionContext();\n const label = (() => {\n switch (connectionStatus) {\n case \"NotConfigured\":\n return (\n <Translation\n defaultMessage=\"Set up SSO\"\n id=\"MtkNQO\"\n description=\"Button label to start SSO setup\"\n />\n );\n case \"Inactive\":\n return (\n <Translation\n defaultMessage=\"Continue setup\"\n id=\"HFxrbY\"\n description=\"Button label to continue incomplete SSO setup\"\n />\n );\n case \"Active\":\n case \"Expiring\":\n case \"Expired\":\n return (\n <Translation\n defaultMessage=\"Manage\"\n id=\"T1VKzP\"\n description=\"Button label to manage SSO settings\"\n />\n );\n default:\n return unreachable(connectionStatus);\n }\n })();\n\n if (href) {\n return (\n <Button variant=\"secondary\" asChild>\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {label} <ExternalLinkIcon aria-hidden />\n </a>\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"secondary\"\n loading={isPending}\n disabled={isPending}\n onClick={initConfig}\n >\n {label} <ExternalLinkIcon aria-hidden />\n </Button>\n );\n}\n\ninterface AdminPortalSsoConnectionLoadingProps extends WidgetRootDomProps {}\n\nconst AdminPortalSsoConnectionLoading: React.FC<\n AdminPortalSsoConnectionLoadingProps\n> = (props) => {\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"loading\", props)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Skeleton>\n <IconPanel color=\"panel\">\n <ProviderIcon provider=\"okta\" size=\"2\" />\n </IconPanel>\n </Skeleton>\n <Flex direction=\"column\" gap=\"1\" my=\"-4px\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Okta</Text>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Last session 10 minutes ago</Text>\n </Skeleton>\n </Flex>\n </Flex>\n <Flex gap=\"5\" align=\"center\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Status state=\"error\">Requires action</Status>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Button variant=\"secondary\">\n Manage <ExternalLinkIcon aria-hidden />\n </Button>\n </Skeleton>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\ninterface AdminPortalSsoConnectionErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst AdminPortalSsoConnectionError: React.FC<\n AdminPortalSsoConnectionErrorProps\n> = ({ error, ...domProps }) => {\n const translate = useTranslation();\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const { heading, message } = getErrorMessage(error, translate);\n\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"error\", domProps)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Flex\n align=\"center\"\n justify=\"center\"\n width=\"24px\"\n height=\"24px\"\n style={{\n borderRadius: \"9999px\",\n backgroundColor: \"var(--red-a4)\",\n color: \"var(--red-a11)\",\n flexShrink: 0,\n }}\n >\n <Cross2Icon width=\"18px\" height=\"18px\" />\n </Flex>\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {heading}\n </Text>\n <Text size=\"2\" color=\"gray\">\n {message}\n </Text>\n </Flex>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\nfunction getRelativeTimeString(\n currentDate: Date | null,\n lastSession: Date | null,\n) {\n if (!currentDate || !lastSession) {\n return null;\n }\n\n const rtf = new Intl.RelativeTimeFormat(\"en\", { numeric: \"auto\" });\n const diff = lastSession.getTime() - currentDate.getTime();\n\n const diffSeconds = Math.round(diff / 1000);\n const diffMinutes = Math.round(diffSeconds / 60);\n const diffHours = Math.round(diffMinutes / 60);\n const diffDays = Math.round(diffHours / 24);\n const diffMonths = Math.round(diffDays / 30);\n const diffYears = Math.round(diffMonths / 12);\n\n if (Math.abs(diffSeconds) < 60) {\n return \"now\";\n }\n\n if (Math.abs(diffMinutes) < 60) {\n return rtf.format(diffMinutes, \"minute\");\n }\n\n if (Math.abs(diffHours) < 24) {\n return rtf.format(diffHours, \"hour\");\n }\n\n if (Math.abs(diffDays) < 30) {\n return rtf.format(diffDays, \"day\");\n }\n\n if (Math.abs(diffMonths) < 12) {\n return rtf.format(diffMonths, \"month\");\n }\n\n return rtf.format(diffYears, \"year\");\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"admin-portal-sso-connection\",\n widgetState: state,\n });\n}\n\nexport type {\n AdminPortalSsoConnectionProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionErrorProps,\n};\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnectionError,\n /** @internal */\n AdminPortalOpenButton,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/admin-portal-sso-connection.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Box, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { Button, Skeleton } from \"./elements.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport {\n ExternalLinkIcon,\n InfoCircledIcon,\n Cross2Icon,\n} from \"@radix-ui/react-icons\";\nimport * as CardList from \"./card-list.js\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport {\n getIdentityProviderName,\n type IdentityProvider,\n} from \"./identity-providers.js\";\nimport { Status } from \"./status.js\";\nimport {\n getDomProps,\n unreachable,\n type WidgetRootState,\n type WidgetRootDomProps,\n} from \"./utils.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\n\ninterface NotConfiguredProps {\n connectionStatus: \"NotConfigured\";\n identityProvider?: never;\n expiryDate?: never;\n}\n\ninterface InactiveProps {\n connectionStatus: \"Inactive\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface ActiveProps {\n connectionStatus: \"Active\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface RequiresActionProps {\n connectionStatus: \"Expired\" | \"Expiring\";\n identityProvider: IdentityProvider;\n expiryDate: Date | null;\n}\n\nexport type AdminPortalSsoConnectionStatusProps =\n | NotConfiguredProps\n | InactiveProps\n | ActiveProps\n | RequiresActionProps;\n\ntype AdminPortalSsoConnectionProps = WidgetRootDomProps &\n AdminPortalSsoConnectionStatusProps & {\n currentDate: Date | null;\n lastSession: Date | null;\n adminPortalOpenButton: React.ReactNode;\n };\n\ninterface AdminPortalSsoConnectionContextValue {\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}\n\nconst AdminPortalSsoConnectionContext =\n React.createContext<AdminPortalSsoConnectionContextValue | null>(null);\nAdminPortalSsoConnectionContext.displayName = \"AdminPortalSsoConnectionContext\";\n\nfunction useAdminPortalSsoConnectionContext() {\n const context = React.useContext(AdminPortalSsoConnectionContext);\n if (!context) {\n throw new Error(\n \"useAdminPortalSsoConnectionContext must be used within a AdminPortalSsoConnectionContext provider\",\n );\n }\n return context;\n}\n\nconst AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps> = ({\n currentDate,\n connectionStatus,\n identityProvider,\n expiryDate,\n lastSession,\n adminPortalOpenButton,\n ...domProps\n}) => {\n return (\n <CardList.Root size=\"2\" {...getWidgetRootDomProps(\"resolved\", domProps)}>\n <AdminPortalSsoConnectionContext.Provider value={{ connectionStatus }}>\n <CardList.Item>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n {(() => {\n if (connectionStatus === \"NotConfigured\") {\n return (\n <>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"You haven't set up Single Sign-On yet.\"\n id=\"KDs1Ib\"\n description=\"Empty state message when SSO is not configured\"\n />\n </Text>\n {adminPortalOpenButton}\n </>\n );\n }\n\n return (\n <>\n <SessionInfo\n connectionStatus={connectionStatus}\n identityProvider={identityProvider}\n lastSession={lastSession}\n currentDate={currentDate}\n />\n <Flex gap=\"5\" align=\"center\">\n <SsoStatus status={connectionStatus} />\n {adminPortalOpenButton}\n </Flex>\n </>\n );\n })()}\n </Flex>\n </CardList.Item>\n {connectionStatus === \"Expired\" && (\n <CardList.Item>\n <Flex align=\"start\" gap=\"2\">\n <Box asChild mt=\"2px\" flexShrink=\"0\">\n <InfoCircledIcon color=\"gray\" />\n </Box>\n {(() => {\n if (connectionStatus === \"Expired\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate has expired. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"5tX19v\"\n description=\"Error message when SAML certificate has expired (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate expired on {expiryDate}. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"vmTW/h\"\n description=\"Error message when SAML certificate has expired with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n\n if (connectionStatus === \"Expiring\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate is expiring soon. When expired, users won't be able to sign-in.\"\n id=\"3dgA5f\"\n description=\"Warning message when SAML certificate is expiring soon (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate will expire on {expiryDate}. When expired, users won't be able to sign-in.\"\n id=\"xT9Exy\"\n description=\"Warning message when SAML certificate is expiring with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n })()}\n </Flex>\n </CardList.Item>\n )}\n </AdminPortalSsoConnectionContext.Provider>\n </CardList.Root>\n );\n};\n\nfunction SsoStatus({\n status,\n}: {\n status: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n if (status === \"NotConfigured\") {\n return null;\n }\n\n if (status === \"Inactive\") {\n return (\n <Status state=\"waiting\">\n <Translation\n defaultMessage=\"Setup in progress\"\n id=\"MQR5mR\"\n description=\"Status label when SSO setup is incomplete\"\n />\n </Status>\n );\n }\n\n if (status === \"Expired\") {\n return (\n <Status state=\"error\">\n <Translation\n defaultMessage=\"Requires action\"\n id=\"Yo2vHC\"\n description=\"Status label when SSO requires attention\"\n />\n </Status>\n );\n }\n\n if (status === \"Active\" || status === \"Expiring\") {\n return (\n <Status state=\"success\">\n <Translation\n defaultMessage=\"Connected\"\n id=\"8S+Cyw\"\n description=\"Status label when SSO is active\"\n />\n </Status>\n );\n }\n\n return unreachable(status);\n}\n\nfunction SessionInfo({\n currentDate,\n identityProvider,\n lastSession,\n connectionStatus,\n}: {\n identityProvider: IdentityProvider;\n lastSession: Date | null;\n currentDate: Date | null;\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n const relativeTimeString = React.useMemo(() => {\n if (\n !lastSession ||\n !currentDate ||\n connectionStatus === \"NotConfigured\" ||\n connectionStatus === \"Inactive\"\n ) {\n return null;\n }\n\n return getRelativeTimeString(currentDate, lastSession);\n }, [lastSession, currentDate, connectionStatus]);\n\n return (\n <Flex gap=\"4\" align=\"center\">\n <IconPanel color=\"panel\">\n <ProviderIcon provider={identityProvider} size=\"2\" />\n </IconPanel>\n {lastSession ? (\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n {relativeTimeString ? (\n <Text color=\"gray\" size=\"2\">\n <Translation\n defaultMessage=\"Last session {relativeTime}\"\n id=\"yN72Gc\"\n description=\"Label showing when the last SSO session occurred\"\n values={{ relativeTime: relativeTimeString }}\n />\n </Text>\n ) : null}\n </Flex>\n ) : (\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n )}\n </Flex>\n );\n}\n\nfunction AdminPortalOpenButton({\n isPending,\n initConfig,\n}: {\n isPending: boolean;\n initConfig: () => void;\n}) {\n const { connectionStatus } = useAdminPortalSsoConnectionContext();\n const label = (() => {\n switch (connectionStatus) {\n case \"NotConfigured\":\n return (\n <Translation\n defaultMessage=\"Set up SSO\"\n id=\"MtkNQO\"\n description=\"Button label to start SSO setup\"\n />\n );\n case \"Inactive\":\n return (\n <Translation\n defaultMessage=\"Continue setup\"\n id=\"HFxrbY\"\n description=\"Button label to continue incomplete SSO setup\"\n />\n );\n case \"Active\":\n case \"Expiring\":\n case \"Expired\":\n return (\n <Translation\n defaultMessage=\"Manage\"\n id=\"T1VKzP\"\n description=\"Button label to manage SSO settings\"\n />\n );\n default:\n return unreachable(connectionStatus);\n }\n })();\n\n return (\n <Button\n variant=\"secondary\"\n loading={isPending}\n disabled={isPending}\n onClick={initConfig}\n >\n {label} <ExternalLinkIcon aria-hidden />\n </Button>\n );\n}\n\ninterface AdminPortalSsoConnectionLoadingProps extends WidgetRootDomProps {}\n\nconst AdminPortalSsoConnectionLoading: React.FC<\n AdminPortalSsoConnectionLoadingProps\n> = (props) => {\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"loading\", props)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Skeleton>\n <IconPanel color=\"panel\">\n <ProviderIcon provider=\"okta\" size=\"2\" />\n </IconPanel>\n </Skeleton>\n <Flex direction=\"column\" gap=\"1\" my=\"-4px\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Okta</Text>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Last session 10 minutes ago</Text>\n </Skeleton>\n </Flex>\n </Flex>\n <Flex gap=\"5\" align=\"center\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Status state=\"error\">Requires action</Status>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Button variant=\"secondary\">\n Manage <ExternalLinkIcon aria-hidden />\n </Button>\n </Skeleton>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\ninterface AdminPortalSsoConnectionErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst AdminPortalSsoConnectionError: React.FC<\n AdminPortalSsoConnectionErrorProps\n> = ({ error, ...domProps }) => {\n const translate = useTranslation();\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const { heading, message } = getErrorMessage(error, translate);\n\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"error\", domProps)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Flex\n align=\"center\"\n justify=\"center\"\n width=\"24px\"\n height=\"24px\"\n style={{\n borderRadius: \"9999px\",\n backgroundColor: \"var(--red-a4)\",\n color: \"var(--red-a11)\",\n flexShrink: 0,\n }}\n >\n <Cross2Icon width=\"18px\" height=\"18px\" />\n </Flex>\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {heading}\n </Text>\n <Text size=\"2\" color=\"gray\">\n {message}\n </Text>\n </Flex>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\nfunction getRelativeTimeString(\n currentDate: Date | null,\n lastSession: Date | null,\n) {\n if (!currentDate || !lastSession) {\n return null;\n }\n\n const rtf = new Intl.RelativeTimeFormat(\"en\", { numeric: \"auto\" });\n const diff = lastSession.getTime() - currentDate.getTime();\n\n const diffSeconds = Math.round(diff / 1000);\n const diffMinutes = Math.round(diffSeconds / 60);\n const diffHours = Math.round(diffMinutes / 60);\n const diffDays = Math.round(diffHours / 24);\n const diffMonths = Math.round(diffDays / 30);\n const diffYears = Math.round(diffMonths / 12);\n\n if (Math.abs(diffSeconds) < 60) {\n return \"now\";\n }\n\n if (Math.abs(diffMinutes) < 60) {\n return rtf.format(diffMinutes, \"minute\");\n }\n\n if (Math.abs(diffHours) < 24) {\n return rtf.format(diffHours, \"hour\");\n }\n\n if (Math.abs(diffDays) < 30) {\n return rtf.format(diffDays, \"day\");\n }\n\n if (Math.abs(diffMonths) < 12) {\n return rtf.format(diffMonths, \"month\");\n }\n\n return rtf.format(diffYears, \"year\");\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"admin-portal-sso-connection\",\n widgetState: state,\n });\n}\n\nexport type {\n AdminPortalSsoConnectionProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionErrorProps,\n};\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnectionError,\n /** @internal */\n AdminPortalOpenButton,\n};\n"],"mappings":";AAoGkB,mBAEI,KAFJ;AAlGlB,YAAY,WAAW;AACvB,SAAS,KAAK,MAAM,MAAM,YAAY;AACtC,SAAS,QAAQ,gBAAgB;AACjC,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,YAAY,cAAc;AAC1B,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,OAEK;AACP,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AA2ChC,MAAM,kCACJ,MAAM,cAA2D,IAAI;AACvE,gCAAgC,cAAc;AAE9C,SAAS,qCAAqC;AAC5C,QAAM,UAAU,MAAM,WAAW,+BAA+B;AAChE,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,MAAM,2BAAoE,CAAC;AAAA,EACzE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,SACE,oBAAC,SAAS,MAAT,EAAc,MAAK,KAAK,GAAG,sBAAsB,YAAY,QAAQ,GACpE,+BAAC,gCAAgC,UAAhC,EAAyC,OAAO,EAAE,iBAAiB,GAClE;AAAA,wBAAC,SAAS,MAAT,EACC,8BAAC,QAAK,WAAU,OAAM,SAAQ,WAAU,OAAM,UAAS,KAAI,KACvD,iBAAM;AACN,UAAI,qBAAqB,iBAAiB;AACxC,eACE,iCACE;AAAA,8BAAC,QAAK,MAAK,KAAI,OAAM,QACnB;AAAA,YAAC;AAAA;AAAA,cACC,gBAAe;AAAA,cACf,IAAG;AAAA,cACH,aAAY;AAAA;AAAA,UACd,GACF;AAAA,UACC;AAAA,WACH;AAAA,MAEJ;AAEA,aACE,iCACE;AAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QACA,qBAAC,QAAK,KAAI,KAAI,OAAM,UAClB;AAAA,8BAAC,aAAU,QAAQ,kBAAkB;AAAA,UACpC;AAAA,WACH;AAAA,SACF;AAAA,IAEJ,GAAG,GACL,GACF;AAAA,IACC,qBAAqB,aACpB,oBAAC,SAAS,MAAT,EACC,+BAAC,QAAK,OAAM,SAAQ,KAAI,KACtB;AAAA,0BAAC,OAAI,SAAO,MAAC,IAAG,OAAM,YAAW,KAC/B,8BAAC,mBAAgB,OAAM,QAAO,GAChC;AAAA,OACE,MAAM;AACN,YAAI,qBAAqB,WAAW;AAClC,iBACE,oBAAC,QAAK,MAAK,KAAI,OAAM,QACjB,iBAAM;AACN,gBAAI,CAAC,YAAY;AACf,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC,gBAAe;AAAA,kBACf,IAAG;AAAA,kBACH,aAAY;AAAA;AAAA,cACd;AAAA,YAEJ;AAEA,mBACE;AAAA,cAAC;AAAA;AAAA,gBACC,gBAAe;AAAA,gBACf,IAAG;AAAA,gBACH,aAAY;AAAA,gBACZ,QAAQ;AAAA,kBACN,YACE,oBAAC,QAAK,QAAO,QAAO,IAAG,QACpB,sBAAY,eAAe,SAAS;AAAA,oBACnC,OAAO;AAAA,oBACP,KAAK;AAAA,oBACL,MAAM;AAAA,kBACR,CAAC,GACH;AAAA,gBAEJ;AAAA;AAAA,YACF;AAAA,UAEJ,GAAG,GACL;AAAA,QAEJ;AAEA,YAAI,qBAAqB,YAAY;AACnC,iBACE,oBAAC,QAAK,MAAK,KAAI,OAAM,QACjB,iBAAM;AACN,gBAAI,CAAC,YAAY;AACf,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC,gBAAe;AAAA,kBACf,IAAG;AAAA,kBACH,aAAY;AAAA;AAAA,cACd;AAAA,YAEJ;AAEA,mBACE;AAAA,cAAC;AAAA;AAAA,gBACC,gBAAe;AAAA,gBACf,IAAG;AAAA,gBACH,aAAY;AAAA,gBACZ,QAAQ;AAAA,kBACN,YACE,oBAAC,QAAK,QAAO,QAAO,IAAG,QACpB,sBAAY,eAAe,SAAS;AAAA,oBACnC,OAAO;AAAA,oBACP,KAAK;AAAA,oBACL,MAAM;AAAA,kBACR,CAAC,GACH;AAAA,gBAEJ;AAAA;AAAA,YACF;AAAA,UAEJ,GAAG,GACL;AAAA,QAEJ;AAAA,MACF,GAAG;AAAA,OACL,GACF;AAAA,KAEJ,GACF;AAEJ;AAEA,SAAS,UAAU;AAAA,EACjB;AACF,GAEG;AACD,MAAI,WAAW,iBAAiB;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI,WAAW,YAAY;AACzB,WACE,oBAAC,UAAO,OAAM,WACZ;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,EAEJ;AAEA,MAAI,WAAW,WAAW;AACxB,WACE,oBAAC,UAAO,OAAM,SACZ;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,EAEJ;AAEA,MAAI,WAAW,YAAY,WAAW,YAAY;AAChD,WACE,oBAAC,UAAO,OAAM,WACZ;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,EAEJ;AAEA,SAAO,YAAY,MAAM;AAC3B;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,qBAAqB,MAAM,QAAQ,MAAM;AAC7C,QACE,CAAC,eACD,CAAC,eACD,qBAAqB,mBACrB,qBAAqB,YACrB;AACA,aAAO;AAAA,IACT;AAEA,WAAO,sBAAsB,aAAa,WAAW;AAAA,EACvD,GAAG,CAAC,aAAa,aAAa,gBAAgB,CAAC;AAE/C,SACE,qBAAC,QAAK,KAAI,KAAI,OAAM,UAClB;AAAA,wBAAC,aAAU,OAAM,SACf,8BAAC,gBAAa,UAAU,kBAAkB,MAAK,KAAI,GACrD;AAAA,IACC,cACC,qBAAC,QAAK,WAAU,UACd;AAAA,0BAAC,QAAK,MAAK,KAAI,QAAO,QACnB,kCAAwB,gBAAgB,GAC3C;AAAA,MACC,qBACC,oBAAC,QAAK,OAAM,QAAO,MAAK,KACtB;AAAA,QAAC;AAAA;AAAA,UACC,gBAAe;AAAA,UACf,IAAG;AAAA,UACH,aAAY;AAAA,UACZ,QAAQ,EAAE,cAAc,mBAAmB;AAAA;AAAA,MAC7C,GACF,IACE;AAAA,OACN,IAEA,oBAAC,QAAK,MAAK,KAAI,QAAO,QACnB,kCAAwB,gBAAgB,GAC3C;AAAA,KAEJ;AAEJ;AAEA,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AACF,GAGG;AACD,QAAM,EAAE,iBAAiB,IAAI,mCAAmC;AAChE,QAAM,SAAS,MAAM;AACnB,YAAQ,kBAAkB;AAAA,MACxB,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACC,gBAAe;AAAA,YACf,IAAG;AAAA,YACH,aAAY;AAAA;AAAA,QACd;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACC,gBAAe;AAAA,YACf,IAAG;AAAA,YACH,aAAY;AAAA;AAAA,QACd;AAAA,MAEJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACC,gBAAe;AAAA,YACf,IAAG;AAAA,YACH,aAAY;AAAA;AAAA,QACd;AAAA,MAEJ;AACE,eAAO,YAAY,gBAAgB;AAAA,IACvC;AAAA,EACF,GAAG;AAEH,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,MAER;AAAA;AAAA,QAAM;AAAA,QAAC,oBAAC,oBAAiB,eAAW,MAAC;AAAA;AAAA;AAAA,EACxC;AAEJ;AAIA,MAAM,kCAEF,CAAC,UAAU;AACb,SACE,oBAAC,QAAK,MAAK,KAAK,GAAG,sBAAsB,WAAW,KAAK,GACvD,+BAAC,QAAK,WAAU,OAAM,SAAQ,WAAU,OAAM,UAAS,KAAI,KACzD;AAAA,yBAAC,QAAK,KAAI,KAAI,OAAM,UAClB;AAAA,0BAAC,YACC,8BAAC,aAAU,OAAM,SACf,8BAAC,gBAAa,UAAS,QAAO,MAAK,KAAI,GACzC,GACF;AAAA,MACA,qBAAC,QAAK,WAAU,UAAS,KAAI,KAAI,IAAG,QAClC;AAAA,4BAAC,YAEC,8BAAC,QAAK,MAAK,KAAI,kBAAI,GACrB;AAAA,QACA,oBAAC,YAEC,8BAAC,QAAK,MAAK,KAAI,yCAA2B,GAC5C;AAAA,SACF;AAAA,OACF;AAAA,IACA,qBAAC,QAAK,KAAI,KAAI,OAAM,UAClB;AAAA,0BAAC,YAEC,8BAAC,UAAO,OAAM,SAAQ,6BAAe,GACvC;AAAA,MACA,oBAAC,YAEC,+BAAC,UAAO,SAAQ,aAAY;AAAA;AAAA,QACnB,oBAAC,oBAAiB,eAAW,MAAC;AAAA,SACvC,GACF;AAAA,OACF;AAAA,KACF,GACF;AAEJ;AAMA,MAAM,gCAEF,CAAC,EAAE,OAAO,GAAG,SAAS,MAAM;AAC9B,QAAM,YAAY,eAAe;AACjC,QAAM,UAAU,MAAM;AACpB,YAAQ,MAAM,KAAK;AAAA,EACrB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,EAAE,SAAS,QAAQ,IAAI,gBAAgB,OAAO,SAAS;AAE7D,SACE,oBAAC,QAAK,MAAK,KAAK,GAAG,sBAAsB,SAAS,QAAQ,GACxD,8BAAC,QAAK,WAAU,OAAM,SAAQ,WAAU,OAAM,UAAS,KAAI,KACzD,+BAAC,QAAK,KAAI,KAAI,OAAM,UAClB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,QAAO;AAAA,QACP,OAAO;AAAA,UACL,cAAc;AAAA,UACd,iBAAiB;AAAA,UACjB,OAAO;AAAA,UACP,YAAY;AAAA,QACd;AAAA,QAEA,8BAAC,cAAW,OAAM,QAAO,QAAO,QAAO;AAAA;AAAA,IACzC;AAAA,IACA,qBAAC,QAAK,WAAU,UACd;AAAA,0BAAC,QAAK,MAAK,KAAI,QAAO,QACnB,mBACH;AAAA,MACA,oBAAC,QAAK,MAAK,KAAI,OAAM,QAClB,mBACH;AAAA,OACF;AAAA,KACF,GACF,GACF;AAEJ;AAEA,SAAS,sBACP,aACA,aACA;AACA,MAAI,CAAC,eAAe,CAAC,aAAa;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,KAAK,mBAAmB,MAAM,EAAE,SAAS,OAAO,CAAC;AACjE,QAAM,OAAO,YAAY,QAAQ,IAAI,YAAY,QAAQ;AAEzD,QAAM,cAAc,KAAK,MAAM,OAAO,GAAI;AAC1C,QAAM,cAAc,KAAK,MAAM,cAAc,EAAE;AAC/C,QAAM,YAAY,KAAK,MAAM,cAAc,EAAE;AAC7C,QAAM,WAAW,KAAK,MAAM,YAAY,EAAE;AAC1C,QAAM,aAAa,KAAK,MAAM,WAAW,EAAE;AAC3C,QAAM,YAAY,KAAK,MAAM,aAAa,EAAE;AAE5C,MAAI,KAAK,IAAI,WAAW,IAAI,IAAI;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,IAAI,WAAW,IAAI,IAAI;AAC9B,WAAO,IAAI,OAAO,aAAa,QAAQ;AAAA,EACzC;AAEA,MAAI,KAAK,IAAI,SAAS,IAAI,IAAI;AAC5B,WAAO,IAAI,OAAO,WAAW,MAAM;AAAA,EACrC;AAEA,MAAI,KAAK,IAAI,QAAQ,IAAI,IAAI;AAC3B,WAAO,IAAI,OAAO,UAAU,KAAK;AAAA,EACnC;AAEA,MAAI,KAAK,IAAI,UAAU,IAAI,IAAI;AAC7B,WAAO,IAAI,OAAO,YAAY,OAAO;AAAA,EACvC;AAEA,SAAO,IAAI,OAAO,WAAW,MAAM;AACrC;AAEA,SAAS,sBACP,OACA,UACA;AACA,SAAO,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,cAAc;AAAA,IACd,UAAU;AAAA,IACV,aAAa;AAAA,EACf,CAAC;AACH;","names":[]}
@@ -26,7 +26,7 @@ const ApiKeysContextProvider = ({ children }) => {
26
26
  return /* @__PURE__ */ jsx(ApiKeysContext.Provider, { value: context, children });
27
27
  };
28
28
  const NOOP = () => void 0;
29
- const EMPTY_PAGINATION = {};
29
+ const EMPTY_PAGINATION = { before: null, after: null };
30
30
  function useApiKeysContext(initialContext) {
31
31
  const context = React.useContext(ApiKeysContext);
32
32
  if (context) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/api-keys/api-keys-context.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n ApiKeysAction,\n ApiKeysState,\n useApiKeysState,\n} from \"./api-keys-state.js\";\nimport { ListMetadata } from \"../../api/endpoint.js\";\n\nexport interface ApiKeysContextType {\n state: ApiKeysState;\n dispatch: React.Dispatch<ApiKeysAction>;\n}\n\nconst ApiKeysContext = React.createContext<ApiKeysContextType | undefined>(\n undefined,\n);\nApiKeysContext.displayName = \"ApiKeysContext\";\n\nconst initialState: ApiKeysState = {\n pagination: null,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n};\n\nexport const ApiKeysContextProvider: React.FC<{\n children?: React.ReactNode;\n}> = ({ children }) => {\n const [state, dispatch] = useApiKeysState(initialState);\n\n const context = React.useMemo<ApiKeysContextType>(\n () => ({\n state,\n dispatch,\n }),\n [state, dispatch],\n );\n\n return (\n <ApiKeysContext.Provider value={context}>\n {children}\n </ApiKeysContext.Provider>\n );\n};\n\nconst NOOP = () => void 0;\nconst EMPTY_PAGINATION: ListMetadata = {};\n\n/**\n * The context may be provided if it is instantiated in the tree above the user.\n */\nexport function useApiKeysContext(\n initialContext?: ApiKeysContextType | null,\n): ApiKeysContextType {\n const context = React.useContext(ApiKeysContext);\n\n if (context) {\n return context;\n }\n\n if (initialContext) {\n return initialContext;\n }\n\n return {\n dispatch: NOOP,\n state: {\n pagination: EMPTY_PAGINATION,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n },\n };\n}\n"],"mappings":";AAyCI;AAvCJ,YAAY,WAAW;AACvB;AAAA,EAGE;AAAA,OACK;AAQP,MAAM,iBAAiB,MAAM;AAAA,EAC3B;AACF;AACA,eAAe,cAAc;AAE7B,MAAM,eAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AACjB;AAEO,MAAM,yBAER,CAAC,EAAE,SAAS,MAAM;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,gBAAgB,YAAY;AAEtD,QAAM,UAAU,MAAM;AAAA,IACpB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC7B,UACH;AAEJ;AAEA,MAAM,OAAO,MAAM;AACnB,MAAM,mBAAiC,CAAC;AAKjC,SAAS,kBACd,gBACoB;AACpB,QAAM,UAAU,MAAM,WAAW,cAAc;AAE/C,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,MACL,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,eAAe;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/api-keys/api-keys-context.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n ApiKeysAction,\n ApiKeysState,\n useApiKeysState,\n} from \"./api-keys-state.js\";\nimport { ListMetadata } from \"../../api/endpoint.js\";\n\nexport interface ApiKeysContextType {\n state: ApiKeysState;\n dispatch: React.Dispatch<ApiKeysAction>;\n}\n\nconst ApiKeysContext = React.createContext<ApiKeysContextType | undefined>(\n undefined,\n);\nApiKeysContext.displayName = \"ApiKeysContext\";\n\nconst initialState: ApiKeysState = {\n pagination: null,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n};\n\nexport const ApiKeysContextProvider: React.FC<{\n children?: React.ReactNode;\n}> = ({ children }) => {\n const [state, dispatch] = useApiKeysState(initialState);\n\n const context = React.useMemo<ApiKeysContextType>(\n () => ({\n state,\n dispatch,\n }),\n [state, dispatch],\n );\n\n return (\n <ApiKeysContext.Provider value={context}>\n {children}\n </ApiKeysContext.Provider>\n );\n};\n\nconst NOOP = () => void 0;\nconst EMPTY_PAGINATION: ListMetadata = { before: null, after: null };\n\n/**\n * The context may be provided if it is instantiated in the tree above the user.\n */\nexport function useApiKeysContext(\n initialContext?: ApiKeysContextType | null,\n): ApiKeysContextType {\n const context = React.useContext(ApiKeysContext);\n\n if (context) {\n return context;\n }\n\n if (initialContext) {\n return initialContext;\n }\n\n return {\n dispatch: NOOP,\n state: {\n pagination: EMPTY_PAGINATION,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n },\n };\n}\n"],"mappings":";AAyCI;AAvCJ,YAAY,WAAW;AACvB;AAAA,EAGE;AAAA,OACK;AAQP,MAAM,iBAAiB,MAAM;AAAA,EAC3B;AACF;AACA,eAAe,cAAc;AAE7B,MAAM,eAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AACjB;AAEO,MAAM,yBAER,CAAC,EAAE,SAAS,MAAM;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,gBAAgB,YAAY;AAEtD,QAAM,UAAU,MAAM;AAAA,IACpB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC7B,UACH;AAEJ;AAEA,MAAM,OAAO,MAAM;AACnB,MAAM,mBAAiC,EAAE,QAAQ,MAAM,OAAO,KAAK;AAK5D,SAAS,kBACd,gBACoB;AACpB,QAAM,UAAU,MAAM,WAAW,cAAc;AAE/C,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,MACL,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,eAAe;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
@@ -14,6 +14,7 @@ import { ApiKeysSearch } from "./api-keys-search.js";
14
14
  import { Translation } from "../i18n/translation.js";
15
15
  import { useTranslation } from "../i18n/use-translation.js";
16
16
  import { useLocale } from "../i18n/use-locale.js";
17
+ import { getListMetadata } from "../utils.js";
17
18
  function NoApiKeys() {
18
19
  const { clearSearch } = useApiKeysSearchContext();
19
20
  return /* @__PURE__ */ jsxs(Flex, { p: "6", gap: "4", justify: "center", align: "center", direction: "column", children: [
@@ -142,9 +143,10 @@ function ApiKeysTable({
142
143
  apiKeys
143
144
  }) {
144
145
  const { dispatch } = useApiKeysContext();
145
- const hasPagination = apiKeys.listMetadata.before || apiKeys.listMetadata.after;
146
- const hasPreviousPage = apiKeys.listMetadata.after;
147
- const hasNextPage = apiKeys.listMetadata.before;
146
+ const pagination = getListMetadata(apiKeys);
147
+ const hasPagination = !!(pagination.before || pagination.after);
148
+ const hasPreviousPage = !!pagination.after;
149
+ const hasNextPage = !!pagination.before;
148
150
  return /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "stretch", gap: "3", children: [
149
151
  /* @__PURE__ */ jsx(ApiKeysTableHeader, {}),
150
152
  apiKeys.data.length === 0 ? /* @__PURE__ */ jsx(NoApiKeys, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -195,7 +197,7 @@ function ApiKeysTable({
195
197
  size: "1",
196
198
  onClick: () => dispatch({
197
199
  type: "SET_PAGINATION",
198
- pagination: { after: apiKeys.listMetadata.after }
200
+ pagination
199
201
  }),
200
202
  children: /* @__PURE__ */ jsx(
201
203
  Translation,
@@ -215,7 +217,7 @@ function ApiKeysTable({
215
217
  size: "1",
216
218
  onClick: () => dispatch({
217
219
  type: "SET_PAGINATION",
218
- pagination: { before: apiKeys.listMetadata.before }
220
+ pagination
219
221
  }),
220
222
  children: /* @__PURE__ */ jsx(
221
223
  Translation,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/api-keys/api-keys-table.tsx"],"sourcesContent":["import { Flex, Text, Table, Code, Heading } from \"@radix-ui/themes\";\nimport { Button, DropdownMenu, IconButton } from \"../elements.js\";\nimport { DotsHorizontalIcon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { useState } from \"react\";\nimport { RevokeApiKeyDialog } from \"./revoke-api-key-dialog.js\";\nimport { CreateApiKeyButton } from \"./create-api-key.js\";\nimport { ApiKeyDetailsDialog } from \"./api-key-details-dialog.js\";\nimport { useIsHydrated } from \"../use-is-hydrated.js\";\nimport { RelativeTime } from \"./relative-time.js\";\nimport {\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"../../api/endpoint.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\nimport { ApiKeysSearch } from \"./api-keys-search.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\nimport { useLocale } from \"../i18n/use-locale.js\";\n\nfunction NoApiKeys() {\n const { clearSearch } = useApiKeysSearchContext();\n return (\n <Flex p=\"6\" gap=\"4\" justify=\"center\" align=\"center\" direction=\"column\">\n <Flex direction=\"column\" gap=\"1\" maxWidth=\"420px\" align=\"center\">\n <MagnifyingGlassIcon\n style={{ color: \"var(--gray-9)\" }}\n width=\"32px\"\n height=\"32px\"\n />\n <Heading size=\"5\" mb=\"1\" wrap=\"balance\" as=\"h3\">\n <Translation\n defaultMessage=\"No API keys match your search\"\n id=\"cKitHb\"\n description=\"Empty state message when no API keys match search\"\n />\n </Heading>\n </Flex>\n\n <Button variant=\"secondary\" onClick={clearSearch}>\n <Translation\n defaultMessage=\"Clear search\"\n id=\"jTupOW\"\n description=\"Button to clear API key search filters\"\n />\n </Button>\n </Flex>\n );\n}\n\nfunction ApiKeysTableHeader() {\n return (\n <Flex justify=\"between\" align=\"center\">\n <ApiKeysSearch name=\"api-keys-widget-search\" style={{ width: \"390px\" }} />\n <CreateApiKeyButton />\n </Flex>\n );\n}\n\nfunction CreatedOn({ createdOn }: { createdOn: Date }) {\n const isHydrated = useIsHydrated();\n const locale = useLocale();\n return (\n <>\n {createdOn.toLocaleDateString(locale, {\n timeZone: isHydrated ? undefined : \"UTC\",\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </>\n );\n}\n\ninterface ApiKeyRowProps {\n apiKey: ListOrganizationApiKeysResponseData;\n}\n\nfunction ApiKeyRow({ apiKey }: ApiKeyRowProps) {\n const [revokeDialogOpen, setRevokeDialogOpen] = useState(false);\n const [detailsOpen, setDetailsOpen] = useState(false);\n const translate = useTranslation();\n return (\n <>\n <RevokeApiKeyDialog\n // always remount the form when the dialog is opened to reset the validation errors\n key={`${revokeDialogOpen}`}\n open={revokeDialogOpen}\n onOpenChange={setRevokeDialogOpen}\n apiKey={apiKey}\n />\n <ApiKeyDetailsDialog\n open={detailsOpen}\n onOpenChange={setDetailsOpen}\n apiKey={apiKey}\n permissions={apiKey.permissions}\n />\n <Table.Row align=\"center\">\n <Table.Cell>\n <Text>{apiKey.name}</Text>\n </Table.Cell>\n <Table.Cell>\n <Code color=\"gray\">{apiKey.obfuscatedValue}</Code>\n </Table.Cell>\n <Table.Cell>\n <Text\n style={apiKey.lastUsedAt ? undefined : { color: \"var(--gray-10)\" }}\n >\n <RelativeTime\n date={apiKey.lastUsedAt ? new Date(apiKey.lastUsedAt) : undefined}\n />\n </Text>\n </Table.Cell>\n <Table.Cell>\n <Text>\n <CreatedOn createdOn={new Date(apiKey.createdAt)} />\n </Text>\n </Table.Cell>\n <Table.Cell justify=\"end\">\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n {(() => {\n const title = translate({\n defaultMessage: \"API key actions\",\n id: \"RIBfYe\",\n description: \"Tooltip for API key actions menu button\",\n });\n return (\n <IconButton title={title}>\n <DotsHorizontalIcon />\n </IconButton>\n );\n })()}\n </DropdownMenu.Trigger>\n <DropdownMenu.Content size=\"2\" align=\"end\">\n <DropdownMenu.Item onSelect={() => setDetailsOpen(true)}>\n <Translation\n defaultMessage=\"View details\"\n id=\"VGKbbj\"\n description=\"Menu item to view API key details\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onSelect={() => setRevokeDialogOpen(true)}\n >\n <Translation\n defaultMessage=\"Revoke key\"\n id=\"KZIJPP\"\n description=\"Menu item to revoke an API key\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Table.Cell>\n </Table.Row>\n </>\n );\n}\n\nexport function ApiKeysTable({\n apiKeys,\n}: {\n apiKeys: ListOrganizationApiKeysResponse;\n}) {\n const { dispatch } = useApiKeysContext();\n const hasPagination =\n apiKeys.listMetadata.before || apiKeys.listMetadata.after;\n const hasPreviousPage = apiKeys.listMetadata.after;\n const hasNextPage = apiKeys.listMetadata.before;\n\n return (\n <Flex direction=\"column\" align=\"stretch\" gap=\"3\">\n <ApiKeysTableHeader />\n {apiKeys.data.length === 0 ? (\n <NoApiKeys />\n ) : (\n <>\n <Table.Root variant=\"ghost\" size=\"2\">\n <Table.Header>\n <Table.Row>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Name\"\n id=\"VYbVXN\"\n description=\"Table column header for API key name\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Secret key\"\n id=\"H5k7GB\"\n description=\"Table column header for API key secret value\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Last used\"\n id=\"E46t3O\"\n description=\"Table column header for API key last used timestamp\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Created\"\n id=\"CXHhXd\"\n description=\"Table column header for API key creation date\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"28px\" />\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {apiKeys.data.map((apiKey) => (\n <ApiKeyRow key={apiKey.id} apiKey={apiKey} />\n ))}\n </Table.Body>\n </Table.Root>\n {hasPagination && (\n <Flex gap=\"2\" justify=\"end\">\n <Button\n variant=\"secondary\"\n disabled={!hasPreviousPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination: { after: apiKeys.listMetadata.after },\n })\n }\n >\n <Translation\n defaultMessage=\"Previous\"\n id=\"f7TUj0\"\n description=\"Button to navigate to previous page of API keys\"\n />\n </Button>\n <Button\n variant=\"secondary\"\n disabled={!hasNextPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination: { before: apiKeys.listMetadata.before },\n })\n }\n >\n <Translation\n defaultMessage=\"Next\"\n id=\"L2EBxV\"\n description=\"Button to navigate to next page of API keys\"\n />\n </Button>\n </Flex>\n )}\n </>\n )}\n </Flex>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/api-keys/api-keys-table.tsx"],"sourcesContent":["import { Flex, Text, Table, Code, Heading } from \"@radix-ui/themes\";\nimport { Button, DropdownMenu, IconButton } from \"../elements.js\";\nimport { DotsHorizontalIcon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { useState } from \"react\";\nimport { RevokeApiKeyDialog } from \"./revoke-api-key-dialog.js\";\nimport { CreateApiKeyButton } from \"./create-api-key.js\";\nimport { ApiKeyDetailsDialog } from \"./api-key-details-dialog.js\";\nimport { useIsHydrated } from \"../use-is-hydrated.js\";\nimport { RelativeTime } from \"./relative-time.js\";\nimport {\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"../../api/endpoint.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\nimport { ApiKeysSearch } from \"./api-keys-search.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\nimport { useLocale } from \"../i18n/use-locale.js\";\nimport { getListMetadata } from \"../utils.js\";\n\nfunction NoApiKeys() {\n const { clearSearch } = useApiKeysSearchContext();\n return (\n <Flex p=\"6\" gap=\"4\" justify=\"center\" align=\"center\" direction=\"column\">\n <Flex direction=\"column\" gap=\"1\" maxWidth=\"420px\" align=\"center\">\n <MagnifyingGlassIcon\n style={{ color: \"var(--gray-9)\" }}\n width=\"32px\"\n height=\"32px\"\n />\n <Heading size=\"5\" mb=\"1\" wrap=\"balance\" as=\"h3\">\n <Translation\n defaultMessage=\"No API keys match your search\"\n id=\"cKitHb\"\n description=\"Empty state message when no API keys match search\"\n />\n </Heading>\n </Flex>\n\n <Button variant=\"secondary\" onClick={clearSearch}>\n <Translation\n defaultMessage=\"Clear search\"\n id=\"jTupOW\"\n description=\"Button to clear API key search filters\"\n />\n </Button>\n </Flex>\n );\n}\n\nfunction ApiKeysTableHeader() {\n return (\n <Flex justify=\"between\" align=\"center\">\n <ApiKeysSearch name=\"api-keys-widget-search\" style={{ width: \"390px\" }} />\n <CreateApiKeyButton />\n </Flex>\n );\n}\n\nfunction CreatedOn({ createdOn }: { createdOn: Date }) {\n const isHydrated = useIsHydrated();\n const locale = useLocale();\n return (\n <>\n {createdOn.toLocaleDateString(locale, {\n timeZone: isHydrated ? undefined : \"UTC\",\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </>\n );\n}\n\ninterface ApiKeyRowProps {\n apiKey: ListOrganizationApiKeysResponseData;\n}\n\nfunction ApiKeyRow({ apiKey }: ApiKeyRowProps) {\n const [revokeDialogOpen, setRevokeDialogOpen] = useState(false);\n const [detailsOpen, setDetailsOpen] = useState(false);\n const translate = useTranslation();\n return (\n <>\n <RevokeApiKeyDialog\n // always remount the form when the dialog is opened to reset the validation errors\n key={`${revokeDialogOpen}`}\n open={revokeDialogOpen}\n onOpenChange={setRevokeDialogOpen}\n apiKey={apiKey}\n />\n <ApiKeyDetailsDialog\n open={detailsOpen}\n onOpenChange={setDetailsOpen}\n apiKey={apiKey}\n permissions={apiKey.permissions}\n />\n <Table.Row align=\"center\">\n <Table.Cell>\n <Text>{apiKey.name}</Text>\n </Table.Cell>\n <Table.Cell>\n <Code color=\"gray\">{apiKey.obfuscatedValue}</Code>\n </Table.Cell>\n <Table.Cell>\n <Text\n style={apiKey.lastUsedAt ? undefined : { color: \"var(--gray-10)\" }}\n >\n <RelativeTime\n date={apiKey.lastUsedAt ? new Date(apiKey.lastUsedAt) : undefined}\n />\n </Text>\n </Table.Cell>\n <Table.Cell>\n <Text>\n <CreatedOn createdOn={new Date(apiKey.createdAt)} />\n </Text>\n </Table.Cell>\n <Table.Cell justify=\"end\">\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n {(() => {\n const title = translate({\n defaultMessage: \"API key actions\",\n id: \"RIBfYe\",\n description: \"Tooltip for API key actions menu button\",\n });\n return (\n <IconButton title={title}>\n <DotsHorizontalIcon />\n </IconButton>\n );\n })()}\n </DropdownMenu.Trigger>\n <DropdownMenu.Content size=\"2\" align=\"end\">\n <DropdownMenu.Item onSelect={() => setDetailsOpen(true)}>\n <Translation\n defaultMessage=\"View details\"\n id=\"VGKbbj\"\n description=\"Menu item to view API key details\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onSelect={() => setRevokeDialogOpen(true)}\n >\n <Translation\n defaultMessage=\"Revoke key\"\n id=\"KZIJPP\"\n description=\"Menu item to revoke an API key\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Table.Cell>\n </Table.Row>\n </>\n );\n}\n\nexport function ApiKeysTable({\n apiKeys,\n}: {\n apiKeys: ListOrganizationApiKeysResponse;\n}) {\n const { dispatch } = useApiKeysContext();\n\n // The API response previously returned an object with the `listMetadata`\n // property. We might not need this, but it's a defensive check until we\n // verify the API response changes are correct.\n const pagination = getListMetadata(apiKeys);\n\n const hasPagination = !!(pagination.before || pagination.after);\n const hasPreviousPage = !!pagination.after;\n const hasNextPage = !!pagination.before;\n\n return (\n <Flex direction=\"column\" align=\"stretch\" gap=\"3\">\n <ApiKeysTableHeader />\n {apiKeys.data.length === 0 ? (\n <NoApiKeys />\n ) : (\n <>\n <Table.Root variant=\"ghost\" size=\"2\">\n <Table.Header>\n <Table.Row>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Name\"\n id=\"VYbVXN\"\n description=\"Table column header for API key name\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Secret key\"\n id=\"H5k7GB\"\n description=\"Table column header for API key secret value\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Last used\"\n id=\"E46t3O\"\n description=\"Table column header for API key last used timestamp\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Created\"\n id=\"CXHhXd\"\n description=\"Table column header for API key creation date\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"28px\" />\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {apiKeys.data.map((apiKey) => (\n <ApiKeyRow key={apiKey.id} apiKey={apiKey} />\n ))}\n </Table.Body>\n </Table.Root>\n {hasPagination && (\n <Flex gap=\"2\" justify=\"end\">\n <Button\n variant=\"secondary\"\n disabled={!hasPreviousPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination,\n })\n }\n >\n <Translation\n defaultMessage=\"Previous\"\n id=\"f7TUj0\"\n description=\"Button to navigate to previous page of API keys\"\n />\n </Button>\n <Button\n variant=\"secondary\"\n disabled={!hasNextPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination,\n })\n }\n >\n <Translation\n defaultMessage=\"Next\"\n id=\"L2EBxV\"\n description=\"Button to navigate to next page of API keys\"\n />\n </Button>\n </Flex>\n )}\n </>\n )}\n </Flex>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,72 @@
1
+ import * as React from 'react';
2
+ import { WidgetRootDomProps } from './utils.js';
3
+ import { DirectoryType, DirectoryMetadata, DirectoryState } from '../api/endpoint.js';
4
+ import './elements.js';
5
+ import '@radix-ui/themes';
6
+ import '@radix-ui/themes/props';
7
+ import '../dialog-C15qCLN3.js';
8
+ import '@radix-ui/themes/components/dialog';
9
+ import '../alert-dialog-BlG3_awx.js';
10
+ import '@radix-ui/themes/components/alert-dialog';
11
+ import '../dropdown-menu-BQ5LtvdR.js';
12
+ import '@radix-ui/themes/components/dropdown-menu';
13
+ import '../select-KR89Qnvm.js';
14
+ import '@radix-ui/themes/components/select';
15
+ import '@tanstack/react-query';
16
+ import '../api/widgets-api-client.js';
17
+
18
+ interface BaseDirectorySyncProps {
19
+ type?: DirectoryType;
20
+ metadata?: DirectoryMetadata;
21
+ lastSyncAt?: string | null;
22
+ link?: string | null;
23
+ errorMessage?: never;
24
+ userCount?: never;
25
+ groupCount?: never;
26
+ currentDate?: never;
27
+ state: DirectoryState;
28
+ }
29
+ interface NotConfiguredProps extends BaseDirectorySyncProps {
30
+ state: (typeof DirectoryState)["unlinked"];
31
+ }
32
+ interface SetupInProgressProps extends Omit<BaseDirectorySyncProps, "type"> {
33
+ state: (typeof DirectoryState)["validating"];
34
+ type: DirectoryType;
35
+ }
36
+ interface ErrorBeforeConfigProps extends Omit<BaseDirectorySyncProps, "type" | "errorMessage"> {
37
+ state: DirectoryState;
38
+ type: DirectoryType;
39
+ errorMessage: React.ReactNode;
40
+ }
41
+ interface ValidatingProps extends Omit<BaseDirectorySyncProps, "type"> {
42
+ state: (typeof DirectoryState)["validating"];
43
+ type: DirectoryType;
44
+ }
45
+ interface ActiveProps extends Omit<BaseDirectorySyncProps, "type" | "lastSyncAt" | "currentDate" | "errorMessage"> {
46
+ state: (typeof DirectoryState)["linked"];
47
+ type: DirectoryType;
48
+ lastSyncAt: string | null;
49
+ currentDate?: Date | null;
50
+ errorMessage?: React.ReactNode;
51
+ }
52
+ interface InvalidCredentialsProps extends Omit<BaseDirectorySyncProps, "type" | "errorMessage"> {
53
+ state: (typeof DirectoryState)["invalid_credentials"];
54
+ type: DirectoryType;
55
+ errorMessage: React.ReactNode;
56
+ }
57
+ interface DeletingProps extends Omit<BaseDirectorySyncProps, "type"> {
58
+ state: (typeof DirectoryState)["deleting"];
59
+ type: DirectoryType;
60
+ }
61
+ type DirectorySyncStatusProps = NotConfiguredProps | SetupInProgressProps | ErrorBeforeConfigProps | ValidatingProps | ActiveProps | InvalidCredentialsProps | DeletingProps;
62
+ type DirectorySyncProps = WidgetRootDomProps & DirectorySyncStatusProps;
63
+ declare const DirectorySync: React.FC<DirectorySyncProps>;
64
+ interface DirectorySyncLoadingProps extends WidgetRootDomProps {
65
+ }
66
+ declare const DirectorySyncLoading: React.FC<DirectorySyncLoadingProps>;
67
+ interface DirectorySyncErrorProps extends WidgetRootDomProps {
68
+ error: unknown;
69
+ }
70
+ declare const DirectorySyncError: React.FC<DirectorySyncErrorProps>;
71
+
72
+ export { DirectorySync, DirectorySyncError, type DirectorySyncErrorProps, DirectorySyncLoading, type DirectorySyncLoadingProps, type DirectorySyncProps, type DirectorySyncStatusProps };