@workos-inc/widgets 1.8.0 → 1.8.2

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 (90) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/api/endpoint.cjs +4 -1
  3. package/dist/cjs/api/endpoint.cjs.map +1 -1
  4. package/dist/cjs/api/endpoint.d.cts +17 -9
  5. package/dist/cjs/experimental/api/fetch.cjs +1083 -0
  6. package/dist/cjs/experimental/api/fetch.cjs.map +1 -0
  7. package/dist/cjs/experimental/api/fetch.d.cts +1871 -0
  8. package/dist/cjs/experimental/api/react-query.cjs +1863 -0
  9. package/dist/cjs/experimental/api/react-query.cjs.map +1 -0
  10. package/dist/cjs/experimental/api/react-query.d.cts +2685 -0
  11. package/dist/cjs/experimental/api/swr.cjs +1972 -0
  12. package/dist/cjs/experimental/api/swr.cjs.map +1 -0
  13. package/dist/cjs/experimental/api/swr.d.cts +2585 -0
  14. package/dist/cjs/lib/add-mfa-dialog.cjs +2 -2
  15. package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
  16. package/dist/cjs/lib/admin-portal-domain-verification.cjs.map +1 -1
  17. package/dist/cjs/lib/api/user.d.cts +2 -2
  18. package/dist/cjs/lib/api-keys/api-keys-search.cjs +2 -2
  19. package/dist/cjs/lib/api-keys/api-keys-search.cjs.map +1 -1
  20. package/dist/cjs/lib/api-keys/create-api-key.cjs +8 -8
  21. package/dist/cjs/lib/api-keys/create-api-key.cjs.map +1 -1
  22. package/dist/cjs/lib/change-password-dialog.cjs +18 -18
  23. package/dist/cjs/lib/change-password-dialog.cjs.map +1 -1
  24. package/dist/cjs/lib/copy-button.cjs.map +1 -1
  25. package/dist/cjs/lib/edit-user-profile-dialog.cjs +8 -8
  26. package/dist/cjs/lib/edit-user-profile-dialog.cjs.map +1 -1
  27. package/dist/cjs/lib/elements/utils.cjs +3 -4
  28. package/dist/cjs/lib/elements/utils.cjs.map +1 -1
  29. package/dist/cjs/lib/elements.cjs.map +1 -1
  30. package/dist/cjs/lib/elevated-access.cjs +2 -2
  31. package/dist/cjs/lib/elevated-access.cjs.map +1 -1
  32. package/dist/cjs/lib/marker.cjs.map +1 -1
  33. package/dist/cjs/lib/organization-switcher.cjs.map +1 -1
  34. package/dist/cjs/lib/otp-input.cjs +6 -7
  35. package/dist/cjs/lib/otp-input.cjs.map +1 -1
  36. package/dist/cjs/lib/provider-icon.cjs.map +1 -1
  37. package/dist/cjs/lib/set-password-dialog.cjs +12 -12
  38. package/dist/cjs/lib/set-password-dialog.cjs.map +1 -1
  39. package/dist/cjs/lib/status.cjs.map +1 -1
  40. package/dist/cjs/lib/users-search.cjs +2 -2
  41. package/dist/cjs/lib/users-search.cjs.map +1 -1
  42. package/dist/cjs/organization-switcher.client.cjs.map +1 -1
  43. package/dist/esm/api/endpoint.d.ts +17 -9
  44. package/dist/esm/api/endpoint.js +4 -1
  45. package/dist/esm/api/endpoint.js.map +1 -1
  46. package/dist/esm/experimental/api/fetch.d.ts +1871 -0
  47. package/dist/esm/experimental/api/fetch.js +954 -0
  48. package/dist/esm/experimental/api/fetch.js.map +1 -0
  49. package/dist/esm/experimental/api/react-query.d.ts +2685 -0
  50. package/dist/esm/experimental/api/react-query.js +1641 -0
  51. package/dist/esm/experimental/api/react-query.js.map +1 -0
  52. package/dist/esm/experimental/api/swr.d.ts +2585 -0
  53. package/dist/esm/experimental/api/swr.js +1731 -0
  54. package/dist/esm/experimental/api/swr.js.map +1 -0
  55. package/dist/esm/lib/add-mfa-dialog.js +1 -1
  56. package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
  57. package/dist/esm/lib/admin-portal-domain-verification.js.map +1 -1
  58. package/dist/esm/lib/api/user.d.ts +2 -2
  59. package/dist/esm/lib/api-keys/api-keys-search.js +1 -1
  60. package/dist/esm/lib/api-keys/api-keys-search.js.map +1 -1
  61. package/dist/esm/lib/api-keys/create-api-key.js +1 -1
  62. package/dist/esm/lib/api-keys/create-api-key.js.map +1 -1
  63. package/dist/esm/lib/change-password-dialog.js +1 -1
  64. package/dist/esm/lib/change-password-dialog.js.map +1 -1
  65. package/dist/esm/lib/copy-button.js.map +1 -1
  66. package/dist/esm/lib/edit-user-profile-dialog.js +1 -1
  67. package/dist/esm/lib/edit-user-profile-dialog.js.map +1 -1
  68. package/dist/esm/lib/elements/utils.js +1 -2
  69. package/dist/esm/lib/elements/utils.js.map +1 -1
  70. package/dist/esm/lib/elements.js.map +1 -1
  71. package/dist/esm/lib/elevated-access.js +1 -1
  72. package/dist/esm/lib/elevated-access.js.map +1 -1
  73. package/dist/esm/lib/marker.js.map +1 -1
  74. package/dist/esm/lib/organization-switcher.js.map +1 -1
  75. package/dist/esm/lib/otp-input.js +6 -3
  76. package/dist/esm/lib/otp-input.js.map +1 -1
  77. package/dist/esm/lib/provider-icon.js.map +1 -1
  78. package/dist/esm/lib/set-password-dialog.js +1 -1
  79. package/dist/esm/lib/set-password-dialog.js.map +1 -1
  80. package/dist/esm/lib/status.js.map +1 -1
  81. package/dist/esm/lib/users-search.js +1 -1
  82. package/dist/esm/lib/users-search.js.map +1 -1
  83. package/dist/esm/organization-switcher.client.js.map +1 -1
  84. package/package.json +33 -23
  85. package/dist/cjs/lib/use-layout-effect.cjs +0 -31
  86. package/dist/cjs/lib/use-layout-effect.cjs.map +0 -1
  87. package/dist/cjs/lib/use-layout-effect.d.cts +0 -5
  88. package/dist/esm/lib/use-layout-effect.d.ts +0 -5
  89. package/dist/esm/lib/use-layout-effect.js +0 -7
  90. package/dist/esm/lib/use-layout-effect.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { Members200, Members403, Members404, useUpdateMember, useInviteMember, RemoveMember200, RemoveMember400, RemoveMember403, RemoveMember404, RevokeInvite200, RevokeInvite400, RevokeInvite403, RevokeInvite404, ResendInvite201, ResendInvite400, ResendInvite403, ResendInvite404 } from '../../api/endpoint.js';
2
+ import { Members200, Members403, Members404, useUpdateMember, useInviteMember, RemoveMember200, RemoveMember400, RemoveMember403, RemoveMember404, RevokeInvite200, RevokeInvite400, RevokeInvite403, RevokeInvite404, ResendInvite201, ResendInvite400, ResendInvite403, ResendInvite404, ResendInvite422 } from '../../api/endpoint.js';
3
3
  import { UsersManagementContextType } from '../users-management-context.js';
4
4
  import '../../api/widgets-api-client.js';
5
5
  import 'react';
@@ -19,7 +19,7 @@ declare const useDeleteUser: () => _tanstack_react_query.UseMutationResult<Remov
19
19
  declare const useRevokeUserInvite: () => _tanstack_react_query.UseMutationResult<RevokeInvite200, RevokeInvite400 | RevokeInvite403 | RevokeInvite404, {
20
20
  userId: string;
21
21
  }, unknown>;
22
- declare const useResendUserInvite: () => _tanstack_react_query.UseMutationResult<ResendInvite201, ResendInvite400 | ResendInvite403 | ResendInvite404, {
22
+ declare const useResendUserInvite: () => _tanstack_react_query.UseMutationResult<ResendInvite201, ResendInvite400 | ResendInvite403 | ResendInvite404 | ResendInvite422, {
23
23
  userId: string;
24
24
  }, unknown>;
25
25
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
3
+ import { useComposedRefs } from "radix-ui/internal";
4
4
  import { Cross2Icon, MagnifyingGlassIcon } from "@radix-ui/react-icons";
5
5
  import cx from "clsx";
6
6
  import * as React from "react";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/api-keys/api-keys-search.tsx"],"sourcesContent":["\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Cross2Icon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport cx from \"clsx\";\nimport * as React from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { IconButton, TextField, TextFieldSlot } from \"../elements.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { namespaceClassNames } from \"../utils.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\n\ntype ApiKeysSearchProps = React.ComponentPropsWithoutRef<typeof TextField>;\n\nexport const ApiKeysSearch = React.forwardRef<\n HTMLInputElement,\n ApiKeysSearchProps\n>(({ className, ...props }, ref) => {\n const { inputRef, clearSearch, searchValue, setSearchValue } =\n useApiKeysSearchContext();\n const { dispatch } = useApiKeysContext();\n const translate = useTranslation();\n\n const filter = useDebouncedCallback((value) => {\n dispatch({ type: \"FILTER_BY_SEARCH\", searchQuery: value });\n }, 200);\n\n const resetSearch = () => {\n clearSearch();\n filter.cancel();\n };\n\n return (\n <TextField\n ref={useComposedRefs(inputRef, ref)}\n className={cx(namespaceClassNames(\"api-keys-search\"), className)}\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"GC8aGI\",\n description: \"Placeholder for API key search input\",\n })}\n value={searchValue}\n onChange={(event) => {\n const value = event.target.value;\n setSearchValue(value);\n filter(value);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n resetSearch();\n }\n }}\n {...props}\n >\n <TextFieldSlot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextFieldSlot>\n\n <TextFieldSlot side=\"right\">\n {!!searchValue && (\n <IconButton\n size=\"1\"\n onClick={resetSearch}\n title={translate({\n defaultMessage: \"Clear search\",\n id: \"7enwzK\",\n description: \"Title tooltip for clear search button\",\n })}\n >\n <Cross2Icon aria-hidden=\"true\" />\n </IconButton>\n )}\n </TextFieldSlot>\n </TextField>\n );\n});\n"],"mappings":";AAkCI,SAwBI,KAxBJ;AAhCJ,SAAS,uBAAuB;AAChC,SAAS,YAAY,2BAA2B;AAChD,OAAO,QAAQ;AACf,YAAY,WAAW;AACvB,SAAS,4BAA4B;AACrC,SAAS,YAAY,WAAW,qBAAqB;AACrD,SAAS,+BAA+B;AACxC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAIxB,MAAM,gBAAgB,MAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,EAAE,UAAU,aAAa,aAAa,eAAe,IACzD,wBAAwB;AAC1B,QAAM,EAAE,SAAS,IAAI,kBAAkB;AACvC,QAAM,YAAY,eAAe;AAEjC,QAAM,SAAS,qBAAqB,CAAC,UAAU;AAC7C,aAAS,EAAE,MAAM,oBAAoB,aAAa,MAAM,CAAC;AAAA,EAC3D,GAAG,GAAG;AAEN,QAAM,cAAc,MAAM;AACxB,gBAAY;AACZ,WAAO,OAAO;AAAA,EAChB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,gBAAgB,UAAU,GAAG;AAAA,MAClC,WAAW,GAAG,oBAAoB,iBAAiB,GAAG,SAAS;AAAA,MAC/D,cAAa;AAAA,MACb,aAAa,UAAU;AAAA,QACrB,gBAAgB;AAAA,QAChB,IAAI;AAAA,QACJ,aAAa;AAAA,MACf,CAAC;AAAA,MACD,OAAO;AAAA,MACP,UAAU,CAAC,UAAU;AACnB,cAAM,QAAQ,MAAM,OAAO;AAC3B,uBAAe,KAAK;AACpB,eAAO,KAAK;AAAA,MACd;AAAA,MACA,WAAW,CAAC,UAAU;AACpB,YAAI,MAAM,QAAQ,UAAU;AAC1B,gBAAM,eAAe;AACrB,sBAAY;AAAA,QACd;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,iBAAc,MAAK,QAClB,8BAAC,uBAAoB,eAAY,QAAO,QAAO,MAAK,OAAM,MAAK,GACjE;AAAA,QAEA,oBAAC,iBAAc,MAAK,SACjB,WAAC,CAAC,eACD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,OAAO,UAAU;AAAA,cACf,gBAAgB;AAAA,cAChB,IAAI;AAAA,cACJ,aAAa;AAAA,YACf,CAAC;AAAA,YAED,8BAAC,cAAW,eAAY,QAAO;AAAA;AAAA,QACjC,GAEJ;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/api-keys/api-keys-search.tsx"],"sourcesContent":["\"use client\";\n\nimport { useComposedRefs } from \"radix-ui/internal\";\nimport { Cross2Icon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport cx from \"clsx\";\nimport * as React from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { IconButton, TextField, TextFieldSlot } from \"../elements.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { namespaceClassNames } from \"../utils.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\n\ntype ApiKeysSearchProps = React.ComponentPropsWithoutRef<typeof TextField>;\n\nexport const ApiKeysSearch = React.forwardRef<\n HTMLInputElement,\n ApiKeysSearchProps\n>(({ className, ...props }, ref) => {\n const { inputRef, clearSearch, searchValue, setSearchValue } =\n useApiKeysSearchContext();\n const { dispatch } = useApiKeysContext();\n const translate = useTranslation();\n\n const filter = useDebouncedCallback((value) => {\n dispatch({ type: \"FILTER_BY_SEARCH\", searchQuery: value });\n }, 200);\n\n const resetSearch = () => {\n clearSearch();\n filter.cancel();\n };\n\n return (\n <TextField\n ref={useComposedRefs(inputRef, ref)}\n className={cx(namespaceClassNames(\"api-keys-search\"), className)}\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"GC8aGI\",\n description: \"Placeholder for API key search input\",\n })}\n value={searchValue}\n onChange={(event) => {\n const value = event.target.value;\n setSearchValue(value);\n filter(value);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n resetSearch();\n }\n }}\n {...props}\n >\n <TextFieldSlot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextFieldSlot>\n\n <TextFieldSlot side=\"right\">\n {!!searchValue && (\n <IconButton\n size=\"1\"\n onClick={resetSearch}\n title={translate({\n defaultMessage: \"Clear search\",\n id: \"7enwzK\",\n description: \"Title tooltip for clear search button\",\n })}\n >\n <Cross2Icon aria-hidden=\"true\" />\n </IconButton>\n )}\n </TextFieldSlot>\n </TextField>\n );\n});\n"],"mappings":";AAkCI,SAwBI,KAxBJ;AAhCJ,SAAS,uBAAuB;AAChC,SAAS,YAAY,2BAA2B;AAChD,OAAO,QAAQ;AACf,YAAY,WAAW;AACvB,SAAS,4BAA4B;AACrC,SAAS,YAAY,WAAW,qBAAqB;AACrD,SAAS,+BAA+B;AACxC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAIxB,MAAM,gBAAgB,MAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,EAAE,UAAU,aAAa,aAAa,eAAe,IACzD,wBAAwB;AAC1B,QAAM,EAAE,SAAS,IAAI,kBAAkB;AACvC,QAAM,YAAY,eAAe;AAEjC,QAAM,SAAS,qBAAqB,CAAC,UAAU;AAC7C,aAAS,EAAE,MAAM,oBAAoB,aAAa,MAAM,CAAC;AAAA,EAC3D,GAAG,GAAG;AAEN,QAAM,cAAc,MAAM;AACxB,gBAAY;AACZ,WAAO,OAAO;AAAA,EAChB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,gBAAgB,UAAU,GAAG;AAAA,MAClC,WAAW,GAAG,oBAAoB,iBAAiB,GAAG,SAAS;AAAA,MAC/D,cAAa;AAAA,MACb,aAAa,UAAU;AAAA,QACrB,gBAAgB;AAAA,QAChB,IAAI;AAAA,QACJ,aAAa;AAAA,MACf,CAAC;AAAA,MACD,OAAO;AAAA,MACP,UAAU,CAAC,UAAU;AACnB,cAAM,QAAQ,MAAM,OAAO;AAC3B,uBAAe,KAAK;AACpB,eAAO,KAAK;AAAA,MACd;AAAA,MACA,WAAW,CAAC,UAAU;AACpB,YAAI,MAAM,QAAQ,UAAU;AAC1B,gBAAM,eAAe;AACrB,sBAAY;AAAA,QACd;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,iBAAc,MAAK,QAClB,8BAAC,uBAAoB,eAAY,QAAO,QAAO,MAAK,OAAM,MAAK,GACjE;AAAA,QAEA,oBAAC,iBAAc,MAAK,SACjB,WAAC,CAAC,eACD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,OAAO,UAAU;AAAA,cACf,gBAAgB;AAAA,cAChB,IAAI;AAAA,cACJ,aAAa;AAAA,YACf,CAAC;AAAA,YAED,8BAAC,cAAW,eAAY,QAAO;AAAA;AAAA,QACjC,GAEJ;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;","names":[]}
