@workos-inc/widgets 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/cjs/api/endpoint.cjs +1 -0
  3. package/dist/cjs/api/endpoint.cjs.map +1 -1
  4. package/dist/cjs/api/endpoint.d.cts +1 -0
  5. package/dist/cjs/index.cjs +5 -2
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/index.d.cts +1 -0
  8. package/dist/cjs/lib/add-mfa-dialog.cjs +133 -61
  9. package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
  10. package/dist/cjs/lib/admin-portal-domain-verification.cjs +41 -5
  11. package/dist/cjs/lib/admin-portal-domain-verification.cjs.map +1 -1
  12. package/dist/cjs/lib/admin-portal-sso-connection.cjs +121 -44
  13. package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
  14. package/dist/cjs/lib/api-keys/api-key-details-card.cjs +25 -3
  15. package/dist/cjs/lib/api-keys/api-key-details-card.cjs.map +1 -1
  16. package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs +25 -3
  17. package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs.map +1 -1
  18. package/dist/cjs/lib/api-keys/api-keys-search.cjs +13 -4
  19. package/dist/cjs/lib/api-keys/api-keys-search.cjs.map +1 -1
  20. package/dist/cjs/lib/api-keys/api-keys-table.cjs +94 -12
  21. package/dist/cjs/lib/api-keys/api-keys-table.cjs.map +1 -1
  22. package/dist/cjs/lib/api-keys/api-keys.cjs +16 -2
  23. package/dist/cjs/lib/api-keys/api-keys.cjs.map +1 -1
  24. package/dist/cjs/lib/api-keys/create-api-key.cjs +172 -20
  25. package/dist/cjs/lib/api-keys/create-api-key.cjs.map +1 -1
  26. package/dist/cjs/lib/api-keys/relative-time.cjs +12 -2
  27. package/dist/cjs/lib/api-keys/relative-time.cjs.map +1 -1
  28. package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs +49 -7
  29. package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs.map +1 -1
  30. package/dist/cjs/lib/change-password-dialog.cjs +122 -16
  31. package/dist/cjs/lib/change-password-dialog.cjs.map +1 -1
  32. package/dist/cjs/lib/copy-button.cjs +14 -2
  33. package/dist/cjs/lib/copy-button.cjs.map +1 -1
  34. package/dist/cjs/lib/copy-button.d.cts +2 -1
  35. package/dist/cjs/lib/delete-domain-dialog.cjs +52 -19
  36. package/dist/cjs/lib/delete-domain-dialog.cjs.map +1 -1
  37. package/dist/cjs/lib/delete-user-dialog.cjs +46 -11
  38. package/dist/cjs/lib/delete-user-dialog.cjs.map +1 -1
  39. package/dist/cjs/lib/delete-user-dialog.d.cts +2 -2
  40. package/dist/cjs/lib/domain-actions.cjs +51 -7
  41. package/dist/cjs/lib/domain-actions.cjs.map +1 -1
  42. package/dist/cjs/lib/domain-item.cjs +42 -8
  43. package/dist/cjs/lib/domain-item.cjs.map +1 -1
  44. package/dist/cjs/lib/edit-user-profile-dialog.cjs +62 -11
  45. package/dist/cjs/lib/edit-user-profile-dialog.cjs.map +1 -1
  46. package/dist/cjs/lib/edit-user-role-dialog.cjs +90 -17
  47. package/dist/cjs/lib/edit-user-role-dialog.cjs.map +1 -1
  48. package/dist/cjs/lib/elements.cjs +14 -3
  49. package/dist/cjs/lib/elements.cjs.map +1 -1
  50. package/dist/cjs/lib/elements.d.cts +5 -2
  51. package/dist/cjs/lib/elevated-access.cjs +78 -18
  52. package/dist/cjs/lib/elevated-access.cjs.map +1 -1
  53. package/dist/cjs/lib/generic-error.cjs +53 -11
  54. package/dist/cjs/lib/generic-error.cjs.map +1 -1
  55. package/dist/cjs/lib/generic-error.d.cts +5 -1
  56. package/dist/cjs/lib/i18n/intl-context.cjs +47 -0
  57. package/dist/cjs/lib/i18n/intl-context.cjs.map +1 -0
  58. package/dist/cjs/lib/i18n/intl-context.d.cts +29 -0
  59. package/dist/cjs/lib/i18n/translation.cjs +67 -0
  60. package/dist/cjs/lib/i18n/translation.cjs.map +1 -0
  61. package/dist/cjs/lib/i18n/translation.d.cts +16 -0
  62. package/dist/cjs/lib/i18n/use-locale.cjs +33 -0
  63. package/dist/cjs/lib/i18n/use-locale.cjs.map +1 -0
  64. package/dist/cjs/lib/i18n/use-locale.d.cts +7 -0
  65. package/dist/cjs/lib/i18n/use-translation.cjs +47 -0
  66. package/dist/cjs/lib/i18n/use-translation.cjs.map +1 -0
  67. package/dist/cjs/lib/i18n/use-translation.d.cts +15 -0
  68. package/dist/cjs/lib/identity-providers.d.cts +1 -1
  69. package/dist/cjs/lib/invite-user-dialog.cjs +69 -14
  70. package/dist/cjs/lib/invite-user-dialog.cjs.map +1 -1
  71. package/dist/cjs/lib/logout-all-sessions-dialog.cjs +33 -4
  72. package/dist/cjs/lib/logout-all-sessions-dialog.cjs.map +1 -1
  73. package/dist/cjs/lib/logout-dialog.cjs +34 -10
  74. package/dist/cjs/lib/logout-dialog.cjs.map +1 -1
  75. package/dist/cjs/lib/organization-switcher.cjs +12 -2
  76. package/dist/cjs/lib/organization-switcher.cjs.map +1 -1
  77. package/dist/cjs/lib/pipes.cjs +175 -36
  78. package/dist/cjs/lib/pipes.cjs.map +1 -1
  79. package/dist/cjs/lib/resend-invite-dialog.cjs +67 -17
  80. package/dist/cjs/lib/resend-invite-dialog.cjs.map +1 -1
  81. package/dist/cjs/lib/reset-mfa-dialog.cjs +50 -7
  82. package/dist/cjs/lib/reset-mfa-dialog.cjs.map +1 -1
  83. package/dist/cjs/lib/revoke-invite-dialog.cjs +42 -10
  84. package/dist/cjs/lib/revoke-invite-dialog.cjs.map +1 -1
  85. package/dist/cjs/lib/save-button.cjs +9 -1
  86. package/dist/cjs/lib/save-button.cjs.map +1 -1
  87. package/dist/cjs/lib/set-password-dialog.cjs +101 -13
  88. package/dist/cjs/lib/set-password-dialog.cjs.map +1 -1
  89. package/dist/cjs/lib/user-actions-dropdown.cjs +54 -6
  90. package/dist/cjs/lib/user-actions-dropdown.cjs.map +1 -1
  91. package/dist/cjs/lib/user-profile.cjs +81 -10
  92. package/dist/cjs/lib/user-profile.cjs.map +1 -1
  93. package/dist/cjs/lib/user-security.cjs +127 -25
  94. package/dist/cjs/lib/user-security.cjs.map +1 -1
  95. package/dist/cjs/lib/user-sessions.cjs +74 -15
  96. package/dist/cjs/lib/user-sessions.cjs.map +1 -1
  97. package/dist/cjs/lib/users-management.cjs +265 -49
  98. package/dist/cjs/lib/users-management.cjs.map +1 -1
  99. package/dist/cjs/lib/users-search.cjs +18 -4
  100. package/dist/cjs/lib/users-search.cjs.map +1 -1
  101. package/dist/cjs/lib/utils.cjs +10 -7
  102. package/dist/cjs/lib/utils.cjs.map +1 -1
  103. package/dist/cjs/lib/utils.d.cts +2 -1
  104. package/dist/cjs/lib/view-dns-record-dialog.cjs +89 -18
  105. package/dist/cjs/lib/view-dns-record-dialog.cjs.map +1 -1
  106. package/dist/cjs/workos-widgets.client.cjs +2 -2
  107. package/dist/cjs/workos-widgets.client.cjs.map +1 -1
  108. package/dist/esm/api/endpoint.d.ts +1 -0
  109. package/dist/esm/api/endpoint.js +1 -0
  110. package/dist/esm/api/endpoint.js.map +1 -1
  111. package/dist/esm/index.d.ts +1 -0
  112. package/dist/esm/index.js +3 -1
  113. package/dist/esm/index.js.map +1 -1
  114. package/dist/esm/lib/add-mfa-dialog.js +133 -61
  115. package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
  116. package/dist/esm/lib/admin-portal-domain-verification.js +41 -5
  117. package/dist/esm/lib/admin-portal-domain-verification.js.map +1 -1
  118. package/dist/esm/lib/admin-portal-sso-connection.js +121 -44
  119. package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
  120. package/dist/esm/lib/api-keys/api-key-details-card.js +25 -3
  121. package/dist/esm/lib/api-keys/api-key-details-card.js.map +1 -1
  122. package/dist/esm/lib/api-keys/api-key-details-dialog.js +25 -3
  123. package/dist/esm/lib/api-keys/api-key-details-dialog.js.map +1 -1
  124. package/dist/esm/lib/api-keys/api-keys-search.js +13 -4
  125. package/dist/esm/lib/api-keys/api-keys-search.js.map +1 -1
  126. package/dist/esm/lib/api-keys/api-keys-table.js +94 -12
  127. package/dist/esm/lib/api-keys/api-keys-table.js.map +1 -1
  128. package/dist/esm/lib/api-keys/api-keys.js +16 -2
  129. package/dist/esm/lib/api-keys/api-keys.js.map +1 -1
  130. package/dist/esm/lib/api-keys/create-api-key.js +172 -20
  131. package/dist/esm/lib/api-keys/create-api-key.js.map +1 -1
  132. package/dist/esm/lib/api-keys/relative-time.js +12 -2
  133. package/dist/esm/lib/api-keys/relative-time.js.map +1 -1
  134. package/dist/esm/lib/api-keys/revoke-api-key-dialog.js +49 -7
  135. package/dist/esm/lib/api-keys/revoke-api-key-dialog.js.map +1 -1
  136. package/dist/esm/lib/change-password-dialog.js +122 -16
  137. package/dist/esm/lib/change-password-dialog.js.map +1 -1
  138. package/dist/esm/lib/copy-button.d.ts +2 -1
  139. package/dist/esm/lib/copy-button.js +14 -2
  140. package/dist/esm/lib/copy-button.js.map +1 -1
  141. package/dist/esm/lib/delete-domain-dialog.js +52 -19
  142. package/dist/esm/lib/delete-domain-dialog.js.map +1 -1
  143. package/dist/esm/lib/delete-user-dialog.d.ts +2 -2
  144. package/dist/esm/lib/delete-user-dialog.js +36 -11
  145. package/dist/esm/lib/delete-user-dialog.js.map +1 -1
  146. package/dist/esm/lib/domain-actions.js +41 -7
  147. package/dist/esm/lib/domain-actions.js.map +1 -1
  148. package/dist/esm/lib/domain-item.js +42 -8
  149. package/dist/esm/lib/domain-item.js.map +1 -1
  150. package/dist/esm/lib/edit-user-profile-dialog.js +62 -11
  151. package/dist/esm/lib/edit-user-profile-dialog.js.map +1 -1
  152. package/dist/esm/lib/edit-user-role-dialog.js +90 -17
  153. package/dist/esm/lib/edit-user-role-dialog.js.map +1 -1
  154. package/dist/esm/lib/elements.d.ts +5 -2
  155. package/dist/esm/lib/elements.js +14 -3
  156. package/dist/esm/lib/elements.js.map +1 -1
  157. package/dist/esm/lib/elevated-access.js +78 -18
  158. package/dist/esm/lib/elevated-access.js.map +1 -1
  159. package/dist/esm/lib/generic-error.d.ts +5 -1
  160. package/dist/esm/lib/generic-error.js +53 -11
  161. package/dist/esm/lib/generic-error.js.map +1 -1
  162. package/dist/esm/lib/i18n/intl-context.d.ts +29 -0
  163. package/dist/esm/lib/i18n/intl-context.js +12 -0
  164. package/dist/esm/lib/i18n/intl-context.js.map +1 -0
  165. package/dist/esm/lib/i18n/translation.d.ts +16 -0
  166. package/dist/esm/lib/i18n/translation.js +45 -0
  167. package/dist/esm/lib/i18n/translation.js.map +1 -0
  168. package/dist/esm/lib/i18n/use-locale.d.ts +7 -0
  169. package/dist/esm/lib/i18n/use-locale.js +9 -0
  170. package/dist/esm/lib/i18n/use-locale.js.map +1 -0
  171. package/dist/esm/lib/i18n/use-translation.d.ts +15 -0
  172. package/dist/esm/lib/i18n/use-translation.js +23 -0
  173. package/dist/esm/lib/i18n/use-translation.js.map +1 -0
  174. package/dist/esm/lib/identity-providers.d.ts +1 -1
  175. package/dist/esm/lib/invite-user-dialog.js +70 -15
  176. package/dist/esm/lib/invite-user-dialog.js.map +1 -1
  177. package/dist/esm/lib/logout-all-sessions-dialog.js +33 -4
  178. package/dist/esm/lib/logout-all-sessions-dialog.js.map +1 -1
  179. package/dist/esm/lib/logout-dialog.js +34 -10
  180. package/dist/esm/lib/logout-dialog.js.map +1 -1
  181. package/dist/esm/lib/organization-switcher.js +12 -2
  182. package/dist/esm/lib/organization-switcher.js.map +1 -1
  183. package/dist/esm/lib/pipes.js +175 -36
  184. package/dist/esm/lib/pipes.js.map +1 -1
  185. package/dist/esm/lib/resend-invite-dialog.js +67 -17
  186. package/dist/esm/lib/resend-invite-dialog.js.map +1 -1
  187. package/dist/esm/lib/reset-mfa-dialog.js +50 -7
  188. package/dist/esm/lib/reset-mfa-dialog.js.map +1 -1
  189. package/dist/esm/lib/revoke-invite-dialog.js +42 -10
  190. package/dist/esm/lib/revoke-invite-dialog.js.map +1 -1
  191. package/dist/esm/lib/save-button.js +9 -1
  192. package/dist/esm/lib/save-button.js.map +1 -1
  193. package/dist/esm/lib/set-password-dialog.js +101 -13
  194. package/dist/esm/lib/set-password-dialog.js.map +1 -1
  195. package/dist/esm/lib/user-actions-dropdown.js +54 -6
  196. package/dist/esm/lib/user-actions-dropdown.js.map +1 -1
  197. package/dist/esm/lib/user-profile.js +81 -10
  198. package/dist/esm/lib/user-profile.js.map +1 -1
  199. package/dist/esm/lib/user-security.js +127 -25
  200. package/dist/esm/lib/user-security.js.map +1 -1
  201. package/dist/esm/lib/user-sessions.js +74 -15
  202. package/dist/esm/lib/user-sessions.js.map +1 -1
  203. package/dist/esm/lib/users-management.js +266 -51
  204. package/dist/esm/lib/users-management.js.map +1 -1
  205. package/dist/esm/lib/users-search.js +18 -4
  206. package/dist/esm/lib/users-search.js.map +1 -1
  207. package/dist/esm/lib/utils.d.ts +2 -1
  208. package/dist/esm/lib/utils.js +10 -7
  209. package/dist/esm/lib/utils.js.map +1 -1
  210. package/dist/esm/lib/view-dns-record-dialog.js +89 -18
  211. package/dist/esm/lib/view-dns-record-dialog.js.map +1 -1
  212. package/dist/esm/workos-widgets.client.js +2 -2
  213. package/dist/esm/workos-widgets.client.js.map +1 -1
  214. package/package.json +11 -2
