@workos-inc/widgets 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/README.md +68 -1
  2. package/dist/cjs/card-list.d.ts +6 -0
  3. package/dist/cjs/card-list.d.ts.map +1 -0
  4. package/dist/cjs/card-list.js +13 -0
  5. package/dist/cjs/card-list.js.map +1 -0
  6. package/dist/cjs/index.d.ts +3 -0
  7. package/dist/cjs/index.d.ts.map +1 -1
  8. package/dist/cjs/index.js +7 -1
  9. package/dist/cjs/index.js.map +1 -1
  10. package/dist/cjs/lib/add-mfa-dialog.d.ts +9 -0
  11. package/dist/cjs/lib/add-mfa-dialog.d.ts.map +1 -0
  12. package/dist/cjs/lib/add-mfa-dialog.js +135 -0
  13. package/dist/cjs/lib/add-mfa-dialog.js.map +1 -0
  14. package/dist/cjs/lib/api/user.d.ts +13 -57
  15. package/dist/cjs/lib/api/user.d.ts.map +1 -1
  16. package/dist/cjs/lib/api/user.js +44 -314
  17. package/dist/cjs/lib/api/user.js.map +1 -1
  18. package/dist/cjs/lib/change-password-dialog.d.ts +8 -0
  19. package/dist/cjs/lib/change-password-dialog.d.ts.map +1 -0
  20. package/dist/cjs/lib/change-password-dialog.js +97 -0
  21. package/dist/cjs/lib/change-password-dialog.js.map +1 -0
  22. package/dist/cjs/lib/copy-button.d.ts +8 -0
  23. package/dist/cjs/lib/copy-button.d.ts.map +1 -0
  24. package/dist/cjs/lib/copy-button.js +63 -0
  25. package/dist/cjs/lib/copy-button.js.map +1 -0
  26. package/dist/cjs/lib/delete-user-dialog.d.ts +2 -2
  27. package/dist/cjs/lib/delete-user-dialog.d.ts.map +1 -1
  28. package/dist/cjs/lib/delete-user-dialog.js +1 -1
  29. package/dist/cjs/lib/delete-user-dialog.js.map +1 -1
  30. package/dist/cjs/lib/edit-user-profile-dialog.d.ts +10 -0
  31. package/dist/cjs/lib/edit-user-profile-dialog.d.ts.map +1 -0
  32. package/dist/cjs/lib/edit-user-profile-dialog.js +85 -0
  33. package/dist/cjs/lib/edit-user-profile-dialog.js.map +1 -0
  34. package/dist/cjs/lib/edit-user-role-dialog.d.ts +12 -0
  35. package/dist/cjs/lib/edit-user-role-dialog.d.ts.map +1 -0
  36. package/dist/cjs/lib/{edit-user-details-dialog.js → edit-user-role-dialog.js} +11 -7
  37. package/dist/cjs/lib/edit-user-role-dialog.js.map +1 -0
  38. package/dist/cjs/lib/elements.d.ts +1 -0
  39. package/dist/cjs/lib/elements.d.ts.map +1 -1
  40. package/dist/cjs/lib/elements.js +10 -4
  41. package/dist/cjs/lib/elements.js.map +1 -1
  42. package/dist/cjs/lib/elevated-access.d.ts +8 -0
  43. package/dist/cjs/lib/elevated-access.d.ts.map +1 -0
  44. package/dist/cjs/lib/elevated-access.js +130 -0
  45. package/dist/cjs/lib/elevated-access.js.map +1 -0
  46. package/dist/cjs/lib/generic-error.d.ts +4 -0
  47. package/dist/cjs/lib/generic-error.d.ts.map +1 -0
  48. package/dist/cjs/lib/generic-error.js +57 -0
  49. package/dist/cjs/lib/generic-error.js.map +1 -0
  50. package/dist/cjs/lib/icon-panel.d.ts +3 -0
  51. package/dist/cjs/lib/icon-panel.d.ts.map +1 -0
  52. package/dist/cjs/lib/icon-panel.js +16 -0
  53. package/dist/cjs/lib/icon-panel.js.map +1 -0
  54. package/dist/cjs/lib/icons.d.ts +3 -0
  55. package/dist/cjs/lib/icons.d.ts.map +1 -0
  56. package/dist/cjs/lib/icons.js +8 -0
  57. package/dist/cjs/lib/icons.js.map +1 -0
  58. package/dist/cjs/lib/invite-user-dialog.d.ts.map +1 -1
  59. package/dist/cjs/lib/invite-user-dialog.js +7 -5
  60. package/dist/cjs/lib/invite-user-dialog.js.map +1 -1
  61. package/dist/cjs/lib/logout-all-sessions-dialog.d.ts +9 -0
  62. package/dist/cjs/lib/logout-all-sessions-dialog.d.ts.map +1 -0
  63. package/dist/cjs/lib/logout-all-sessions-dialog.js +52 -0
  64. package/dist/cjs/lib/logout-all-sessions-dialog.js.map +1 -0
  65. package/dist/cjs/lib/logout-dialog.d.ts +10 -0
  66. package/dist/cjs/lib/logout-dialog.d.ts.map +1 -0
  67. package/dist/cjs/lib/logout-dialog.js +58 -0
  68. package/dist/cjs/lib/logout-dialog.js.map +1 -0
  69. package/dist/cjs/lib/marker.d.ts +14 -0
  70. package/dist/cjs/lib/marker.d.ts.map +1 -0
  71. package/dist/cjs/lib/marker.js +38 -0
  72. package/dist/cjs/lib/marker.js.map +1 -0
  73. package/dist/cjs/lib/oauth-icons.d.ts +4 -0
  74. package/dist/cjs/lib/oauth-icons.d.ts.map +1 -0
  75. package/dist/cjs/lib/oauth-icons.js +67 -0
  76. package/dist/cjs/lib/oauth-icons.js.map +1 -0
  77. package/dist/cjs/lib/organization-switcher.d.ts +24 -0
  78. package/dist/cjs/lib/organization-switcher.d.ts.map +1 -0
  79. package/dist/cjs/lib/organization-switcher.js +35 -0
  80. package/dist/cjs/lib/organization-switcher.js.map +1 -0
  81. package/dist/cjs/lib/otp-input.d.ts +20 -0
  82. package/dist/cjs/lib/otp-input.d.ts.map +1 -0
  83. package/dist/cjs/lib/otp-input.js +174 -0
  84. package/dist/cjs/lib/otp-input.js.map +1 -0
  85. package/dist/cjs/lib/resend-invite-dialog.d.ts +2 -2
  86. package/dist/cjs/lib/resend-invite-dialog.d.ts.map +1 -1
  87. package/dist/cjs/lib/resend-invite-dialog.js +1 -1
  88. package/dist/cjs/lib/resend-invite-dialog.js.map +1 -1
  89. package/dist/cjs/lib/reset-mfa-dialog.d.ts +9 -0
  90. package/dist/cjs/lib/reset-mfa-dialog.d.ts.map +1 -0
  91. package/dist/cjs/lib/reset-mfa-dialog.js +60 -0
  92. package/dist/cjs/lib/reset-mfa-dialog.js.map +1 -0
  93. package/dist/cjs/lib/revoke-invite-dialog.d.ts +2 -2
  94. package/dist/cjs/lib/revoke-invite-dialog.d.ts.map +1 -1
  95. package/dist/cjs/lib/revoke-invite-dialog.js +1 -1
  96. package/dist/cjs/lib/revoke-invite-dialog.js.map +1 -1
  97. package/dist/cjs/lib/save-button.d.ts +11 -0
  98. package/dist/cjs/lib/save-button.d.ts.map +1 -0
  99. package/dist/cjs/lib/save-button.js +47 -0
  100. package/dist/cjs/lib/save-button.js.map +1 -0
  101. package/dist/cjs/lib/set-password-dialog.d.ts +8 -0
  102. package/dist/cjs/lib/set-password-dialog.d.ts.map +1 -0
  103. package/dist/cjs/lib/set-password-dialog.js +80 -0
  104. package/dist/cjs/lib/set-password-dialog.js.map +1 -0
  105. package/dist/cjs/lib/use-dialog-close.d.ts +2 -0
  106. package/dist/cjs/lib/use-dialog-close.d.ts.map +1 -0
  107. package/dist/cjs/lib/use-dialog-close.js +43 -0
  108. package/dist/cjs/lib/use-dialog-close.js.map +1 -0
  109. package/dist/cjs/lib/use-security-settings.d.ts +11 -0
  110. package/dist/cjs/lib/use-security-settings.d.ts.map +1 -0
  111. package/dist/cjs/lib/use-security-settings.js +39 -0
  112. package/dist/cjs/lib/use-security-settings.js.map +1 -0
  113. package/dist/cjs/lib/user-actions-dropdown.d.ts +2 -2
  114. package/dist/cjs/lib/user-actions-dropdown.d.ts.map +1 -1
  115. package/dist/cjs/lib/user-actions-dropdown.js +8 -4
  116. package/dist/cjs/lib/user-actions-dropdown.js.map +1 -1
  117. package/dist/cjs/lib/user-profile.d.ts +11 -0
  118. package/dist/cjs/lib/user-profile.d.ts.map +1 -0
  119. package/dist/cjs/lib/user-profile.js +36 -0
  120. package/dist/cjs/lib/user-profile.js.map +1 -0
  121. package/dist/cjs/lib/user-security.d.ts +11 -0
  122. package/dist/cjs/lib/user-security.d.ts.map +1 -0
  123. package/dist/cjs/lib/user-security.js +64 -0
  124. package/dist/cjs/lib/user-security.js.map +1 -0
  125. package/dist/cjs/lib/user-sessions.d.ts +12 -0
  126. package/dist/cjs/lib/user-sessions.d.ts.map +1 -0
  127. package/dist/cjs/lib/user-sessions.js +72 -0
  128. package/dist/cjs/lib/user-sessions.js.map +1 -0
  129. package/dist/cjs/lib/users-filter.d.ts +2 -2
  130. package/dist/cjs/lib/users-filter.d.ts.map +1 -1
  131. package/dist/cjs/lib/users-filter.js.map +1 -1
  132. package/dist/cjs/lib/users-management-context.d.ts +0 -9
  133. package/dist/cjs/lib/users-management-context.d.ts.map +1 -1
  134. package/dist/cjs/lib/users-management-context.js +13 -26
  135. package/dist/cjs/lib/users-management-context.js.map +1 -1
  136. package/dist/cjs/lib/users-management-state.d.ts +3 -3
  137. package/dist/cjs/lib/users-management-state.d.ts.map +1 -1
  138. package/dist/cjs/lib/users-management-state.js.map +1 -1
  139. package/dist/cjs/lib/users-management.d.ts +3 -4
  140. package/dist/cjs/lib/users-management.d.ts.map +1 -1
  141. package/dist/cjs/lib/users-management.js +8 -26
  142. package/dist/cjs/lib/users-management.js.map +1 -1
  143. package/dist/cjs/lib/utils.d.ts +10 -2
  144. package/dist/cjs/lib/utils.d.ts.map +1 -1
  145. package/dist/cjs/lib/utils.js +18 -0
  146. package/dist/cjs/lib/utils.js.map +1 -1
  147. package/dist/cjs/organization-switcher.client.d.ts +8 -0
  148. package/dist/cjs/organization-switcher.client.d.ts.map +1 -0
  149. package/dist/cjs/organization-switcher.client.js +37 -0
  150. package/dist/cjs/organization-switcher.client.js.map +1 -0
  151. package/dist/cjs/user-profile.client.d.ts +7 -0
  152. package/dist/cjs/user-profile.client.d.ts.map +1 -0
  153. package/dist/cjs/user-profile.client.js +31 -0
  154. package/dist/cjs/user-profile.client.js.map +1 -0
  155. package/dist/cjs/user-security.client.d.ts +7 -0
  156. package/dist/cjs/user-security.client.d.ts.map +1 -0
  157. package/dist/cjs/user-security.client.js +27 -0
  158. package/dist/cjs/user-security.client.js.map +1 -0
  159. package/dist/cjs/user-sessions.client.d.ts +12 -0
  160. package/dist/cjs/user-sessions.client.d.ts.map +1 -0
  161. package/dist/cjs/user-sessions.client.js +48 -0
  162. package/dist/cjs/user-sessions.client.js.map +1 -0
  163. package/dist/cjs/users-management.client.d.ts +2 -1
  164. package/dist/cjs/users-management.client.d.ts.map +1 -1
  165. package/dist/cjs/users-management.client.js +12 -43
  166. package/dist/cjs/users-management.client.js.map +1 -1
  167. package/dist/esm/card-list.d.ts +6 -0
  168. package/dist/esm/card-list.d.ts.map +1 -0
  169. package/dist/esm/card-list.js +9 -0
  170. package/dist/esm/card-list.js.map +1 -0
  171. package/dist/esm/index.d.ts +3 -0
  172. package/dist/esm/index.d.ts.map +1 -1
  173. package/dist/esm/index.js +3 -0
  174. package/dist/esm/index.js.map +1 -1
  175. package/dist/esm/lib/add-mfa-dialog.d.ts +9 -0
  176. package/dist/esm/lib/add-mfa-dialog.d.ts.map +1 -0
  177. package/dist/esm/lib/add-mfa-dialog.js +109 -0
  178. package/dist/esm/lib/add-mfa-dialog.js.map +1 -0
  179. package/dist/esm/lib/api/user.d.ts +13 -57
  180. package/dist/esm/lib/api/user.d.ts.map +1 -1
  181. package/dist/esm/lib/api/user.js +44 -313
  182. package/dist/esm/lib/api/user.js.map +1 -1
  183. package/dist/esm/lib/change-password-dialog.d.ts +8 -0
  184. package/dist/esm/lib/change-password-dialog.d.ts.map +1 -0
  185. package/dist/esm/lib/change-password-dialog.js +71 -0
  186. package/dist/esm/lib/change-password-dialog.js.map +1 -0
  187. package/dist/esm/lib/copy-button.d.ts +8 -0
  188. package/dist/esm/lib/copy-button.d.ts.map +1 -0
  189. package/dist/esm/lib/copy-button.js +37 -0
  190. package/dist/esm/lib/copy-button.js.map +1 -0
  191. package/dist/esm/lib/delete-user-dialog.d.ts +2 -2
  192. package/dist/esm/lib/delete-user-dialog.d.ts.map +1 -1
  193. package/dist/esm/lib/delete-user-dialog.js +1 -1
  194. package/dist/esm/lib/delete-user-dialog.js.map +1 -1
  195. package/dist/esm/lib/edit-user-profile-dialog.d.ts +10 -0
  196. package/dist/esm/lib/edit-user-profile-dialog.d.ts.map +1 -0
  197. package/dist/esm/lib/edit-user-profile-dialog.js +59 -0
  198. package/dist/esm/lib/edit-user-profile-dialog.js.map +1 -0
  199. package/dist/esm/lib/edit-user-role-dialog.d.ts +12 -0
  200. package/dist/esm/lib/edit-user-role-dialog.d.ts.map +1 -0
  201. package/dist/esm/lib/{edit-user-details-dialog.js → edit-user-role-dialog.js} +10 -6
  202. package/dist/esm/lib/edit-user-role-dialog.js.map +1 -0
  203. package/dist/esm/lib/elements.d.ts +1 -0
  204. package/dist/esm/lib/elements.d.ts.map +1 -1
  205. package/dist/esm/lib/elements.js +9 -3
  206. package/dist/esm/lib/elements.js.map +1 -1
  207. package/dist/esm/lib/elevated-access.d.ts +8 -0
  208. package/dist/esm/lib/elevated-access.d.ts.map +1 -0
  209. package/dist/esm/lib/elevated-access.js +104 -0
  210. package/dist/esm/lib/elevated-access.js.map +1 -0
  211. package/dist/esm/lib/generic-error.d.ts +4 -0
  212. package/dist/esm/lib/generic-error.d.ts.map +1 -0
  213. package/dist/esm/lib/generic-error.js +31 -0
  214. package/dist/esm/lib/generic-error.js.map +1 -0
  215. package/dist/esm/lib/icon-panel.d.ts +3 -0
  216. package/dist/esm/lib/icon-panel.d.ts.map +1 -0
  217. package/dist/esm/lib/icon-panel.js +13 -0
  218. package/dist/esm/lib/icon-panel.js.map +1 -0
  219. package/dist/esm/lib/icons.d.ts +3 -0
  220. package/dist/esm/lib/icons.d.ts.map +1 -0
  221. package/dist/esm/lib/icons.js +5 -0
  222. package/dist/esm/lib/icons.js.map +1 -0
  223. package/dist/esm/lib/invite-user-dialog.d.ts.map +1 -1
  224. package/dist/esm/lib/invite-user-dialog.js +7 -5
  225. package/dist/esm/lib/invite-user-dialog.js.map +1 -1
  226. package/dist/esm/lib/logout-all-sessions-dialog.d.ts +9 -0
  227. package/dist/esm/lib/logout-all-sessions-dialog.d.ts.map +1 -0
  228. package/dist/esm/lib/logout-all-sessions-dialog.js +26 -0
  229. package/dist/esm/lib/logout-all-sessions-dialog.js.map +1 -0
  230. package/dist/esm/lib/logout-dialog.d.ts +10 -0
  231. package/dist/esm/lib/logout-dialog.d.ts.map +1 -0
  232. package/dist/esm/lib/logout-dialog.js +32 -0
  233. package/dist/esm/lib/logout-dialog.js.map +1 -0
  234. package/dist/esm/lib/marker.d.ts +14 -0
  235. package/dist/esm/lib/marker.d.ts.map +1 -0
  236. package/dist/esm/lib/marker.js +9 -0
  237. package/dist/esm/lib/marker.js.map +1 -0
  238. package/dist/esm/lib/oauth-icons.d.ts +4 -0
  239. package/dist/esm/lib/oauth-icons.d.ts.map +1 -0
  240. package/dist/esm/lib/oauth-icons.js +39 -0
  241. package/dist/esm/lib/oauth-icons.js.map +1 -0
  242. package/dist/esm/lib/organization-switcher.d.ts +24 -0
  243. package/dist/esm/lib/organization-switcher.d.ts.map +1 -0
  244. package/dist/esm/lib/organization-switcher.js +29 -0
  245. package/dist/esm/lib/organization-switcher.js.map +1 -0
  246. package/dist/esm/lib/otp-input.d.ts +20 -0
  247. package/dist/esm/lib/otp-input.d.ts.map +1 -0
  248. package/dist/esm/lib/otp-input.js +148 -0
  249. package/dist/esm/lib/otp-input.js.map +1 -0
  250. package/dist/esm/lib/resend-invite-dialog.d.ts +2 -2
  251. package/dist/esm/lib/resend-invite-dialog.d.ts.map +1 -1
  252. package/dist/esm/lib/resend-invite-dialog.js +1 -1
  253. package/dist/esm/lib/resend-invite-dialog.js.map +1 -1
  254. package/dist/esm/lib/reset-mfa-dialog.d.ts +9 -0
  255. package/dist/esm/lib/reset-mfa-dialog.d.ts.map +1 -0
  256. package/dist/esm/lib/reset-mfa-dialog.js +34 -0
  257. package/dist/esm/lib/reset-mfa-dialog.js.map +1 -0
  258. package/dist/esm/lib/revoke-invite-dialog.d.ts +2 -2
  259. package/dist/esm/lib/revoke-invite-dialog.d.ts.map +1 -1
  260. package/dist/esm/lib/revoke-invite-dialog.js +1 -1
  261. package/dist/esm/lib/revoke-invite-dialog.js.map +1 -1
  262. package/dist/esm/lib/save-button.d.ts +11 -0
  263. package/dist/esm/lib/save-button.d.ts.map +1 -0
  264. package/dist/esm/lib/save-button.js +44 -0
  265. package/dist/esm/lib/save-button.js.map +1 -0
  266. package/dist/esm/lib/set-password-dialog.d.ts +8 -0
  267. package/dist/esm/lib/set-password-dialog.d.ts.map +1 -0
  268. package/dist/esm/lib/set-password-dialog.js +54 -0
  269. package/dist/esm/lib/set-password-dialog.js.map +1 -0
  270. package/dist/esm/lib/use-dialog-close.d.ts +2 -0
  271. package/dist/esm/lib/use-dialog-close.d.ts.map +1 -0
  272. package/dist/esm/lib/use-dialog-close.js +17 -0
  273. package/dist/esm/lib/use-dialog-close.js.map +1 -0
  274. package/dist/esm/lib/use-security-settings.d.ts +11 -0
  275. package/dist/esm/lib/use-security-settings.d.ts.map +1 -0
  276. package/dist/esm/lib/use-security-settings.js +36 -0
  277. package/dist/esm/lib/use-security-settings.js.map +1 -0
  278. package/dist/esm/lib/user-actions-dropdown.d.ts +2 -2
  279. package/dist/esm/lib/user-actions-dropdown.d.ts.map +1 -1
  280. package/dist/esm/lib/user-actions-dropdown.js +8 -4
  281. package/dist/esm/lib/user-actions-dropdown.js.map +1 -1
  282. package/dist/esm/lib/user-profile.d.ts +11 -0
  283. package/dist/esm/lib/user-profile.d.ts.map +1 -0
  284. package/dist/esm/lib/user-profile.js +27 -0
  285. package/dist/esm/lib/user-profile.js.map +1 -0
  286. package/dist/esm/lib/user-security.d.ts +11 -0
  287. package/dist/esm/lib/user-security.d.ts.map +1 -0
  288. package/dist/esm/lib/user-security.js +32 -0
  289. package/dist/esm/lib/user-security.js.map +1 -0
  290. package/dist/esm/lib/user-sessions.d.ts +12 -0
  291. package/dist/esm/lib/user-sessions.d.ts.map +1 -0
  292. package/dist/esm/lib/user-sessions.js +40 -0
  293. package/dist/esm/lib/user-sessions.js.map +1 -0
  294. package/dist/esm/lib/users-filter.d.ts +2 -2
  295. package/dist/esm/lib/users-filter.d.ts.map +1 -1
  296. package/dist/esm/lib/users-filter.js.map +1 -1
  297. package/dist/esm/lib/users-management-context.d.ts +0 -9
  298. package/dist/esm/lib/users-management-context.d.ts.map +1 -1
  299. package/dist/esm/lib/users-management-context.js +13 -25
  300. package/dist/esm/lib/users-management-context.js.map +1 -1
  301. package/dist/esm/lib/users-management-state.d.ts +3 -3
  302. package/dist/esm/lib/users-management-state.d.ts.map +1 -1
  303. package/dist/esm/lib/users-management-state.js.map +1 -1
  304. package/dist/esm/lib/users-management.d.ts +3 -4
  305. package/dist/esm/lib/users-management.d.ts.map +1 -1
  306. package/dist/esm/lib/users-management.js +9 -27
  307. package/dist/esm/lib/users-management.js.map +1 -1
  308. package/dist/esm/lib/users-search.d.ts +1 -1
  309. package/dist/esm/lib/users-search.d.ts.map +1 -1
  310. package/dist/esm/lib/utils.d.ts +10 -2
  311. package/dist/esm/lib/utils.d.ts.map +1 -1
  312. package/dist/esm/lib/utils.js +16 -0
  313. package/dist/esm/lib/utils.js.map +1 -1
  314. package/dist/esm/organization-switcher.client.d.ts +8 -0
  315. package/dist/esm/organization-switcher.client.d.ts.map +1 -0
  316. package/dist/esm/organization-switcher.client.js +33 -0
  317. package/dist/esm/organization-switcher.client.js.map +1 -0
  318. package/dist/esm/user-profile.client.d.ts +7 -0
  319. package/dist/esm/user-profile.client.d.ts.map +1 -0
  320. package/dist/esm/user-profile.client.js +27 -0
  321. package/dist/esm/user-profile.client.js.map +1 -0
  322. package/dist/esm/user-security.client.d.ts +7 -0
  323. package/dist/esm/user-security.client.d.ts.map +1 -0
  324. package/dist/esm/user-security.client.js +23 -0
  325. package/dist/esm/user-security.client.js.map +1 -0
  326. package/dist/esm/user-sessions.client.d.ts +12 -0
  327. package/dist/esm/user-sessions.client.d.ts.map +1 -0
  328. package/dist/esm/user-sessions.client.js +44 -0
  329. package/dist/esm/user-sessions.client.js.map +1 -0
  330. package/dist/esm/users-management.client.d.ts +2 -1
  331. package/dist/esm/users-management.client.d.ts.map +1 -1
  332. package/dist/esm/users-management.client.js +12 -20
  333. package/dist/esm/users-management.client.js.map +1 -1
  334. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  335. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  336. package/package.json +10 -4
  337. package/src/card-list.tsx +26 -0
  338. package/src/index.ts +3 -0
  339. package/src/lib/add-mfa-dialog.tsx +379 -0
  340. package/src/lib/api/user.ts +54 -458
  341. package/src/lib/card-list.css +3 -0
  342. package/src/lib/change-password-dialog.tsx +290 -0
  343. package/src/lib/copy-button.tsx +53 -0
  344. package/src/lib/delete-user-dialog.tsx +9 -6
  345. package/src/lib/edit-user-profile-dialog.tsx +181 -0
  346. package/src/lib/{edit-user-details-dialog.tsx → edit-user-role-dialog.tsx} +12 -9
  347. package/src/lib/elements.tsx +34 -1
  348. package/src/lib/elevated-access.tsx +261 -0
  349. package/src/lib/generic-error.tsx +70 -0
  350. package/src/lib/icon-panel.tsx +26 -0
  351. package/src/lib/icons.tsx +21 -0
  352. package/src/lib/invite-user-dialog.tsx +15 -10
  353. package/src/lib/logout-all-sessions-dialog.tsx +82 -0
  354. package/src/lib/logout-dialog.tsx +89 -0
  355. package/src/lib/marker.css +81 -0
  356. package/src/lib/marker.tsx +39 -0
  357. package/src/lib/oauth-icons.tsx +138 -0
  358. package/src/lib/organization-switcher.tsx +160 -0
  359. package/src/lib/otp-input.tsx +276 -0
  360. package/src/lib/resend-invite-dialog.tsx +9 -6
  361. package/src/lib/reset-mfa-dialog.tsx +104 -0
  362. package/src/lib/revoke-invite-dialog.tsx +9 -6
  363. package/src/lib/save-button.css +60 -0
  364. package/src/lib/save-button.tsx +113 -0
  365. package/src/lib/set-password-dialog.tsx +204 -0
  366. package/src/lib/use-dialog-close.tsx +19 -0
  367. package/src/lib/use-security-settings.tsx +49 -0
  368. package/src/lib/user-actions-dropdown.tsx +10 -6
  369. package/src/lib/user-profile.tsx +247 -0
  370. package/src/lib/user-security.tsx +187 -0
  371. package/src/lib/user-sessions.tsx +204 -0
  372. package/src/lib/users-filter.tsx +2 -2
  373. package/src/lib/users-management-context.tsx +21 -36
  374. package/src/lib/users-management-state.ts +3 -3
  375. package/src/lib/users-management.tsx +21 -77
  376. package/src/lib/utils.ts +30 -2
  377. package/src/organization-switcher.client.tsx +77 -0
  378. package/src/styles.css +44 -0
  379. package/src/user-profile.client.tsx +51 -0
  380. package/src/user-security.client.tsx +55 -0
  381. package/src/user-sessions.client.tsx +96 -0
  382. package/src/users-management.client.tsx +28 -39
  383. package/dist/cjs/lib/api/role.d.ts +0 -9
  384. package/dist/cjs/lib/api/role.d.ts.map +0 -1
  385. package/dist/cjs/lib/api/role.js +0 -115
  386. package/dist/cjs/lib/api/role.js.map +0 -1
  387. package/dist/cjs/lib/edit-user-details-dialog.d.ts +0 -12
  388. package/dist/cjs/lib/edit-user-details-dialog.d.ts.map +0 -1
  389. package/dist/cjs/lib/edit-user-details-dialog.js.map +0 -1
  390. package/dist/esm/lib/api/role.d.ts +0 -9
  391. package/dist/esm/lib/api/role.d.ts.map +0 -1
  392. package/dist/esm/lib/api/role.js +0 -110
  393. package/dist/esm/lib/api/role.js.map +0 -1
  394. package/dist/esm/lib/edit-user-details-dialog.d.ts +0 -12
  395. package/dist/esm/lib/edit-user-details-dialog.d.ts.map +0 -1
  396. package/dist/esm/lib/edit-user-details-dialog.js.map +0 -1
  397. package/src/lib/api/role.ts +0 -147
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
 