@@ -14,7 +14,7 @@ import {
14
14
  TextField,
15
15
  TextFieldSlot
16
16
  } from "../elements.js";
17
- import * as Form from "@radix-ui/react-form";
17
+ import { Form } from "radix-ui";
18
18
  import {
19
19
  ExclamationTriangleIcon,
20
20
  InfoCircledIcon,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/api-keys/create-api-key.tsx"],"sourcesContent":["import {\n Box,\n Checkbox,\n Flex,\n ScrollArea,\n Text,\n Callout,\n} from \"@radix-ui/themes\";\nimport {\n Dialog,\n Label,\n Button,\n TextField,\n TextFieldSlot,\n} from \"../elements.js\";\nimport * as Form from \"@radix-ui/react-form\";\nimport {\n ExclamationTriangleIcon,\n InfoCircledIcon,\n MagnifyingGlassIcon,\n} from \"@radix-ui/react-icons\";\nimport { CopyButton, CopyIconButton } from \"../copy-button.js\";\nimport * as React from \"react\";\nimport {\n useListOrganizationApiKeyPermissions,\n ListOrganizationApiKeyPermission,\n} from \"../../api/endpoint.js\";\nimport { useCreateApiKey } from \"../api/api-key.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\n\nexport function CreateApiKeyDialog() {\n const {\n state: { createDialogOpen, createdApiKey },\n dispatch,\n } = useApiKeysContext();\n\n return (\n <Dialog.Root\n open={createDialogOpen}\n onOpenChange={(open) => {\n if (!open) {\n dispatch({ type: \"CLOSE_CREATE_DIALOG\" });\n }\n }}\n >\n {createdApiKey ? (\n <SaveApiKeyContent apiKey={createdApiKey.value} />\n ) : (\n <CreateApiKeyForm\n // always remount the form when the dialog is opened to reset the validation errors\n key={`${createDialogOpen}`}\n />\n )}\n </Dialog.Root>\n );\n}\n\nfunction CreateApiKeyForm() {\n const { dispatch } = useApiKeysContext();\n const translate = useTranslation();\n const [errors, setErrors] = React.useState<{\n name: boolean;\n }>({ name: false });\n\n const validate = (formData: FormData) => {\n const name = formData.get(\"name\")?.toString() ?? \"\";\n const errors = { name: !name.trim().length };\n setErrors(errors);\n const isValid = Object.values(errors).every((error) => error === false);\n return isValid;\n };\n\n const {\n mutate: createOrganizationApiKey,\n error,\n isPending,\n isSuccess,\n } = useCreateApiKey();\n const permissions = useListOrganizationApiKeyPermissions({ limit: 100 });\n\n return (\n <Dialog.Content maxWidth=\"529px\">\n <Dialog.Title size=\"4\" weight={\"bold\"}>\n <Translation\n defaultMessage=\"Create API key\"\n id=\"eUFRNS\"\n description=\"Dialog title for creating a new API key\"\n />\n </Dialog.Title>\n <Form.Root\n onSubmit={(e) => {\n if (isPending) return;\n e.preventDefault();\n const data = new FormData(e.currentTarget);\n const isValid = validate(data);\n if (!isValid) {\n return;\n }\n\n createOrganizationApiKey(\n {\n data: {\n name: data.get(\"name\")?.toString() ?? \"\",\n permissions: data.getAll(\"permission\").map(String) || [],\n },\n },\n {\n onSuccess: (data) => {\n dispatch({ type: \"SET_CREATED_API_KEY\", apiKey: data });\n },\n },\n );\n }}\n >\n <Flex direction=\"column\" align=\"stretch\" gap=\"4\">\n {error && (\n <Callout.Root color=\"red\" role=\"alert\">\n <Callout.Icon>\n <ExclamationTriangleIcon />\n </Callout.Icon>\n <Callout.Text>\n <Translation\n defaultMessage=\"An error occurred while creating the API key.\"\n id=\"0LyBVd\"\n description=\"Error message when API key creation fails\"\n />\n </Callout.Text>\n </Callout.Root>\n )}\n <Form.Field name=\"name\" asChild>\n <Flex direction=\"column\" align=\"stretch\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Name\"\n id=\"v0VmRy\"\n description=\"Label for API key name input field\"\n />\n </Label>\n </Form.Label>\n <Form.Control asChild>\n <TextField\n data-1p-ignore\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"A descriptive name for the API key\",\n id: \"moyvr4\",\n description: \"Placeholder for API key name input\",\n })}\n />\n </Form.Control>\n {errors.name && (\n <Form.Message asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"The name is required\"\n id=\"oF9d2V\"\n description=\"Validation error when API key name is empty\"\n />\n </Text>\n </Form.Message>\n )}\n </Flex>\n </Form.Field>\n {permissions.isSuccess && permissions.data.data.length > 0 && (\n <PermissionsField permissions={permissions.data.data} />\n )}\n </Flex>\n\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\" disabled={isPending || isSuccess}>\n <Translation\n defaultMessage=\"Cancel\"\n id=\"AyVAAW\"\n description=\"Button to cancel API key creation\"\n />\n </Button>\n </Dialog.Close>\n <Button type=\"submit\" loading={isPending || isSuccess}>\n <Translation\n defaultMessage=\"Create API key\"\n id=\"d4BNWL\"\n description=\"Button to submit and create the API key\"\n />\n </Button>\n </Flex>\n </Form.Root>\n </Dialog.Content>\n );\n}\n\nfunction SaveApiKeyContent({ apiKey }: { apiKey: string }) {\n return (\n <Dialog.Content maxWidth=\"529px\">\n <Dialog.Title size=\"4\" weight={\"bold\"}>\n <Translation\n defaultMessage=\"Save your key\"\n id=\"wFFCij\"\n description=\"Dialog title prompting user to save their API key\"\n />\n </Dialog.Title>\n <Dialog.Description size=\"2\">\n <Translation\n defaultMessage=\"Please save this API key in a secure location. If you lose it, you'll need to generate a new one.\"\n id=\"sy+2x7\"\n description=\"Warning message about saving the API key\"\n />\n </Dialog.Description>\n <Callout.Root mt=\"5\" mb=\"4\">\n <Callout.Icon>\n <InfoCircledIcon />\n </Callout.Icon>\n <Callout.Text>\n <Translation\n defaultMessage=\"You won't be able to access the key again. Please copy it now.\"\n id=\"EFAK/K\"\n description=\"Callout warning that the key won't be accessible again\"\n />\n </Callout.Text>\n </Callout.Root>\n <TextField value={apiKey} readOnly>\n <TextFieldSlot side=\"right\">\n <CopyIconButton value={apiKey} />\n </TextFieldSlot>\n </TextField>\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <CopyButton value={apiKey}>\n <Translation\n defaultMessage=\"Copy and close\"\n id=\"ViYtvQ\"\n description=\"Button to copy API key and close dialog\"\n />\n </CopyButton>\n </Dialog.Close>\n </Flex>\n </Dialog.Content>\n );\n}\n\nfunction Permission({\n checked,\n permission,\n onChange,\n}: {\n checked: boolean;\n permission: ListOrganizationApiKeyPermission;\n onChange: (isChecked: boolean) => void;\n}) {\n return (\n <label\n htmlFor={permission.slug}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n padding: \"var(--space-2) var(--space-4)\",\n gap: \"var(--space-3)\",\n borderBottom: \"1px solid var(--gray-6)\",\n cursor: \"pointer\",\n }}\n >\n <Checkbox\n checked={checked}\n id={permission.slug}\n name=\"permission\"\n value={permission.slug}\n onCheckedChange={(e) => onChange(e === \"indeterminate\" ? false : e)}\n />\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {permission.name}\n </Text>\n <Text size=\"2\" color=\"gray\">\n {permission.description}\n </Text>\n </Flex>\n </label>\n );\n}\n\nfunction PermissionsField({\n permissions = [],\n}: {\n permissions: ListOrganizationApiKeyPermission[];\n}) {\n const [selectedPermissions, setSelectedPermissions] = React.useState<\n ListOrganizationApiKeyPermission[]\n >([]);\n const [filter, setFilter] = React.useState(\"\");\n const fieldRef = React.useRef<HTMLDivElement | null>(null);\n const translate = useTranslation();\n const filteredPermissions = React.useMemo(() => {\n return permissions.filter((p) => {\n return (\n !filter.trim().length ||\n p.description?.toLowerCase().match(filter.toLowerCase()) ||\n p.name.toLowerCase().match(filter.toLowerCase()) ||\n p.slug.toLowerCase().match(filter.toLowerCase())\n );\n });\n }, [permissions, filter]);\n\n React.useEffect(() => {\n const onResize = () => {\n if (fieldRef.current && filteredPermissions.length !== 0) {\n fieldRef.current.style.minHeight = \"unset\";\n }\n };\n window.addEventListener(\"resize\", onResize);\n return () => {\n window.removeEventListener(\"resize\", onResize);\n };\n }, [filteredPermissions.length]);\n\n return (\n <Form.Field name=\"permissions\" asChild>\n <Flex direction=\"column\" align=\"stretch\" gap=\"1\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Permissions\"\n id=\"6YN1wO\"\n description=\"Label for API key permissions field\"\n />\n </Label>\n </Form.Label>\n <Text size=\"2\" mb=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"Only enable the minimum permissions required for your use case.\"\n id=\"q2VEtG\"\n description=\"Help text for API key permissions selection\"\n />\n </Text>\n <Flex\n ref={fieldRef}\n style={{\n borderRadius: \"var(--radius-3)\",\n borderColor: \"var(--gray-6)\",\n borderWidth: \"1px\",\n borderStyle: \"solid\",\n }}\n direction=\"column\"\n align=\"stretch\"\n >\n <TextField\n name=\"search\"\n value={filter}\n size=\"2\"\n onChange={(e) => {\n if (fieldRef.current) {\n fieldRef.current.style.minHeight =\n fieldRef.current.clientHeight + 2 + \"px\";\n }\n setFilter(e.target.value);\n }}\n style={{\n height: \"40px\",\n borderRadius: \"var(--radius-3) var(--radius-3) 0 0\",\n boxShadow: \"none\",\n }}\n placeholder={translate({\n defaultMessage: \"Search\",\n id: \"iyNcly\",\n description: \"Placeholder for permissions search input\",\n })}\n >\n <TextFieldSlot side=\"left\" px=\"3\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextFieldSlot>\n </TextField>\n {filteredPermissions.length > 0 ? (\n <>\n <ScrollArea\n scrollbars=\"vertical\"\n style={{\n flex: 1,\n maxHeight: \"calc(50vh - 150px)\",\n border: \"1px solid var(--gray-6)\",\n borderWidth: \"1px 0 0\",\n }}\n >\n {filteredPermissions.map((permission) => (\n <Permission\n checked={selectedPermissions.some(\n (sp) => sp.slug === permission.slug,\n )}\n key={permission.slug}\n permission={permission}\n onChange={(isChecked) =>\n setSelectedPermissions((prev) =>\n isChecked\n ? [...prev, permission]\n : prev.filter((sp) => sp.slug !== permission.slug),\n )\n }\n />\n ))}\n </ScrollArea>\n <Box\n px=\"4\"\n py=\"3\"\n mt={\"-1px\"}\n flexGrow=\"0\"\n style={{\n borderTop: \"0 solid var(--gray-6)\",\n borderWidth: \"1px 0 0\",\n }}\n >\n <SelectedPermissions\n total={permissions.length}\n selected={selectedPermissions.length}\n onToggle={() =>\n setSelectedPermissions((prev) =>\n prev.length === permissions.length ? [] : permissions,\n )\n }\n />\n </Box>\n </>\n ) : (\n <Flex\n gap=\"4\"\n pt=\"6\"\n pb=\"6\"\n style={{ borderTop: \"1px solid var(--gray-6)\" }}\n flexGrow=\"1\"\n justify=\"center\"\n align=\"center\"\n direction=\"column\"\n >\n <MagnifyingGlassIcon\n style={{\n color: \"var(--gray-9)\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n }}\n />\n <Text size=\"2\" align=\"center\" mb=\"2\" wrap=\"balance\" weight=\"bold\">\n <Translation\n defaultMessage=\"No permissions match your search\"\n id=\"xjqT9f\"\n description=\"Empty state message when no permissions match search\"\n />\n </Text>\n <Button\n variant=\"secondary\"\n size=\"1\"\n onClick={() => setFilter(\"\")}\n >\n <Translation\n defaultMessage=\"Clear search\"\n id=\"YrMs63\"\n description=\"Button to clear permissions search\"\n />\n </Button>\n </Flex>\n )}\n </Flex>\n </Flex>\n </Form.Field>\n );\n}\n\nfunction SelectedPermissions({\n total,\n selected,\n onToggle,\n}: {\n total: number;\n selected: number;\n onToggle: () => void;\n}) {\n return (\n <Flex align=\"center\" gap=\"2\">\n <Text size=\"1\" style={{ lineHeight: 1, color: \"var(--gray-11)\" }}>\n {selected === 0 ? (\n <Translation\n defaultMessage=\"No permissions selected\"\n id=\"FqU9hv\"\n description=\"Message when no permissions are selected\"\n />\n ) : selected === 1 ? (\n <Translation\n defaultMessage=\"1 permission selected\"\n id=\"VouLgT\"\n description=\"Message showing count of selected permissions\"\n />\n ) : (\n <Translation\n defaultMessage=\"{count} permissions selected\"\n id=\"ZL90DI\"\n description=\"Message showing count of selected permissions\"\n values={{ count: selected }}\n />\n )}\n </Text>\n <Text\n size=\"1\"\n onClick={onToggle}\n style={{ cursor: \"pointer\", color: \"var(--accent-10)\" }}\n >\n {total === selected ? (\n <Translation\n defaultMessage=\"Deselect all\"\n id=\"63f7SY\"\n description=\"Button to deselect all permissions\"\n />\n ) : (\n <Translation\n defaultMessage=\"Select all\"\n id=\"onTqlA\"\n description=\"Button to select all permissions\"\n />\n )}\n </Text>\n </Flex>\n );\n}\n\nexport function CreateApiKeyButton() {\n const { dispatch } = useApiKeysContext();\n return (\n <Button\n variant=\"secondary\"\n onClick={() => dispatch({ type: \"OPEN_CREATE_DIALOG\" })}\n >\n <Translation\n defaultMessage=\"Create API key\"\n id=\"vq5724\"\n description=\"Button to open create API key dialog\"\n />\n </Button>\n );\n}\n"],"mappings":"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","names":["errors","error","data"]}