@@ -29,13 +29,15 @@ import { UsersSearch } from "./users-search.js";
29
29
  import {
30
30
  getBestName,
31
31
  getComparativeReadableDate,
32
- getDomProps,
33
- pluralize
32
+ getDomProps
34
33
  } from "./utils.js";
35
34
  import { USER_ROW_LIMIT } from "./constants.js";
36
35
  import { useUsersManagementContext } from "./users-management-context.js";
37
36
  import { GenericError } from "./generic-error.js";
38
37
  import { DotsHorizontalIcon } from "@radix-ui/react-icons";
38
+ import { Translation } from "./i18n/translation.js";
39
+ import { useTranslation } from "./i18n/use-translation.js";
40
+ import { useLocale } from "./i18n/use-locale.js";
39
41
  const UsersManagement = ({
40
42
  userData,
41
43
  rolesData,
@@ -49,6 +51,7 @@ const UsersManagement = ({
49
51
  const { listMetadata: pagination = {} } = userData;
50
52
  const { dispatch } = useUsersManagementContext();
51
53
  const isMultipleRolesEnabled = rolesData.multipleRolesEnabled;
54
+ const translate = useTranslation();
52
55
  const [deferredLoading, setDeferredLoading] = React.useState(false);
53
56
  React.useEffect(() => {
54
57
  if (isPending) {
@@ -81,13 +84,48 @@ const UsersManagement = ({
81
84
  }
82
85
  ) })
83
86
  ] }),
84
- /* @__PURE__ */ jsx(Box, { flexGrow: "0", flexShrink: "0", style: { placeSelf: "flex-end" }, children: /* @__PURE__ */ jsx(InviteUserDialog, { children: /* @__PURE__ */ jsx(Button, { children: "Invite user" }) }) })
87
+ /* @__PURE__ */ jsx(Box, { flexGrow: "0", flexShrink: "0", style: { placeSelf: "flex-end" }, children: /* @__PURE__ */ jsx(InviteUserDialog, { children: /* @__PURE__ */ jsx(Button, { children: /* @__PURE__ */ jsx(
88
+ Translation,
89
+ {
90
+ defaultMessage: "Invite user",
91
+ id: "NBXpRj",
92
+ description: "Button text to invite a new user to the organization"
93
+ }
94
+ ) }) }) })
85
95
  ] }),