3
3
  import * as React from "react";
4
- import type { PaginationData } from "./api/user";
5
4
  import {
6
5
  UsersManagementAction,
7
6
  UsersManagementState,
7
+ useUsersManagementState,
8
8
  } from "./users-management-state";
9
+ import { ListMetadata } from "@repo/api";
9
10
 
10
11
  export interface UsersManagementContextType {
11
- authToken: (() => Promise<string>) | null;
12
12
  state: UsersManagementState;
13
13
  dispatch: React.Dispatch<UsersManagementAction>;
14
14
  }
@@ -18,19 +18,34 @@ const UsersManagementContext = React.createContext<
18
18
  >(undefined);
19
19
  UsersManagementContext.displayName = "UsersManagementContext";
20
20
 
21
+ const initialState: UsersManagementState = {
22
+ pagination: null,
23
+ role: null,
24
+ searchQuery: null,
25
+ };
26
+
21
27
  export const UsersManagementContextProvider: React.FC<{
22
28
  children?: React.ReactNode;
23
- value: UsersManagementContextType;
24
- }> = ({ children, value }) => {
29
+ }> = ({ children }) => {
30
+ const [state, dispatch] = useUsersManagementState(initialState);
31
+
32
+ const context = React.useMemo<UsersManagementContextType>(
33
+ () => ({
34
+ state,
35
+ dispatch,
36
+ }),
37
+ [state, dispatch],
38
+ );
39
+
25
40
  return (
26
- <UsersManagementContext.Provider value={value}>
41
+ <UsersManagementContext.Provider value={context}>
27
42
  {children}
28
43
  </UsersManagementContext.Provider>
29
44
  );
30
45
  };