1
+ {"version":3,"sources":["../../../../src/lib/api-keys/create-api-key.tsx"],"sourcesContent":["import {\n Box,\n Checkbox,\n Flex,\n ScrollArea,\n Text,\n Callout,\n} from \"@radix-ui/themes\";\nimport {\n Dialog,\n Label,\n Button,\n TextField,\n TextFieldSlot,\n} from \"../elements.js\";\nimport { Form } from \"radix-ui\";\nimport {\n ExclamationTriangleIcon,\n InfoCircledIcon,\n MagnifyingGlassIcon,\n} from \"@radix-ui/react-icons\";\nimport { CopyButton, CopyIconButton } from \"../copy-button.js\";\nimport * as React from \"react\";\nimport {\n useListOrganizationApiKeyPermissions,\n ListOrganizationApiKeyPermission,\n} from \"../../api/endpoint.js\";\nimport { useCreateApiKey } from \"../api/api-key.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\n\nexport function CreateApiKeyDialog() {\n const {\n state: { createDialogOpen, createdApiKey },\n dispatch,\n } = useApiKeysContext();\n\n return (\n <Dialog.Root\n open={createDialogOpen}\n onOpenChange={(open) => {\n if (!open) {\n dispatch({ type: \"CLOSE_CREATE_DIALOG\" });\n }\n }}\n >\n {createdApiKey ? (\n <SaveApiKeyContent apiKey={createdApiKey.value} />\n ) : (\n <CreateApiKeyForm\n // always remount the form when the dialog is opened to reset the validation errors\n key={`${createDialogOpen}`}\n />\n )}\n </Dialog.Root>\n );\n}\n\nfunction CreateApiKeyForm() {\n const { dispatch } = useApiKeysContext();\n const translate = useTranslation();\n const [errors, setErrors] = React.useState<{\n name: boolean;\n }>({ name: false });\n\n const validate = (formData: FormData) => {\n const name = formData.get(\"name\")?.toString() ?? \"\";\n const errors = { name: !name.trim().length };\n setErrors(errors);\n const isValid = Object.values(errors).every((error) => error === false);\n return isValid;\n };\n\n const {\n mutate: createOrganizationApiKey,\n error,\n isPending,\n isSuccess,\n } = useCreateApiKey();\n const permissions = useListOrganizationApiKeyPermissions({ limit: 100 });\n\n return (\n <Dialog.Content maxWidth=\"529px\">\n <Dialog.Title size=\"4\" weight={\"bold\"}>\n <Translation\n defaultMessage=\"Create API key\"\n id=\"eUFRNS\"\n description=\"Dialog title for creating a new API key\"\n />\n </Dialog.Title>\n <Form.Root\n onSubmit={(e) => {\n if (isPending) return;\n e.preventDefault();\n const data = new FormData(e.currentTarget);\n const isValid = validate(data);\n if (!isValid) {\n return;\n }\n\n createOrganizationApiKey(\n {\n data: {\n name: data.get(\"name\")?.toString() ?? \"\",\n permissions: data.getAll(\"permission\").map(String) || [],\n },\n },\n {\n onSuccess: (data) => {\n dispatch({ type: \"SET_CREATED_API_KEY\", apiKey: data });\n },\n },\n );\n }}\n >\n <Flex direction=\"column\" align=\"stretch\" gap=\"4\">\n {error && (\n <Callout.Root color=\"red\" role=\"alert\">\n <Callout.Icon>\n <ExclamationTriangleIcon />\n </Callout.Icon>\n <Callout.Text>\n <Translation\n defaultMessage=\"An error occurred while creating the API key.\"\n id=\"0LyBVd\"\n description=\"Error message when API key creation fails\"\n />\n </Callout.Text>\n </Callout.Root>\n )}\n <Form.Field name=\"name\" asChild>\n <Flex direction=\"column\" align=\"stretch\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Name\"\n id=\"v0VmRy\"\n description=\"Label for API key name input field\"\n />\n </Label>\n </Form.Label>\n <Form.Control asChild>\n <TextField\n data-1p-ignore\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"A descriptive name for the API key\",\n id: \"moyvr4\",\n description: \"Placeholder for API key name input\",\n })}\n />\n </Form.Control>\n {errors.name && (\n <Form.Message asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"The name is required\"\n id=\"oF9d2V\"\n description=\"Validation error when API key name is empty\"\n />\n </Text>\n </Form.Message>\n )}\n </Flex>\n </Form.Field>\n {permissions.isSuccess && permissions.data.data.length > 0 && (\n <PermissionsField permissions={permissions.data.data} />\n )}\n </Flex>\n\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\" disabled={isPending || isSuccess}>\n <Translation\n defaultMessage=\"Cancel\"\n id=\"AyVAAW\"\n description=\"Button to cancel API key creation\"\n />\n </Button>\n </Dialog.Close>\n <Button type=\"submit\" loading={isPending || isSuccess}>\n <Translation\n defaultMessage=\"Create API key\"\n id=\"d4BNWL\"\n description=\"Button to submit and create the API key\"\n />\n </Button>\n </Flex>\n </Form.Root>\n </Dialog.Content>\n );\n}\n\nfunction SaveApiKeyContent({ apiKey }: { apiKey: string }) {\n return (\n <Dialog.Content maxWidth=\"529px\">\n <Dialog.Title size=\"4\" weight={\"bold\"}>\n <Translation\n defaultMessage=\"Save your key\"\n id=\"wFFCij\"\n description=\"Dialog title prompting user to save their API key\"\n />\n </Dialog.Title>\n <Dialog.Description size=\"2\">\n <Translation\n defaultMessage=\"Please save this API key in a secure location. If you lose it, you'll need to generate a new one.\"\n id=\"sy+2x7\"\n description=\"Warning message about saving the API key\"\n />\n </Dialog.Description>\n <Callout.Root mt=\"5\" mb=\"4\">\n <Callout.Icon>\n <InfoCircledIcon />\n </Callout.Icon>\n <Callout.Text>\n <Translation\n defaultMessage=\"You won't be able to access the key again. Please copy it now.\"\n id=\"EFAK/K\"\n description=\"Callout warning that the key won't be accessible again\"\n />\n </Callout.Text>\n </Callout.Root>\n <TextField value={apiKey} readOnly>\n <TextFieldSlot side=\"right\">\n <CopyIconButton value={apiKey} />\n </TextFieldSlot>\n </TextField>\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <CopyButton value={apiKey}>\n <Translation\n defaultMessage=\"Copy and close\"\n id=\"ViYtvQ\"\n description=\"Button to copy API key and close dialog\"\n />\n </CopyButton>\n </Dialog.Close>\n </Flex>\n </Dialog.Content>\n );\n}\n\nfunction Permission({\n checked,\n permission,\n onChange,\n}: {\n checked: boolean;\n permission: ListOrganizationApiKeyPermission;\n onChange: (isChecked: boolean) => void;\n}) {\n return (\n <label\n htmlFor={permission.slug}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n padding: \"var(--space-2) var(--space-4)\",\n gap: \"var(--space-3)\",\n borderBottom: \"1px solid var(--gray-6)\",\n cursor: \"pointer\",\n }}\n >\n <Checkbox\n checked={checked}\n id={permission.slug}\n name=\"permission\"\n value={permission.slug}\n onCheckedChange={(e) => onChange(e === \"indeterminate\" ? false : e)}\n />\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {permission.name}\n </Text>\n <Text size=\"2\" color=\"gray\">\n {permission.description}\n </Text>\n </Flex>\n </label>\n );\n}\n\nfunction PermissionsField({\n permissions = [],\n}: {\n permissions: ListOrganizationApiKeyPermission[];\n}) {\n const [selectedPermissions, setSelectedPermissions] = React.useState<\n ListOrganizationApiKeyPermission[]\n >([]);\n const [filter, setFilter] = React.useState(\"\");\n const fieldRef = React.useRef<HTMLDivElement | null>(null);\n const translate = useTranslation();\n const filteredPermissions = React.useMemo(() => {\n return permissions.filter((p) => {\n return (\n !filter.trim().length ||\n p.description?.toLowerCase().match(filter.toLowerCase()) ||\n p.name.toLowerCase().match(filter.toLowerCase()) ||\n p.slug.toLowerCase().match(filter.toLowerCase())\n );\n });\n }, [permissions, filter]);\n\n React.useEffect(() => {\n const onResize = () => {\n if (fieldRef.current && filteredPermissions.length !== 0) {\n fieldRef.current.style.minHeight = \"unset\";\n }\n };\n window.addEventListener(\"resize\", onResize);\n return () => {\n window.removeEventListener(\"resize\", onResize);\n };\n }, [filteredPermissions.length]);\n\n return (\n <Form.Field name=\"permissions\" asChild>\n <Flex direction=\"column\" align=\"stretch\" gap=\"1\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Permissions\"\n id=\"6YN1wO\"\n description=\"Label for API key permissions field\"\n />\n </Label>\n </Form.Label>\n <Text size=\"2\" mb=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"Only enable the minimum permissions required for your use case.\"\n id=\"q2VEtG\"\n description=\"Help text for API key permissions selection\"\n />\n </Text>\n <Flex\n ref={fieldRef}\n style={{\n borderRadius: \"var(--radius-3)\",\n borderColor: \"var(--gray-6)\",\n borderWidth: \"1px\",\n borderStyle: \"solid\",\n }}\n direction=\"column\"\n align=\"stretch\"\n >\n <TextField\n name=\"search\"\n value={filter}\n size=\"2\"\n onChange={(e) => {\n if (fieldRef.current) {\n fieldRef.current.style.minHeight =\n fieldRef.current.clientHeight + 2 + \"px\";\n }\n setFilter(e.target.value);\n }}\n style={{\n height: \"40px\",\n borderRadius: \"var(--radius-3) var(--radius-3) 0 0\",\n boxShadow: \"none\",\n }}\n placeholder={translate({\n defaultMessage: \"Search\",\n id: \"iyNcly\",\n description: \"Placeholder for permissions search input\",\n })}\n >\n <TextFieldSlot side=\"left\" px=\"3\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextFieldSlot>\n </TextField>\n {filteredPermissions.length > 0 ? (\n <>\n <ScrollArea\n scrollbars=\"vertical\"\n style={{\n flex: 1,\n maxHeight: \"calc(50vh - 150px)\",\n border: \"1px solid var(--gray-6)\",\n borderWidth: \"1px 0 0\",\n }}\n >\n {filteredPermissions.map((permission) => (\n <Permission\n checked={selectedPermissions.some(\n (sp) => sp.slug === permission.slug,\n )}\n key={permission.slug}\n permission={permission}\n onChange={(isChecked) =>\n setSelectedPermissions((prev) =>\n isChecked\n ? [...prev, permission]\n : prev.filter((sp) => sp.slug !== permission.slug),\n )\n }\n />\n ))}\n </ScrollArea>\n <Box\n px=\"4\"\n py=\"3\"\n mt={\"-1px\"}\n flexGrow=\"0\"\n style={{\n borderTop: \"0 solid var(--gray-6)\",\n borderWidth: \"1px 0 0\",\n }}\n >\n <SelectedPermissions\n total={permissions.length}\n selected={selectedPermissions.length}\n onToggle={() =>\n setSelectedPermissions((prev) =>\n prev.length === permissions.length ? [] : permissions,\n )\n }\n />\n </Box>\n </>\n ) : (\n <Flex\n gap=\"4\"\n pt=\"6\"\n pb=\"6\"\n style={{ borderTop: \"1px solid var(--gray-6)\" }}\n flexGrow=\"1\"\n justify=\"center\"\n align=\"center\"\n direction=\"column\"\n >\n <MagnifyingGlassIcon\n style={{\n color: \"var(--gray-9)\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n }}\n />\n <Text size=\"2\" align=\"center\" mb=\"2\" wrap=\"balance\" weight=\"bold\">\n <Translation\n defaultMessage=\"No permissions match your search\"\n id=\"xjqT9f\"\n description=\"Empty state message when no permissions match search\"\n />\n </Text>\n <Button\n variant=\"secondary\"\n size=\"1\"\n onClick={() => setFilter(\"\")}\n >\n <Translation\n defaultMessage=\"Clear search\"\n id=\"YrMs63\"\n description=\"Button to clear permissions search\"\n />\n </Button>\n </Flex>\n )}\n </Flex>\n </Flex>\n </Form.Field>\n );\n}\n\nfunction SelectedPermissions({\n total,\n selected,\n onToggle,\n}: {\n total: number;\n selected: number;\n onToggle: () => void;\n}) {\n return (\n <Flex align=\"center\" gap=\"2\">\n <Text size=\"1\" style={{ lineHeight: 1, color: \"var(--gray-11)\" }}>\n {selected === 0 ? (\n <Translation\n defaultMessage=\"No permissions selected\"\n id=\"FqU9hv\"\n description=\"Message when no permissions are selected\"\n />\n ) : selected === 1 ? (\n <Translation\n defaultMessage=\"1 permission selected\"\n id=\"VouLgT\"\n description=\"Message showing count of selected permissions\"\n />\n ) : (\n <Translation\n defaultMessage=\"{count} permissions selected\"\n id=\"ZL90DI\"\n description=\"Message showing count of selected permissions\"\n values={{ count: selected }}\n />\n )}\n </Text>\n <Text\n size=\"1\"\n onClick={onToggle}\n style={{ cursor: \"pointer\", color: \"var(--accent-10)\" }}\n >\n {total === selected ? (\n <Translation\n defaultMessage=\"Deselect all\"\n id=\"63f7SY\"\n description=\"Button to deselect all permissions\"\n />\n ) : (\n <Translation\n defaultMessage=\"Select all\"\n id=\"onTqlA\"\n description=\"Button to select all permissions\"\n />\n )}\n </Text>\n </Flex>\n );\n}\n\nexport function CreateApiKeyButton() {\n const { dispatch } = useApiKeysContext();\n return (\n <Button\n variant=\"secondary\"\n onClick={() => dispatch({ type: \"OPEN_CREATE_DIALOG\" })}\n >\n <Translation\n defaultMessage=\"Create API key\"\n id=\"vq5724\"\n description=\"Button to open create API key dialog\"\n />\n </Button>\n );\n}\n"],"mappings":"AAgDQ,SAsUI,UAtUJ,KAsEI,YAtEJ;AAhDR;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY,sBAAsB;AAC3C,YAAY,WAAW;AACvB;AAAA,EACE;AAAA,OAEK;AACP,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAExB,SAAS,qBAAqB;AACnC,QAAM;AAAA,IACJ,OAAO,EAAE,kBAAkB,cAAc;AAAA,IACzC;AAAA,EACF,IAAI,kBAAkB;AAEtB,SACE;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,MAAM;AAAA,MACN,cAAc,CAAC,SAAS;AACtB,YAAI,CAAC,MAAM;AACT,mBAAS,EAAE,MAAM,sBAAsB,CAAC;AAAA,QAC1C;AAAA,MACF;AAAA,MAEC,0BACC,oBAAC,qBAAkB,QAAQ,cAAc,OAAO,IAEhD;AAAA,QAAC;AAAA;AAAA,QAEM,GAAG,gBAAgB;AAAA,MAC1B;AAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,mBAAmB;AAC1B,QAAM,EAAE,SAAS,IAAI,kBAAkB;AACvC,QAAM,YAAY,eAAe;AACjC,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAE/B,EAAE,MAAM,MAAM,CAAC;AAElB,QAAM,WAAW,CAAC,aAAuB;AACvC,UAAM,OAAO,SAAS,IAAI,MAAM,GAAG,SAAS,KAAK;AACjD,UAAMA,UAAS,EAAE,MAAM,CAAC,KAAK,KAAK,EAAE,OAAO;AAC3C,cAAUA,OAAM;AAChB,UAAM,UAAU,OAAO,OAAOA,OAAM,EAAE,MAAM,CAACC,WAAUA,WAAU,KAAK;AACtE,WAAO;AAAA,EACT;AAEA,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,gBAAgB;AACpB,QAAM,cAAc,qCAAqC,EAAE,OAAO,IAAI,CAAC;AAEvE,SACE,qBAAC,OAAO,SAAP,EAAe,UAAS,SACvB;AAAA,wBAAC,OAAO,OAAP,EAAa,MAAK,KAAI,QAAQ,QAC7B;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,IACA;AAAA,MAAC,KAAK;AAAA,MAAL;AAAA,QACC,UAAU,CAAC,MAAM;AACf,cAAI,UAAW;AACf,YAAE,eAAe;AACjB,gBAAM,OAAO,IAAI,SAAS,EAAE,aAAa;AACzC,gBAAM,UAAU,SAAS,IAAI;AAC7B,cAAI,CAAC,SAAS;AACZ;AAAA,UACF;AAEA;AAAA,YACE;AAAA,cACE,MAAM;AAAA,gBACJ,MAAM,KAAK,IAAI,MAAM,GAAG,SAAS,KAAK;AAAA,gBACtC,aAAa,KAAK,OAAO,YAAY,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,cACzD;AAAA,YACF;AAAA,YACA;AAAA,cACE,WAAW,CAACC,UAAS;AACnB,yBAAS,EAAE,MAAM,uBAAuB,QAAQA,MAAK,CAAC;AAAA,cACxD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QAEA;AAAA,+BAAC,QAAK,WAAU,UAAS,OAAM,WAAU,KAAI,KAC1C;AAAA,qBACC,qBAAC,QAAQ,MAAR,EAAa,OAAM,OAAM,MAAK,SAC7B;AAAA,kCAAC,QAAQ,MAAR,EACC,8BAAC,2BAAwB,GAC3B;AAAA,cACA,oBAAC,QAAQ,MAAR,EACC;AAAA,gBAAC;AAAA;AAAA,kBACC,gBAAe;AAAA,kBACf,IAAG;AAAA,kBACH,aAAY;AAAA;AAAA,cACd,GACF;AAAA,eACF;AAAA,YAEF,oBAAC,KAAK,OAAL,EAAW,MAAK,QAAO,SAAO,MAC7B,+BAAC,QAAK,WAAU,UAAS,OAAM,WAAU,KAAI,KAC3C;AAAA,kCAAC,KAAK,OAAL,EAAW,SAAO,MACjB,8BAAC,SACC;AAAA,gBAAC;AAAA;AAAA,kBACC,gBAAe;AAAA,kBACf,IAAG;AAAA,kBACH,aAAY;AAAA;AAAA,cACd,GACF,GACF;AAAA,cACA,oBAAC,KAAK,SAAL,EAAa,SAAO,MACnB;AAAA,gBAAC;AAAA;AAAA,kBACC,kBAAc;AAAA,kBACd,cAAa;AAAA,kBACb,aAAa,UAAU;AAAA,oBACrB,gBAAgB;AAAA,oBAChB,IAAI;AAAA,oBACJ,aAAa;AAAA,kBACf,CAAC;AAAA;AAAA,cACH,GACF;AAAA,cACC,OAAO,QACN,oBAAC,KAAK,SAAL,EAAa,SAAO,MACnB,8BAAC,QAAK,MAAK,KAAI,OAAM,OACnB;AAAA,gBAAC;AAAA;AAAA,kBACC,gBAAe;AAAA,kBACf,IAAG;AAAA,kBACH,aAAY;AAAA;AAAA,cACd,GACF,GACF;AAAA,eAEJ,GACF;AAAA,YACC,YAAY,aAAa,YAAY,KAAK,KAAK,SAAS,KACvD,oBAAC,oBAAiB,aAAa,YAAY,KAAK,MAAM;AAAA,aAE1D;AAAA,UAEA,qBAAC,QAAK,OAAM,UAAS,KAAI,KAAI,SAAQ,OAAM,IAAG,KAC5C;AAAA,gCAAC,OAAO,OAAP,EACC,8BAAC,UAAO,SAAQ,aAAY,UAAU,aAAa,WACjD;AAAA,cAAC;AAAA;AAAA,gBACC,gBAAe;AAAA,gBACf,IAAG;AAAA,gBACH,aAAY;AAAA;AAAA,YACd,GACF,GACF;AAAA,YACA,oBAAC,UAAO,MAAK,UAAS,SAAS,aAAa,WAC1C;AAAA,cAAC;AAAA;AAAA,gBACC,gBAAe;AAAA,gBACf,IAAG;AAAA,gBACH,aAAY;AAAA;AAAA,YACd,GACF;AAAA,aACF;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAEA,SAAS,kBAAkB,EAAE,OAAO,GAAuB;AACzD,SACE,qBAAC,OAAO,SAAP,EAAe,UAAS,SACvB;AAAA,wBAAC,OAAO,OAAP,EAAa,MAAK,KAAI,QAAQ,QAC7B;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,IACA,oBAAC,OAAO,aAAP,EAAmB,MAAK,KACvB;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,IACA,qBAAC,QAAQ,MAAR,EAAa,IAAG,KAAI,IAAG,KACtB;AAAA,0BAAC,QAAQ,MAAR,EACC,8BAAC,mBAAgB,GACnB;AAAA,MACA,oBAAC,QAAQ,MAAR,EACC;AAAA,QAAC;AAAA;AAAA,UACC,gBAAe;AAAA,UACf,IAAG;AAAA,UACH,aAAY;AAAA;AAAA,MACd,GACF;AAAA,OACF;AAAA,IACA,oBAAC,aAAU,OAAO,QAAQ,UAAQ,MAChC,8BAAC,iBAAc,MAAK,SAClB,8BAAC,kBAAe,OAAO,QAAQ,GACjC,GACF;AAAA,IACA,oBAAC,QAAK,OAAM,UAAS,KAAI,KAAI,SAAQ,OAAM,IAAG,KAC5C,8BAAC,OAAO,OAAP,EACC,8BAAC,cAAW,OAAO,QACjB;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF,GACF,GACF;AAAA,KACF;AAEJ;AAEA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,WAAW;AAAA,MACpB,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,KAAK;AAAA,QACL,cAAc;AAAA,QACd,QAAQ;AAAA,MACV;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,IAAI,WAAW;AAAA,YACf,MAAK;AAAA,YACL,OAAO,WAAW;AAAA,YAClB,iBAAiB,CAAC,MAAM,SAAS,MAAM,kBAAkB,QAAQ,CAAC;AAAA;AAAA,QACpE;AAAA,QACA,qBAAC,QAAK,WAAU,UACd;AAAA,8BAAC,QAAK,MAAK,KAAI,QAAO,QACnB,qBAAW,MACd;AAAA,UACA,oBAAC,QAAK,MAAK,KAAI,OAAM,QAClB,qBAAW,aACd;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB,cAAc,CAAC;AACjB,GAEG;AACD,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,MAAM,SAE1D,CAAC,CAAC;AACJ,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,WAAW,MAAM,OAA8B,IAAI;AACzD,QAAM,YAAY,eAAe;AACjC,QAAM,sBAAsB,MAAM,QAAQ,MAAM;AAC9C,WAAO,YAAY,OAAO,CAAC,MAAM;AAC/B,aACE,CAAC,OAAO,KAAK,EAAE,UACf,EAAE,aAAa,YAAY,EAAE,MAAM,OAAO,YAAY,CAAC,KACvD,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,YAAY,CAAC,KAC/C,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,YAAY,CAAC;AAAA,IAEnD,CAAC;AAAA,EACH,GAAG,CAAC,aAAa,MAAM,CAAC;AAExB,QAAM,UAAU,MAAM;AACpB,UAAM,WAAW,MAAM;AACrB,UAAI,SAAS,WAAW,oBAAoB,WAAW,GAAG;AACxD,iBAAS,QAAQ,MAAM,YAAY;AAAA,MACrC;AAAA,IACF;AACA,WAAO,iBAAiB,UAAU,QAAQ;AAC1C,WAAO,MAAM;AACX,aAAO,oBAAoB,UAAU,QAAQ;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,oBAAoB,MAAM,CAAC;AAE/B,SACE,oBAAC,KAAK,OAAL,EAAW,MAAK,eAAc,SAAO,MACpC,+BAAC,QAAK,WAAU,UAAS,OAAM,WAAU,KAAI,KAC3C;AAAA,wBAAC,KAAK,OAAL,EAAW,SAAO,MACjB,8BAAC,SACC;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF,GACF;AAAA,IACA,oBAAC,QAAK,MAAK,KAAI,IAAG,KAAI,OAAM,QAC1B;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,GACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,OAAO;AAAA,UACL,cAAc;AAAA,UACd,aAAa;AAAA,UACb,aAAa;AAAA,UACb,aAAa;AAAA,QACf;AAAA,QACA,WAAU;AAAA,QACV,OAAM;AAAA,QAEN;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO;AAAA,cACP,MAAK;AAAA,cACL,UAAU,CAAC,MAAM;AACf,oBAAI,SAAS,SAAS;AACpB,2BAAS,QAAQ,MAAM,YACrB,SAAS,QAAQ,eAAe,IAAI;AAAA,gBACxC;AACA,0BAAU,EAAE,OAAO,KAAK;AAAA,cAC1B;AAAA,cACA,OAAO;AAAA,gBACL,QAAQ;AAAA,gBACR,cAAc;AAAA,gBACd,WAAW;AAAA,cACb;AAAA,cACA,aAAa,UAAU;AAAA,gBACrB,gBAAgB;AAAA,gBAChB,IAAI;AAAA,gBACJ,aAAa;AAAA,cACf,CAAC;AAAA,cAED,8BAAC,iBAAc,MAAK,QAAO,IAAG,KAC5B,8BAAC,uBAAoB,eAAY,QAAO,QAAO,MAAK,OAAM,MAAK,GACjE;AAAA;AAAA,UACF;AAAA,UACC,oBAAoB,SAAS,IAC5B,iCACE;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,YAAW;AAAA,gBACX,OAAO;AAAA,kBACL,MAAM;AAAA,kBACN,WAAW;AAAA,kBACX,QAAQ;AAAA,kBACR,aAAa;AAAA,gBACf;AAAA,gBAEC,8BAAoB,IAAI,CAAC,eACxB;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAS,oBAAoB;AAAA,sBAC3B,CAAC,OAAO,GAAG,SAAS,WAAW;AAAA,oBACjC;AAAA,oBAEA;AAAA,oBACA,UAAU,CAAC,cACT;AAAA,sBAAuB,CAAC,SACtB,YACI,CAAC,GAAG,MAAM,UAAU,IACpB,KAAK,OAAO,CAAC,OAAO,GAAG,SAAS,WAAW,IAAI;AAAA,oBACrD;AAAA;AAAA,kBAPG,WAAW;AAAA,gBASlB,CACD;AAAA;AAAA,YACH;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH,IAAG;AAAA,gBACH,IAAI;AAAA,gBACJ,UAAS;AAAA,gBACT,OAAO;AAAA,kBACL,WAAW;AAAA,kBACX,aAAa;AAAA,gBACf;AAAA,gBAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,YAAY;AAAA,oBACnB,UAAU,oBAAoB;AAAA,oBAC9B,UAAU,MACR;AAAA,sBAAuB,CAAC,SACtB,KAAK,WAAW,YAAY,SAAS,CAAC,IAAI;AAAA,oBAC5C;AAAA;AAAA,gBAEJ;AAAA;AAAA,YACF;AAAA,aACF,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,KAAI;AAAA,cACJ,IAAG;AAAA,cACH,IAAG;AAAA,cACH,OAAO,EAAE,WAAW,0BAA0B;AAAA,cAC9C,UAAS;AAAA,cACT,SAAQ;AAAA,cACR,OAAM;AAAA,cACN,WAAU;AAAA,cAEV;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO;AAAA,sBACP,OAAO;AAAA,sBACP,QAAQ;AAAA,oBACV;AAAA;AAAA,gBACF;AAAA,gBACA,oBAAC,QAAK,MAAK,KAAI,OAAM,UAAS,IAAG,KAAI,MAAK,WAAU,QAAO,QACzD;AAAA,kBAAC;AAAA;AAAA,oBACC,gBAAe;AAAA,oBACf,IAAG;AAAA,oBACH,aAAY;AAAA;AAAA,gBACd,GACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,SAAS,MAAM,UAAU,EAAE;AAAA,oBAE3B;AAAA,sBAAC;AAAA;AAAA,wBACC,gBAAe;AAAA,wBACf,IAAG;AAAA,wBACH,aAAY;AAAA;AAAA,oBACd;AAAA;AAAA,gBACF;AAAA;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF,GACF;AAEJ;AAEA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,qBAAC,QAAK,OAAM,UAAS,KAAI,KACvB;AAAA,wBAAC,QAAK,MAAK,KAAI,OAAO,EAAE,YAAY,GAAG,OAAO,iBAAiB,GAC5D,uBAAa,IACZ;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,IACE,aAAa,IACf;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA;AAAA,IACd,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,gBAAe;AAAA,QACf,IAAG;AAAA,QACH,aAAY;AAAA,QACZ,QAAQ,EAAE,OAAO,SAAS;AAAA;AAAA,IAC5B,GAEJ;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,OAAO,EAAE,QAAQ,WAAW,OAAO,mBAAmB;AAAA,QAErD,oBAAU,WACT;AAAA,UAAC;AAAA;AAAA,YACC,gBAAe;AAAA,YACf,IAAG;AAAA,YACH,aAAY;AAAA;AAAA,QACd,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,gBAAe;AAAA,YACf,IAAG;AAAA,YACH,aAAY;AAAA;AAAA,QACd;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAEO,SAAS,qBAAqB;AACnC,QAAM,EAAE,SAAS,IAAI,kBAAkB;AACvC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS,MAAM,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAAA,MAEtD;AAAA,QAAC;AAAA;AAAA,UACC,gBAAe;AAAA,UACf,IAAG;AAAA,UACH,aAAY;AAAA;AAAA,MACd;AAAA;AAAA,EACF;AAEJ;","names":["errors","error","data"]}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { Callout, Flex, Text, VisuallyHidden } from "@radix-ui/themes";
4
- import * as Form from "@radix-ui/react-form";
4
+ import { Form } from "radix-ui";
5
5
  import * as React from "react";