86
96
  /* @__PURE__ */ jsxs(Table.Root, { variant: "ghost", size: "1", children: [
87
97
  /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
88
- /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "260px", children: "User" }),
89
- /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "100px", children: `Role${isMultipleRolesEnabled ? "s" : ""}` }),
90
- /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "140px", children: "Last active" }),
98
+ /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "260px", children: /* @__PURE__ */ jsx(
99
+ Translation,
100
+ {
101
+ defaultMessage: "User",
102
+ id: "BBh86k",
103
+ description: "Column header for user information in the users table"
104
+ }
105
+ ) }),
106
+ /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "100px", children: isMultipleRolesEnabled ? /* @__PURE__ */ jsx(
107
+ Translation,
108
+ {
109
+ defaultMessage: "Roles",
110
+ id: "A1DuWM",
111
+ description: "Column header for user roles when multiple roles are enabled"
112
+ }
113
+ ) : /* @__PURE__ */ jsx(
114
+ Translation,
115
+ {
116
+ defaultMessage: "Role",
117
+ id: "nQbe+Y",
118
+ description: "Column header for user role when only single role is allowed"
119
+ }
120
+ ) }),
121
+ /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "140px", children: /* @__PURE__ */ jsx(
122
+ Translation,
123
+ {
124
+ defaultMessage: "Last active",
125
+ id: "oOwLGt",
126
+ description: "Column header showing when users were last active"
127
+ }
128
+ ) }),
91
129
  /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "28px" })