31
46
 
32
47
  const NOOP = () => void 0;
33
- const EMPTY_PAGINATION: PaginationData = {};
48
+ const EMPTY_PAGINATION: ListMetadata = {};
34
49
 
35
50
  /**
36
51
  * The context may be provided if it is instantiated in the tree above the user.
@@ -39,15 +54,6 @@ export function useUsersManagementContext(
39
54
  initialContext?: UsersManagementContextType | null,
40
55
  ): UsersManagementContextType {
41
56
  const context = React.useContext(UsersManagementContext);
42
- const providedToken = initialContext?.authToken ?? null;
43
- const hasContext = !!context;
44
- React.useEffect(() => {
45
- if (!providedToken && !hasContext) {
46
- console.error(
47
- "useUsersManagementContext was called from a component outside of the UsersManagementContext provider without providing an authToken directly. Resulting queries may not run as expected.",
48
- );
49
- }
50
- }, [providedToken, hasContext]);
51
57
 
52
58
  if (context) {
53
59
  return context;
@@ -58,7 +64,6 @@ export function useUsersManagementContext(
58
64
  }
59
65
 
60
66
  return {
61
- authToken: null,
62
67
  dispatch: NOOP,
63
68
  state: {
64
69
  pagination: EMPTY_PAGINATION,
@@ -67,23 +72,3 @@ export function useUsersManagementContext(
67
72
  },
68
73
  };
69
74
  }
70
-
71
- /**
72
- * The auth token may be provided if it is instantiated in the tree above the
73
- * user management context. Otherwise we'll use the context value if it exists.
74
- */
75
- export function useUsersManagementPagniatoin(
76
- args: { authToken?: string | null } | undefined | null,
77
- ) {
78
- const context = React.useContext(UsersManagementContext);
79
- const providedToken = args?.authToken;
80
- const hasContext = !!context;
81
- React.useEffect(() => {
82
- if (!providedToken && !hasContext) {
83
- console.error(
84
- "useUsersManagementAuthToken was called from a component outside of the UsersManagementContext provider without providing an authToken directly. Resulting queries may not run as expected.",
85
- );
86
- }
87
- }, [providedToken, hasContext]);
88
- return providedToken || context?.authToken || null;
89
- }
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
- import type { PaginationData } from "./api/user";
3
2
  import { canUseDOM } from "./utils";
