@workos-inc/widgets 1.6.1 → 1.7.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/dist/cjs/admin-portal-domain-verification.client.d.cts +11 -0
  3. package/dist/cjs/admin-portal-sso-connection.client.d.cts +11 -0
  4. package/dist/cjs/alert-dialog-BlG3_awx.d.cts +25 -0
  5. package/dist/cjs/api-keys.client.d.cts +11 -0
  6. package/dist/cjs/dialog-C15qCLN3.d.cts +23 -0
  7. package/dist/cjs/dropdown-menu-BQ5LtvdR.d.cts +48 -0
  8. package/dist/cjs/index.d.cts +8 -0
  9. package/dist/cjs/lib/add-mfa-dialog.cjs +22 -14
  10. package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
  11. package/dist/cjs/lib/add-mfa-dialog.d.cts +2 -2
  12. package/dist/cjs/lib/admin-portal-domain-verification.cjs +6 -8
  13. package/dist/cjs/lib/admin-portal-domain-verification.cjs.map +1 -1
  14. package/dist/cjs/lib/admin-portal-domain-verification.d.cts +11 -0
  15. package/dist/cjs/lib/admin-portal-sso-connection.cjs +7 -8
  16. package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
  17. package/dist/cjs/lib/admin-portal-sso-connection.d.cts +11 -0
  18. package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs +3 -3
  19. package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs.map +1 -1
  20. package/dist/cjs/lib/api-keys/api-keys-search.cjs +2 -6
  21. package/dist/cjs/lib/api-keys/api-keys-search.cjs.map +1 -1
  22. package/dist/cjs/lib/api-keys/api-keys-table.cjs +18 -19
  23. package/dist/cjs/lib/api-keys/api-keys-table.cjs.map +1 -1
  24. package/dist/cjs/lib/api-keys/api-keys.cjs +2 -2
  25. package/dist/cjs/lib/api-keys/api-keys.cjs.map +1 -1
  26. package/dist/cjs/lib/api-keys/api-keys.d.cts +12 -0
  27. package/dist/cjs/lib/api-keys/create-api-key.cjs +20 -14
  28. package/dist/cjs/lib/api-keys/create-api-key.cjs.map +1 -1
  29. package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs +7 -7
  30. package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs.map +1 -1
  31. package/dist/cjs/lib/api-keys/skeleton-table.cjs +3 -2
  32. package/dist/cjs/lib/api-keys/skeleton-table.cjs.map +1 -1
  33. package/dist/cjs/lib/change-password-dialog.cjs +11 -9
  34. package/dist/cjs/lib/change-password-dialog.cjs.map +1 -1
  35. package/dist/cjs/lib/change-password-dialog.d.cts +2 -2
  36. package/dist/cjs/lib/copy-button.cjs +51 -29
  37. package/dist/cjs/lib/copy-button.cjs.map +1 -1
  38. package/dist/cjs/lib/copy-button.d.cts +22 -4
  39. package/dist/cjs/lib/delete-domain-dialog.cjs +8 -7
  40. package/dist/cjs/lib/delete-domain-dialog.cjs.map +1 -1
  41. package/dist/cjs/lib/delete-user-dialog.cjs +15 -7
  42. package/dist/cjs/lib/delete-user-dialog.cjs.map +1 -1
  43. package/dist/cjs/lib/delete-user-dialog.d.cts +2 -2
  44. package/dist/cjs/lib/domain-actions.cjs +8 -8
  45. package/dist/cjs/lib/domain-actions.cjs.map +1 -1
  46. package/dist/cjs/lib/edit-user-profile-dialog.cjs +10 -9
  47. package/dist/cjs/lib/edit-user-profile-dialog.cjs.map +1 -1
  48. package/dist/cjs/lib/edit-user-profile-dialog.d.cts +2 -2
  49. package/dist/cjs/lib/edit-user-role-dialog.cjs +15 -15
  50. package/dist/cjs/lib/edit-user-role-dialog.cjs.map +1 -1
  51. package/dist/cjs/lib/edit-user-role-dialog.d.cts +2 -2
  52. package/dist/cjs/lib/elements/alert-dialog.cjs +76 -0
  53. package/dist/cjs/lib/elements/alert-dialog.cjs.map +1 -0
  54. package/dist/cjs/lib/elements/alert-dialog.d.cts +3 -0
  55. package/dist/cjs/lib/elements/dialog.cjs +74 -0
  56. package/dist/cjs/lib/elements/dialog.cjs.map +1 -0
  57. package/dist/cjs/lib/elements/dialog.d.cts +3 -0
  58. package/dist/cjs/lib/elements/dropdown-menu.cjs +162 -0
  59. package/dist/cjs/lib/elements/dropdown-menu.cjs.map +1 -0
  60. package/dist/cjs/lib/elements/dropdown-menu.d.cts +3 -0
  61. package/dist/cjs/lib/elements/select.cjs +112 -0
  62. package/dist/cjs/lib/elements/select.cjs.map +1 -0
  63. package/dist/cjs/lib/elements/select.d.cts +4 -0
  64. package/dist/cjs/lib/elements/utils.cjs +54 -0
  65. package/dist/cjs/lib/elements/utils.cjs.map +1 -0
  66. package/dist/cjs/lib/elements/utils.d.cts +15 -0
  67. package/dist/cjs/lib/elements.cjs +73 -219
  68. package/dist/cjs/lib/elements.cjs.map +1 -1
  69. package/dist/cjs/lib/elements.d.cts +16 -13
  70. package/dist/cjs/lib/elevated-access.cjs +18 -10
  71. package/dist/cjs/lib/elevated-access.cjs.map +1 -1
  72. package/dist/cjs/lib/empty-state.d.cts +12 -0
  73. package/dist/cjs/lib/invite-user-dialog.cjs +13 -12
  74. package/dist/cjs/lib/invite-user-dialog.cjs.map +1 -1
  75. package/dist/cjs/lib/logout-all-sessions-dialog.cjs +7 -6
  76. package/dist/cjs/lib/logout-all-sessions-dialog.cjs.map +1 -1
  77. package/dist/cjs/lib/logout-all-sessions-dialog.d.cts +2 -2
  78. package/dist/cjs/lib/logout-dialog.cjs +7 -6
  79. package/dist/cjs/lib/logout-dialog.cjs.map +1 -1
  80. package/dist/cjs/lib/logout-dialog.d.cts +2 -2
  81. package/dist/cjs/lib/organization-switcher.cjs +38 -20
  82. package/dist/cjs/lib/organization-switcher.cjs.map +1 -1
  83. package/dist/cjs/lib/organization-switcher.d.cts +16 -2
  84. package/dist/cjs/lib/otp-input.d.cts +8 -0
  85. package/dist/cjs/lib/pipes.cjs +31 -42
  86. package/dist/cjs/lib/pipes.cjs.map +1 -1
  87. package/dist/cjs/lib/pipes.d.cts +12 -0
  88. package/dist/cjs/lib/resend-invite-dialog.cjs +23 -13
  89. package/dist/cjs/lib/resend-invite-dialog.cjs.map +1 -1
  90. package/dist/cjs/lib/resend-invite-dialog.d.cts +2 -2
  91. package/dist/cjs/lib/reset-mfa-dialog.cjs +9 -8
  92. package/dist/cjs/lib/reset-mfa-dialog.cjs.map +1 -1
  93. package/dist/cjs/lib/reset-mfa-dialog.d.cts +2 -2
  94. package/dist/cjs/lib/revoke-invite-dialog.cjs +17 -8
  95. package/dist/cjs/lib/revoke-invite-dialog.cjs.map +1 -1
  96. package/dist/cjs/lib/revoke-invite-dialog.d.cts +2 -2
  97. package/dist/cjs/lib/save-button.cjs +3 -2
  98. package/dist/cjs/lib/save-button.cjs.map +1 -1
  99. package/dist/cjs/lib/save-button.d.cts +12 -1
  100. package/dist/cjs/lib/set-password-dialog.cjs +11 -9
  101. package/dist/cjs/lib/set-password-dialog.cjs.map +1 -1
  102. package/dist/cjs/lib/set-password-dialog.d.cts +2 -2
  103. package/dist/cjs/lib/user-actions-dropdown.cjs +9 -8
  104. package/dist/cjs/lib/user-actions-dropdown.cjs.map +1 -1
  105. package/dist/cjs/lib/user-profile.cjs +1 -1
  106. package/dist/cjs/lib/user-profile.cjs.map +1 -1
  107. package/dist/cjs/lib/user-profile.d.cts +11 -0
  108. package/dist/cjs/lib/user-security.cjs +3 -3
  109. package/dist/cjs/lib/user-security.cjs.map +1 -1
  110. package/dist/cjs/lib/user-security.d.cts +12 -0
  111. package/dist/cjs/lib/user-sessions.cjs +3 -11
  112. package/dist/cjs/lib/user-sessions.cjs.map +1 -1
  113. package/dist/cjs/lib/user-sessions.d.cts +12 -0
  114. package/dist/cjs/lib/users-filter.cjs +5 -6
  115. package/dist/cjs/lib/users-filter.cjs.map +1 -1
  116. package/dist/cjs/lib/users-filter.d.cts +2 -2
  117. package/dist/cjs/lib/users-management.cjs +22 -34
  118. package/dist/cjs/lib/users-management.cjs.map +1 -1
  119. package/dist/cjs/lib/users-management.d.cts +11 -0
  120. package/dist/cjs/lib/users-search.cjs +2 -6
  121. package/dist/cjs/lib/users-search.cjs.map +1 -1
  122. package/dist/cjs/lib/utils.cjs +25 -2
  123. package/dist/cjs/lib/utils.cjs.map +1 -1
  124. package/dist/cjs/lib/utils.d.cts +17 -3
  125. package/dist/cjs/lib/view-dns-record-dialog.cjs +9 -8
  126. package/dist/cjs/lib/view-dns-record-dialog.cjs.map +1 -1
  127. package/dist/cjs/lib/widgets-context.d.cts +8 -0
  128. package/dist/cjs/organization-switcher.client.cjs +33 -5
  129. package/dist/cjs/organization-switcher.client.cjs.map +1 -1
  130. package/dist/cjs/organization-switcher.client.d.cts +11 -0
  131. package/dist/cjs/pipes.client.d.cts +11 -0
  132. package/dist/cjs/select-KR89Qnvm.d.cts +30 -0
  133. package/dist/cjs/user-profile.client.d.cts +11 -0
  134. package/dist/cjs/user-security.client.d.cts +11 -0
  135. package/dist/cjs/user-sessions.client.d.cts +11 -0
  136. package/dist/cjs/users-management.client.d.cts +11 -0
  137. package/dist/cjs/utils.cjs +59 -0
  138. package/dist/cjs/utils.cjs.map +1 -0
  139. package/dist/cjs/utils.d.cts +3 -0
  140. package/dist/cjs/workos-widgets.client.d.cts +8 -0
  141. package/dist/css/lib/provider-icon.css +6 -0
  142. package/dist/esm/admin-portal-domain-verification.client.d.ts +11 -0
  143. package/dist/esm/admin-portal-sso-connection.client.d.ts +11 -0
  144. package/dist/esm/alert-dialog-BlG3_awx.d.ts +25 -0
  145. package/dist/esm/api-keys.client.d.ts +11 -0
  146. package/dist/esm/dialog-C15qCLN3.d.ts +23 -0
  147. package/dist/esm/dropdown-menu-BQ5LtvdR.d.ts +48 -0
  148. package/dist/esm/index.d.ts +8 -0
  149. package/dist/esm/lib/add-mfa-dialog.d.ts +2 -2
  150. package/dist/esm/lib/add-mfa-dialog.js +16 -9
  151. package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
  152. package/dist/esm/lib/admin-portal-domain-verification.d.ts +11 -0
  153. package/dist/esm/lib/admin-portal-domain-verification.js +6 -8
  154. package/dist/esm/lib/admin-portal-domain-verification.js.map +1 -1
  155. package/dist/esm/lib/admin-portal-sso-connection.d.ts +11 -0
  156. package/dist/esm/lib/admin-portal-sso-connection.js +8 -9
  157. package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
  158. package/dist/esm/lib/api-keys/api-key-details-dialog.js +3 -3
  159. package/dist/esm/lib/api-keys/api-key-details-dialog.js.map +1 -1
  160. package/dist/esm/lib/api-keys/api-keys-search.js +2 -6
  161. package/dist/esm/lib/api-keys/api-keys-search.js.map +1 -1
  162. package/dist/esm/lib/api-keys/api-keys-table.js +18 -32
  163. package/dist/esm/lib/api-keys/api-keys-table.js.map +1 -1
  164. package/dist/esm/lib/api-keys/api-keys.d.ts +12 -0
  165. package/dist/esm/lib/api-keys/api-keys.js +2 -2
  166. package/dist/esm/lib/api-keys/api-keys.js.map +1 -1
  167. package/dist/esm/lib/api-keys/create-api-key.js +17 -14
  168. package/dist/esm/lib/api-keys/create-api-key.js.map +1 -1
  169. package/dist/esm/lib/api-keys/revoke-api-key-dialog.js +4 -4
  170. package/dist/esm/lib/api-keys/revoke-api-key-dialog.js.map +1 -1
  171. package/dist/esm/lib/api-keys/skeleton-table.js +2 -1
  172. package/dist/esm/lib/api-keys/skeleton-table.js.map +1 -1
  173. package/dist/esm/lib/change-password-dialog.d.ts +2 -2
  174. package/dist/esm/lib/change-password-dialog.js +8 -12
  175. package/dist/esm/lib/change-password-dialog.js.map +1 -1
  176. package/dist/esm/lib/copy-button.d.ts +22 -4
  177. package/dist/esm/lib/copy-button.js +49 -28
  178. package/dist/esm/lib/copy-button.js.map +1 -1
  179. package/dist/esm/lib/delete-domain-dialog.js +4 -3
  180. package/dist/esm/lib/delete-domain-dialog.js.map +1 -1
  181. package/dist/esm/lib/delete-user-dialog.d.ts +2 -2
  182. package/dist/esm/lib/delete-user-dialog.js +13 -15
  183. package/dist/esm/lib/delete-user-dialog.js.map +1 -1
  184. package/dist/esm/lib/domain-actions.js +4 -4
  185. package/dist/esm/lib/domain-actions.js.map +1 -1
  186. package/dist/esm/lib/edit-user-profile-dialog.d.ts +2 -2
  187. package/dist/esm/lib/edit-user-profile-dialog.js +7 -12
  188. package/dist/esm/lib/edit-user-profile-dialog.js.map +1 -1
  189. package/dist/esm/lib/edit-user-role-dialog.d.ts +2 -2
  190. package/dist/esm/lib/edit-user-role-dialog.js +9 -19
  191. package/dist/esm/lib/edit-user-role-dialog.js.map +1 -1
  192. package/dist/esm/lib/elements/alert-dialog.d.ts +3 -0
  193. package/dist/esm/lib/elements/alert-dialog.js +45 -0
  194. package/dist/esm/lib/elements/alert-dialog.js.map +1 -0
  195. package/dist/esm/lib/elements/dialog.d.ts +3 -0
  196. package/dist/esm/lib/elements/dialog.js +43 -0
  197. package/dist/esm/lib/elements/dialog.js.map +1 -0
  198. package/dist/esm/lib/elements/dropdown-menu.d.ts +3 -0
  199. package/dist/esm/lib/elements/dropdown-menu.js +131 -0
  200. package/dist/esm/lib/elements/dropdown-menu.js.map +1 -0
  201. package/dist/esm/lib/elements/select.d.ts +4 -0
  202. package/dist/esm/lib/elements/select.js +77 -0
  203. package/dist/esm/lib/elements/select.js.map +1 -0
  204. package/dist/esm/lib/elements/utils.d.ts +15 -0
  205. package/dist/esm/lib/elements/utils.js +20 -0
  206. package/dist/esm/lib/elements/utils.js.map +1 -0
  207. package/dist/esm/lib/elements.d.ts +16 -13
  208. package/dist/esm/lib/elements.js +71 -215
  209. package/dist/esm/lib/elements.js.map +1 -1
  210. package/dist/esm/lib/elevated-access.js +14 -6
  211. package/dist/esm/lib/elevated-access.js.map +1 -1
  212. package/dist/esm/lib/empty-state.d.ts +12 -0
  213. package/dist/esm/lib/invite-user-dialog.js +10 -24
  214. package/dist/esm/lib/invite-user-dialog.js.map +1 -1
  215. package/dist/esm/lib/logout-all-sessions-dialog.d.ts +2 -2
  216. package/dist/esm/lib/logout-all-sessions-dialog.js +6 -9
  217. package/dist/esm/lib/logout-all-sessions-dialog.js.map +1 -1
  218. package/dist/esm/lib/logout-dialog.d.ts +2 -2
  219. package/dist/esm/lib/logout-dialog.js +6 -9
  220. package/dist/esm/lib/logout-dialog.js.map +1 -1
  221. package/dist/esm/lib/organization-switcher.d.ts +16 -2
  222. package/dist/esm/lib/organization-switcher.js +33 -13
  223. package/dist/esm/lib/organization-switcher.js.map +1 -1
  224. package/dist/esm/lib/otp-input.d.ts +8 -0
  225. package/dist/esm/lib/pipes.d.ts +12 -0
  226. package/dist/esm/lib/pipes.js +27 -47
  227. package/dist/esm/lib/pipes.js.map +1 -1
  228. package/dist/esm/lib/resend-invite-dialog.d.ts +2 -2
  229. package/dist/esm/lib/resend-invite-dialog.js +17 -20
  230. package/dist/esm/lib/resend-invite-dialog.js.map +1 -1
  231. package/dist/esm/lib/reset-mfa-dialog.d.ts +2 -2
  232. package/dist/esm/lib/reset-mfa-dialog.js +6 -9
  233. package/dist/esm/lib/reset-mfa-dialog.js.map +1 -1
  234. package/dist/esm/lib/revoke-invite-dialog.d.ts +2 -2
  235. package/dist/esm/lib/revoke-invite-dialog.js +14 -15
  236. package/dist/esm/lib/revoke-invite-dialog.js.map +1 -1
  237. package/dist/esm/lib/save-button.d.ts +12 -1
  238. package/dist/esm/lib/save-button.js +4 -9
  239. package/dist/esm/lib/save-button.js.map +1 -1
  240. package/dist/esm/lib/set-password-dialog.d.ts +2 -2
  241. package/dist/esm/lib/set-password-dialog.js +8 -12
  242. package/dist/esm/lib/set-password-dialog.js.map +1 -1
  243. package/dist/esm/lib/user-actions-dropdown.js +8 -11
  244. package/dist/esm/lib/user-actions-dropdown.js.map +1 -1
  245. package/dist/esm/lib/user-profile.d.ts +11 -0
  246. package/dist/esm/lib/user-profile.js +2 -2
  247. package/dist/esm/lib/user-profile.js.map +1 -1
  248. package/dist/esm/lib/user-security.d.ts +12 -0
  249. package/dist/esm/lib/user-security.js +4 -4
  250. package/dist/esm/lib/user-security.js.map +1 -1
  251. package/dist/esm/lib/user-sessions.d.ts +12 -0
  252. package/dist/esm/lib/user-sessions.js +5 -13
  253. package/dist/esm/lib/user-sessions.js.map +1 -1
  254. package/dist/esm/lib/users-filter.d.ts +2 -2
  255. package/dist/esm/lib/users-filter.js +5 -6
  256. package/dist/esm/lib/users-filter.js.map +1 -1
  257. package/dist/esm/lib/users-management.d.ts +11 -0
  258. package/dist/esm/lib/users-management.js +23 -39
  259. package/dist/esm/lib/users-management.js.map +1 -1
  260. package/dist/esm/lib/users-search.js +2 -6
  261. package/dist/esm/lib/users-search.js.map +1 -1
  262. package/dist/esm/lib/utils.d.ts +17 -3
  263. package/dist/esm/lib/utils.js +24 -2
  264. package/dist/esm/lib/utils.js.map +1 -1
  265. package/dist/esm/lib/view-dns-record-dialog.js +7 -17
  266. package/dist/esm/lib/view-dns-record-dialog.js.map +1 -1
  267. package/dist/esm/lib/widgets-context.d.ts +8 -0
  268. package/dist/esm/organization-switcher.client.d.ts +11 -0
  269. package/dist/esm/organization-switcher.client.js +33 -5
  270. package/dist/esm/organization-switcher.client.js.map +1 -1
  271. package/dist/esm/pipes.client.d.ts +11 -0
  272. package/dist/esm/select-KR89Qnvm.d.ts +30 -0
  273. package/dist/esm/user-profile.client.d.ts +11 -0
  274. package/dist/esm/user-security.client.d.ts +11 -0
  275. package/dist/esm/user-sessions.client.d.ts +11 -0
  276. package/dist/esm/users-management.client.d.ts +11 -0
  277. package/dist/esm/utils.d.ts +3 -0
  278. package/dist/esm/utils.js +25 -0
  279. package/dist/esm/utils.js.map +1 -0
  280. package/dist/esm/workos-widgets.client.d.ts +8 -0
  281. package/package.json +11 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/elevated-access.tsx"],"sourcesContent":["import * as Form from \"@radix-ui/react-form\";\nimport { AlertDialog, Callout, Dialog, 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 { PrimaryButton, SecondaryButton } from \"./elements.js\";\nimport * as Otp from \"./otp-input.js\";\n\ninterface ElevatedAccessProps extends PropsWithChildren {\n onVerified?: () => Promise<unknown>;\n type?: \"dialog\" | \"alert\";\n}\n\nexport function ElevatedAccess({\n type = \"dialog\",\n children,\n onVerified,\n}: ElevatedAccessProps) {\n const { elevatedAccess } = useElevatedAccessToken();\n const [authenticationChallengeId, setAuthenticationChallengeId] =\n useState<string>();\n\n const prevAccessToken = useRef(elevatedAccess);\n\n useEffect(() => {\n prevAccessToken.current = elevatedAccess;\n }, [elevatedAccess]);\n\n if (elevatedAccess) {\n return <>{children}</>;\n }\n\n if (!authenticationChallengeId) {\n // FIXME: This should be refactored\n // eslint-disable-next-line react-hooks/refs\n const hasTokenExpired = !!prevAccessToken.current;\n\n return (\n <SendVerificationEmailForm\n type={type}\n hasTokenExpired={hasTokenExpired}\n onSuccess={(challengeId) => {\n setAuthenticationChallengeId(challengeId);\n }}\n />\n );\n }\n\n if (authenticationChallengeId) {\n return (\n <VerificationIdentityForm\n type={type}\n authenticationChallengeId={authenticationChallengeId}\n onSuccess={() => {\n // Reset the challenge id\n setAuthenticationChallengeId(undefined);\n\n return onVerified?.();\n }}\n />\n );\n }\n\n return null;\n}\n\ninterface SendVerificationEmailFormProps {\n onSuccess: (challengeId: string) => unknown | Promise<unknown>;\n type: \"dialog\" | \"alert\";\n hasTokenExpired: boolean;\n}\n\nfunction SendVerificationEmailForm({\n onSuccess,\n type,\n hasTokenExpired,\n}: SendVerificationEmailFormProps) {\n const { data: me } = useMe();\n const sendVerification = useSendVerification({\n mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },\n });\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n sendVerification.mutate();\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Title>\n {hasTokenExpired\n ? \"Your verification token has expired\"\n : \"Verify your identity\"}\n </Title>\n\n <Description color=\"gray\" mb=\"5\">\n To continue, we need to confirm your identity. We'll send a temporary\n verification code to{\" \"}\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n .\n </Description>\n\n {sendVerification.error && (\n <Callout.Root color=\"red\" mt=\"-2\" mb=\"0\">\n <Callout.Text>\n {getMutationErrorMessage(sendVerification.error)}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <SecondaryButton type=\"button\" disabled={sendVerification.isPending}>\n Cancel\n </SecondaryButton>\n </Close>\n <PrimaryButton type=\"submit\" loading={sendVerification.isPending}>\n Send verification code\n </PrimaryButton>\n </Flex>\n </form>\n );\n}\n\ninterface VerificationIdentityFormProps {\n onSuccess?: () => unknown | Promise<unknown>;\n authenticationChallengeId: string;\n type: \"dialog\" | \"alert\";\n}\n\nfunction VerificationIdentityForm({\n onSuccess,\n authenticationChallengeId,\n type,\n}: VerificationIdentityFormProps) {\n const { data: me } = useMe();\n const { setElevatedAccess } = useElevatedAccessToken();\n const verifyIdentity = useVerify();\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const code = formData.get(\"otp-code\")?.toString() ?? \"\";\n\n setIsSubmitting(true);\n\n try {\n // Mutate async so we can wait for the onSuccess callback as well\n const newAuthState = await verifyIdentity.mutateAsync({\n data: {\n code,\n authenticationChallengeId,\n },\n });\n\n const in10Seconds = new Date(Date.now() + 5 * 1000);\n\n setElevatedAccess({\n token: newAuthState.elevatedAccessToken,\n // expiresAt: newAuthState.expiresAt,\n expiresAt: in10Seconds.toISOString(),\n });\n\n if (onSuccess) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n await onSuccess();\n }\n } catch (error) {\n console.error(error);\n }\n\n setIsSubmitting(false);\n };\n\n return (\n <Form.Root onSubmit={handleSubmit}>\n <Title>Verify your identity</Title>\n\n <Description color=\"gray\">\n A verification code was sent to{\" \"}\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n . Please enter it below.\n </Description>\n\n <Flex direction=\"column\" gap=\"2\" mt=\"5\" mx=\"auto\" width=\"fit-content\">\n <Otp.Root\n autoSubmit\n gap=\"2\"\n justify=\"center\"\n columns=\"repeat(6, 48px)\"\n width=\"fit-content\"\n rows=\"48px\"\n name=\"otp-code\"\n readOnly={isSubmitting}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {verifyIdentity.error && (\n <Text color=\"red\" size=\"2\" as=\"p\">\n {getMutationErrorMessage(verifyIdentity.error)}\n </Text>\n )}\n </Flex>\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <SecondaryButton type=\"button\">Cancel</SecondaryButton>\n </Close>\n\n <PrimaryButton type=\"submit\" loading={isSubmitting}>\n Confirm\n </PrimaryButton>\n </Flex>\n </Form.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = typeof error === \"string\" ? error : \"\";\n\n if (error instanceof Error) {\n message = error.message;\n } else if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (!message || message === \"Bad Request\") {\n message = \"Invalid code, please try again.\";\n }\n\n return message;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/elevated-access.tsx"],"sourcesContent":["import * as Form from \"@radix-ui/react-form\";\nimport { Callout, Flex, Text } from \"@radix-ui/themes\";\nimport { useMe, useSendVerification, useVerify } from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { PropsWithChildren, useEffect, useRef, useState } from \"react\";\nimport { AlertDialog, Dialog, Button } from \"./elements.js\";\nimport * as Otp from \"./otp-input.js\";\n\ninterface ElevatedAccessProps extends PropsWithChildren {\n onVerified?: () => Promise<unknown>;\n type?: \"dialog\" | \"alert\";\n}\n\nexport function ElevatedAccess({\n type = \"dialog\",\n children,\n onVerified,\n}: ElevatedAccessProps) {\n const { elevatedAccess } = useElevatedAccessToken();\n const [authenticationChallengeId, setAuthenticationChallengeId] =\n useState<string>();\n\n const prevAccessToken = useRef(elevatedAccess);\n\n useEffect(() => {\n prevAccessToken.current = elevatedAccess;\n }, [elevatedAccess]);\n\n if (elevatedAccess) {\n return <>{children}</>;\n }\n\n if (!authenticationChallengeId) {\n // FIXME: This should be refactored\n // eslint-disable-next-line react-hooks/refs\n const hasTokenExpired = !!prevAccessToken.current;\n\n return (\n <SendVerificationEmailForm\n type={type}\n hasTokenExpired={hasTokenExpired}\n onSuccess={(challengeId) => {\n setAuthenticationChallengeId(challengeId);\n }}\n />\n );\n }\n\n if (authenticationChallengeId) {\n return (\n <VerificationIdentityForm\n type={type}\n authenticationChallengeId={authenticationChallengeId}\n onSuccess={() => {\n // Reset the challenge id\n setAuthenticationChallengeId(undefined);\n\n return onVerified?.();\n }}\n />\n );\n }\n\n return null;\n}\n\ninterface SendVerificationEmailFormProps {\n onSuccess: (challengeId: string) => unknown | Promise<unknown>;\n type: \"dialog\" | \"alert\";\n hasTokenExpired: boolean;\n}\n\nfunction SendVerificationEmailForm({\n onSuccess,\n type,\n hasTokenExpired,\n}: SendVerificationEmailFormProps) {\n const { data: me } = useMe();\n const sendVerification = useSendVerification({\n mutation: { onSuccess: (data) => onSuccess(data.authenticationChallenge) },\n });\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n sendVerification.mutate();\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Title>\n {hasTokenExpired\n ? \"Your verification token has expired\"\n : \"Verify your identity\"}\n </Title>\n\n <Description color=\"gray\" mb=\"5\">\n To continue, we need to confirm your identity. We'll send a temporary\n verification code to{\" \"}\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n .\n </Description>\n\n {sendVerification.error && (\n <Callout.Root color=\"red\" mt=\"-2\" mb=\"0\">\n <Callout.Text>\n {getMutationErrorMessage(sendVerification.error)}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={sendVerification.isPending}\n >\n Cancel\n </Button>\n </Close>\n <Button type=\"submit\" loading={sendVerification.isPending}>\n Send verification code\n </Button>\n </Flex>\n </form>\n );\n}\n\ninterface VerificationIdentityFormProps {\n onSuccess?: () => unknown | Promise<unknown>;\n authenticationChallengeId: string;\n type: \"dialog\" | \"alert\";\n}\n\nfunction VerificationIdentityForm({\n onSuccess,\n authenticationChallengeId,\n type,\n}: VerificationIdentityFormProps) {\n const { data: me } = useMe();\n const { setElevatedAccess } = useElevatedAccessToken();\n const verifyIdentity = useVerify();\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const Title = type === \"dialog\" ? Dialog.Title : AlertDialog.Title;\n const Description =\n type === \"dialog\" ? Dialog.Description : AlertDialog.Description;\n const Close = type === \"dialog\" ? Dialog.Close : AlertDialog.Cancel;\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const formData = new FormData(event.currentTarget);\n const code = formData.get(\"otp-code\")?.toString() ?? \"\";\n\n setIsSubmitting(true);\n\n try {\n // Mutate async so we can wait for the onSuccess callback as well\n const newAuthState = await verifyIdentity.mutateAsync({\n data: {\n code,\n authenticationChallengeId,\n },\n });\n\n const in10Seconds = new Date(Date.now() + 5 * 1000);\n\n setElevatedAccess({\n token: newAuthState.elevatedAccessToken,\n // expiresAt: newAuthState.expiresAt,\n expiresAt: in10Seconds.toISOString(),\n });\n\n if (onSuccess) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n await onSuccess();\n }\n } catch (error) {\n console.error(error);\n }\n\n setIsSubmitting(false);\n };\n\n return (\n <Form.Root onSubmit={handleSubmit}>\n <Title>Verify your identity</Title>\n\n <Description color=\"gray\">\n A verification code was sent to{\" \"}\n <Text weight=\"bold\" highContrast>\n {me?.email}\n </Text>\n . Please enter it below.\n </Description>\n\n <Flex direction=\"column\" gap=\"2\" mt=\"5\" mx=\"auto\" width=\"fit-content\">\n <Otp.Root\n autoSubmit\n gap=\"2\"\n justify=\"center\"\n columns=\"repeat(6, 48px)\"\n width=\"fit-content\"\n rows=\"48px\"\n name=\"otp-code\"\n readOnly={isSubmitting}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {verifyIdentity.error && (\n <Text color=\"red\" size=\"2\" as=\"p\">\n {getMutationErrorMessage(verifyIdentity.error)}\n </Text>\n )}\n </Flex>\n\n <Flex justify=\"end\" align=\"center\" gap=\"3\" mt=\"5\">\n <Close>\n <Button variant=\"secondary\" type=\"button\">\n Cancel\n </Button>\n </Close>\n <Button type=\"submit\" loading={isSubmitting}>\n Confirm\n </Button>\n </Flex>\n </Form.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = typeof error === \"string\" ? error : \"\";\n\n if (error instanceof Error) {\n message = error.message;\n } else if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (!message || message === \"Bad Request\") {\n message = \"Invalid code, please try again.\";\n }\n\n return message;\n}\n"],"mappings":"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","names":[]}