92
130
  ] }) }),
93
131
  /* @__PURE__ */ jsx(
@@ -161,8 +199,11 @@ const UsersManagement = ({
161
199
  /* @__PURE__ */ jsx(Table.Cell, { justify: "end", children: /* @__PURE__ */ jsx(UserActionsDropdown, { user, children: /* @__PURE__ */ jsx(
162
200
  IconButton,
163
201
  {
164
- title: "User actions",
165
- "aria-label": "User actions",
202
+ title: translate({
203
+ defaultMessage: "User actions",
204
+ id: "1nsmNS",
205
+ description: "Button tooltip for opening user actions menu"
206
+ }),
166
207
  children: /* @__PURE__ */ jsx(DotsHorizontalIcon, {})
167
208
  }
168
209
  ) }) })
@@ -187,7 +228,14 @@ const UsersManagement = ({
187
228
  });
188
229
  }
189
230
  },
190
- children: "Previous"
231
+ children: /* @__PURE__ */ jsx(
232
+ Translation,
233
+ {
234
+ defaultMessage: "Previous",
235
+ id: "910Q6b",
236
+ description: "Button text to navigate to the previous page of users"
237
+ }
238
+ )
191
239
  }
192
240
  ),
193
241
  /* @__PURE__ */ jsx(
@@ -205,7 +253,14 @@ const UsersManagement = ({
205
253
  });
206
254
  }