6
6
  import { Button, Dialog, Label, PasswordField } from "./elements.js";
7
7
  import { useUpdatePassword } from "../api/endpoint.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/change-password-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { Callout, Flex, Text, VisuallyHidden } from \"@radix-ui/themes\";\nimport * as Form from \"@radix-ui/react-form\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport { Button, Dialog, Label, PasswordField } from \"./elements.js\";\nimport { useUpdatePassword } from \"../api/endpoint.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface ChangePasswordDialogProps extends Dialog.RootProps {\n children?: ReactNode;\n}\n\nexport function ChangePasswordDialog({\n children,\n ...props\n}: ChangePasswordDialogProps) {\n const [open, setOpen] = React.useState(false);\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>{children}</Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <Content onClose={handleClose} />\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps {\n onClose: () => void;\n}\n\nfunction Content({ onClose }: ContentProps) {\n const translate = useTranslation();\n const changePassword = useUpdatePassword({\n mutation: {\n onError: (error) => {\n const errorMsg = getMutationErrorMessage(error);\n if (errorMsg === \"Invalid credentials\") {\n setServerErrors({\n currentPassword:\n \"Your current password is incorrect. Please, try again.\",\n });\n }\n },\n },\n });\n const [disableSubmit, setDisableSubmit] = React.useState(true);\n const [serverErrors, setServerErrors] = React.useState<{\n currentPassword?: string;\n password?: string;\n confirmPassword?: string;\n }>({});\n\n const errorMessage = React.useMemo(() => {\n if (changePassword.error) {\n return getMutationErrorMessage(changePassword.error);\n }\n\n return null;\n }, [changePassword.error]);\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const currentPassword = formData.get(\"oldPassword\")?.toString() ?? \"\";\n const newPassword = formData.get(\"password\")?.toString() ?? \"\";\n\n changePassword.mutate({\n data: { currentPassword, newPassword },\n });\n };\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Change Password\"\n id=\"kAYx7z\"\n description=\"Dialog title for changing password\"\n />\n </Dialog.Title>\n <VisuallyHidden>\n <Dialog.Description>\n <Translation\n defaultMessage=\"Change your account password\"\n id=\"R5rXuR\"\n description=\"Dialog description for changing password\"\n />\n </Dialog.Description>\n </VisuallyHidden>\n\n {errorMessage && errorMessage !== \"Invalid credentials\" ? (\n <Callout.Root color=\"red\" my=\"-2\">\n <Callout.Text>{errorMessage}</Callout.Text>\n </Callout.Root>\n ) : null}\n\n <Form.Root\n onSubmit={handleSubmit}\n onChange={(event) => {\n const formData = new FormData(event.currentTarget);\n const currentPassword = formData.get(\"oldPassword\")?.toString() ?? \"\";\n const newPassword = formData.get(\"password\")?.toString() ?? \"\";\n const confirmPassword =\n formData.get(\"confirmPassword\")?.toString() ?? \"\";\n\n setDisableSubmit(\n currentPassword === \"\" ||\n newPassword === \"\" ||\n confirmPassword === \"\",\n );\n setServerErrors({});\n }}\n onClearServerErrors={() => {\n setServerErrors({});\n }}\n >\n <Flex mt=\"5\" direction=\"column\" gap=\"4\">\n <Form.Field\n name=\"oldPassword\"\n asChild\n serverInvalid={!serverErrors.currentPassword}\n >\n <Flex direction=\"column\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Enter your current password\"\n id=\"uqn8py\"\n description=\"Label for current password field\"\n />\n </Label>\n </Form.Label>\n\n <Form.Control asChild>\n <PasswordField\n autoFocus\n required\n disabled={\n changePassword.isPending || changePassword.isSuccess\n }\n autoComplete=\"current-password\"\n placeholder={translate({\n defaultMessage: \"Current password\",\n id: \"P2oB4G\",\n description: \"Placeholder for current password field\",\n })}\n />\n </Form.Control>\n\n <Form.Message match=\"valueMissing\" asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Please enter your current password\"\n id=\"QKO3st\"\n description=\"Error message when current password is missing\"\n />\n </Text>\n </Form.Message>\n\n {serverErrors.currentPassword && (\n <Form.Message asChild>\n <Text size=\"2\" color=\"red\">\n {serverErrors.currentPassword}\n </Text>\n </Form.Message>\n )}\n </Flex>\n </Form.Field>\n\n <Form.Field\n name=\"password\"\n asChild\n serverInvalid={!serverErrors.password}\n >\n <Flex direction=\"column\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Enter your new password\"\n id=\"b/+TBS\"\n description=\"Label for new password field\"\n />\n </Label>\n </Form.Label>\n\n <Form.Control asChild>\n <PasswordField\n autoComplete=\"new-password\"\n placeholder={translate({\n defaultMessage: \"New password\",\n id: \"8d23GS\",\n description: \"Placeholder for new password field\",\n })}\n required\n disabled={\n changePassword.isPending || changePassword.isSuccess\n }\n />\n </Form.Control>\n\n <Form.Message match=\"valueMissing\" asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Please enter your new password\"\n id=\"L4yLAf\"\n description=\"Error message when new password is missing\"\n />\n </Text>\n </Form.Message>\n <Form.Message match={(value) => value.length < 8} asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Password must be at least 8 characters\"\n id=\"WRjyrh\"\n description=\"Error message when password is too short\"\n />\n </Text>\n </Form.Message>\n <Form.Message\n match={(value, formData) =>\n value === formData.get(\"oldPassword\")\n }\n asChild\n >\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"You cannot reuse your current password\"\n id=\"mEkhOO\"\n description=\"Error message when user tries to reuse current password\"\n />\n </Text>\n </Form.Message>\n </Flex>\n </Form.Field>\n\n <Form.Field\n name=\"confirmPassword\"\n asChild\n serverInvalid={!serverErrors.confirmPassword}\n >\n <Flex direction=\"column\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Confirm your new password\"\n id=\"K83lBn\"\n description=\"Label for password confirmation field\"\n />\n </Label>\n </Form.Label>\n\n <Form.Control asChild>\n <PasswordField\n autoComplete=\"new-password\"\n placeholder={translate({\n defaultMessage: \"Confirm new password\",\n id: \"cubpBN\",\n description: \"Placeholder for password confirmation field\",\n })}\n required\n disabled={\n changePassword.isPending || changePassword.isSuccess\n }\n />\n </Form.Control>\n <Form.Message match=\"valueMissing\" asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Please confirm your new password\"\n id=\"fXZhqG\"\n description=\"Error message when password confirmation is missing\"\n />\n </Text>\n </Form.Message>\n <Form.Message\n match={(value, formData) => value !== formData.get(\"password\")}\n asChild\n >\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"The new passwords you entered don't match.\"\n id=\"Zdq2Hr\"\n description=\"Error message when passwords don't match\"\n />\n </Text>\n </Form.Message>\n </Flex>\n </Form.Field>\n </Flex>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={changePassword.isPending || changePassword.isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n\n <SaveButton\n type=\"submit\"\n loading={changePassword.isPending}\n done={changePassword.isSuccess}\n onDone={onClose}\n disabled={disableSubmit || undefined}\n >\n <Translation\n defaultMessage=\"Change password\"\n id=\"8GDtZu\"\n description=\"Submit button text to change password\"\n />\n </SaveButton>\n </Flex>\n </Form.Root>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">{errorMessage}</section>\n </VisuallyHidden>\n </>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n return \"Something went wrong. Please try again.\";\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they come from the API and are displayed dynamically\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/change-password-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { Callout, Flex, Text, VisuallyHidden } from \"@radix-ui/themes\";\nimport { Form } from \"radix-ui\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport { Button, Dialog, Label, PasswordField } from \"./elements.js\";\nimport { useUpdatePassword } from \"../api/endpoint.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface ChangePasswordDialogProps extends Dialog.RootProps {\n children?: ReactNode;\n}\n\nexport function ChangePasswordDialog({\n children,\n ...props\n}: ChangePasswordDialogProps) {\n const [open, setOpen] = React.useState(false);\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>{children}</Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <Content onClose={handleClose} />\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps {\n onClose: () => void;\n}\n\nfunction Content({ onClose }: ContentProps) {\n const translate = useTranslation();\n const changePassword = useUpdatePassword({\n mutation: {\n onError: (error) => {\n const errorMsg = getMutationErrorMessage(error);\n if (errorMsg === \"Invalid credentials\") {\n setServerErrors({\n currentPassword:\n \"Your current password is incorrect. Please, try again.\",\n });\n }\n },\n },\n });\n const [disableSubmit, setDisableSubmit] = React.useState(true);\n const [serverErrors, setServerErrors] = React.useState<{\n currentPassword?: string;\n password?: string;\n confirmPassword?: string;\n }>({});\n\n const errorMessage = React.useMemo(() => {\n if (changePassword.error) {\n return getMutationErrorMessage(changePassword.error);\n }\n\n return null;\n }, [changePassword.error]);\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const currentPassword = formData.get(\"oldPassword\")?.toString() ?? \"\";\n const newPassword = formData.get(\"password\")?.toString() ?? \"\";\n\n changePassword.mutate({\n data: { currentPassword, newPassword },\n });\n };\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Change Password\"\n id=\"kAYx7z\"\n description=\"Dialog title for changing password\"\n />\n </Dialog.Title>\n <VisuallyHidden>\n <Dialog.Description>\n <Translation\n defaultMessage=\"Change your account password\"\n id=\"R5rXuR\"\n description=\"Dialog description for changing password\"\n />\n </Dialog.Description>\n </VisuallyHidden>\n\n {errorMessage && errorMessage !== \"Invalid credentials\" ? (\n <Callout.Root color=\"red\" my=\"-2\">\n <Callout.Text>{errorMessage}</Callout.Text>\n </Callout.Root>\n ) : null}\n\n <Form.Root\n onSubmit={handleSubmit}\n onChange={(event) => {\n const formData = new FormData(event.currentTarget);\n const currentPassword = formData.get(\"oldPassword\")?.toString() ?? \"\";\n const newPassword = formData.get(\"password\")?.toString() ?? \"\";\n const confirmPassword =\n formData.get(\"confirmPassword\")?.toString() ?? \"\";\n\n setDisableSubmit(\n currentPassword === \"\" ||\n newPassword === \"\" ||\n confirmPassword === \"\",\n );\n setServerErrors({});\n }}\n onClearServerErrors={() => {\n setServerErrors({});\n }}\n >\n <Flex mt=\"5\" direction=\"column\" gap=\"4\">\n <Form.Field\n name=\"oldPassword\"\n asChild\n serverInvalid={!serverErrors.currentPassword}\n >\n <Flex direction=\"column\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Enter your current password\"\n id=\"uqn8py\"\n description=\"Label for current password field\"\n />\n </Label>\n </Form.Label>\n\n <Form.Control asChild>\n <PasswordField\n autoFocus\n required\n disabled={\n changePassword.isPending || changePassword.isSuccess\n }\n autoComplete=\"current-password\"\n placeholder={translate({\n defaultMessage: \"Current password\",\n id: \"P2oB4G\",\n description: \"Placeholder for current password field\",\n })}\n />\n </Form.Control>\n\n <Form.Message match=\"valueMissing\" asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Please enter your current password\"\n id=\"QKO3st\"\n description=\"Error message when current password is missing\"\n />\n </Text>\n </Form.Message>\n\n {serverErrors.currentPassword && (\n <Form.Message asChild>\n <Text size=\"2\" color=\"red\">\n {serverErrors.currentPassword}\n </Text>\n </Form.Message>\n )}\n </Flex>\n </Form.Field>\n\n <Form.Field\n name=\"password\"\n asChild\n serverInvalid={!serverErrors.password}\n >\n <Flex direction=\"column\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Enter your new password\"\n id=\"b/+TBS\"\n description=\"Label for new password field\"\n />\n </Label>\n </Form.Label>\n\n <Form.Control asChild>\n <PasswordField\n autoComplete=\"new-password\"\n placeholder={translate({\n defaultMessage: \"New password\",\n id: \"8d23GS\",\n description: \"Placeholder for new password field\",\n })}\n required\n disabled={\n changePassword.isPending || changePassword.isSuccess\n }\n />\n </Form.Control>\n\n <Form.Message match=\"valueMissing\" asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Please enter your new password\"\n id=\"L4yLAf\"\n description=\"Error message when new password is missing\"\n />\n </Text>\n </Form.Message>\n <Form.Message match={(value) => value.length < 8} asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Password must be at least 8 characters\"\n id=\"WRjyrh\"\n description=\"Error message when password is too short\"\n />\n </Text>\n </Form.Message>\n <Form.Message\n match={(value, formData) =>\n value === formData.get(\"oldPassword\")\n }\n asChild\n >\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"You cannot reuse your current password\"\n id=\"mEkhOO\"\n description=\"Error message when user tries to reuse current password\"\n />\n </Text>\n </Form.Message>\n </Flex>\n </Form.Field>\n\n <Form.Field\n name=\"confirmPassword\"\n asChild\n serverInvalid={!serverErrors.confirmPassword}\n >\n <Flex direction=\"column\" gap=\"2\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Confirm your new password\"\n id=\"K83lBn\"\n description=\"Label for password confirmation field\"\n />\n </Label>\n </Form.Label>\n\n <Form.Control asChild>\n <PasswordField\n autoComplete=\"new-password\"\n placeholder={translate({\n defaultMessage: \"Confirm new password\",\n id: \"cubpBN\",\n description: \"Placeholder for password confirmation field\",\n })}\n required\n disabled={\n changePassword.isPending || changePassword.isSuccess\n }\n />\n </Form.Control>\n <Form.Message match=\"valueMissing\" asChild>\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"Please confirm your new password\"\n id=\"fXZhqG\"\n description=\"Error message when password confirmation is missing\"\n />\n </Text>\n </Form.Message>\n <Form.Message\n match={(value, formData) => value !== formData.get(\"password\")}\n asChild\n >\n <Text size=\"2\" color=\"red\">\n <Translation\n defaultMessage=\"The new passwords you entered don't match.\"\n id=\"Zdq2Hr\"\n description=\"Error message when passwords don't match\"\n />\n </Text>\n </Form.Message>\n </Flex>\n </Form.Field>\n </Flex>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={changePassword.isPending || changePassword.isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n\n <SaveButton\n type=\"submit\"\n loading={changePassword.isPending}\n done={changePassword.isSuccess}\n onDone={onClose}\n disabled={disableSubmit || undefined}\n >\n <Translation\n defaultMessage=\"Change password\"\n id=\"8GDtZu\"\n description=\"Submit button text to change password\"\n />\n </SaveButton>\n </Flex>\n </Form.Root>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">{errorMessage}</section>\n </VisuallyHidden>\n </>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n return \"Something went wrong. Please try again.\";\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they come from the API and are displayed dynamically\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/copy-button.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { IconButton, Button } from \"./elements.js\";\nimport { CheckIcon, CopyIcon } from \"@radix-ui/react-icons\";\nimport { Slot, Slottable } from \"@radix-ui/themes\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface CopyButtonOwnProps {\n value: string;\n withIcon?: boolean;\n}\n\ninterface CopyButtonProps\n extends CopyButtonOwnProps,\n Omit<React.ComponentProps<typeof Button>, keyof CopyButtonOwnProps> {}\n\nexport const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(\n function CopyButton(\n { value, asChild, children, style, withIcon = false, ...props },\n ref,\n ) {\n const Comp = asChild ? Slot : Button;\n const [hasCopied, copy] = useCopy(value);\n return (\n <Comp type=\"button\" onPointerUp={copy} ref={ref} {...props}>\n {withIcon &&\n (hasCopied ? <CheckIcon aria-hidden /> : <CopyIcon aria-hidden />)}\n <Slottable>{children}</Slottable>\n </Comp>\n );\n },\n);\n\ninterface CopyIconButtonOwnProps {\n value: string;\n}\n\ninterface CopyIconButtonProps\n extends CopyIconButtonOwnProps,\n Omit<\n React.ComponentProps<typeof IconButton>,\n \"asChild\" | \"children\" | \"title\" | keyof CopyIconButtonOwnProps\n > {\n title?: string;\n}\n\nexport const CopyIconButton = React.forwardRef<\n HTMLButtonElement,\n CopyIconButtonProps\n>(function CopyIconButton({ value, style, ...props }, ref) {\n const [hasCopied, copy] = useCopy(value);\n const translate = useTranslation();\n const copiedText = translate({\n defaultMessage: \"Copied\",\n id: \"xgUx3Z\",\n description: \"Text shown after content has been copied\",\n });\n const copyToClipboardText = translate({\n defaultMessage: \"Copy to clipboard\",\n id: \"h9d9dv\",\n description: \"Button text to copy content to clipboard\",\n });\n return (\n <IconButton\n type=\"button\"\n onPointerUp={copy}\n ref={ref}\n title={hasCopied ? copiedText : copyToClipboardText}\n aria-label={copyToClipboardText}\n {...props}\n >\n {hasCopied ? <CheckIcon /> : <CopyIcon />}\n </IconButton>\n );\n});\n\nfunction useCopy(value: string) {\n const [hasCopied, setHasCopied] = React.useState(false);\n const timeoutRef = React.useRef<number | undefined>(undefined);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setHasCopied(true);\n\n // Clear any existing timeout\n if (timeoutRef.current) {\n window.clearTimeout(timeoutRef.current);\n }\n\n // Set new timeout\n timeoutRef.current = window.setTimeout(() => {\n setHasCopied(false);\n }, 3000);\n } catch (err) {\n console.error(\"Failed to copy text:\", err);\n }\n };\n\n // Cleanup timeout on unmount\n React.useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n window.clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return [hasCopied, copy] as const;\n}\n"],"mappings":"AAuBM,SAEiB,KAFjB;AAvBN,YAAY,WAAW;AACvB,SAAS,YAAY,cAAc;AACnC,SAAS,WAAW,gBAAgB;AACpC,SAAS,MAAM,iBAAiB;AAChC,SAAS,sBAAsB;AAWxB,MAAM,aAAa,MAAM;AAAA,EAC9B,SAASA,YACP,EAAE,OAAO,SAAS,UAAU,OAAO,WAAW,OAAO,GAAG,MAAM,GAC9D,KACA;AACA,UAAM,OAAO,UAAU,OAAO;AAC9B,UAAM,CAAC,WAAW,IAAI,IAAI,QAAQ,KAAK;AACvC,WACE,qBAAC,QAAK,MAAK,UAAS,aAAa,MAAM,KAAW,GAAG,OAClD;AAAA,mBACE,YAAY,oBAAC,aAAU,eAAW,MAAC,IAAK,oBAAC,YAAS,eAAW,MAAC;AAAA,MACjE,oBAAC,aAAW,UAAS;AAAA,OACvB;AAAA,EAEJ;AACF;AAeO,MAAM,iBAAiB,MAAM,WAGlC,SAASC,gBAAe,EAAE,OAAO,OAAO,GAAG,MAAM,GAAG,KAAK;AACzD,QAAM,CAAC,WAAW,IAAI,IAAI,QAAQ,KAAK;AACvC,QAAM,YAAY,eAAe;AACjC,QAAM,aAAa,UAAU;AAAA,IAC3B,gBAAgB;AAAA,IAChB,IAAI;AAAA,IACJ,aAAa;AAAA,EACf,CAAC;AACD,QAAM,sBAAsB,UAAU;AAAA,IACpC,gBAAgB;AAAA,IAChB,IAAI;AAAA,IACJ,aAAa;AAAA,EACf,CAAC;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAa;AAAA,MACb;AAAA,MACA,OAAO,YAAY,aAAa;AAAA,MAChC,cAAY;AAAA,MACX,GAAG;AAAA,MAEH,sBAAY,oBAAC,aAAU,IAAK,oBAAC,YAAS;AAAA;AAAA,EACzC;AAEJ,CAAC;AAED,SAAS,QAAQ,OAAe;AAC9B,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,aAAa,MAAM,OAA2B,MAAS;AAE7D,QAAM,OAAO,YAAY;AACvB,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,mBAAa,IAAI;AAGjB,UAAI,WAAW,SAAS;AACtB,eAAO,aAAa,WAAW,OAAO;AAAA,MACxC;AAGA,iBAAW,UAAU,OAAO,WAAW,MAAM;AAC3C,qBAAa,KAAK;AAAA,MACpB,GAAG,GAAI;AAAA,IACT,SAAS,KAAK;AACZ,cAAQ,MAAM,wBAAwB,GAAG;AAAA,IAC3C;AAAA,EACF;AAGA,QAAM,UAAU,MAAM;AACpB,WAAO,MAAM;AACX,UAAI,WAAW,SAAS;AACtB,eAAO,aAAa,WAAW,OAAO;AAAA,MACxC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO,CAAC,WAAW,IAAI;AACzB;","names":["CopyButton","CopyIconButton"]}