@@ -3,6 +3,18 @@ import { WidgetRootDomProps } from './utils.cjs';
3
3
  import '../api/endpoint.cjs';
4
4
  import '@tanstack/react-query';
5
5
  import '../api/widgets-api-client.cjs';
6
+ import './elements.cjs';
7
+ import 'react';
8
+ import '@radix-ui/themes';
9
+ import '@radix-ui/themes/props';
10
+ import '../dialog-C15qCLN3.cjs';
11
+ import '@radix-ui/themes/components/dialog';
12
+ import '../alert-dialog-BlG3_awx.cjs';
13
+ import '@radix-ui/themes/components/alert-dialog';
14
+ import '../dropdown-menu-BQ5LtvdR.cjs';
15
+ import '@radix-ui/themes/components/dropdown-menu';
16
+ import '../select-KR89Qnvm.cjs';
17
+ import '@radix-ui/themes/components/select';
6
18
 
7
19
  interface EmptyStateProps extends WidgetRootDomProps {
8
20
  heading: string;
@@ -76,11 +76,11 @@ function InviteUserDialog({ children }) {
76
76
  };
77
77
  const formErrors = getFormErrors(inviteUser.error);
78
78
  useFormFieldFocusOnError(dialogId, inviteUser.error);
79
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Dialog.Root, { open, onOpenChange: setOpen, children: [
80
- children && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Dialog.Trigger, { children }),
81
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.DialogContent, { maxWidth: "480px", children: [
82
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Dialog.Title, { children: "Invite user" }),
83
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Dialog.Description, { children: "An invitation will be sent to this email address with a link to complete their account." }),
79
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.Dialog.Root, { open, onOpenChange: setOpen, children: [
80
+ children && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Dialog.Trigger, { children }),
81
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.Dialog.Content, { maxWidth: "480px", children: [
82
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Dialog.Title, { children: "Invite user" }),
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Dialog.Description, { children: "An invitation will be sent to this email address with a link to complete their account." }),
84
84
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Flex, { direction: "column", gap: "4", mt: "5", asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
85
85
  "form",
86
86
  {
@@ -134,23 +134,23 @@ function InviteUserDialog({ children }) {
134
134
  "aria-describedby": ariaDescribedBy,
135
135
  ...props
136
136
  }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
137
- import_themes.Select.Root,
137
+ import_elements.Select.Root,
138
138
  {
139
139
  ...props,
140
140
  value: selectedRole,
141
141
  onValueChange: setSelectedRole,
142
142
  children: [
143
143
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
144
- import_elements.SelectTrigger,
144
+ import_elements.Select.Trigger,
145
145
  {
146
146
  id,
147
147
  "aria-invalid": ariaInvalid,
148
148
  "aria-describedby": ariaDescribedBy
149
149
  }
150
150
  ),
151
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.SelectContent, { children: [
152
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.SelectItem, { value: PLACEHOLDER_ROLE, disabled: true, children: "Select a role" }),
153
- roles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.SelectItem, { value: role.slug, children: role.name }, role.slug))
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.Select.Content, { children: [
152
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Select.Item, { value: PLACEHOLDER_ROLE, disabled: true, children: "Select a role" }),
153
+ roles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Select.Item, { value: role.slug, children: role.name }, role.slug))
154
154
  ] })
155
155
  ]