207
255
  },
208
- children: "Next"
256
+ children: /* @__PURE__ */ jsx(
257
+ Translation,
258
+ {
259
+ defaultMessage: "Next",
260
+ id: "UlAY08",
261
+ description: "Button text to navigate to the next page of users"
262
+ }
263
+ )
209
264
  }
210
265
  )
211
266
  ] }) : null
@@ -214,6 +269,15 @@ const UsersManagement = ({
214
269
  ) });
215
270
  };
216
271
  const UsersManagementLoading = (props) => {
272
+ const translate = useTranslation();
273
+ const placeholderText = /* @__PURE__ */ jsx(
274
+ Translation,
275
+ {
276
+ defaultMessage: "All",
277
+ id: "l/Do9/",
278
+ description: "Filter option to show all users"
279
+ }
280
+ );
217
281
  return /* @__PURE__ */ jsxs(
218
282
  Flex,
219
283
  {
@@ -223,19 +287,57 @@ const UsersManagementLoading = (props) => {
223
287
  children: [
224
288
  /* @__PURE__ */ jsxs(Grid, { columns: "1fr auto", gap: "2", children: [
225
289
  /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "center", children: [
226
- /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Box, { flexBasis: "380px", flexGrow: "0", flexShrink: "1", children: /* @__PURE__ */ jsx(TextField, {}) }) }),
227
- /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Box, { flexGrow: "0", flexShrink: "0", children: /* @__PURE__ */ jsxs(Select.Root, { value: "all", onValueChange: () => void 0, children: [
228
- /* @__PURE__ */ jsx(Select.Trigger, { children: "All" }),
229
- /* @__PURE__ */ jsx(Select.Content, { children: /* @__PURE__ */ jsx(Select.Item, { value: "all", children: "All" }) })
290
+ /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Box, { flexBasis: "380px", flexGrow: "0", flexShrink: "1", children: /* @__PURE__ */ jsx(
291
+ TextField,
292
+ {
293
+ disabled: true,
294
+ "aria-label": translate({
295
+ defaultMessage: "User search",
296
+ id: "lzPOKv",
297
+ description: "Label for the user search input field"
298
+ })
299
+ }
300
+ ) }) }),
301
+ /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Box, { flexGrow: "0", flexShrink: "0", children: /* @__PURE__ */ jsxs(Select.Root, { disabled: true, value: "all", onValueChange: () => void 0, children: [
302
+ /* @__PURE__ */ jsx(Select.Trigger, { children: placeholderText }),
303
+ /* @__PURE__ */ jsx(Select.Content, { children: /* @__PURE__ */ jsx(Select.Item, { value: "all", children: placeholderText }) })
230
304
  ] }) }) })
231
305
  ] }),
232
- /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Box, { flexGrow: "0", flexShrink: "0", style: { placeSelf: "flex-end" }, children: /* @__PURE__ */ jsx(Button, { children: "Invite user" }) }) })
306
+ /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Box, { flexGrow: "0", flexShrink: "0", style: { placeSelf: "flex-end" }, children: /* @__PURE__ */ jsx(Button, { disabled: true, children: /* @__PURE__ */ jsx(
307
+ Translation,
308
+ {
309
+ defaultMessage: "Invite user",
310
+ id: "NBXpRj",
311
+ description: "Button text to invite a new user to the organization"
312
+ }
313
+ ) }) }) })
233
314
  ] }),