1
+ {"version":3,"sources":["../../../src/lib/copy-button.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { IconButton, Button } from \"./elements.js\";\nimport { CheckIcon, CopyIcon } from \"@radix-ui/react-icons\";\nimport { Slot, Slottable } from \"@radix-ui/themes\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface CopyButtonOwnProps {\n value: string;\n withIcon?: boolean;\n}\n\ninterface CopyButtonProps\n extends\n CopyButtonOwnProps,\n Omit<React.ComponentProps<typeof Button>, keyof CopyButtonOwnProps> {}\n\nexport const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(\n function CopyButton(\n { value, asChild, children, style, withIcon = false, ...props },\n ref,\n ) {\n const Comp = asChild ? Slot : Button;\n const [hasCopied, copy] = useCopy(value);\n return (\n <Comp type=\"button\" onPointerUp={copy} ref={ref} {...props}>\n {withIcon &&\n (hasCopied ? <CheckIcon aria-hidden /> : <CopyIcon aria-hidden />)}\n <Slottable>{children}</Slottable>\n </Comp>\n );\n },\n);\n\ninterface CopyIconButtonOwnProps {\n value: string;\n}\n\ninterface CopyIconButtonProps\n extends\n CopyIconButtonOwnProps,\n Omit<\n React.ComponentProps<typeof IconButton>,\n \"asChild\" | \"children\" | \"title\" | keyof CopyIconButtonOwnProps\n > {\n title?: string;\n}\n\nexport const CopyIconButton = React.forwardRef<\n HTMLButtonElement,\n CopyIconButtonProps\n>(function CopyIconButton({ value, style, ...props }, ref) {\n const [hasCopied, copy] = useCopy(value);\n const translate = useTranslation();\n const copiedText = translate({\n defaultMessage: \"Copied\",\n id: \"xgUx3Z\",\n description: \"Text shown after content has been copied\",\n });\n const copyToClipboardText = translate({\n defaultMessage: \"Copy to clipboard\",\n id: \"h9d9dv\",\n description: \"Button text to copy content to clipboard\",\n });\n return (\n <IconButton\n type=\"button\"\n onPointerUp={copy}\n ref={ref}\n title={hasCopied ? copiedText : copyToClipboardText}\n aria-label={copyToClipboardText}\n {...props}\n >\n {hasCopied ? <CheckIcon /> : <CopyIcon />}\n </IconButton>\n );\n});\n\nfunction useCopy(value: string) {\n const [hasCopied, setHasCopied] = React.useState(false);\n const timeoutRef = React.useRef<number | undefined>(undefined);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setHasCopied(true);\n\n // Clear any existing timeout\n if (timeoutRef.current) {\n window.clearTimeout(timeoutRef.current);\n }\n\n // Set new timeout\n timeoutRef.current = window.setTimeout(() => {\n setHasCopied(false);\n }, 3000);\n } catch (err) {\n console.error(\"Failed to copy text:\", err);\n }\n };\n\n // Cleanup timeout on unmount\n React.useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n window.clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return [hasCopied, copy] as const;\n}\n"],"mappings":"AAwBM,SAEiB,KAFjB;AAxBN,YAAY,WAAW;AACvB,SAAS,YAAY,cAAc;AACnC,SAAS,WAAW,gBAAgB;AACpC,SAAS,MAAM,iBAAiB;AAChC,SAAS,sBAAsB;AAYxB,MAAM,aAAa,MAAM;AAAA,EAC9B,SAASA,YACP,EAAE,OAAO,SAAS,UAAU,OAAO,WAAW,OAAO,GAAG,MAAM,GAC9D,KACA;AACA,UAAM,OAAO,UAAU,OAAO;AAC9B,UAAM,CAAC,WAAW,IAAI,IAAI,QAAQ,KAAK;AACvC,WACE,qBAAC,QAAK,MAAK,UAAS,aAAa,MAAM,KAAW,GAAG,OAClD;AAAA,mBACE,YAAY,oBAAC,aAAU,eAAW,MAAC,IAAK,oBAAC,YAAS,eAAW,MAAC;AAAA,MACjE,oBAAC,aAAW,UAAS;AAAA,OACvB;AAAA,EAEJ;AACF;AAgBO,MAAM,iBAAiB,MAAM,WAGlC,SAASC,gBAAe,EAAE,OAAO,OAAO,GAAG,MAAM,GAAG,KAAK;AACzD,QAAM,CAAC,WAAW,IAAI,IAAI,QAAQ,KAAK;AACvC,QAAM,YAAY,eAAe;AACjC,QAAM,aAAa,UAAU;AAAA,IAC3B,gBAAgB;AAAA,IAChB,IAAI;AAAA,IACJ,aAAa;AAAA,EACf,CAAC;AACD,QAAM,sBAAsB,UAAU;AAAA,IACpC,gBAAgB;AAAA,IAChB,IAAI;AAAA,IACJ,aAAa;AAAA,EACf,CAAC;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAa;AAAA,MACb;AAAA,MACA,OAAO,YAAY,aAAa;AAAA,MAChC,cAAY;AAAA,MACX,GAAG;AAAA,MAEH,sBAAY,oBAAC,aAAU,IAAK,oBAAC,YAAS;AAAA;AAAA,EACzC;AAEJ,CAAC;AAED,SAAS,QAAQ,OAAe;AAC9B,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,aAAa,MAAM,OAA2B,MAAS;AAE7D,QAAM,OAAO,YAAY;AACvB,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,mBAAa,IAAI;AAGjB,UAAI,WAAW,SAAS;AACtB,eAAO,aAAa,WAAW,OAAO;AAAA,MACxC;AAGA,iBAAW,UAAU,OAAO,WAAW,MAAM;AAC3C,qBAAa,KAAK;AAAA,MACpB,GAAG,GAAI;AAAA,IACT,SAAS,KAAK;AACZ,cAAQ,MAAM,wBAAwB,GAAG;AAAA,IAC3C;AAAA,EACF;AAGA,QAAM,UAAU,MAAM;AACpB,WAAO,MAAM;AACX,UAAI,WAAW,SAAS;AACtB,eAAO,aAAa,WAAW,OAAO;AAAA,MACxC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO,CAAC,WAAW,IAAI;AACzB;","names":["CopyButton","CopyIconButton"]}
@@ -4,7 +4,7 @@ import { Callout, Flex, Text, VisuallyHidden } from "@radix-ui/themes";
4
4
  import { getMeQueryKey, useUpdateMe } from "../api/endpoint.js";