156
156
  }
@@ -162,10 +162,11 @@ function InviteUserDialog({ children }) {
162
162
  ) }),
163
163
  formErrors.form ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Callout.Root, { color: "red", mt: "4", mb: "-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Callout.Text, { children: formErrors.form }) }) : null,
164
164
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { mt: "5", gap: "3", justify: "end", children: [
165
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Dialog.Close, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.SecondaryButton, { disabled: inviteUser.isPending, children: "Cancel" }) }),
165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Dialog.Close, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Button, { variant: "secondary", disabled: inviteUser.isPending, children: "Cancel" }) }),
166
166
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
167
- import_elements.PrimaryButton,
167
+ import_elements.Button,
168
168
  {
169
+ type: "submit",
169
170
  form: formId,
170
171
  loading: inviteUser.isPending,
171
172
  disabled: rolesQuery.isPending || void 0,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/invite-user-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Callout,\n Dialog,\n Flex,\n Select,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport {\n DialogContent,\n PrimaryButton,\n SecondaryButton,\n SelectContent,\n SelectItem,\n SelectTrigger,\n TextField,\n} from \"./elements.js\";\nimport { Label } from \"./elements.js\";\nimport { isErrorLike } from \"./utils.js\";\nimport { useInviteUser } from \"./api/user.js\";\nimport { InviteMemberInput, MemberRole, useRoles } from \"../api/endpoint.js\";\n\n/**\n * Used to stub a fake value for the role select. It will be selected by default\n * before the role query resolves, or if the query results in an error. We do\n * this because we need to provide _any_ value to the select to avoid\n * controlled/uncontrolled bugs.\n */\nconst PLACEHOLDER_ROLE = \"_rolePlaceholder\";\n\ninterface InviteUserDialogProps {\n children?: React.ReactNode;\n}\n\nexport function InviteUserDialog({ children }: InviteUserDialogProps) {\n const [open, setOpen] = React.useState(false);\n const dialogId = toId(\"invite-user\", React.useId());\n const formId = toId(dialogId, \"form\");\n\n const inviteUser = useInviteUser();\n const rolesQuery = useRoles({\n query: { initialData: [] },\n });\n const roles = rolesQuery.data;\n const [selectedRole, setSelectedRole] = React.useState(\n () => getDefaultRole(roles)?.slug || PLACEHOLDER_ROLE,\n );\n React.useEffect(() => {\n // Update the selected role if it's not in the list (eg if the list was\n // previously empty and the query resolved)\n setSelectedRole((selectedRole) => {\n if (roles.find((role) => role.slug === selectedRole)) {\n // if current selected role is in the new list, don't change it\n return selectedRole;\n }\n return getDefaultRole(roles)?.slug || PLACEHOLDER_ROLE;\n });\n }, [roles]);\n\n const onSubmitForm = (data: InviteMemberInput) => {\n if (inviteUser.isPending || rolesQuery.status !== \"success\") {\n return;\n }\n inviteUser.mutate(\n { data },\n {\n onSuccess: () => {\n setOpen(false);\n },\n },\n );\n };\n\n const formErrors = getFormErrors(inviteUser.error);\n useFormFieldFocusOnError(dialogId, inviteUser.error);\n\n return (\n <Dialog.Root open={open} onOpenChange={setOpen}>\n {children && <Dialog.Trigger>{children}</Dialog.Trigger>}\n <DialogContent maxWidth=\"480px\" key={String(open)}>\n <Dialog.Title>Invite user</Dialog.Title>\n <Dialog.Description>\n An invitation will be sent to this email address with a link to\n complete their account.\n </Dialog.Description>\n <Flex direction=\"column\" gap=\"4\" mt=\"5\" asChild>\n <form\n id={formId}\n onSubmit={async (event) => {\n event.preventDefault();\n onSubmitForm({\n email: event.currentTarget.email.value,\n roles: [selectedRole],\n });\n }}\n >\n <FormField\n rootId={dialogId}\n name=\"email\"\n label=\"Email address\"\n error={formErrors.fields.email}\n required\n control={(props) => (\n <TextField\n {...props}\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n type=\"email\"\n autoComplete=\"off\"\n placeholder=\"Enter an email address\"\n />\n )}\n />\n\n <FormField\n rootId={dialogId}\n name=\"role\"\n label=\"Role\"\n error={formErrors.fields.role}\n disabled={rolesQuery.isPending || roles.length <= 1}\n info={\n roles.length === 1 ? (\n <>\n New users will be invited with the{\" \"}\n <Text weight=\"bold\">{roles[0].name}</Text> role, as it is\n the only one available.\n </>\n ) : undefined\n }\n control={({\n id,\n \"aria-invalid\": ariaInvalid,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n }) => (\n <Select.Root\n {...props}\n value={selectedRole}\n onValueChange={setSelectedRole}\n >\n <SelectTrigger\n id={id}\n aria-invalid={ariaInvalid}\n aria-describedby={ariaDescribedBy}\n />\n <SelectContent>\n <SelectItem value={PLACEHOLDER_ROLE} disabled>\n Select a role\n </SelectItem>\n {roles.map((role) => (\n <SelectItem key={role.slug} value={role.slug}>\n {role.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select.Root>\n )}\n />\n </form>\n </Flex>\n\n {formErrors.form ? (\n <Callout.Root color=\"red\" mt=\"4\" mb=\"-2\">\n <Callout.Text>{formErrors.form}</Callout.Text>\n </Callout.Root>\n ) : null}\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <SecondaryButton disabled={inviteUser.isPending}>\n Cancel\n </SecondaryButton>\n </Dialog.Close>\n <PrimaryButton\n form={formId}\n loading={inviteUser.isPending}\n disabled={rolesQuery.isPending || undefined}\n >\n Invite\n </PrimaryButton>\n </Flex>\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">{formErrors.form}</section>\n </VisuallyHidden>\n </DialogContent>\n </Dialog.Root>\n );\n}\n\ninterface FormControlRenderProps {\n id: string;\n name: string;\n \"aria-describedby\": string | undefined;\n \"aria-invalid\"?: boolean;\n required: boolean | undefined;\n disabled: boolean | undefined;\n}\n\nfunction FormField({\n rootId,\n name,\n label,\n error,\n info,\n control,\n required,\n disabled,\n}: {\n rootId: string;\n name: string;\n label: string;\n error?: React.ReactNode;\n info?: React.ReactNode;\n control: (props: FormControlRenderProps) => React.ReactNode;\n required?: boolean;\n disabled?: boolean;\n}) {\n const fieldId = toId(rootId, name);\n const errorId = toId(rootId, name, \"error\");\n const infoId = toId(rootId, name, \"info\");\n return (\n <Flex direction=\"column\" gap=\"1\">\n <Label htmlFor={fieldId}>{label}</Label>\n {control({\n id: fieldId,\n name,\n \"aria-describedby\": (() => {\n const tags: string[] = [];\n if (error) {\n tags.push(errorId);\n }\n if (info) {\n tags.push(infoId);\n }\n if (tags.length === 0) {\n return undefined;\n }\n return tags.join(\" \");\n })(),\n \"aria-invalid\": !!error || undefined,\n required: required || undefined,\n disabled: disabled || undefined,\n })}\n\n {error ? (\n <Text color=\"red\" size=\"2\" id={errorId}>\n {error}\n </Text>\n ) : null}\n {info ? (\n <Text color=\"gray\" size=\"2\" id={infoId} mt=\"1\">\n {info}\n </Text>\n ) : null}\n </Flex>\n );\n}\n\nfunction toId(...parts: string[]) {\n return parts.join(\"-\");\n}\n\nfunction getFormErrors(queryError: unknown) {\n const formErrors = {\n form: null as string | null,\n fields: {\n email: null as string | null,\n role: null as string | null,\n },\n };\n\n if (queryError) {\n if (!isErrorLike(queryError)) {\n return {\n ...formErrors,\n form: \"An unexpected error occurred. Please try again.\",\n };\n }\n\n switch (queryError.message.toLowerCase()) {\n case \"user already exists\":\n case \"user already invited\":\n case \"invalid email\":\n formErrors.fields.email = queryError.message;\n break;\n case \"invalid role\":\n formErrors.fields.role = queryError.message;\n break;\n default:\n // TODO handle more cases for various server errors\n formErrors.form =\n \"There was an error inviting this user. Please refresh the page and try again.\";\n break;\n }\n }\n\n return formErrors;\n}\n\nfunction useFormFieldFocusOnError(dialogId: string, queryError: unknown) {\n React.useEffect(() => {\n const fieldErrors = getFormErrors(queryError).fields;\n for (const [name, error] of Object.entries(fieldErrors)) {\n if (error) {\n const fieldElement = document.getElementById(toId(dialogId, name)) as\n | HTMLInputElement\n | HTMLButtonElement\n | null;\n if (fieldElement) {\n fieldElement?.focus();\n if (\"select\" in fieldElement) {\n fieldElement.select();\n }\n }\n break;\n }\n }\n }, [dialogId, queryError]);\n}\n\nfunction getDefaultRole(roles: MemberRole[]) {\n return roles.find((role) => role.default) || roles[0];\n}\n"],"mappings":"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","names":["import_elements","selectedRole"]}