234
315
  /* @__PURE__ */ jsxs(Table.Root, { variant: "ghost", size: "1", children: [
235
316
  /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
236
- /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "260px", children: /* @__PURE__ */ jsx(Skeleton, { loading: true, children: "User" }) }),
237
- /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "100px", children: /* @__PURE__ */ jsx(Skeleton, { children: "Role" }) }),
238
- /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "140px", children: /* @__PURE__ */ jsx(Skeleton, { children: "Last active" }) }),
317
+ /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "260px", children: /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(
318
+ Translation,
319
+ {
320
+ defaultMessage: "User",
321
+ id: "BBh86k",
322
+ description: "Column header for user information in the users table"
323
+ }
324
+ ) }) }),
325
+ /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "100px", children: /* @__PURE__ */ jsx(Skeleton, { children: /* @__PURE__ */ jsx(
326
+ Translation,
327
+ {
328
+ defaultMessage: "Role",
329
+ id: "FK7mP4",
330
+ description: "Column header for user role"
331
+ }
332
+ ) }) }),
333
+ /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "140px", children: /* @__PURE__ */ jsx(Skeleton, { children: /* @__PURE__ */ jsx(
334
+ Translation,
335
+ {
336
+ defaultMessage: "Last active",
337
+ id: "oOwLGt",
338
+ description: "Column header showing when users were last active"
339
+ }
340
+ ) }) }),
239
341
  /* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "28px" })
240
342
  ] }) }),
241
343
  /* @__PURE__ */ jsx(Table.Body, { children: Array.from({ length: USER_ROW_LIMIT }, (_, index) => /* @__PURE__ */ jsxs(Table.Row, { align: "center", children: [
@@ -260,8 +362,22 @@ const UsersManagementLoading = (props) => {
260
362
  ] }, index)) })
261
363
  ] }),
262
364
  /* @__PURE__ */ jsxs(Flex, { gap: "2", justify: "end", children: [
263
- /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "1", children: "Previous" }) }),
264
- /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "1", children: "Next" }) })
365
+ /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Button, { disabled: true, variant: "secondary", size: "1", children: /* @__PURE__ */ jsx(
366
+ Translation,
367
+ {
368
+ defaultMessage: "Previous",
369
+ id: "910Q6b",
370
+ description: "Button text to navigate to the previous page of users"
371
+ }
372
+ ) }) }),
373
+ /* @__PURE__ */ jsx(Skeleton, { loading: true, children: /* @__PURE__ */ jsx(Button, { disabled: true, variant: "secondary", size: "1", children: /* @__PURE__ */ jsx(
374
+ Translation,
375
+ {
376
+ defaultMessage: "Next",
377
+ id: "UlAY08",
378
+ description: "Button text to navigate to the next page of users"
379
+ }
380
+ ) }) })
265
381
  ] })
266
382
  ]
267
383
  }
@@ -282,24 +398,73 @@ const UsersManagementError = ({
282
398
  };
283
399
  function UserBadge({ user }) {
284
400
  if (user.isLoggedInUser) {
285
- return /* @__PURE__ */ jsx(Badge, { color: "gray", style: { userSelect: "none" }, children: "You" });
401
+ return /* @__PURE__ */ jsx(Badge, { color: "gray", style: { userSelect: "none" }, children: /* @__PURE__ */ jsx(
402
+ Translation,
403
+ {
404
+ defaultMessage: "You",
405
+ id: "ER1Vmv",
406
+ description: "Badge indicating the current logged-in user"
407
+ }
408
+ ) });
286
409
  }
287
410
  if (user.status === "Invited") {
288
411
  return /* @__PURE__ */ jsxs(Badge, { color: "amber", style: { userSelect: "none" }, children: [
289
- /* @__PURE__ */ jsx(VisuallyHidden, { children: "Status: " }),
290
- "Invited"
412
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
413
+ Translation,
414
+ {
415
+ defaultMessage: "Status: ",
416
+ id: "E2o/+H",
417
+ description: "Prefix for status indicator in screen reader"
418
+ }
419
+ ) }),
420
+ /* @__PURE__ */ jsx(
421
+ Translation,
422
+ {
423
+ defaultMessage: "Invited",
424
+ id: "byIkUu",
425
+ description: "Badge status indicating user has been invited but not yet accepted"
426
+ }
427
+ )
291
428
  ] });