3
+ import { ListMetadata } from "@repo/api";
4
4
 
5
5
  export function useUsersManagementState(initialState: UsersManagementState) {
6
6
  const [[state, effects], dispatch] = React.useReducer(reducer, [
@@ -110,14 +110,14 @@ function reducer(
110
110
  export interface UsersManagementState {
111
111
  searchQuery: string | null;
112
112
  role: string | null;
113
- pagination: PaginationData | null;
113
+ pagination: ListMetadata | null;
114
114
  }
115
115
 
116
116
  export type UsersManagementAction =
117
117
  | { type: "INIT"; params: URLSearchParams }
118
118
  | { type: "FILTER_BY_SEARCH"; searchQuery: string | null }
119
119
  | { type: "FILTER_BY_ROLE"; role: string | null }
120
- | { type: "SET_PAGINATION"; pagination: PaginationData };
120
+ | { type: "SET_PAGINATION"; pagination: ListMetadata };
121
121
 
122
122
  type EffectFn = {
123
123
  (): void;
@@ -5,15 +5,13 @@ import {
5
5
  Box,
6
6
  Flex,
7
7
  Grid,
8
- Heading,
9
8
  Select,
9
+ Separator,
10
10
  Table,
11
11
  Text,
12
12
  type TextProps,
13
13
  VisuallyHidden,
14
14
  } from "@radix-ui/themes";
15
- import type { Role } from "./api/role";
16
- import type { Paginated, User } from "./api/user";
17
15
  import {
18
16
  Avatar,
19
17
  Badge,
@@ -36,11 +34,12 @@ import { getBestName, getComparativeReadableDate } from "./utils";
36
34
  import { USER_ROW_LIMIT } from "./constants";
37
35
  import { useUsersManagementContext } from "./users-management-context";
38
36
  import clsx from "clsx";
39
- import { ApiError, FetchError, NoAuthTokenError } from "./errors";
37
+ import { Member, MemberRole, MembersQueryResult } from "@repo/api";
38
+ import { GenericError } from "./generic-error";
40
39
 
41
40
  interface UsersManagementProps {
42
- rolesData: Role[];
43
- userData: Paginated<User[]>;
41
+ rolesData: MemberRole[];
42
+ userData: MembersQueryResult;
44
43
  disableRolesFilter?: boolean;
45
44
  // When the users list is loading new users
46
45
  isPending: boolean;
@@ -52,10 +51,10 @@ export const UsersManagement = ({
52
51
  isPending,
53
52
  disableRolesFilter,
54
53
  }: UsersManagementProps) => {
55
- const users = userData?.data;
54
+ const users = userData?.data ?? [];
56
55
  const usersCount = users?.length ?? 0;
57
56
  const isHydrated = useIsHydrated();
58
- const { pagination } = userData;
57
+ const { listMetadata: pagination = {} } = userData;
59
58
  const { dispatch } = useUsersManagementContext();
60
59
 
61
60
  // we only want to show the loading indicator for some buttons if the request
@@ -120,7 +119,7 @@ export const UsersManagement = ({
120
119
  {users.length > 0 ? (
121
120
  users.map((user) => {
122
121
  // TODO only support one role for now
123
- const userRole = user.roles[0]?.name;
122
+ const userRole = user?.roles?.at(0)?.name;
124
123
  const userDisplayName = getBestName(user);
125
124
  const dimText =
126
125
  user.status === "InviteRevoked" ||
@@ -186,11 +185,7 @@ export const UsersManagement = ({
186
185
  </TableCellText>
187
186
  </Table.Cell>
188
187
  <Table.Cell>
189
- <LastActive
190
- user={user}
191
- isHydrated={isHydrated}
192
- dim={dimText}
193
- />
188
+ <LastActive user={user} isHydrated={isHydrated} />
194
189
  </Table.Cell>
195
190
  <Table.Cell justify="end">
196
191
  <UserActionsDropdown user={user}>
@@ -356,59 +351,16 @@ export function UsersManagementLoading() {
356
351
  }
357
352
 
358
353
  export function UsersManagementError({ error }: { error: unknown }) {
359
- React.useEffect(() => {
360
- console.error(error);
361
- }, [error]);
362
-
363
- const render = (heading: string, message: React.ReactNode) => (
364
- <UsersManagementRoot justify="center" align="center" minHeight="676px">
365
- <Flex
366
- p="8"
367
- justify="center"
368
- align="center"
369
- direction="column"
370
- maxWidth="520px"
371
- >
372
- <Heading size="5" align="center" mb="1" wrap="balance" asChild>
373
- <h3>{heading}</h3>
374
- </Heading>
375
- <Text align="center" wrap="balance">
376
- {message}
377
- </Text>
378
- </Flex>
354
+ return (
355
+ <UsersManagementRoot
356
+ direction="row"
357
+ justify="center"
358
+ align="center"
359
+ minHeight="676px"
360
+ >
361
+ <GenericError error={error} />
379
362
  </UsersManagementRoot>
380
363
  );
381
-
382
- if (error instanceof FetchError) {
383
- return render(
384
- "Error fetching data",
385
- "An error occurred. You may need to configure CORS in the WorkOS Dashboard. " +
386
- "Contact your organization admin for support.",
387
- );
388
- }
389
-
390
- if (error instanceof NoAuthTokenError) {
391
- return render(
392
- "Error fetching data",
393
- "Authorization error. You likely forgot to provide an authorization " +
394
- "token to the Users Management Widget.",
395
- );
396
- }
397
-
398
- if (error instanceof ApiError && error.status === 404) {
399
- // The widgets API treats all authorization errors as 404s. If there is a
400
- // legitimate 404, it's a bug on our end but there's currently no way to
401
- // distinguish between the two.
402
- return render(
403
- "Error fetching data",
404
- "Authorization error. Contact your organization admin for support.",
405
- );
406
- }
407
-
408
- return render(
409
- "Error fetching data",
410
- "Unknown error. Contact your organization admin for support.",
411
- );
412
364
  }
413
365
 
414
366
  function UsersManagementRoot({
@@ -429,7 +381,7 @@ function UsersManagementRoot({
429
381
  );
430
382
  }
431
383
 
432
- function UserBadge({ user }: { user: User }) {
384
+ function UserBadge({ user }: { user: Member }) {
433
385
  // TODO: This is not yet available in the data. Update here after API is updated.
434
386
  if (user.isLoggedInUser) {
435
387
  return (
@@ -465,7 +417,7 @@ function UserBadge({ user }: { user: User }) {
465
417
  }
466
418
 
467
419
  interface LastActiveProps {
468
- user: User;
420
+ user: Member;
469
421
  isHydrated: boolean;
470
422
  dim?: boolean;
471
423
  }
@@ -477,13 +429,7 @@ function LastActive(props: LastActiveProps) {
477
429
  <VisuallyHidden>
478
430
  {props.user.status === "Active" ? "Never" : "Not active"}
479
431
  </VisuallyHidden>
480
- <TableCellText
481
- dim={props.dim}
482
- aria-hidden
483
- style={{ userSelect: "none" }}
484
- >
485
-
486
- </TableCellText>
432
+ <Separator />
487
433
  </>
488
434
  );
489
435
  }
@@ -529,9 +475,7 @@ function LastActiveImpl({
529
475
  return (
530
476
  <>
531
477
  <VisuallyHidden>Unknown</VisuallyHidden>
532
- <TableCellText dim={dim} aria-hidden style={{ userSelect: "none" }}>
533
-
534
- </TableCellText>
478
+ <Separator />
535
479
  </>
536
480
  );
537
481
  }
package/src/lib/utils.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { User } from "./api/user";
1
+ import { Member } from "@repo/api";
2
+ import { UAParser } from "ua-parser-js";
2
3
  import { WIDGETS_CLASS_NAMESPACE } from "./constants";
3
4
 
4
5
  export const canUseDOM = !!(
@@ -10,7 +11,7 @@ export const canUseDOM = !!(
10
11
  export function getBestName({
11
12
  firstName,
12
13
  lastName,
13
- }: Pick<User, "firstName" | "lastName">) {
14
+ }: Pick<Member, "firstName" | "lastName">) {
14
15
  return [firstName, lastName].filter(Boolean).join(" ") || null;
15
16
  }
16
17
 
@@ -101,3 +102,30 @@ export function namespaceClassNames(...classNames: string[]): string {
101
102
  .map((className) => `${WIDGETS_CLASS_NAMESPACE}-${className}`)
102
103
  .join(" ");
103
104
  }
105
+
106
+ export function parseUserAgent(userAgent?: string | null) {
107
+ const { browser, device, os } = UAParser(userAgent ?? "");
108
+
109
+ const browserName = browser.name?.replace(/^Mobile\s*/i, "");
110
+ const pretty = [browserName, os.name].filter(Boolean).join(" on ");
111
+
112
+ return { pretty, isMobile: device.type === "mobile" };
113
+ }
114
+
115
+ export function getUserLocation(
116
+ location?: {
117
+ cityName: string;
118
+ countryISOCode: string;
119
+ } | null,
120
+ ipAddress?: string | null,
121
+ ) {
122
+ if (location) {
123
+ return `${location.cityName}, ${location.countryISOCode}`;
124
+ }
125
+
126
+ if (ipAddress) {
127
+ return ipAddress;
128
+ }
129
+
130
+ return "Unknown location";
131
+ }
@@ -0,0 +1,77 @@
1
+ "use client";
2
+
3
+ import {
4
+ ApiProvider,
5
+ AuthToken,
6
+ OrganizationInfo,
7
+ useOrganizations,
8
+ } from "@repo/api";
9
+ import * as React from "react";
10
+ import { ErrorBoundary } from "./lib/error-boundary";
11
+ import { useIsHydrated } from "./lib/use-is-hydrated";
12
+ import {
13
+ OrganizationSwitcherError,
14
+ OrganizationSwitcherLoading,
15
+ OrganizationSwitcherPassthroughProps,
16
+ OrganizationSwitcher as OrganizationSwitcherPresentational,
17
+ } from "./lib/organization-switcher";
18
+ import { useWorkOsApiUrl } from "./lib/widgets-context";
19
+ import { keepPreviousData } from "@tanstack/react-query";
20
+
21
+ export interface OrganizationSwitcherProps
22
+ extends OrganizationSwitcherPassthroughProps {
23
+ authToken: AuthToken;
24
+ }
25
+
26
+ export const OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({
27
+ authToken,
28
+ ...passthroughProps
29
+ }) => {
30
+ const baseUrl = useWorkOsApiUrl();
31
+
32
+ return (
33
+ <ErrorBoundary FallbackComponent={OrganizationSwitcherError}>
34
+ <ApiProvider authToken={authToken} baseUrl={baseUrl}>
35
+ <OrganizationSwitcherContent {...passthroughProps} />
36
+ </ApiProvider>
37
+ </ErrorBoundary>
38
+ );
39
+ };
40
+
41
+ // Constant reference to avoid unnecessary prop changes
42
+ const emptyOrganizations: OrganizationInfo[] = [];
43
+
44
+ const OrganizationSwitcherContent = ({
45
+ variant,
46
+ ...rest
47
+ }: OrganizationSwitcherPassthroughProps) => {
48
+ const isHydrated = useIsHydrated();
49
+ const organizationsQuery = useOrganizations({
50
+ query: {
51
+ placeholderData: keepPreviousData,
52
+ },
53
+ });
54
+
55
+ const organizations = organizationsQuery.data?.data ?? emptyOrganizations;
56
+
57
+ if (
58
+ organizationsQuery.isLoading ||
59
+ // render loading state on the server to prevent FOUC or hydration mismatch
60
+ !isHydrated
61
+ ) {
62
+ return <OrganizationSwitcherLoading organizations={organizations} />;
63
+ }
64
+
65
+ if (organizationsQuery.isError) {
66
+ return <OrganizationSwitcherError error={organizationsQuery.error} />;
67
+ }
68
+
69
+ return (
70
+ <ErrorBoundary FallbackComponent={OrganizationSwitcherError}>
71
+ <OrganizationSwitcherPresentational
72
+ organizations={organizations}
73
+ {...rest}
74
+ />
75
+ </ErrorBoundary>
76
+ );
77
+ };
package/src/styles.css ADDED
@@ -0,0 +1,44 @@
1
+ @import "./lib/card-list.css";
2
+ @import "./lib/marker.css";
3
+ @import "./lib/save-button.css";
4
+
5
+ /**
6
+ * Dialog exit animation
7
+ */
8
+ @keyframes woswidgets-dialog-out {
9
+ from {
10
+ opacity: 1;
11
+ transform: translateY(0px);
12
+ }
13
+ to {
14
+ opacity: 0;
15
+ transform: translateY(10px) scale(0.97);
16
+ }
17
+ }
18
+
19
+ @keyframes woswidgets-dialog-overlay-out {
20
+ from {
21
+ opacity: 1;
22
+ }
23
+ to {
24
+ opacity: 0;
25
+ }
26
+ }
27
+
28
+ @media (prefers-reduced-motion: no-preference) {
29
+ .rt-BaseDialogContent[data-state="closed"] {
30
+ transition: none;
31
+ animation: woswidgets-dialog-out 150ms ease-out;
32
+ }
33
+
34
+ .rt-BaseDialogOverlay[data-state="closed"] {
35
+ transition: none;
36
+ animation: woswidgets-dialog-overlay-out 300ms ease-out;
37
+ }
38
+
39
+ .rt-BaseDialogOverlay:where([data-state="closed"])::before {
40
+ transition: none;
41
+ animation: none;
42
+ opacity: 1;
43
+ }
44
+ }
@@ -0,0 +1,51 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import {
5
+ UserProfileError,
6
+ UserProfileLoading,
7
+ UserProfile as UserProfilePresentational,
8
+ } from "./lib/user-profile";
9
+ import { useIsHydrated } from "./lib/use-is-hydrated";
10
+ import { ApiProvider, AuthToken, useMe } from "@repo/api";
11
+ import { useWorkOsApiUrl } from "./lib/widgets-context";
12
+ import { ErrorBoundary } from "./lib/error-boundary";
13
+
14
+ export interface UserProfileProps {
15
+ authToken: AuthToken;
16
+ }
17
+
18
+ export const UserProfile: React.FC<UserProfileProps> = ({ authToken }) => {
19
+ const baseUrl = useWorkOsApiUrl();
20
+
21
+ return (
22
+ <ApiProvider authToken={authToken} baseUrl={baseUrl}>
23
+ <UserProfileContent />
24
+ </ApiProvider>
25
+ );
26
+ };
27
+
28
+ const UserProfileContent = () => {
29
+ const isHydrated = useIsHydrated();
30
+ const meQuery = useMe();
31
+
32
+ if (
33
+ // render loading state on the server to prevent FOUC or hydration mismatch
34
+ !isHydrated ||
35
+ meQuery.isLoading
36
+ ) {
37
+ return <UserProfileLoading />;
38
+ }
39
+
40
+ if (meQuery.isError) {
41
+ return <UserProfileError error={meQuery.error} />;
42
+ }
43
+
44
+ const user = meQuery.data!;
45
+
46
+ return (
47
+ <ErrorBoundary FallbackComponent={UserProfileError}>
48
+ <UserProfilePresentational userData={user} />
49
+ </ErrorBoundary>
50
+ );
51
+ };
@@ -0,0 +1,55 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import {
5
+ ApiProvider,
6
+ AuthToken,
7
+ useAuthenticationInformation,
8
+ } from "@repo/api";
9
+ import {
10
+ UserSecurityError,
11
+ UserSecurityLoading,
12
+ UserSecurity as UserSecurityPresentational,
13
+ } from "./lib/user-security";
14
+ import { useIsHydrated } from "./lib/use-is-hydrated";
15
+ import { useWorkOsApiUrl } from "./lib/widgets-context";
16
+ import { ErrorBoundary } from "./lib/error-boundary";
17
+
18
+ export interface UserSecurityProps {
19
+ authToken: AuthToken;
20
+ }
21
+
22
+ export const UserSecurity: React.FC<UserSecurityProps> = ({ authToken }) => {
23
+ const baseUrl = useWorkOsApiUrl();
24
+
25
+ return (
26
+ <ApiProvider authToken={authToken} baseUrl={baseUrl}>
27
+ <UserSecurityContent />
28
+ </ApiProvider>
29
+ );
30
+ };
31
+
32
+ const UserSecurityContent = () => {
33
+ const isHydrated = useIsHydrated();
34
+ const {
35
+ data: settings,
36
+ isLoading,
37
+ isError,
38
+ isSuccess,
39
+ error,
40
+ } = useAuthenticationInformation();
41
+
42
+ if (!isHydrated || isLoading) {
43
+ return <UserSecurityLoading />;
44
+ }
45
+
46
+ if (isError || !isSuccess) {
47
+ return <UserSecurityError error={error} />;
48
+ }
49
+
50
+ return (
51
+ <ErrorBoundary FallbackComponent={UserSecurityError}>
52
+ <UserSecurityPresentational settings={settings.data} />
53
+ </ErrorBoundary>
54
+ );
55
+ };
@@ -0,0 +1,96 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import {
5
+ UserSessionsError,
6
+ UserSessionsLoading,
7
+ UserSessions as UserSessionsPresentational,
8
+ } from "./lib/user-sessions";
9
+ import { useIsHydrated } from "./lib/use-is-hydrated";
10
+ import { ApiProvider, useApi, useSessions } from "@repo/api";
11
+ import { useWorkOsApiUrl } from "./lib/widgets-context";
12
+ import { ErrorBoundary } from "./lib/error-boundary";
13
+ import { useQuery } from "@tanstack/react-query";
14
+
15
+ type UserSessionsWithoutCurrentSessionIdProps = {
16
+ authToken: () => Promise<string>;
17
+ };
18
+
19
+ type UserSessionsWithCurrentSessionIdProps = {
20
+ authToken: string;
21
+ currentSessionId: string;
22
+ };
23
+
24
+ type UserSessionsProps =
25
+ | UserSessionsWithoutCurrentSessionIdProps
26
+ | UserSessionsWithCurrentSessionIdProps;
27
+
28
+ export const UserSessions: React.FC<UserSessionsProps> = (props) => {
29
+ const baseUrl = useWorkOsApiUrl();
30
+
31
+ return (
32
+ <ApiProvider authToken={props.authToken} baseUrl={baseUrl}>
33
+ <UserSessionsContent
34
+ currentSessionId={
35
+ "currentSessionId" in props ? props.currentSessionId : undefined
36
+ }
37
+ />
38
+ </ApiProvider>
39
+ );
40
+ };
41
+
42
+ const UserSessionsContent = ({
43
+ currentSessionId,
44
+ }: {
45
+ currentSessionId?: string;
46
+ }) => {
47
+ const isHydrated = useIsHydrated();
48
+ const sessionsQuery = useSessions();
49
+ const currentSessionIdQuery = useCurrentSessionIdQuery(currentSessionId);
50
+
51
+ if (
52
+ !isHydrated ||
53
+ sessionsQuery.isLoading ||
54
+ currentSessionIdQuery.isLoading
55
+ ) {
56
+ return <UserSessionsLoading />;
57
+ }
58
+
59
+ if (sessionsQuery.isError || currentSessionIdQuery.isError) {
60
+ return (
61
+ <UserSessionsError
62
+ error={sessionsQuery.error || currentSessionIdQuery.error}
63
+ />
64
+ );
65
+ }
66
+
67
+ return (
68
+ <ErrorBoundary FallbackComponent={UserSessionsError}>
69
+ <UserSessionsPresentational
70
+ sessionsData={sessionsQuery.data?.data || []}
71
+ currentSessionId={currentSessionIdQuery.data ?? ""}
72
+ />
73
+ </ErrorBoundary>
74
+ );
75
+ };
76
+
77
+ function useCurrentSessionIdQuery(currentSessionId?: string) {
78
+ const { authToken } = useApi();
79
+
80
+ return useQuery({
81
+ queryKey: ["authToken"],
82
+ queryFn: async () => {
83
+ if (currentSessionId) {
84
+ return currentSessionId;
85
+ }
86
+
87
+ const res = await Promise.resolve(authToken);
88
+ const claims = getClaims(res);
89
+ return claims.sid;
90
+ },
91
+ });
92
+ }
93
+
94
+ function getClaims(accessToken: string) {
95
+ return JSON.parse(atob(accessToken.split(".")[1])) as { sid: string };
96
+ }