1
+ {"version":3,"sources":["../../../src/lib/invite-user-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { Callout, Flex, Text, VisuallyHidden } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { Dialog, Button, Select, TextField } from \"./elements.js\";\nimport { Label } from \"./elements.js\";\nimport { isErrorLike } from \"./utils.js\";\nimport { useInviteUser } from \"./api/user.js\";\nimport { InviteMemberInput, MemberRole, useRoles } from \"../api/endpoint.js\";\n\n/**\n * Used to stub a fake value for the role select. It will be selected by default\n * before the role query resolves, or if the query results in an error. We do\n * this because we need to provide _any_ value to the select to avoid\n * controlled/uncontrolled bugs.\n */\nconst PLACEHOLDER_ROLE = \"_rolePlaceholder\";\n\ninterface InviteUserDialogProps {\n children?: React.ReactNode;\n}\n\nexport function InviteUserDialog({ children }: InviteUserDialogProps) {\n const [open, setOpen] = React.useState(false);\n const dialogId = toId(\"invite-user\", React.useId());\n const formId = toId(dialogId, \"form\");\n\n const inviteUser = useInviteUser();\n const rolesQuery = useRoles({\n query: { initialData: [] },\n });\n const roles = rolesQuery.data;\n const [selectedRole, setSelectedRole] = React.useState(\n () => getDefaultRole(roles)?.slug || PLACEHOLDER_ROLE,\n );\n React.useEffect(() => {\n // Update the selected role if it's not in the list (eg if the list was\n // previously empty and the query resolved)\n setSelectedRole((selectedRole) => {\n if (roles.find((role) => role.slug === selectedRole)) {\n // if current selected role is in the new list, don't change it\n return selectedRole;\n }\n return getDefaultRole(roles)?.slug || PLACEHOLDER_ROLE;\n });\n }, [roles]);\n\n const onSubmitForm = (data: InviteMemberInput) => {\n if (inviteUser.isPending || rolesQuery.status !== \"success\") {\n return;\n }\n inviteUser.mutate(\n { data },\n {\n onSuccess: () => {\n setOpen(false);\n },\n },\n );\n };\n\n const formErrors = getFormErrors(inviteUser.error);\n useFormFieldFocusOnError(dialogId, inviteUser.error);\n\n return (\n <Dialog.Root open={open} onOpenChange={setOpen}>\n {children && <Dialog.Trigger>{children}</Dialog.Trigger>}\n <Dialog.Content maxWidth=\"480px\" key={String(open)}>\n <Dialog.Title>Invite user</Dialog.Title>\n <Dialog.Description>\n An invitation will be sent to this email address with a link to\n complete their account.\n </Dialog.Description>\n <Flex direction=\"column\" gap=\"4\" mt=\"5\" asChild>\n <form\n id={formId}\n onSubmit={async (event) => {\n event.preventDefault();\n onSubmitForm({\n email: event.currentTarget.email.value,\n roles: [selectedRole],\n });\n }}\n >\n <FormField\n rootId={dialogId}\n name=\"email\"\n label=\"Email address\"\n error={formErrors.fields.email}\n required\n control={(props) => (\n <TextField\n {...props}\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n type=\"email\"\n autoComplete=\"off\"\n placeholder=\"Enter an email address\"\n />\n )}\n />\n\n <FormField\n rootId={dialogId}\n name=\"role\"\n label=\"Role\"\n error={formErrors.fields.role}\n disabled={rolesQuery.isPending || roles.length <= 1}\n info={\n roles.length === 1 ? (\n <>\n New users will be invited with the{\" \"}\n <Text weight=\"bold\">{roles[0].name}</Text> role, as it is\n the only one available.\n </>\n ) : undefined\n }\n control={({\n id,\n \"aria-invalid\": ariaInvalid,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n }) => (\n <Select.Root\n {...props}\n value={selectedRole}\n onValueChange={setSelectedRole}\n >\n <Select.Trigger\n id={id}\n aria-invalid={ariaInvalid}\n aria-describedby={ariaDescribedBy}\n />\n <Select.Content>\n <Select.Item value={PLACEHOLDER_ROLE} disabled>\n Select a role\n </Select.Item>\n {roles.map((role) => (\n <Select.Item key={role.slug} value={role.slug}>\n {role.name}\n </Select.Item>\n ))}\n </Select.Content>\n </Select.Root>\n )}\n />\n </form>\n </Flex>\n\n {formErrors.form ? (\n <Callout.Root color=\"red\" mt=\"4\" mb=\"-2\">\n <Callout.Text>{formErrors.form}</Callout.Text>\n </Callout.Root>\n ) : null}\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button variant=\"secondary\" disabled={inviteUser.isPending}>\n Cancel\n </Button>\n </Dialog.Close>\n <Button\n type=\"submit\"\n form={formId}\n loading={inviteUser.isPending}\n disabled={rolesQuery.isPending || undefined}\n >\n Invite\n </Button>\n </Flex>\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">{formErrors.form}</section>\n </VisuallyHidden>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface FormControlRenderProps {\n id: string;\n name: string;\n \"aria-describedby\": string | undefined;\n \"aria-invalid\"?: boolean;\n required: boolean | undefined;\n disabled: boolean | undefined;\n}\n\nfunction FormField({\n rootId,\n name,\n label,\n error,\n info,\n control,\n required,\n disabled,\n}: {\n rootId: string;\n name: string;\n label: string;\n error?: React.ReactNode;\n info?: React.ReactNode;\n control: (props: FormControlRenderProps) => React.ReactNode;\n required?: boolean;\n disabled?: boolean;\n}) {\n const fieldId = toId(rootId, name);\n const errorId = toId(rootId, name, \"error\");\n const infoId = toId(rootId, name, \"info\");\n return (\n <Flex direction=\"column\" gap=\"1\">\n <Label htmlFor={fieldId}>{label}</Label>\n {control({\n id: fieldId,\n name,\n \"aria-describedby\": (() => {\n const tags: string[] = [];\n if (error) {\n tags.push(errorId);\n }\n if (info) {\n tags.push(infoId);\n }\n if (tags.length === 0) {\n return undefined;\n }\n return tags.join(\" \");\n })(),\n \"aria-invalid\": !!error || undefined,\n required: required || undefined,\n disabled: disabled || undefined,\n })}\n\n {error ? (\n <Text color=\"red\" size=\"2\" id={errorId}>\n {error}\n </Text>\n ) : null}\n {info ? (\n <Text color=\"gray\" size=\"2\" id={infoId} mt=\"1\">\n {info}\n </Text>\n ) : null}\n </Flex>\n );\n}\n\nfunction toId(...parts: string[]) {\n return parts.join(\"-\");\n}\n\nfunction getFormErrors(queryError: unknown) {\n const formErrors = {\n form: null as string | null,\n fields: {\n email: null as string | null,\n role: null as string | null,\n },\n };\n\n if (queryError) {\n if (!isErrorLike(queryError)) {\n return {\n ...formErrors,\n form: \"An unexpected error occurred. Please try again.\",\n };\n }\n\n switch (queryError.message.toLowerCase()) {\n case \"user already exists\":\n case \"user already invited\":\n case \"invalid email\":\n formErrors.fields.email = queryError.message;\n break;\n case \"invalid role\":\n formErrors.fields.role = queryError.message;\n break;\n default:\n // TODO handle more cases for various server errors\n formErrors.form =\n \"There was an error inviting this user. Please refresh the page and try again.\";\n break;\n }\n }\n\n return formErrors;\n}\n\nfunction useFormFieldFocusOnError(dialogId: string, queryError: unknown) {\n React.useEffect(() => {\n const fieldErrors = getFormErrors(queryError).fields;\n for (const [name, error] of Object.entries(fieldErrors)) {\n if (error) {\n const fieldElement = document.getElementById(toId(dialogId, name)) as\n | HTMLInputElement\n | HTMLButtonElement\n | null;\n if (fieldElement) {\n fieldElement?.focus();\n if (\"select\" in fieldElement) {\n fieldElement.select();\n }\n }\n break;\n }\n }\n }, [dialogId, queryError]);\n}\n\nfunction getDefaultRole(roles: MemberRole[]) {\n return roles.find((role) => role.default) || roles[0];\n}\n"],"mappings":"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","names":["import_elements","selectedRole"]}
@@ -57,9 +57,9 @@ function LogoutAllSessionsDialog({
57
57
  queryKey: (0, import_endpoint.getSessionsQueryKey)()
58
58
  });
59
59
  }, [client, onOpenChange]);