292
429
  }
293
430
  if (user.status === "InviteExpired") {
294
431
  return /* @__PURE__ */ jsxs(Badge, { color: "red", style: { userSelect: "none" }, children: [
295
- /* @__PURE__ */ jsx(VisuallyHidden, { children: "Status: Invite " }),
296
- "Expired"
432
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
433
+ Translation,
434
+ {
435
+ defaultMessage: "Status: Invite ",
436
+ id: "BWvbwY",
437
+ description: "Prefix for invite status indicator in screen reader"
438
+ }
439
+ ) }),
440
+ /* @__PURE__ */ jsx(
441
+ Translation,
442
+ {
443
+ defaultMessage: "Expired",
444
+ id: "+0sQaN",
445
+ description: "Badge status indicating user invitation has expired"
446
+ }
447
+ )
297
448
  ] });
298
449
  }
299
450
  if (user.status === "InviteRevoked") {
300
451
  return /* @__PURE__ */ jsxs(Badge, { color: "red", style: { userSelect: "none" }, children: [
301
- /* @__PURE__ */ jsx(VisuallyHidden, { children: "Status: Invite " }),
302
- "Revoked"
452
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
453
+ Translation,
454
+ {
455
+ defaultMessage: "Status: Invite ",
456
+ id: "BWvbwY",
457
+ description: "Prefix for invite status indicator in screen reader"
458
+ }
459
+ ) }),
460
+ /* @__PURE__ */ jsx(
461
+ Translation,
462
+ {
463
+ defaultMessage: "Revoked",
464
+ id: "NNBv+r",
465
+ description: "Badge status indicating user invitation has been revoked"
466
+ }
467
+ )
303
468
  ] });
304
469
  }
305
470
  return null;
@@ -307,7 +472,21 @@ function UserBadge({ user }) {
307
472
  function LastActive(props) {
308
473
  if (!props.user.lastActivityAt) {
309
474
  return /* @__PURE__ */ jsxs(Fragment, { children: [
310
- /* @__PURE__ */ jsx(VisuallyHidden, { children: props.user.status === "Active" ? "Never" : "Not active" }),
475
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: props.user.status === "Active" ? /* @__PURE__ */ jsx(
476
+ Translation,
477
+ {
478
+ defaultMessage: "Never",
479
+ id: "0duvF4",
480
+ description: "Screen reader text indicating user has never been active"
481
+ }
482
+ ) : /* @__PURE__ */ jsx(
483
+ Translation,
484
+ {
485
+ defaultMessage: "Not active",
486
+ id: "hd2+kk",
487
+ description: "Screen reader text indicating user is not active"
488
+ }
489
+ ) }),
311
490
  /* @__PURE__ */ jsx(Separator, {})
312
491
  ] });
313
492
  }