5
5
  import { useQueryClient } from "@tanstack/react-query";
6
6
  import * as React from "react";
7
- import * as Form from "@radix-ui/react-form";
7
+ import { Form } from "radix-ui";
8
8
  import { Dialog, Label, Button, TextField } from "./elements.js";
9
9
  import { SaveButton } from "./save-button.js";
10
10
  import { Translation } from "./i18n/translation.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/edit-user-profile-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { Callout, Flex, Text, VisuallyHidden } from \"@radix-ui/themes\";\nimport { getMeQueryKey, Me, useUpdateMe } from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport * as Form from \"@radix-ui/react-form\";\nimport { Dialog, Label, Button, TextField } from \"./elements.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface EditUserProfileDialogProps extends Dialog.RootProps {\n user: Me;\n children?: ReactNode;\n}\n\nexport function EditUserProfileDialog({\n children,\n user,\n ...props\n}: EditUserProfileDialogProps) {\n const [open, setOpen] = React.useState(false);\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>{children}</Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <Content user={user} onClose={handleClose} />\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps extends Pick<EditUserProfileDialogProps, \"user\"> {\n onClose: () => void;\n}\n\nfunction Content({ user, onClose }: ContentProps) {\n const translate = useTranslation();\n const client = useQueryClient();\n const updateMe = useUpdateMe({\n mutation: {\n onSettled: () => {\n client.invalidateQueries({ queryKey: getMeQueryKey() });\n },\n onSuccess: (newProfile) => {\n client.setQueryData(getMeQueryKey(), {\n ...user,\n firstName: newProfile.firstName || user.firstName,\n lastName: newProfile.lastName || user.lastName,\n });\n },\n },\n });\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Edit name\"\n id=\"pcK9ly\"\n description=\"Dialog title for editing user name\"\n />\n </Dialog.Title>\n <VisuallyHidden>\n <Dialog.Description>\n <Translation\n defaultMessage=\"Edit the details of {email}\"\n id=\"SEsXx0\"\n description=\"Dialog description for editing user details\"\n values={{ email: <Text weight=\"bold\">{user.email}</Text> }}\n />\n </Dialog.Description>\n </VisuallyHidden>\n\n {updateMe.error ? (\n <Callout.Root color=\"red\" my=\"-2\">\n <Callout.Text>{getMutationErrorMessage(updateMe.error)}</Callout.Text>\n </Callout.Root>\n ) : null}\n\n <Form.Root\n onSubmit={async (event) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const firstName = formData.get(\"firstName\")?.toString();\n const lastName = formData.get(\"lastName\")?.toString();\n updateMe.mutate({\n data: {\n firstName: firstName ?? undefined,\n lastName: lastName ?? undefined,\n },\n });\n }}\n >\n <Flex my=\"5\" direction=\"column\" gap=\"4\">\n <Form.Field name=\"firstName\" asChild>\n <Flex direction=\"column\" gap=\"1\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"First name\"\n id=\"DAYdcg\"\n description=\"Label for first name field\"\n />\n </Label>\n </Form.Label>\n <Form.Control asChild>\n <TextField\n data-1p-ignore\n autoComplete=\"given-name\"\n defaultValue={user.firstName ?? \"\"}\n placeholder={translate({\n defaultMessage: \"Your first name\",\n id: \"gUTpgG\",\n description: \"Placeholder for first name field\",\n })}\n disabled={updateMe.isPending || updateMe.isSuccess}\n />\n </Form.Control>\n </Flex>\n </Form.Field>\n\n <Form.Field name=\"lastName\" asChild>\n <Flex direction=\"column\" gap=\"1\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Last name\"\n id=\"IwcAMv\"\n description=\"Label for last name field\"\n />\n </Label>\n </Form.Label>\n <Form.Control asChild>\n <TextField\n data-1p-ignore\n autoComplete=\"family-name\"\n defaultValue={user.lastName ?? \"\"}\n placeholder={translate({\n defaultMessage: \"Your last name\",\n id: \"Gy8eW0\",\n description: \"Placeholder for last name field\",\n })}\n disabled={updateMe.isPending || updateMe.isSuccess}\n />\n </Form.Control>\n </Flex>\n </Form.Field>\n </Flex>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n disabled={updateMe.isPending || updateMe.isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <SaveButton\n type=\"submit\"\n loading={updateMe.isPending}\n done={updateMe.isSuccess}\n onDone={onClose}\n >\n <Translation\n defaultMessage=\"Save\"\n id=\"RT8KNi\"\n description=\"Save button text\"\n />\n </SaveButton>\n </Flex>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">\n {getMutationErrorMessage(updateMe.error)}\n </section>\n </VisuallyHidden>\n </Form.Root>\n </>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n // TODO Handle server errors\n return \"Something went wrong. Please try again.\";\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they are displayed dynamically\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/edit-user-profile-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { Callout, Flex, Text, VisuallyHidden } from \"@radix-ui/themes\";\nimport { getMeQueryKey, Me, useUpdateMe } from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport { Form } from \"radix-ui\";\nimport { Dialog, Label, Button, TextField } from \"./elements.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface EditUserProfileDialogProps extends Dialog.RootProps {\n user: Me;\n children?: ReactNode;\n}\n\nexport function EditUserProfileDialog({\n children,\n user,\n ...props\n}: EditUserProfileDialogProps) {\n const [open, setOpen] = React.useState(false);\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>{children}</Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <Content user={user} onClose={handleClose} />\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps extends Pick<EditUserProfileDialogProps, \"user\"> {\n onClose: () => void;\n}\n\nfunction Content({ user, onClose }: ContentProps) {\n const translate = useTranslation();\n const client = useQueryClient();\n const updateMe = useUpdateMe({\n mutation: {\n onSettled: () => {\n client.invalidateQueries({ queryKey: getMeQueryKey() });\n },\n onSuccess: (newProfile) => {\n client.setQueryData(getMeQueryKey(), {\n ...user,\n firstName: newProfile.firstName || user.firstName,\n lastName: newProfile.lastName || user.lastName,\n });\n },\n },\n });\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Edit name\"\n id=\"pcK9ly\"\n description=\"Dialog title for editing user name\"\n />\n </Dialog.Title>\n <VisuallyHidden>\n <Dialog.Description>\n <Translation\n defaultMessage=\"Edit the details of {email}\"\n id=\"SEsXx0\"\n description=\"Dialog description for editing user details\"\n values={{ email: <Text weight=\"bold\">{user.email}</Text> }}\n />\n </Dialog.Description>\n </VisuallyHidden>\n\n {updateMe.error ? (\n <Callout.Root color=\"red\" my=\"-2\">\n <Callout.Text>{getMutationErrorMessage(updateMe.error)}</Callout.Text>\n </Callout.Root>\n ) : null}\n\n <Form.Root\n onSubmit={async (event) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const firstName = formData.get(\"firstName\")?.toString();\n const lastName = formData.get(\"lastName\")?.toString();\n updateMe.mutate({\n data: {\n firstName: firstName ?? undefined,\n lastName: lastName ?? undefined,\n },\n });\n }}\n >\n <Flex my=\"5\" direction=\"column\" gap=\"4\">\n <Form.Field name=\"firstName\" asChild>\n <Flex direction=\"column\" gap=\"1\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"First name\"\n id=\"DAYdcg\"\n description=\"Label for first name field\"\n />\n </Label>\n </Form.Label>\n <Form.Control asChild>\n <TextField\n data-1p-ignore\n autoComplete=\"given-name\"\n defaultValue={user.firstName ?? \"\"}\n placeholder={translate({\n defaultMessage: \"Your first name\",\n id: \"gUTpgG\",\n description: \"Placeholder for first name field\",\n })}\n disabled={updateMe.isPending || updateMe.isSuccess}\n />\n </Form.Control>\n </Flex>\n </Form.Field>\n\n <Form.Field name=\"lastName\" asChild>\n <Flex direction=\"column\" gap=\"1\">\n <Form.Label asChild>\n <Label>\n <Translation\n defaultMessage=\"Last name\"\n id=\"IwcAMv\"\n description=\"Label for last name field\"\n />\n </Label>\n </Form.Label>\n <Form.Control asChild>\n <TextField\n data-1p-ignore\n autoComplete=\"family-name\"\n defaultValue={user.lastName ?? \"\"}\n placeholder={translate({\n defaultMessage: \"Your last name\",\n id: \"Gy8eW0\",\n description: \"Placeholder for last name field\",\n })}\n disabled={updateMe.isPending || updateMe.isSuccess}\n />\n </Form.Control>\n </Flex>\n </Form.Field>\n </Flex>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n disabled={updateMe.isPending || updateMe.isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <SaveButton\n type=\"submit\"\n loading={updateMe.isPending}\n done={updateMe.isSuccess}\n onDone={onClose}\n >\n <Translation\n defaultMessage=\"Save\"\n id=\"RT8KNi\"\n description=\"Save button text\"\n />\n </SaveButton>\n </Flex>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">\n {getMutationErrorMessage(updateMe.error)}\n </section>\n </VisuallyHidden>\n </Form.Root>\n </>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n // TODO Handle server errors\n return \"Something went wrong. Please try again.\";\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they are displayed dynamically\n"],"mappings":"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","names":[]}
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
3
- import { useLayoutEffect } from "../use-layout-effect.js";
2
+ import { useComposedRefs, useLayoutEffect } from "radix-ui/internal";
4
3
  function useDialogOverlayHack(forwardedRef, { className, selector }) {
5
4
  const [node, setNode] = React.useState(null);
6
5
  const ref = useComposedRefs(forwardedRef, setNode);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/elements/utils.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { useLayoutEffect } from \"../use-layout-effect.js\";\n\n/**\n * HACK: Radix themes does not expose the dialog overlay, but we want consumer\n * to be able to style it with a classname. This will add a classname to the\n * overlay when the dialog content is mounted.\n */\nexport function useDialogOverlayHack(\n forwardedRef: React.Ref<HTMLDivElement | null>,\n { className, selector }: { className: string; selector: string },\n): { ref: React.Ref<HTMLDivElement | null> } {\n const [node, setNode] = React.useState<HTMLDivElement | null>(null);\n const ref = useComposedRefs(forwardedRef, setNode as any);\n useLayoutEffect(() => {\n if (!node) {\n return;\n }\n const document = node.ownerDocument;\n const overlay = document.querySelector<HTMLDivElement>(selector);\n overlay?.classList.add(className);\n }, [node, className, selector]);\n\n return { ref };\n}\n"],"mappings":"AAAA,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAOzB,SAAS,qBACd,cACA,EAAE,WAAW,SAAS,GACqB;AAC3C,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAgC,IAAI;AAClE,QAAM,MAAM,gBAAgB,cAAc,OAAc;AACxD,kBAAgB,MAAM;AACpB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,SAAS,cAA8B,QAAQ;AAC/D,aAAS,UAAU,IAAI,SAAS;AAAA,EAClC,GAAG,CAAC,MAAM,WAAW,QAAQ,CAAC;AAE9B,SAAO,EAAE,IAAI;AACf;","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/elements/utils.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useComposedRefs, useLayoutEffect } from \"radix-ui/internal\";\n\n/**\n * HACK: Radix themes does not expose the dialog overlay, but we want consumer\n * to be able to style it with a classname. This will add a classname to the\n * overlay when the dialog content is mounted.\n */\nexport function useDialogOverlayHack(\n forwardedRef: React.Ref<HTMLDivElement | null>,\n { className, selector }: { className: string; selector: string },\n): { ref: React.Ref<HTMLDivElement | null> } {\n const [node, setNode] = React.useState<HTMLDivElement | null>(null);\n const ref = useComposedRefs(forwardedRef, setNode as any);\n useLayoutEffect(() => {\n if (!node) {\n return;\n }\n const document = node.ownerDocument;\n const overlay = document.querySelector<HTMLDivElement>(selector);\n overlay?.classList.add(className);\n }, [node, className, selector]);\n\n return { ref };\n}\n"],"mappings":"AAAA,YAAY,WAAW;AACvB,SAAS,iBAAiB,uBAAuB;AAO1C,SAAS,qBACd,cACA,EAAE,WAAW,SAAS,GACqB;AAC3C,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAgC,IAAI;AAClE,QAAM,MAAM,gBAAgB,cAAc,OAAc;AACxD,kBAAgB,MAAM;AACpB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,SAAS,cAA8B,QAAQ;AAC/D,aAAS,UAAU,IAAI,SAAS;AAAA,EAClC,GAAG,CAAC,MAAM,WAAW,QAAQ,CAAC;AAE9B,SAAO,EAAE,IAAI;AACf;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/elements.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n Avatar as RadixAvatar,\n AvatarProps as RadixAvatarProps,\n Badge as RadixBadge,\n IconButton as RadixIconButton,\n Skeleton as RadixSkeleton,\n Text,\n TextField as RadixTextField,\n type BadgeProps,\n type ButtonProps as RadixButtonProps,\n type IconButtonProps as RadixIconButtonProps,\n type SkeletonProps,\n type TextProps,\n Button as RadixButton,\n} from \"@radix-ui/themes\";\nimport type {\n GetPropDefTypes,\n avatarPropDefs,\n badgePropDefs,\n buttonPropDefs,\n dialogContentPropDefs,\n dropdownMenuContentPropDefs,\n dropdownMenuItemPropDefs,\n iconButtonPropDefs,\n textPropDefs,\n textFieldRootPropDefs,\n selectTriggerPropDefs,\n skeletonPropDefs,\n} from \"@radix-ui/themes/props\";\nimport cx from \"clsx\";\nimport { useElement } from \"./widgets-context.js\";\nimport { getDomProps, namespaceClassNames } from \"./utils.js\";\nimport { EyeClosedIcon, EyeOpenIcon } from \"@radix-ui/react-icons\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\nexport interface ButtonProps\n extends Omit<RadixButtonProps, \"variant\" | \"color\"> {\n variant?: \"primary\" | \"secondary\" | \"destructive\";\n unsafe_radixVariant?: RadixButtonProps[\"variant\"];\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n { className, variant = \"primary\", unsafe_radixVariant, ...props },\n ref,\n ) {\n const element = useElement(`${variant}Button`);\n\n const themeProps = (() => {\n let props: RadixButtonProps = {};\n if (variant === \"primary\") {\n props = {\n variant: \"solid\",\n } satisfies RadixButtonProps;\n } else if (variant === \"secondary\") {\n props = {\n highContrast: true,\n variant: \"surface\",\n color: \"gray\",\n } satisfies RadixButtonProps;\n } else if (variant === \"destructive\") {\n props = {\n variant: \"solid\",\n color: \"red\",\n } satisfies RadixButtonProps;\n } else {\n variant satisfies never;\n }\n\n if (unsafe_radixVariant) {\n props.variant = unsafe_radixVariant;\n }\n\n return props;\n })();\n\n return (\n <RadixButton\n ref={ref}\n {...getDomProps({\n elementId: `${variant}Button`,\n className: cx(\n className,\n // TODO: Remove BEM-style selector once conventions are standardized\n `button--${variant}`,\n ),\n })}\n {...themeProps}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport interface IconButtonProps extends RadixIconButtonProps {\n title: string;\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton({ className, ...props }, ref) {\n const element = useElement(\"iconButton\");\n return (\n <RadixIconButton\n ref={ref}\n {...getDomProps({ elementId: \"iconButton\", className })}\n variant=\"ghost\"\n color=\"gray\"\n aria-label={props.title}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(\n function Skeleton({ className, ...props }, ref) {\n const element = useElement(\"skeleton\");\n return (\n <RadixSkeleton\n ref={ref}\n {...getDomProps({ elementId: \"skeleton\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Label = React.forwardRef<HTMLLabelElement, TextProps>(\n function Label({ children, className, style = {}, ...props }, ref) {\n const element = useElement(\"label\");\n return (\n <Text\n as=\"label\"\n ref={ref}\n weight=\"bold\"\n size=\"2\"\n {...getDomProps({ elementId: \"label\", className })}\n style={{ width: \"fit-content\", ...style }}\n // Text props are a complex union type depending on the `as` prop value,\n // which breaks down when spreading in `element`.\n {...(props as any)}\n {...element}\n >\n {children}\n </Text>\n );\n },\n);\n\nexport const TextField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function TextField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n />\n );\n});\n\nexport const TextFieldSlot = React.forwardRef<\n HTMLDivElement,\n RadixTextField.SlotProps\n>(function TextFieldSlot({ className, ...props }, ref) {\n return (\n <RadixTextField.Slot\n ref={ref}\n className={cx(namespaceClassNames(\"text-field-slot\"), className)}\n {...props}\n />\n );\n});\n\nexport const PasswordField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function PasswordField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n const [showPassword, setShowPassword] = React.useState(false);\n const translate = useTranslation();\n const hidePasswordText = translate({\n defaultMessage: \"Hide password\",\n id: \"Jv4Vps\",\n description: \"Button text to hide password\",\n });\n const showPasswordText = translate({\n defaultMessage: \"Show password\",\n id: \"UIfBSd\",\n description: \"Button text to show password\",\n });\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n type={showPassword ? \"text\" : \"password\"}\n >\n <RadixTextField.Slot side=\"right\">\n <IconButton\n type=\"button\"\n size=\"1\"\n onClick={() => setShowPassword(!showPassword)}\n title={showPassword ? hidePasswordText : showPasswordText}\n >\n {showPassword ? <EyeOpenIcon /> : <EyeClosedIcon />}\n </IconButton>\n </RadixTextField.Slot>\n </RadixTextField.Root>\n );\n});\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n function Badge({ className, ...props }, ref) {\n const element = useElement(\"badge\");\n return (\n <RadixBadge\n ref={ref}\n {...getDomProps({ elementId: \"badge\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\ninterface AvatarProps extends RadixAvatarProps {\n dim?: boolean;\n}\n\nexport const Avatar = React.forwardRef<HTMLImageElement, AvatarProps>(\n function Avatar({ dim, className, ...props }, ref) {\n const element = useElement(\"avatar\");\n return (\n <RadixAvatar\n ref={ref}\n color=\"gray\"\n {...getDomProps({ elementId: \"avatar\", className })}\n {...props}\n {...element}\n // TODO: use CSS var instead of hard-coded value for opacity\n style={dim ? { opacity: 0.6, ...props.style } : props.style}\n />\n );\n },\n);\n\ntype OmitAsChild<T> = {\n [K in keyof T]: T[K] extends undefined\n ? undefined\n : Omit<NonNullable<T[K]>, \"asChild\">;\n};\n\nexport * as Dialog from \"./elements/dialog.js\";\nexport * as AlertDialog from \"./elements/alert-dialog.js\";\nexport * as DropdownMenu from \"./elements/dropdown-menu.js\";\nexport * as Select from \"./elements/select.js\";\n\nexport type Elements = OmitAsChild<{\n dialog?: GetPropDefTypes<typeof dialogContentPropDefs>;\n primaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n secondaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n destructiveButton?: GetPropDefTypes<typeof buttonPropDefs>;\n iconButton?: GetPropDefTypes<typeof iconButtonPropDefs>;\n textfield?: GetPropDefTypes<typeof textFieldRootPropDefs>;\n select?: GetPropDefTypes<typeof selectTriggerPropDefs>;\n badge?: GetPropDefTypes<typeof badgePropDefs>;\n dropdown?: GetPropDefTypes<typeof dropdownMenuContentPropDefs>;\n primaryMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n destructiveMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n avatar?: Omit<GetPropDefTypes<typeof avatarPropDefs>, \"fallback\">;\n label?: GetPropDefTypes<typeof textPropDefs>;\n skeleton?: GetPropDefTypes<typeof skeletonPropDefs>;\n}>;\n"],"mappings":"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","names":["Button","props","IconButton","Skeleton","Label","TextField","TextFieldSlot","PasswordField","Badge","Avatar"]}