60
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Root, { open, onOpenChange, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.AlertDialogContent, { maxWidth: "480px", children: [
61
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Title, { children: "Sign out of all other devices?" }),
62
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Description, { children: "You will be logged out of all other active sessions on other devices, except this one." }),
60
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Root, { open, onOpenChange, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.AlertDialog.Content, { maxWidth: "480px", children: [
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Title, { children: "Sign out of all other devices?" }),
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Description, { children: "You will be logged out of all other active sessions on other devices, except this one." }),
63
63
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Flex, { gap: "3", justify: "end", mt: "5", asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
64
64
  "form",
65
65
  {
@@ -68,9 +68,10 @@ function LogoutAllSessionsDialog({
68
68
  onSubmitForm();
69
69
  },
70
70
  children: [
71
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Cancel, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
72
- import_elements.SecondaryButton,
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Cancel, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
72
+ import_elements.Button,
73
73
  {
74
+ variant: "secondary",
74
75
  disabled: revokeAllSessions.isPending || revokeAllSessions.isSuccess,
75
76
  children: "Cancel"
76
77
  }
@@ -82,7 +83,7 @@ function LogoutAllSessionsDialog({
82
83
  loading: revokeAllSessions.isPending,
83
84
  done: revokeAllSessions.isSuccess,
84
85
  onDone: handleDone,
85
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.DestructiveButton, { type: "submit", children: "Sign out" })
86
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Button, { variant: "destructive", type: "submit", children: "Sign out" })
86
87
  }
87
88
  )
88
89
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/logout-all-sessions-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { AlertDialog, Flex } from \"@radix-ui/themes\";\nimport { type ReactNode } from \"react\";\nimport {\n AlertDialogContent,\n DestructiveButton,\n SecondaryButton,\n} from \"./elements.js\";\nimport { getSessionsQueryKey, useRevokeAllSessions } from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { SaveButton } from \"./save-button.js\";\n\ninterface LogoutAllSessionsDialogProps extends AlertDialog.RootProps {\n children?: ReactNode;\n currentSessionId: string;\n}\n\nexport function LogoutAllSessionsDialog({\n open,\n onOpenChange,\n children,\n currentSessionId,\n ...props\n}: LogoutAllSessionsDialogProps) {\n const client = useQueryClient();\n\n const revokeAllSessions = useRevokeAllSessions();\n\n const onSubmitForm = () => {\n revokeAllSessions.mutate({ data: { currentSessionId } });\n };\n\n const handleDone = React.useCallback(() => {\n onOpenChange?.(false);\n\n client.invalidateQueries({\n queryKey: getSessionsQueryKey(),\n });\n }, [client, onOpenChange]);\n\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange} {...props}>\n <AlertDialogContent maxWidth=\"480px\">\n <AlertDialog.Title>Sign out of all other devices?</AlertDialog.Title>\n <AlertDialog.Description>\n You will be logged out of all other active sessions on other devices,\n except this one.\n </AlertDialog.Description>\n\n <Flex gap=\"3\" justify=\"end\" mt=\"5\" asChild>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n onSubmitForm();\n }}\n >\n <AlertDialog.Cancel>\n <SecondaryButton\n disabled={\n revokeAllSessions.isPending || revokeAllSessions.isSuccess\n }\n >\n Cancel\n </SecondaryButton>\n </AlertDialog.Cancel>\n\n <SaveButton\n asChild\n loading={revokeAllSessions.isPending}\n done={revokeAllSessions.isSuccess}\n onDone={handleDone}\n >\n <DestructiveButton type=\"submit\">Sign out</DestructiveButton>\n </SaveButton>\n </form>\n </Flex>\n </AlertDialogContent>\n </AlertDialog.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA6CQ;AA3CR,YAAuB;AACvB,oBAAkC;AAElC,sBAIO;AACP,sBAA0D;AAC1D,yBAA+B;AAC/B,yBAA2B;AAOpB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiC;AAC/B,QAAM,aAAS,mCAAe;AAE9B,QAAM,wBAAoB,sCAAqB;AAE/C,QAAM,eAAe,MAAM;AACzB,sBAAkB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;AAAA,EACzD;AAEA,QAAM,aAAa,MAAM,YAAY,MAAM;AACzC,mBAAe,KAAK;AAEpB,WAAO,kBAAkB;AAAA,MACvB,cAAU,qCAAoB;AAAA,IAChC,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,YAAY,CAAC;AAEzB,SACE,4CAAC,0BAAY,MAAZ,EAAiB,MAAY,cAA6B,GAAG,OAC5D,uDAAC,sCAAmB,UAAS,SAC3B;AAAA,gDAAC,0BAAY,OAAZ,EAAkB,4CAA8B;AAAA,IACjD,4CAAC,0BAAY,aAAZ,EAAwB,oGAGzB;AAAA,IAEA,4CAAC,sBAAK,KAAI,KAAI,SAAQ,OAAM,IAAG,KAAI,SAAO,MACxC;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,uBAAa;AAAA,QACf;AAAA,QAEA;AAAA,sDAAC,0BAAY,QAAZ,EACC;AAAA,YAAC;AAAA;AAAA,cACC,UACE,kBAAkB,aAAa,kBAAkB;AAAA,cAEpD;AAAA;AAAA,UAED,GACF;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,SAAO;AAAA,cACP,SAAS,kBAAkB;AAAA,cAC3B,MAAM,kBAAkB;AAAA,cACxB,QAAQ;AAAA,cAER,sDAAC,qCAAkB,MAAK,UAAS,sBAAQ;AAAA;AAAA,UAC3C;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/logout-all-sessions-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Flex } from \"@radix-ui/themes\";\nimport { type ReactNode } from \"react\";\nimport { AlertDialog, Button } from \"./elements.js\";\nimport { getSessionsQueryKey, useRevokeAllSessions } from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { SaveButton } from \"./save-button.js\";\n\ninterface LogoutAllSessionsDialogProps extends AlertDialog.RootProps {\n children?: ReactNode;\n currentSessionId: string;\n}\n\nexport function LogoutAllSessionsDialog({\n open,\n onOpenChange,\n children,\n currentSessionId,\n ...props\n}: LogoutAllSessionsDialogProps) {\n const client = useQueryClient();\n\n const revokeAllSessions = useRevokeAllSessions();\n\n const onSubmitForm = () => {\n revokeAllSessions.mutate({ data: { currentSessionId } });\n };\n\n const handleDone = React.useCallback(() => {\n onOpenChange?.(false);\n\n client.invalidateQueries({\n queryKey: getSessionsQueryKey(),\n });\n }, [client, onOpenChange]);\n\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange} {...props}>\n <AlertDialog.Content maxWidth=\"480px\">\n <AlertDialog.Title>Sign out of all other devices?</AlertDialog.Title>\n <AlertDialog.Description>\n You will be logged out of all other active sessions on other devices,\n except this one.\n </AlertDialog.Description>\n\n <Flex gap=\"3\" justify=\"end\" mt=\"5\" asChild>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n onSubmitForm();\n }}\n >\n <AlertDialog.Cancel>\n <Button\n variant=\"secondary\"\n disabled={\n revokeAllSessions.isPending || revokeAllSessions.isSuccess\n }\n >\n Cancel\n </Button>\n </AlertDialog.Cancel>\n\n <SaveButton\n asChild\n loading={revokeAllSessions.isPending}\n done={revokeAllSessions.isSuccess}\n onDone={handleDone}\n >\n <Button variant=\"destructive\" type=\"submit\">\n Sign out\n </Button>\n </SaveButton>\n </form>\n </Flex>\n </AlertDialog.Content>\n </AlertDialog.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyCQ;AAvCR,YAAuB;AACvB,oBAAqB;AAErB,sBAAoC;AACpC,sBAA0D;AAC1D,yBAA+B;AAC/B,yBAA2B;AAOpB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiC;AAC/B,QAAM,aAAS,mCAAe;AAE9B,QAAM,wBAAoB,sCAAqB;AAE/C,QAAM,eAAe,MAAM;AACzB,sBAAkB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;AAAA,EACzD;AAEA,QAAM,aAAa,MAAM,YAAY,MAAM;AACzC,mBAAe,KAAK;AAEpB,WAAO,kBAAkB;AAAA,MACvB,cAAU,qCAAoB;AAAA,IAChC,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,YAAY,CAAC;AAEzB,SACE,4CAAC,4BAAY,MAAZ,EAAiB,MAAY,cAA6B,GAAG,OAC5D,uDAAC,4BAAY,SAAZ,EAAoB,UAAS,SAC5B;AAAA,gDAAC,4BAAY,OAAZ,EAAkB,4CAA8B;AAAA,IACjD,4CAAC,4BAAY,aAAZ,EAAwB,oGAGzB;AAAA,IAEA,4CAAC,sBAAK,KAAI,KAAI,SAAQ,OAAM,IAAG,KAAI,SAAO,MACxC;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,uBAAa;AAAA,QACf;AAAA,QAEA;AAAA,sDAAC,4BAAY,QAAZ,EACC;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,UACE,kBAAkB,aAAa,kBAAkB;AAAA,cAEpD;AAAA;AAAA,UAED,GACF;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,SAAO;AAAA,cACP,SAAS,kBAAkB;AAAA,cAC3B,MAAM,kBAAkB;AAAA,cACxB,QAAQ;AAAA,cAER,sDAAC,0BAAO,SAAQ,eAAc,MAAK,UAAS,sBAE5C;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { AlertDialog } from '@radix-ui/themes';
3
2
  import { ReactNode } from 'react';
3
+ import { RootProps } from '@radix-ui/themes/components/alert-dialog';
4
4
 
5
- interface LogoutAllSessionsDialogProps extends AlertDialog.RootProps {
5
+ interface LogoutAllSessionsDialogProps extends RootProps {
6
6
  children?: ReactNode;
7
7
  currentSessionId: string;
8
8
  }
@@ -63,9 +63,9 @@ function LogoutDialog({
63
63
  sessionId: session.id
64
64
  });
65
65
  };
66
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Root, { open, onOpenChange, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.AlertDialogContent, { maxWidth: "480px", children: [
67
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Title, { children: "Sign out of device?" }),
68
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.AlertDialog.Description, { children: [
66
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Root, { open, onOpenChange, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.AlertDialog.Content, { maxWidth: "480px", children: [
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Title, { children: "Sign out of device?" }),
68
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.AlertDialog.Description, { children: [
69
69
  "You will be signed out of ",
70
70
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Strong, { children: [
71
71
  device,
@@ -80,9 +80,10 @@ function LogoutDialog({
80
80
  onSubmitForm();
81
81
  },
82
82
  children: [
83
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.AlertDialog.Cancel, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
84
- import_elements.SecondaryButton,
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.AlertDialog.Cancel, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
84
+ import_elements.Button,
85
85
  {
86
+ variant: "secondary",
86
87
  disabled: revokeSession.isPending || revokeSession.isSuccess,
87
88
  children: "Cancel"
88
89
  }
@@ -94,7 +95,7 @@ function LogoutDialog({
94
95
  loading: revokeSession.isPending,
95
96
  done: revokeSession.isSuccess,
96
97
  onDone: handleDone,
97
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.DestructiveButton, { type: "submit", children: "Sign out" })
98
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Button, { variant: "destructive", type: "submit", children: "Sign out" })
98
99
  }
99
100
  )
100
101
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/logout-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { AlertDialog, Flex, Strong } from \"@radix-ui/themes\";\nimport { type ReactNode } from \"react\";\nimport {\n AlertDialogContent,\n DestructiveButton,\n SecondaryButton,\n} from \"./elements.js\";\nimport {\n ActiveSession,\n getSessionsQueryKey,\n useRevokeSession,\n} from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { SaveButton } from \"./save-button.js\";\nimport { parseUserAgent } from \"./utils.js\";\n\ninterface LogoutDialogProps extends AlertDialog.RootProps {\n children?: ReactNode;\n session: ActiveSession;\n}\n\nexport function LogoutDialog({\n children,\n session,\n open,\n onOpenChange,\n ...props\n}: LogoutDialogProps) {\n const client = useQueryClient();\n const userAgent = parseUserAgent(session.userAgent);\n const device = userAgent.pretty;\n\n const revokeSession = useRevokeSession();\n\n const handleDone = React.useCallback(() => {\n onOpenChange?.(false);\n\n client.invalidateQueries({\n queryKey: getSessionsQueryKey(),\n exact: false,\n });\n }, [onOpenChange, client]);\n\n const onSubmitForm = () => {\n revokeSession.mutate({\n sessionId: session.id,\n });\n };\n\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange} {...props}>\n <AlertDialogContent maxWidth=\"480px\">\n <AlertDialog.Title>Sign out of device?</AlertDialog.Title>\n <AlertDialog.Description>\n You will be signed out of <Strong>{device}.</Strong>\n </AlertDialog.Description>\n\n <Flex gap=\"3\" justify=\"end\" mt=\"5\" asChild>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n onSubmitForm();\n }}\n >\n <AlertDialog.Cancel>\n <SecondaryButton\n disabled={revokeSession.isPending || revokeSession.isSuccess}\n >\n Cancel\n </SecondaryButton>\n </AlertDialog.Cancel>\n\n <SaveButton\n asChild\n loading={revokeSession.isPending}\n done={revokeSession.isSuccess}\n onDone={handleDone}\n >\n <DestructiveButton type=\"submit\">Sign out</DestructiveButton>\n </SaveButton>\n </form>\n </Flex>\n </AlertDialogContent>\n </AlertDialog.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuDQ;AArDR,YAAuB;AACvB,oBAA0C;AAE1C,sBAIO;AACP,sBAIO;AACP,yBAA+B;AAC/B,yBAA2B;AAC3B,mBAA+B;AAOxB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,aAAS,mCAAe;AAC9B,QAAM,gBAAY,6BAAe,QAAQ,SAAS;AAClD,QAAM,SAAS,UAAU;AAEzB,QAAM,oBAAgB,kCAAiB;AAEvC,QAAM,aAAa,MAAM,YAAY,MAAM;AACzC,mBAAe,KAAK;AAEpB,WAAO,kBAAkB;AAAA,MACvB,cAAU,qCAAoB;AAAA,MAC9B,OAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,cAAc,MAAM,CAAC;AAEzB,QAAM,eAAe,MAAM;AACzB,kBAAc,OAAO;AAAA,MACnB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,SACE,4CAAC,0BAAY,MAAZ,EAAiB,MAAY,cAA6B,GAAG,OAC5D,uDAAC,sCAAmB,UAAS,SAC3B;AAAA,gDAAC,0BAAY,OAAZ,EAAkB,iCAAmB;AAAA,IACtC,6CAAC,0BAAY,aAAZ,EAAwB;AAAA;AAAA,MACG,6CAAC,wBAAQ;AAAA;AAAA,QAAO;AAAA,SAAC;AAAA,OAC7C;AAAA,IAEA,4CAAC,sBAAK,KAAI,KAAI,SAAQ,OAAM,IAAG,KAAI,SAAO,MACxC;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,uBAAa;AAAA,QACf;AAAA,QAEA;AAAA,sDAAC,0BAAY,QAAZ,EACC;AAAA,YAAC;AAAA;AAAA,cACC,UAAU,cAAc,aAAa,cAAc;AAAA,cACpD;AAAA;AAAA,UAED,GACF;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,SAAO;AAAA,cACP,SAAS,cAAc;AAAA,cACvB,MAAM,cAAc;AAAA,cACpB,QAAQ;AAAA,cAER,sDAAC,qCAAkB,MAAK,UAAS,sBAAQ;AAAA;AAAA,UAC3C;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/logout-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Flex, Strong } from \"@radix-ui/themes\";\nimport { type ReactNode } from \"react\";\nimport { AlertDialog, Button } from \"./elements.js\";\nimport {\n ActiveSession,\n getSessionsQueryKey,\n useRevokeSession,\n} from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { SaveButton } from \"./save-button.js\";\nimport { parseUserAgent } from \"./utils.js\";\n\ninterface LogoutDialogProps extends AlertDialog.RootProps {\n children?: ReactNode;\n session: ActiveSession;\n}\n\nexport function LogoutDialog({\n children,\n session,\n open,\n onOpenChange,\n ...props\n}: LogoutDialogProps) {\n const client = useQueryClient();\n const userAgent = parseUserAgent(session.userAgent);\n const device = userAgent.pretty;\n\n const revokeSession = useRevokeSession();\n\n const handleDone = React.useCallback(() => {\n onOpenChange?.(false);\n\n client.invalidateQueries({\n queryKey: getSessionsQueryKey(),\n exact: false,\n });\n }, [onOpenChange, client]);\n\n const onSubmitForm = () => {\n revokeSession.mutate({\n sessionId: session.id,\n });\n };\n\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange} {...props}>\n <AlertDialog.Content maxWidth=\"480px\">\n <AlertDialog.Title>Sign out of device?</AlertDialog.Title>\n <AlertDialog.Description>\n You will be signed out of <Strong>{device}.</Strong>\n </AlertDialog.Description>\n\n <Flex gap=\"3\" justify=\"end\" mt=\"5\" asChild>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n onSubmitForm();\n }}\n >\n <AlertDialog.Cancel>\n <Button\n variant=\"secondary\"\n disabled={revokeSession.isPending || revokeSession.isSuccess}\n >\n Cancel\n </Button>\n </AlertDialog.Cancel>\n\n <SaveButton\n asChild\n loading={revokeSession.isPending}\n done={revokeSession.isSuccess}\n onDone={handleDone}\n >\n <Button variant=\"destructive\" type=\"submit\">\n Sign out\n </Button>\n </SaveButton>\n </form>\n </Flex>\n </AlertDialog.Content>\n </AlertDialog.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmDQ;AAjDR,YAAuB;AACvB,oBAA6B;AAE7B,sBAAoC;AACpC,sBAIO;AACP,yBAA+B;AAC/B,yBAA2B;AAC3B,mBAA+B;AAOxB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,aAAS,mCAAe;AAC9B,QAAM,gBAAY,6BAAe,QAAQ,SAAS;AAClD,QAAM,SAAS,UAAU;AAEzB,QAAM,oBAAgB,kCAAiB;AAEvC,QAAM,aAAa,MAAM,YAAY,MAAM;AACzC,mBAAe,KAAK;AAEpB,WAAO,kBAAkB;AAAA,MACvB,cAAU,qCAAoB;AAAA,MAC9B,OAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,cAAc,MAAM,CAAC;AAEzB,QAAM,eAAe,MAAM;AACzB,kBAAc,OAAO;AAAA,MACnB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,SACE,4CAAC,4BAAY,MAAZ,EAAiB,MAAY,cAA6B,GAAG,OAC5D,uDAAC,4BAAY,SAAZ,EAAoB,UAAS,SAC5B;AAAA,gDAAC,4BAAY,OAAZ,EAAkB,iCAAmB;AAAA,IACtC,6CAAC,4BAAY,aAAZ,EAAwB;AAAA;AAAA,MACG,6CAAC,wBAAQ;AAAA;AAAA,QAAO;AAAA,SAAC;AAAA,OAC7C;AAAA,IAEA,4CAAC,sBAAK,KAAI,KAAI,SAAQ,OAAM,IAAG,KAAI,SAAO,MACxC;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,uBAAa;AAAA,QACf;AAAA,QAEA;AAAA,sDAAC,4BAAY,QAAZ,EACC;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,UAAU,cAAc,aAAa,cAAc;AAAA,cACpD;AAAA;AAAA,UAED,GACF;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,SAAO;AAAA,cACP,SAAS,cAAc;AAAA,cACvB,MAAM,cAAc;AAAA,cACpB,QAAQ;AAAA,cAER,sDAAC,0BAAO,SAAQ,eAAc,MAAK,UAAS,sBAE5C;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -1,11 +1,11 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { AlertDialog } from '@radix-ui/themes';
3
2
  import { ReactNode } from 'react';
3
+ import { RootProps } from '@radix-ui/themes/components/alert-dialog';
4
4
  import { ActiveSession } from '../api/endpoint.cjs';
5
5
  import '@tanstack/react-query';
6
6
  import '../api/widgets-api-client.cjs';
7
7
 
8
- interface LogoutDialogProps extends AlertDialog.RootProps {
8
+ interface LogoutDialogProps extends RootProps {
9
9
  children?: ReactNode;
10
10
  session: ActiveSession;
11
11
  }
@@ -40,10 +40,12 @@ var import_themes = require("@radix-ui/themes");
40
40
  var import_clsx = __toESM(require("clsx"), 1);
41
41
  var import_utils = require("./utils.js");
42
42
  var import_generic_error = require("./generic-error.js");
43
+ var import_elements = require("./elements.js");
44
+ var import_utils2 = require("../utils.js");
43
45
  const OrganizationSwitcher = ({
44
46
  organizations,
45
47
  switchToOrganization,
46
- variant = "outline",
48
+ variant,
47
49
  organizationLabel = "Organizations",
48
50
  truncateBehavior = "right",
49
51
  children,
@@ -52,15 +54,16 @@ const OrganizationSwitcher = ({
52
54
  const currentOrganization = organizations.find(
53
55
  (organization) => organization.current
54
56
  );
57
+ const invalidateAllWidgets = (0, import_utils2.unstable_useWidgetsInvalidator)();
55
58
  if (!currentOrganization) {
56
59
  return null;
57
60
  }
58
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.DropdownMenu.Root, { children: [
59
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.DropdownMenu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
60
- import_themes.Button,
61
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.DropdownMenu.Root, { children: [
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.DropdownMenu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
63
+ import_elements.Button,
61
64
  {
62
- color: "gray",
63
- variant,
65
+ variant: "secondary",
66
+ ...mapVariantProps(variant),
64
67
  ...getWidgetRootDomProps("resolved", {
65
68
  ...domProps,
66
69
  // TODO: Remove `OrganizationSwitcherTrigger` in the next major
@@ -85,15 +88,15 @@ const OrganizationSwitcher = ({
85
88
  truncateBehavior
86
89
  }
87
90
  ),
88
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Flex, { asChild: true, flexShrink: "0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.DropdownMenu.TriggerIcon, {}) })
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Flex, { asChild: true, flexShrink: "0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.DropdownMenu.TriggerIcon, {}) })
89
92
  ]
90
93
  }
91
94
  )
92
95
  }
93
96
  ) }),
94
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.DropdownMenu.Content, { children: [
95
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.DropdownMenu.Group, { children: [
96
- organizationLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.DropdownMenu.Label, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { children: organizationLabel }) }) : null,
97
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.DropdownMenu.Content, { children: [
98
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_elements.DropdownMenu.Group, { children: [
99
+ organizationLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.DropdownMenu.Label, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { children: organizationLabel }) }) : null,
97
100
  organizations.map((organization) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
98
101
  import_themes.Flex,
99
102
  {
@@ -102,11 +105,18 @@ const OrganizationSwitcher = ({
102
105
  maxWidth: "280px",
103
106
  minWidth: "180px",
104
107
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
105
- import_themes.DropdownMenu.Item,
108
+ import_elements.DropdownMenu.Item,
106
109
  {
107
110
  onClick: () => {
108
111
  if (organization.id !== currentOrganization.id) {
109
- switchToOrganization({ organizationId: organization.id });
112
+ const result = switchToOrganization({
113
+ organizationId: organization.id
114
+ });
115
+ if ((0, import_utils.isPromiseLike)(result)) {
116
+ result.then(invalidateAllWidgets);
117
+ } else {
118
+ invalidateAllWidgets();
119
+ }
110
120
  }
111
121
  },
112
122
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
@@ -152,18 +162,18 @@ const OrganizationSwitcher = ({
152
162
  ] })
153
163
  ] });
154
164
  };
155
- const OrganizationSwitcherLoading = (props) => {
165
+ const OrganizationSwitcherLoading = ({ variant, ...props }) => {
156
166
  return (
157
167
  // Always need DropdownMenu.Root to wrap children than may include
158
168
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
159
- import_themes.Button,
169
+ import_elements.Button,
160
170
  {
161
- color: "gray",
162
- variant: "outline",
171
+ variant: "secondary",
163
172
  disabled: true,
173
+ ...mapVariantProps(variant),
164
174
  ...getWidgetRootDomProps("loading", props),
165
175
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { align: "center", gap: "2", children: [
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Skeleton, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { children: "Loading..." }) }),
176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_elements.Skeleton, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { children: "Loading..." }) }),
167
177
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.ChevronDownIcon, {})
168
178
  ] })
169
179
  }
@@ -172,15 +182,16 @@ const OrganizationSwitcherLoading = (props) => {
172
182
  };
173
183
  function OrganizationSwitcherError({
174
184
  error,
185
+ variant,
175
186
  ...domProps
176
187
  }) {
177
188
  const { heading } = (0, import_generic_error.getErrorMessage)(error);
178
189
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
- import_themes.Button,
190
+ import_elements.Button,
180
191
  {
181
- color: "gray",
182
- variant: "outline",
192
+ variant: "secondary",
183
193
  disabled: true,
194
+ ...mapVariantProps(variant),
184
195
  ...getWidgetRootDomProps("error", domProps),
185
196
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { align: "center", gap: "2", children: [
186
197
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { children: heading }),
@@ -224,6 +235,13 @@ const TruncatedOrganizationName = ({
224
235
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { "aria-hidden": true, children: organizationNameRight })
225
236
  ] });
226
237
  };
238
+ function mapVariantProps(variant) {
239
+ const variantProps = {};
240
+ if (variant) {
241
+ variantProps.unsafe_radixVariant = variant;
242
+ }
243
+ return variantProps;
244
+ }
227
245
  function getWidgetRootDomProps(state, domProps) {
228
246
  return (0, import_utils.getDomProps)({
229
247
  ...domProps,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n Button,\n ChevronDownIcon,\n DropdownMenu,\n Flex,\n Skeleton,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport type { OrganizationInfo } from \"../api/endpoint.js\";\nimport cx from \"clsx\";\nimport {\n getDomProps,\n type WidgetRootDomProps,\n type WidgetRootState,\n} from \"./utils.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ninterface OrganizationSwitcherProps\n extends OrganizationSwitcherPassthroughProps {\n organizations: OrganizationInfo[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant = \"outline\",\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.current,\n );\n\n // Possible if the user has no organizations - we should figure out what to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n color=\"gray\"\n variant={variant}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO: Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n switchToOrganization({ organizationId: organization.id });\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.current && (\n <VisuallyHidden> (current)</VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.current ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = (props) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n color=\"gray\"\n variant=\"outline\"\n disabled\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nfunction OrganizationSwitcherError({\n error,\n ...domProps\n}: OrganizationSwitcherErrorProps) {\n const { heading } = getErrorMessage(error);\n return (\n <Button\n color=\"gray\"\n variant=\"outline\"\n disabled\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n}\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\nconst TruncatedOrganizationName = ({\n organizationName,\n truncateBehavior,\n}: {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n /** @internal */\n OrganizationSwitcherPassthroughProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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","names":["cx"]}
1
+ {"version":3,"sources":["../../../src/lib/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport type { OrganizationInfo } from \"../api/endpoint.js\";\nimport cx from \"clsx\";\nimport {\n getDomProps,\n isPromiseLike,\n type WidgetRootDomProps,\n type WidgetRootState,\n} from \"./utils.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\nimport {\n Button,\n type ButtonProps,\n Skeleton,\n DropdownMenu,\n} from \"./elements.js\";\nimport { unstable_useWidgetsInvalidator as useWidgetsInvalidator } from \"../utils.js\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ninterface OrganizationSwitcherProps\n extends OrganizationSwitcherPassthroughProps {\n organizations: OrganizationInfo[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.current,\n );\n const invalidateAllWidgets = useWidgetsInvalidator();\n\n // TODO: Possible if the user has no organizations - we should figure out what\n // to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO: Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.current && (\n <VisuallyHidden> (current)</VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.current ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n variant?: OrganizationSwitcherVariant;\n}\n\nfunction OrganizationSwitcherError({\n error,\n variant,\n ...domProps\n}: OrganizationSwitcherErrorProps) {\n const { heading } = getErrorMessage(error);\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n}\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\nconst TruncatedOrganizationName = ({\n organizationName,\n truncateBehavior,\n}: {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n /** @internal */\n OrganizationSwitcherPassthroughProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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","names":["import_utils","useWidgetsInvalidator","cx"]}
@@ -3,12 +3,24 @@ import { OrganizationInfo } from '../api/endpoint.cjs';
3
3
  import { WidgetRootDomProps } from './utils.cjs';
4
4
  import '@tanstack/react-query';
5
5
  import '../api/widgets-api-client.cjs';
6
+ import './elements.cjs';
7
+ import 'react';
8
+ import '@radix-ui/themes';
9
+ import '@radix-ui/themes/props';
10
+ import '../dialog-C15qCLN3.cjs';
11
+ import '@radix-ui/themes/components/dialog';
12
+ import '../alert-dialog-BlG3_awx.cjs';
13
+ import '@radix-ui/themes/components/alert-dialog';
14
+ import '../dropdown-menu-BQ5LtvdR.cjs';
15
+ import '@radix-ui/themes/components/dropdown-menu';
16
+ import '../select-KR89Qnvm.cjs';
17
+ import '@radix-ui/themes/components/select';
6
18
 
7
19
  type OrganizationSwitcherVariant = "ghost" | "outline";
8
20
  interface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {
9
21
  switchToOrganization: ({ organizationId, }: {
10
22
  organizationId: string;
11
- }) => void;
23
+ }) => void | Promise<void>;
12
24
  variant?: OrganizationSwitcherVariant;
13
25
  organizationLabel?: string | null;
14
26
  children?: React.ReactNode;
@@ -27,11 +39,13 @@ interface OrganizationSwitcherProps extends OrganizationSwitcherPassthroughProps
27
39
  }
28
40
  declare const OrganizationSwitcher: React.FC<OrganizationSwitcherProps>;
29
41
  interface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {
42
+ variant?: OrganizationSwitcherVariant;
30
43
  }
31
44
  declare const OrganizationSwitcherLoading: React.FC<OrganizationSwitcherLoadingProps>;
32
45
  interface OrganizationSwitcherErrorProps extends WidgetRootDomProps {
33
46
  error: unknown;
47
+ variant?: OrganizationSwitcherVariant;
34
48
  }
35
- declare function OrganizationSwitcherError({ error, ...domProps }: OrganizationSwitcherErrorProps): react_jsx_runtime.JSX.Element;
49
+ declare function OrganizationSwitcherError({ error, variant, ...domProps }: OrganizationSwitcherErrorProps): react_jsx_runtime.JSX.Element;
36
50
 
37
51
  export { OrganizationSwitcher, OrganizationSwitcherError, type OrganizationSwitcherErrorProps, OrganizationSwitcherLoading, type OrganizationSwitcherLoadingProps, type OrganizationSwitcherPassthroughProps, type OrganizationSwitcherProps };