@@ -318,10 +497,11 @@ function LastActiveImpl({
318
497
  isHydrated,
319
498
  dim
320
499
  }) {
500
+ const locale = useLocale();
321
501
  const { lastActiveDateTime, lastActiveDisplay } = React.useMemo(() => {
322
502
  const defaultTimeZone = "America/Los_Angeles";
323
503
  const lastActiveDate = new Date(date);
324
- const lastActiveDateTime2 = lastActiveDate.toLocaleTimeString("en-US", {
504
+ const lastActiveDateTime2 = lastActiveDate.toLocaleTimeString(locale, {
325
505
  // hard-coded timezone before hydration to prevent server/client mismatch
326
506
  timeZone: isHydrated ? void 0 : defaultTimeZone,
327
507
  month: "long",
@@ -330,18 +510,28 @@ function LastActiveImpl({
330
510
  hour: "numeric",
331
511
  minute: "numeric"
332
512
  });
333
- const lastActiveDisplay2 = isHydrated ? getComparativeReadableDate(/* @__PURE__ */ new Date(), lastActiveDate) : lastActiveDate.toLocaleDateString("en-US", {
513
+ const lastActiveDisplay2 = isHydrated ? getComparativeReadableDate(/* @__PURE__ */ new Date(), lastActiveDate, { locale }) : lastActiveDate.toLocaleDateString(locale, {
334
514
  // hard-coded timezone to prevent server/client mismatch
335
515
  timeZone: defaultTimeZone,
336
516
  month: "long",
337
517
  day: "numeric",
338
518
  year: "numeric"
339
519
  });
340
- return { lastActiveDateTime: lastActiveDateTime2, lastActiveDisplay: lastActiveDisplay2 };
341
- }, [isHydrated, date]);
520
+ return {
521
+ lastActiveDateTime: lastActiveDateTime2,
522
+ lastActiveDisplay: lastActiveDisplay2
523
+ };
524
+ }, [isHydrated, date, locale]);
342
525
  if (lastActiveDisplay === "Invalid Date") {
343
526
  return /* @__PURE__ */ jsxs(Fragment, { children: [
344
- /* @__PURE__ */ jsx(VisuallyHidden, { children: "Unknown" }),
527
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
528
+ Translation,
529
+ {
530
+ defaultMessage: "Unknown",
531
+ id: "UUigrK",
532
+ description: "Screen reader text indicating last active date is unknown"
533
+ }
534
+ ) }),
345
535
  /* @__PURE__ */ jsx(Separator, {})
346
536
  ] });
347
537
  }
@@ -402,15 +592,17 @@ const UsersManagementEmptyState = ({ isPending }) => {
402
592
  }
403
593
  if (searchQuery || isClearing) {
404
594
  return /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "center", py: "8", direction: "column", gap: "2", children: [
405
- /* @__PURE__ */ jsxs(Text, { size: "2", children: [
406
- "No users found for query",
407
- " ",
408
- /* @__PURE__ */ jsxs(Text, { weight: "medium", children: [
409
- "\u201C",
410
- isClearing ? lastSearchQuery : searchQuery,
411
- "\u201D"
412
- ] })
413
- ] }),
595
+ /* @__PURE__ */ jsx(Text, { size: "2", children: /* @__PURE__ */ jsx(
596
+ Translation,
597
+ {
598
+ defaultMessage: "No users found for query '{query}'",
599
+ id: "wrEZ8+",
600
+ description: "Message shown when no users match the search query",
601
+ values: {
602
+ query: isClearing ? lastSearchQuery : searchQuery
603
+ }
604
+ }
605
+ ) }),
414
606
  /* @__PURE__ */ jsx(
415
607
  Button,
416
608
  {
@@ -421,12 +613,26 @@ const UsersManagementEmptyState = ({ isPending }) => {
421
613
  clearSearch();
422
614
  },
423
615
  loading: isPending,
424
- children: "Clear search"
616
+ children: /* @__PURE__ */ jsx(
617
+ Translation,
618
+ {
619
+ defaultMessage: "Clear search",
620
+ id: "Xv3fVI",
621
+ description: "Button text to clear the current search query"
622
+ }
623
+ )
425
624
  }
426
625
  )
427
626
  ] });
428
627
  }
429
- return /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", py: "8", gap: "2", children: /* @__PURE__ */ jsx(Text, { size: "2", children: "No users found" }) });
628
+ return /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", py: "8", gap: "2", children: /* @__PURE__ */ jsx(Text, { size: "2", children: /* @__PURE__ */ jsx(
629
+ Translation,
630
+ {
631
+ defaultMessage: "No users found",
632
+ id: "MQ+LoA",
633
+ description: "Message shown when there are no users in the system"
634
+ }
635
+ ) }) });
430
636
  };
431
637
  function UserRolesCellContent({
432
638
  user,
@@ -435,19 +641,28 @@ function UserRolesCellContent({
435
641
  }) {
436
642
  if (!user.roles || user.roles.length === 0) {
437
643
  return /* @__PURE__ */ jsxs(Fragment, { children: [
438
- /* @__PURE__ */ jsx(VisuallyHidden, { children: "No roles assigned" }),
644
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
645
+ Translation,
646
+ {
647
+ defaultMessage: "No roles assigned",
648
+ id: "CVOVB0",
649
+ description: "Screen reader text indicating user has no roles assigned"
650
+ }
651
+ ) }),
439
652
  /* @__PURE__ */ jsx("span", { "aria-hidden": true, style: { userSelect: "none" }, children: "\u2013" })
440
653
  ] });
441
654
  }
442
655
  if (isMultipleRolesEnabled && user.roles.length > 1) {
443
- return /* @__PURE__ */ jsx(
444
- Tooltip,
656
+ const roleNames = user.roles?.map((role) => role.name).join(", ");
657
+ return /* @__PURE__ */ jsx(Tooltip, { content: roleNames, maxWidth: "250px", children: /* @__PURE__ */ jsx(TableCellText, { dim: dimText, children: /* @__PURE__ */ jsx(
658
+ Translation,
445
659
  {
446
- content: user.roles?.map((role) => role.name).join(", "),
447
- maxWidth: "250px",
448
- children: /* @__PURE__ */ jsx(TableCellText, { dim: dimText, children: pluralize("role", user.roles.length) })
660
+ defaultMessage: "{count} roles",
661
+ id: "lWAmRC",
662
+ description: "Shows the number of roles assigned to a user (plural)",
663
+ values: { count: user.roles.length }
449
664
  }
450
- );
665
+ ) }) });
451
666
  }
452
667
  return /* @__PURE__ */ jsx(TableCellText, { dim: dimText, children: user.roles?.[0]?.name });
453
668
  }