1
+ {"version":3,"sources":["../../../src/lib/elements.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n Avatar as RadixAvatar,\n AvatarProps as RadixAvatarProps,\n Badge as RadixBadge,\n IconButton as RadixIconButton,\n Skeleton as RadixSkeleton,\n Text,\n TextField as RadixTextField,\n type BadgeProps,\n type ButtonProps as RadixButtonProps,\n type IconButtonProps as RadixIconButtonProps,\n type SkeletonProps,\n type TextProps,\n Button as RadixButton,\n} from \"@radix-ui/themes\";\nimport type {\n GetPropDefTypes,\n avatarPropDefs,\n badgePropDefs,\n buttonPropDefs,\n dialogContentPropDefs,\n dropdownMenuContentPropDefs,\n dropdownMenuItemPropDefs,\n iconButtonPropDefs,\n textPropDefs,\n textFieldRootPropDefs,\n selectTriggerPropDefs,\n skeletonPropDefs,\n} from \"@radix-ui/themes/props\";\nimport cx from \"clsx\";\nimport { useElement } from \"./widgets-context.js\";\nimport { getDomProps, namespaceClassNames } from \"./utils.js\";\nimport { EyeClosedIcon, EyeOpenIcon } from \"@radix-ui/react-icons\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\nexport interface ButtonProps extends Omit<\n RadixButtonProps,\n \"variant\" | \"color\"\n> {\n variant?: \"primary\" | \"secondary\" | \"destructive\";\n unsafe_radixVariant?: RadixButtonProps[\"variant\"];\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n { className, variant = \"primary\", unsafe_radixVariant, ...props },\n ref,\n ) {\n const element = useElement(`${variant}Button`);\n\n const themeProps = (() => {\n let props: RadixButtonProps = {};\n if (variant === \"primary\") {\n props = {\n variant: \"solid\",\n } satisfies RadixButtonProps;\n } else if (variant === \"secondary\") {\n props = {\n highContrast: true,\n variant: \"surface\",\n color: \"gray\",\n } satisfies RadixButtonProps;\n } else if (variant === \"destructive\") {\n props = {\n variant: \"solid\",\n color: \"red\",\n } satisfies RadixButtonProps;\n } else {\n variant satisfies never;\n }\n\n if (unsafe_radixVariant) {\n props.variant = unsafe_radixVariant;\n }\n\n return props;\n })();\n\n return (\n <RadixButton\n ref={ref}\n {...getDomProps({\n elementId: `${variant}Button`,\n className: cx(\n className,\n // TODO: Remove BEM-style selector once conventions are standardized\n `button--${variant}`,\n ),\n })}\n {...themeProps}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport interface IconButtonProps extends RadixIconButtonProps {\n title: string;\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton({ className, ...props }, ref) {\n const element = useElement(\"iconButton\");\n return (\n <RadixIconButton\n ref={ref}\n {...getDomProps({ elementId: \"iconButton\", className })}\n variant=\"ghost\"\n color=\"gray\"\n aria-label={props.title}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(\n function Skeleton({ className, ...props }, ref) {\n const element = useElement(\"skeleton\");\n return (\n <RadixSkeleton\n ref={ref}\n {...getDomProps({ elementId: \"skeleton\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Label = React.forwardRef<HTMLLabelElement, TextProps>(\n function Label({ children, className, style = {}, ...props }, ref) {\n const element = useElement(\"label\");\n return (\n <Text\n as=\"label\"\n ref={ref}\n weight=\"bold\"\n size=\"2\"\n {...getDomProps({ elementId: \"label\", className })}\n style={{ width: \"fit-content\", ...style }}\n // Text props are a complex union type depending on the `as` prop value,\n // which breaks down when spreading in `element`.\n {...(props as any)}\n {...element}\n >\n {children}\n </Text>\n );\n },\n);\n\nexport const TextField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function TextField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n />\n );\n});\n\nexport const TextFieldSlot = React.forwardRef<\n HTMLDivElement,\n RadixTextField.SlotProps\n>(function TextFieldSlot({ className, ...props }, ref) {\n return (\n <RadixTextField.Slot\n ref={ref}\n className={cx(namespaceClassNames(\"text-field-slot\"), className)}\n {...props}\n />\n );\n});\n\nexport const PasswordField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function PasswordField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n const [showPassword, setShowPassword] = React.useState(false);\n const translate = useTranslation();\n const hidePasswordText = translate({\n defaultMessage: \"Hide password\",\n id: \"Jv4Vps\",\n description: \"Button text to hide password\",\n });\n const showPasswordText = translate({\n defaultMessage: \"Show password\",\n id: \"UIfBSd\",\n description: \"Button text to show password\",\n });\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n type={showPassword ? \"text\" : \"password\"}\n >\n <RadixTextField.Slot side=\"right\">\n <IconButton\n type=\"button\"\n size=\"1\"\n onClick={() => setShowPassword(!showPassword)}\n title={showPassword ? hidePasswordText : showPasswordText}\n >\n {showPassword ? <EyeOpenIcon /> : <EyeClosedIcon />}\n </IconButton>\n </RadixTextField.Slot>\n </RadixTextField.Root>\n );\n});\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n function Badge({ className, ...props }, ref) {\n const element = useElement(\"badge\");\n return (\n <RadixBadge\n ref={ref}\n {...getDomProps({ elementId: \"badge\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\ninterface AvatarProps extends RadixAvatarProps {\n dim?: boolean;\n}\n\nexport const Avatar = React.forwardRef<HTMLImageElement, AvatarProps>(\n function Avatar({ dim, className, ...props }, ref) {\n const element = useElement(\"avatar\");\n return (\n <RadixAvatar\n ref={ref}\n color=\"gray\"\n {...getDomProps({ elementId: \"avatar\", className })}\n {...props}\n {...element}\n // TODO: use CSS var instead of hard-coded value for opacity\n style={dim ? { opacity: 0.6, ...props.style } : props.style}\n />\n );\n },\n);\n\ntype OmitAsChild<T> = {\n [K in keyof T]: T[K] extends undefined\n ? undefined\n : Omit<NonNullable<T[K]>, \"asChild\">;\n};\n\nexport * as Dialog from \"./elements/dialog.js\";\nexport * as AlertDialog from \"./elements/alert-dialog.js\";\nexport * as DropdownMenu from \"./elements/dropdown-menu.js\";\nexport * as Select from \"./elements/select.js\";\n\nexport type Elements = OmitAsChild<{\n dialog?: GetPropDefTypes<typeof dialogContentPropDefs>;\n primaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n secondaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n destructiveButton?: GetPropDefTypes<typeof buttonPropDefs>;\n iconButton?: GetPropDefTypes<typeof iconButtonPropDefs>;\n textfield?: GetPropDefTypes<typeof textFieldRootPropDefs>;\n select?: GetPropDefTypes<typeof selectTriggerPropDefs>;\n badge?: GetPropDefTypes<typeof badgePropDefs>;\n dropdown?: GetPropDefTypes<typeof dropdownMenuContentPropDefs>;\n primaryMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n destructiveMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n avatar?: Omit<GetPropDefTypes<typeof avatarPropDefs>, \"fallback\">;\n label?: GetPropDefTypes<typeof textPropDefs>;\n skeleton?: GetPropDefTypes<typeof skeletonPropDefs>;\n}>;\n"],"mappings":"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","names":["Button","props","IconButton","Skeleton","Label","TextField","TextFieldSlot","PasswordField","Badge","Avatar"]}
@@ -1,5 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import * as Form from "@radix-ui/react-form";
2
+ import { Form } from "radix-ui";
3
3
  import { Callout, Flex, Text } from "@radix-ui/themes";
4
4
  import { useMe, useSendVerification, useVerify } from "../api/endpoint.js";
5
5
  import { useElevatedAccessToken } from "../api/api-provider.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/elevated-access.tsx"],"sourcesContent":["import * as Form from \"@radix-ui/react-form\";\nimport { Callout, Flex, Text } from \"@radix-ui/themes\";\nimport { useMe, useSendVerification, useVerify } from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { PropsWithChildren, useEffect, useRef, useState } from \"react\";\nimport { AlertDialog, Dialog, Button } from \"./elements.js\";\nimport * as Otp from \"./otp-input.js\";\nimport { Translation } from \"./i18n/translation.js\";\n\ninterface ElevatedAccessProps extends PropsWithChildren {\n onVerified?: () => Promise<unknown>;\n type?: \"dialog\" | \"alert\";\n}\n\nexport function ElevatedAccess({\n type = \"dialog\",\n children,\n onVerified,\n}: ElevatedAccessProps) {\n const { elevatedAccess } = useElevatedAccessToken();\n const [authenticationChallengeId, setAuthenticationChallengeId] =\n useState<string>();\n\n const prevAccessToken = useRef(elevatedAccess);\n\n useEffect(() => {\n prevAccessToken.current = elevatedAccess;\n }, [elevatedAccess]);\n\n if (elevatedAccess) {\n return <>{children}</>;\n }\n\n if (!authenticationChallengeId) {\n // FIXME: This should be refactored\n // eslint-disable-next-line react-hooks/refs\n const hasTokenExpired = !!prevAccessToken.current;\n\n return (\n <SendVerificationEmailForm\n type={type}\n hasTokenExpired={hasTokenExpired}\n onSuccess={(challengeId) => {\n setAuthenticationChallengeId(challengeId);\n }}\n />\n );\n }\n\n if (authenticationChallengeId) {\n return (\n <VerificationIdentityForm\n type={type}\n authenticationChallengeId={authenticationChallengeId}\n onSuccess={() => {\n // Reset the challenge id\n setAuthenticationChallengeId(undefined);\n\n return onVerified?.();\n }}\n />\n );\n }\n\n return null;\n}\n\ninterface SendVerificationEmailFormProps {\n onSuccess: (challengeId: string) => unknown | Promise<unknown>;\n type: \"dialog\" | \"alert\";\n hasTokenExpired: boolean;\n}\n\nfunction SendVerificationEmailForm({\n onSuccess,\n type,\n hasTokenExpired,\n}: SendVerificationEmailFormProps) {\n const { data: me } = useMe();\n const sendVerification = useSendVerification({\n mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },\n });\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n sendVerification.mutate();\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Title>\n {hasTokenExpired ? (\n <Translation\n defaultMessage=\"Your verification token has expired\"\n id=\"lb/AsC\"\n description=\"Dialog title when verification token has expired\"\n />\n ) : (\n <Translation\n defaultMessage=\"Verify your identity\"\n id=\"7tGCOh\"\n description=\"Dialog title for identity verification\"\n />\n )}\n </Title>\n\n <Description color=\"gray\" mb=\"5\">\n <Translation\n defaultMessage=\"To continue, we need to confirm your identity. We'll send a temporary verification code to {email}.\"\n id=\"FTUSRM\"\n description=\"Description explaining verification code will be sent\"\n values={{\n email: (\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n ),\n }}\n />\n </Description>\n\n {sendVerification.error && (\n <Callout.Root color=\"red\" mt=\"-2\" mb=\"0\">\n <Callout.Text>\n {getMutationErrorMessage(sendVerification.error)}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={sendVerification.isPending}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Close>\n <Button type=\"submit\" loading={sendVerification.isPending}>\n <Translation\n defaultMessage=\"Send verification code\"\n id=\"XsTeXJ\"\n description=\"Button text to send verification code\"\n />\n </Button>\n </Flex>\n </form>\n );\n}\n\ninterface VerificationIdentityFormProps {\n onSuccess?: () => unknown | Promise<unknown>;\n authenticationChallengeId: string;\n type: \"dialog\" | \"alert\";\n}\n\nfunction VerificationIdentityForm({\n onSuccess,\n authenticationChallengeId,\n type,\n}: VerificationIdentityFormProps) {\n const { data: me } = useMe();\n const { setElevatedAccess } = useElevatedAccessToken();\n const verifyIdentity = useVerify();\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const code = formData.get(\"otp-code\")?.toString() ?? \"\";\n\n setIsSubmitting(true);\n\n try {\n // Mutate async so we can wait for the onSuccess callback as well\n const newAuthState = await verifyIdentity.mutateAsync({\n data: {\n code,\n authenticationChallengeId,\n },\n });\n\n const in10Seconds = new Date(Date.now() + 5 * 1000);\n\n setElevatedAccess({\n token: newAuthState.elevatedAccessToken,\n // expiresAt: newAuthState.expiresAt,\n expiresAt: in10Seconds.toISOString(),\n });\n\n if (onSuccess) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n await onSuccess();\n }\n } catch (error) {\n console.error(error);\n }\n\n setIsSubmitting(false);\n };\n\n return (\n <Form.Root onSubmit={handleSubmit}>\n <Title>\n <Translation\n defaultMessage=\"Verify your identity\"\n id=\"7tGCOh\"\n description=\"Dialog title for identity verification\"\n />\n </Title>\n\n <Description color=\"gray\">\n <Translation\n defaultMessage=\"A verification code was sent to {email}. Please enter it below.\"\n id=\"kvxE0S\"\n description=\"Description explaining where verification code was sent\"\n values={{\n email: (\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n ),\n }}\n />\n </Description>\n\n <Flex direction=\"column\" gap=\"2\" mt=\"5\" mx=\"auto\" width=\"fit-content\">\n <Otp.Root\n autoSubmit\n gap=\"2\"\n justify=\"center\"\n columns=\"repeat(6, 48px)\"\n width=\"fit-content\"\n rows=\"48px\"\n name=\"otp-code\"\n readOnly={isSubmitting}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {verifyIdentity.error && (\n <Text color=\"red\" size=\"2\" as=\"p\">\n {getMutationErrorMessage(verifyIdentity.error)}\n </Text>\n )}\n </Flex>\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button variant=\"secondary\" type=\"button\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Close>\n <Button type=\"submit\" loading={isSubmitting}>\n <Translation\n defaultMessage=\"Confirm\"\n id=\"EmYENK\"\n description=\"Confirm button text for verification\"\n />\n </Button>\n </Flex>\n </Form.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = typeof error === \"string\" ? error : \"\";\n\n if (error instanceof Error) {\n message = error.message;\n } else if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (!message || message === \"Bad Request\") {\n message = \"Invalid code, please try again.\";\n }\n\n return message;\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they are displayed dynamically\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/elevated-access.tsx"],"sourcesContent":["import { Form } from \"radix-ui\";\nimport { Callout, Flex, Text } from \"@radix-ui/themes\";\nimport { useMe, useSendVerification, useVerify } from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { PropsWithChildren, useEffect, useRef, useState } from \"react\";\nimport { AlertDialog, Dialog, Button } from \"./elements.js\";\nimport * as Otp from \"./otp-input.js\";\nimport { Translation } from \"./i18n/translation.js\";\n\ninterface ElevatedAccessProps extends PropsWithChildren {\n onVerified?: () => Promise<unknown>;\n type?: \"dialog\" | \"alert\";\n}\n\nexport function ElevatedAccess({\n type = \"dialog\",\n children,\n onVerified,\n}: ElevatedAccessProps) {\n const { elevatedAccess } = useElevatedAccessToken();\n const [authenticationChallengeId, setAuthenticationChallengeId] =\n useState<string>();\n\n const prevAccessToken = useRef(elevatedAccess);\n\n useEffect(() => {\n prevAccessToken.current = elevatedAccess;\n }, [elevatedAccess]);\n\n if (elevatedAccess) {\n return <>{children}</>;\n }\n\n if (!authenticationChallengeId) {\n // FIXME: This should be refactored\n // eslint-disable-next-line react-hooks/refs\n const hasTokenExpired = !!prevAccessToken.current;\n\n return (\n <SendVerificationEmailForm\n type={type}\n hasTokenExpired={hasTokenExpired}\n onSuccess={(challengeId) => {\n setAuthenticationChallengeId(challengeId);\n }}\n />\n );\n }\n\n if (authenticationChallengeId) {\n return (\n <VerificationIdentityForm\n type={type}\n authenticationChallengeId={authenticationChallengeId}\n onSuccess={() => {\n // Reset the challenge id\n setAuthenticationChallengeId(undefined);\n\n return onVerified?.();\n }}\n />\n );\n }\n\n return null;\n}\n\ninterface SendVerificationEmailFormProps {\n onSuccess: (challengeId: string) => unknown | Promise<unknown>;\n type: \"dialog\" | \"alert\";\n hasTokenExpired: boolean;\n}\n\nfunction SendVerificationEmailForm({\n onSuccess,\n type,\n hasTokenExpired,\n}: SendVerificationEmailFormProps) {\n const { data: me } = useMe();\n const sendVerification = useSendVerification({\n mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },\n });\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n sendVerification.mutate();\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Title>\n {hasTokenExpired ? (\n <Translation\n defaultMessage=\"Your verification token has expired\"\n id=\"lb/AsC\"\n description=\"Dialog title when verification token has expired\"\n />\n ) : (\n <Translation\n defaultMessage=\"Verify your identity\"\n id=\"7tGCOh\"\n description=\"Dialog title for identity verification\"\n />\n )}\n </Title>\n\n <Description color=\"gray\" mb=\"5\">\n <Translation\n defaultMessage=\"To continue, we need to confirm your identity. We'll send a temporary verification code to {email}.\"\n id=\"FTUSRM\"\n description=\"Description explaining verification code will be sent\"\n values={{\n email: (\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n ),\n }}\n />\n </Description>\n\n {sendVerification.error && (\n <Callout.Root color=\"red\" mt=\"-2\" mb=\"0\">\n <Callout.Text>\n {getMutationErrorMessage(sendVerification.error)}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={sendVerification.isPending}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Close>\n <Button type=\"submit\" loading={sendVerification.isPending}>\n <Translation\n defaultMessage=\"Send verification code\"\n id=\"XsTeXJ\"\n description=\"Button text to send verification code\"\n />\n </Button>\n </Flex>\n </form>\n );\n}\n\ninterface VerificationIdentityFormProps {\n onSuccess?: () => unknown | Promise<unknown>;\n authenticationChallengeId: string;\n type: \"dialog\" | \"alert\";\n}\n\nfunction VerificationIdentityForm({\n onSuccess,\n authenticationChallengeId,\n type,\n}: VerificationIdentityFormProps) {\n const { data: me } = useMe();\n const { setElevatedAccess } = useElevatedAccessToken();\n const verifyIdentity = useVerify();\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const code = formData.get(\"otp-code\")?.toString() ?? \"\";\n\n setIsSubmitting(true);\n\n try {\n // Mutate async so we can wait for the onSuccess callback as well\n const newAuthState = await verifyIdentity.mutateAsync({\n data: {\n code,\n authenticationChallengeId,\n },\n });\n\n const in10Seconds = new Date(Date.now() + 5 * 1000);\n\n setElevatedAccess({\n token: newAuthState.elevatedAccessToken,\n // expiresAt: newAuthState.expiresAt,\n expiresAt: in10Seconds.toISOString(),\n });\n\n if (onSuccess) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n await onSuccess();\n }\n } catch (error) {\n console.error(error);\n }\n\n setIsSubmitting(false);\n };\n\n return (\n <Form.Root onSubmit={handleSubmit}>\n <Title>\n <Translation\n defaultMessage=\"Verify your identity\"\n id=\"7tGCOh\"\n description=\"Dialog title for identity verification\"\n />\n </Title>\n\n <Description color=\"gray\">\n <Translation\n defaultMessage=\"A verification code was sent to {email}. Please enter it below.\"\n id=\"kvxE0S\"\n description=\"Description explaining where verification code was sent\"\n values={{\n email: (\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n ),\n }}\n />\n </Description>\n\n <Flex direction=\"column\" gap=\"2\" mt=\"5\" mx=\"auto\" width=\"fit-content\">\n <Otp.Root\n autoSubmit\n gap=\"2\"\n justify=\"center\"\n columns=\"repeat(6, 48px)\"\n width=\"fit-content\"\n rows=\"48px\"\n name=\"otp-code\"\n readOnly={isSubmitting}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {verifyIdentity.error && (\n <Text color=\"red\" size=\"2\" as=\"p\">\n {getMutationErrorMessage(verifyIdentity.error)}\n </Text>\n )}\n </Flex>\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button variant=\"secondary\" type=\"button\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Close>\n <Button type=\"submit\" loading={isSubmitting}>\n <Translation\n defaultMessage=\"Confirm\"\n id=\"EmYENK\"\n description=\"Confirm button text for verification\"\n />\n </Button>\n </Flex>\n </Form.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = typeof error === \"string\" ? error : \"\";\n\n if (error instanceof Error) {\n message = error.message;\n } else if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (!message || message === \"Bad Request\") {\n message = \"Invalid code, please try again.\";\n }\n\n return message;\n}\n\n// Note: Error messages in getMutationErrorMessage are kept as plain strings\n// since they are displayed dynamically\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/marker.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Text } from \"@radix-ui/themes\";\nimport { MarginProps } from \"@radix-ui/themes/props\";\nimport clsx from \"clsx\";\nimport { namespaceClassNames } from \"./utils.js\";\n\ntype TextProps = React.ComponentPropsWithoutRef<typeof Text>;\n\ntype MarkerOwnProps = {\n color?: \"gray\" | \"purple\" | \"blue\" | \"green\" | \"yellow\" | \"red\";\n highContrast?: boolean;\n size?: TextProps[\"size\"];\n};\n\ninterface MarkerProps\n extends Omit<React.ComponentPropsWithRef<\"span\">, \"color\">,\n MarkerOwnProps,\n MarginProps {}\n\nexport const Marker = React.forwardRef<HTMLSpanElement, MarkerProps>(\n function Marker(\n { children, className, highContrast, ...props },\n forwardedRef,\n ) {\n return (\n <Text\n ref={forwardedRef}\n className={clsx(className, namespaceClassNames(\"marker\"))}\n {...props}\n >\n <span className={namespaceClassNames(\"marker-circle\")}>\n <span className={namespaceClassNames(\"marker-content\")}>\n {children}\n </span>\n </span>\n </Text>\n );\n },\n);\n"],"mappings":"AA+BU;AA/BV,YAAY,WAAW;AACvB,SAAS,YAAY;AAErB,OAAO,UAAU;AACjB,SAAS,2BAA2B;AAe7B,MAAM,SAAS,MAAM;AAAA,EAC1B,SAASA,QACP,EAAE,UAAU,WAAW,cAAc,GAAG,MAAM,GAC9C,cACA;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAW,KAAK,WAAW,oBAAoB,QAAQ,CAAC;AAAA,QACvD,GAAG;AAAA,QAEJ,8BAAC,UAAK,WAAW,oBAAoB,eAAe,GAClD,8BAAC,UAAK,WAAW,oBAAoB,gBAAgB,GAClD,UACH,GACF;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;","names":["Marker"]}
1
+ {"version":3,"sources":["../../../src/lib/marker.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Text } from \"@radix-ui/themes\";\nimport { MarginProps } from \"@radix-ui/themes/props\";\nimport clsx from \"clsx\";\nimport { namespaceClassNames } from \"./utils.js\";\n\ntype TextProps = React.ComponentPropsWithoutRef<typeof Text>;\n\ntype MarkerOwnProps = {\n color?: \"gray\" | \"purple\" | \"blue\" | \"green\" | \"yellow\" | \"red\";\n highContrast?: boolean;\n size?: TextProps[\"size\"];\n};\n\ninterface MarkerProps\n extends\n Omit<React.ComponentPropsWithRef<\"span\">, \"color\">,\n MarkerOwnProps,\n MarginProps {}\n\nexport const Marker = React.forwardRef<HTMLSpanElement, MarkerProps>(\n function Marker(\n { children, className, highContrast, ...props },\n forwardedRef,\n ) {\n return (\n <Text\n ref={forwardedRef}\n className={clsx(className, namespaceClassNames(\"marker\"))}\n {...props}\n >\n <span className={namespaceClassNames(\"marker-circle\")}>\n <span className={namespaceClassNames(\"marker-content\")}>\n {children}\n </span>\n </span>\n </Text>\n );\n },\n);\n"],"mappings":"AAgCU;AAhCV,YAAY,WAAW;AACvB,SAAS,YAAY;AAErB,OAAO,UAAU;AACjB,SAAS,2BAA2B;AAgB7B,MAAM,SAAS,MAAM;AAAA,EAC1B,SAASA,QACP,EAAE,UAAU,WAAW,cAAc,GAAG,MAAM,GAC9C,cACA;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAW,KAAK,WAAW,oBAAoB,QAAQ,CAAC;AAAA,QACvD,GAAG;AAAA,QAEJ,8BAAC,UAAK,WAAW,oBAAoB,eAAe,GAClD,8BAAC,UAAK,WAAW,oBAAoB,gBAAgB,GAClD,UACH,GACF;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;","names":["Marker"]}