@burdenoff/microfe-auth 2026.624.3 → 2026.625.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 (36) hide show
  1. package/dist/auth/pages/AuditLogPage.js +73 -72
  2. package/dist/auth/pages/AuditLogPage.js.map +1 -1
  3. package/dist/auth/pages/EmailVerifyPage.js +58 -53
  4. package/dist/auth/pages/EmailVerifyPage.js.map +1 -1
  5. package/dist/auth/pages/LoginPage.js +222 -214
  6. package/dist/auth/pages/LoginPage.js.map +1 -1
  7. package/dist/auth/pages/MagicLinkPage.js +75 -68
  8. package/dist/auth/pages/MagicLinkPage.js.map +1 -1
  9. package/dist/auth/pages/MfaSetupPage.js +176 -138
  10. package/dist/auth/pages/MfaSetupPage.js.map +1 -1
  11. package/dist/auth/pages/MfaVerifyPage.js +60 -52
  12. package/dist/auth/pages/MfaVerifyPage.js.map +1 -1
  13. package/dist/auth/pages/PasswordResetPage.js +277 -262
  14. package/dist/auth/pages/PasswordResetPage.js.map +1 -1
  15. package/dist/auth/pages/ReactivatePage.js +54 -46
  16. package/dist/auth/pages/ReactivatePage.js.map +1 -1
  17. package/dist/auth/pages/RegisterPage.js +223 -213
  18. package/dist/auth/pages/RegisterPage.js.map +1 -1
  19. package/dist/auth/pages/SecurityPage.js +298 -267
  20. package/dist/auth/pages/SecurityPage.js.map +1 -1
  21. package/dist/auth/pages/SessionsPage.js +169 -160
  22. package/dist/auth/pages/SessionsPage.js.map +1 -1
  23. package/dist/auth/pages/SsoCallbackPage.js +53 -50
  24. package/dist/auth/pages/SsoCallbackPage.js.map +1 -1
  25. package/dist/auth/pages/SsoConfigPage.js +466 -444
  26. package/dist/auth/pages/SsoConfigPage.js.map +1 -1
  27. package/dist/auth/pages/SsoLoginPage.js +67 -59
  28. package/dist/auth/pages/SsoLoginPage.js.map +1 -1
  29. package/dist/auth/pages/UserDetailsPage.js +154 -144
  30. package/dist/auth/pages/UserDetailsPage.js.map +1 -1
  31. package/dist/auth/pages/UserProfilePage.js +211 -170
  32. package/dist/auth/pages/UserProfilePage.js.map +1 -1
  33. package/dist/auth/pages/UsersPage.js +572 -576
  34. package/dist/auth/pages/UsersPage.js.map +1 -1
  35. package/dist/microfe-auth.css +1 -1
  36. package/package.json +2 -2
@@ -4,281 +4,290 @@ import { useSessionOperations as r } from "../hooks/useSessionOperations.js";
4
4
  import { formatRelativeTime as i, parseBrowserName as a, parseDeviceName as o } from "../utils/formatters.js";
5
5
  import { ConfirmActionDialog as s } from "../components/ConfirmActionDialog.js";
6
6
  import { useMemo as c, useState as l } from "react";
7
- import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell";
8
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
7
+ import { useNavigate as u } from "react-router-dom";
8
+ import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell";
9
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
10
+ import { EmphasisPanel as m, IllustratedEmptyState as h, NextSteps as g, PagePurpose as _ } from "@burdenoff/fe-libs/ui";
9
11
  //#region src/auth/pages/SessionsPage.tsx
10
- function p() {
11
- let { t: p } = u(), m = (e, t) => {
12
- let n = p(e);
12
+ function v() {
13
+ let v = u(), { t: y } = d(), b = (e, t) => {
14
+ let n = y(e);
13
15
  return n === e ? t : n;
14
- }, h = e((e) => e.isAuthenticated), { activeSessions: g, revokeSession: _, revokeAllSessions: v, isLoading: y, page: b, totalPages: x, totalCount: S, hasMore: C, goToNextPage: w, goToPrevPage: T } = r({
16
+ }, x = e((e) => e.isAuthenticated), { activeSessions: S, revokeSession: C, revokeAllSessions: w, isLoading: T, page: E, totalPages: D, totalCount: O, hasMore: k, goToNextPage: A, goToPrevPage: j } = r({
15
17
  disableTokenInfoQuery: !0,
16
18
  pageSize: 20
17
- }), E = c(() => {
19
+ }), M = c(() => {
18
20
  let e = /* @__PURE__ */ new Map();
19
- for (let t of g) {
21
+ for (let t of S) {
20
22
  let n = o(t.userAgent ?? ""), r = e.get(n);
21
23
  (!r || new Date(t.lastActivityAt) > new Date(r.lastActivityAt)) && e.set(n, t);
22
24
  }
23
25
  return [...e.values()];
24
- }, [g]), [D, O] = l(null), [k, A] = l(null), [j, M] = l(null), [N, P] = l(!1), F = async (e) => {
26
+ }, [S]), [N, P] = l(null), [F, I] = l(null), [L, R] = l(null), [z, B] = l(!1), V = async (e) => {
25
27
  try {
26
- await _(e), A("Session revoked successfully"), M(null);
28
+ await C(e), I("Session revoked successfully"), R(null);
27
29
  } catch (e) {
28
- O(e instanceof Error ? e.message : "Failed to revoke session");
30
+ P(e instanceof Error ? e.message : "Failed to revoke session");
29
31
  }
30
32
  };
31
- return h ? /* @__PURE__ */ f("div", {
33
+ return x ? /* @__PURE__ */ p("div", {
32
34
  className: "max-w-4xl mx-auto p-6",
33
35
  children: [
34
- /* @__PURE__ */ d(s, {
35
- open: j !== null,
36
+ /* @__PURE__ */ f(s, {
37
+ open: L !== null,
36
38
  onOpenChange: (e) => {
37
- e || M(null);
39
+ e || R(null);
38
40
  },
39
41
  title: "Revoke this session?",
40
42
  description: "The selected device will be signed out immediately and will need to authenticate again.",
41
43
  confirmText: "Revoke session",
42
44
  variant: "danger",
43
- isPending: y,
45
+ isPending: T,
44
46
  onConfirm: async () => {
45
- j && await F(j);
47
+ L && await V(L);
46
48
  }
47
49
  }),
48
- /* @__PURE__ */ d(s, {
49
- open: N,
50
- onOpenChange: P,
50
+ /* @__PURE__ */ f(s, {
51
+ open: z,
52
+ onOpenChange: B,
51
53
  title: "Revoke every other session?",
52
54
  description: "All devices except your current one will be signed out immediately.",
53
55
  confirmText: "Revoke all other sessions",
54
56
  variant: "warning",
55
- isPending: y,
57
+ isPending: T,
56
58
  onConfirm: async () => {
57
59
  try {
58
- await v(), A("All other sessions have been revoked"), P(!1);
60
+ await w(), I("All other sessions have been revoked"), B(!1);
59
61
  } catch (e) {
60
- O(e instanceof Error ? e.message : "Failed to revoke all sessions");
62
+ P(e instanceof Error ? e.message : "Failed to revoke all sessions");
61
63
  }
62
64
  }
63
65
  }),
64
- /* @__PURE__ */ d("div", {
66
+ /* @__PURE__ */ f("div", {
65
67
  "aria-live": "polite",
66
68
  "aria-atomic": "true",
67
69
  className: "sr-only",
68
- children: k
70
+ children: F
69
71
  }),
70
- /* @__PURE__ */ d("div", {
72
+ /* @__PURE__ */ f("div", {
71
73
  role: "alert",
72
74
  "aria-live": "assertive",
73
75
  "aria-atomic": "true",
74
76
  className: "sr-only",
75
- children: D
77
+ children: N
76
78
  }),
77
- /* @__PURE__ */ f("div", {
78
- className: "flex items-center justify-between mb-8",
79
- children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("h1", {
79
+ /* @__PURE__ */ p("div", {
80
+ className: "flex items-center justify-between mb-4",
81
+ children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
80
82
  className: "text-3xl font-semibold text-text-primary",
81
- children: m("auth.sessions.title", "Active Sessions")
82
- }), /* @__PURE__ */ f("p", {
83
+ children: b("auth.sessions.title", "Active Sessions")
84
+ }), /* @__PURE__ */ p("p", {
83
85
  className: "text-text-secondary mt-2",
84
86
  children: [
85
- m("auth.sessions.sessionCount", "You have"),
87
+ b("auth.sessions.sessionCount", "You have"),
86
88
  " ",
87
- S,
89
+ O,
88
90
  " ",
89
- m(S === 1 ? "auth.sessions.sessionsSingular" : "auth.sessions.sessionsPlural", S === 1 ? "active session" : "active sessions")
91
+ b(O === 1 ? "auth.sessions.sessionsSingular" : "auth.sessions.sessionsPlural", O === 1 ? "active session" : "active sessions")
90
92
  ]
91
- })] }), /* @__PURE__ */ d("div", {
92
- className: "flex items-center gap-3",
93
- children: S > 1 && /* @__PURE__ */ d("button", {
93
+ })] }), /* @__PURE__ */ f("div", { className: "flex items-center gap-3" })]
94
+ }),
95
+ /* @__PURE__ */ f(_, {
96
+ className: "mb-6",
97
+ children: b("auth.sessions.purpose", "This is every device currently signed in to your account. Recognise them all? If a device looks unfamiliar or you've lost it, revoke its session to sign it out immediately.")
98
+ }),
99
+ /* @__PURE__ */ f(m, {
100
+ className: "mb-8",
101
+ children: /* @__PURE__ */ p("div", {
102
+ className: "flex items-center justify-between gap-4",
103
+ children: [/* @__PURE__ */ p("div", { children: [
104
+ /* @__PURE__ */ f("p", {
105
+ className: "text-sm font-medium text-text-secondary",
106
+ children: b("auth.sessions.summaryLabel", "Devices signed in")
107
+ }),
108
+ /* @__PURE__ */ f("p", {
109
+ className: "mt-1 text-3xl font-semibold text-text-primary",
110
+ children: O
111
+ }),
112
+ /* @__PURE__ */ f("p", {
113
+ className: "mt-1 text-sm text-text-secondary",
114
+ children: b("auth.sessions.summaryHint", "Keep this list trimmed to devices you trust.")
115
+ })
116
+ ] }), O > 1 && /* @__PURE__ */ f("button", {
94
117
  type: "button",
95
- onClick: () => P(!0),
96
- className: "px-4 py-2.5 rounded-xl border border-status-error-border text-status-error-text font-medium hover:bg-status-error-bg-subtle transition-colors duration-200",
97
- children: m("auth.sessions.revokeAll", "Revoke All Sessions")
98
- })
99
- })]
118
+ onClick: () => B(!0),
119
+ className: "shrink-0 px-4 py-2.5 rounded-xl border border-status-error-border text-status-error-text font-medium hover:bg-status-error-bg-subtle transition-colors duration-200",
120
+ children: b("auth.sessions.revokeAllOthers", "Revoke all other sessions")
121
+ })]
122
+ })
100
123
  }),
101
- k && /* @__PURE__ */ f("output", {
124
+ F && /* @__PURE__ */ p("output", {
102
125
  className: "block mb-6 p-4 rounded-xl bg-status-success-bg-subtle border border-status-success-border",
103
- children: [/* @__PURE__ */ d("p", {
126
+ children: [/* @__PURE__ */ f("p", {
104
127
  className: "text-status-success-text",
105
- children: k
106
- }), /* @__PURE__ */ d("button", {
128
+ children: F
129
+ }), /* @__PURE__ */ f("button", {
107
130
  type: "button",
108
- onClick: () => A(null),
131
+ onClick: () => I(null),
109
132
  className: "mt-2 text-sm text-status-success-text hover:underline transition-colors duration-200",
110
133
  children: "Dismiss"
111
134
  })]
112
135
  }),
113
- D && /* @__PURE__ */ f("div", {
136
+ N && /* @__PURE__ */ p("div", {
114
137
  role: "alert",
115
138
  className: "mb-6 flex items-start gap-3 p-4 rounded-xl bg-status-error-bg-subtle border border-status-error-border",
116
- children: [/* @__PURE__ */ d(t, {
139
+ children: [/* @__PURE__ */ f(t, {
117
140
  className: "size-5 text-status-error-text flex-shrink-0 mt-0.5",
118
141
  "aria-hidden": "true"
119
- }), /* @__PURE__ */ f("div", {
142
+ }), /* @__PURE__ */ p("div", {
120
143
  className: "flex-1",
121
- children: [/* @__PURE__ */ d("p", {
144
+ children: [/* @__PURE__ */ f("p", {
122
145
  className: "text-sm text-status-error-text",
123
- children: D
124
- }), /* @__PURE__ */ d("button", {
146
+ children: N
147
+ }), /* @__PURE__ */ f("button", {
125
148
  type: "button",
126
- onClick: () => O(null),
149
+ onClick: () => P(null),
127
150
  className: "mt-2 text-sm text-status-error-text hover:underline transition-colors duration-200",
128
151
  children: "Dismiss"
129
152
  })]
130
153
  })]
131
154
  }),
132
- y ? /* @__PURE__ */ f("div", {
155
+ T ? /* @__PURE__ */ p("div", {
133
156
  "aria-live": "polite",
134
157
  "aria-busy": "true",
135
158
  className: "flex items-center justify-center py-12",
136
- children: [/* @__PURE__ */ d(n, {
159
+ children: [/* @__PURE__ */ f(n, {
137
160
  className: "size-8 text-text-link animate-spin",
138
161
  "aria-hidden": "true"
139
- }), /* @__PURE__ */ d("span", {
162
+ }), /* @__PURE__ */ f("span", {
140
163
  className: "ml-3 text-text-secondary",
141
- children: m("auth.sessions.loading", "Loading sessions...")
164
+ children: b("auth.sessions.loading", "Loading sessions...")
142
165
  })]
143
- }) : E.length === 0 ? /* @__PURE__ */ f("output", {
144
- className: "block text-center py-16 border-2 border-dashed border-border-subtle rounded-xl",
145
- children: [/* @__PURE__ */ d("div", {
146
- className: "size-16 mx-auto mb-4 rounded-full bg-bg-sunken flex items-center justify-center",
147
- children: /* @__PURE__ */ d("svg", {
148
- className: "size-8 text-text-tertiary",
149
- fill: "none",
150
- viewBox: "0 0 24 24",
151
- stroke: "currentColor",
152
- "aria-hidden": "true",
153
- children: /* @__PURE__ */ d("path", {
154
- strokeLinecap: "round",
155
- strokeLinejoin: "round",
156
- strokeWidth: 1.5,
157
- d: "M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
158
- })
159
- })
160
- }), /* @__PURE__ */ d("p", {
161
- className: "text-text-secondary",
162
- children: m("auth.sessions.noSessions", "No active sessions found")
163
- })]
164
- }) : /* @__PURE__ */ d("div", {
166
+ }) : M.length === 0 ? /* @__PURE__ */ f("output", {
167
+ className: "block",
168
+ children: /* @__PURE__ */ f(h, {
169
+ illustration: "empty-sessions",
170
+ title: b("auth.sessions.noSessions", "No active sessions found"),
171
+ description: b("auth.sessions.noSessionsDesc", "When you sign in on a device it will appear here so you can review and manage it.")
172
+ })
173
+ }) : /* @__PURE__ */ f("div", {
165
174
  className: "space-y-4",
166
175
  "aria-live": "polite",
167
- "aria-busy": y,
168
- children: E.map((e) => /* @__PURE__ */ d("div", {
176
+ "aria-busy": T,
177
+ children: M.map((e) => /* @__PURE__ */ f("div", {
169
178
  className: "p-6 rounded-xl border border-border-default bg-bg-surface shadow-sm hover:shadow-md transition-shadow",
170
- children: /* @__PURE__ */ f("div", {
179
+ children: /* @__PURE__ */ p("div", {
171
180
  className: "flex items-start justify-between",
172
- children: [/* @__PURE__ */ f("div", {
181
+ children: [/* @__PURE__ */ p("div", {
173
182
  className: "flex items-start gap-4",
174
- children: [/* @__PURE__ */ d("div", {
183
+ children: [/* @__PURE__ */ f("div", {
175
184
  className: "size-12 rounded-xl bg-bg-accent flex items-center justify-center flex-shrink-0",
176
185
  "aria-hidden": "true",
177
- children: /* @__PURE__ */ d("svg", {
186
+ children: /* @__PURE__ */ f("svg", {
178
187
  className: "size-6 text-text-link",
179
188
  fill: "none",
180
189
  viewBox: "0 0 24 24",
181
190
  stroke: "currentColor",
182
- children: /* @__PURE__ */ d("path", {
191
+ children: /* @__PURE__ */ f("path", {
183
192
  strokeLinecap: "round",
184
193
  strokeLinejoin: "round",
185
194
  strokeWidth: 1.5,
186
195
  d: "M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
187
196
  })
188
197
  })
189
- }), /* @__PURE__ */ f("div", {
198
+ }), /* @__PURE__ */ p("div", {
190
199
  className: "flex-1",
191
200
  children: [
192
- /* @__PURE__ */ f("div", {
201
+ /* @__PURE__ */ p("div", {
193
202
  className: "flex items-center gap-3 mb-1",
194
- children: [/* @__PURE__ */ d("h3", {
203
+ children: [/* @__PURE__ */ f("h3", {
195
204
  className: "text-lg font-semibold text-text-primary",
196
- children: e.isCurrent && o(e.userAgent) === "Unknown Device" ? m("auth.sessions.thisDevice", "This Device") : o(e.userAgent)
197
- }), e.isCurrent && /* @__PURE__ */ d("output", {
205
+ children: e.isCurrent && o(e.userAgent) === "Unknown Device" ? b("auth.sessions.thisDevice", "This Device") : o(e.userAgent)
206
+ }), e.isCurrent && /* @__PURE__ */ f("output", {
198
207
  className: "px-2.5 py-1 rounded-full bg-status-success-bg-subtle text-status-success-text text-xs font-medium",
199
- children: m("auth.sessions.currentSession", "Current Session")
208
+ children: b("auth.sessions.currentSession", "Current Session")
200
209
  })]
201
210
  }),
202
- /* @__PURE__ */ d("p", {
211
+ /* @__PURE__ */ f("p", {
203
212
  className: "text-sm text-text-secondary mb-2",
204
- children: a(e.userAgent) === "Unknown Browser" && e.isCurrent ? m("auth.sessions.currentBrowser", "Current Browser") : a(e.userAgent)
213
+ children: a(e.userAgent) === "Unknown Browser" && e.isCurrent ? b("auth.sessions.currentBrowser", "Current Browser") : a(e.userAgent)
205
214
  }),
206
- /* @__PURE__ */ f("dl", {
215
+ /* @__PURE__ */ p("dl", {
207
216
  className: "flex flex-wrap gap-4 text-sm text-text-secondary",
208
217
  children: [
209
- e.ipAddress && e.ipAddress !== "unknown" && /* @__PURE__ */ f("div", {
218
+ e.ipAddress && e.ipAddress !== "unknown" && /* @__PURE__ */ p("div", {
210
219
  className: "flex items-center gap-1.5",
211
220
  children: [
212
- /* @__PURE__ */ d("svg", {
221
+ /* @__PURE__ */ f("svg", {
213
222
  className: "size-4",
214
223
  fill: "none",
215
224
  viewBox: "0 0 24 24",
216
225
  stroke: "currentColor",
217
226
  "aria-hidden": "true",
218
- children: /* @__PURE__ */ d("path", {
227
+ children: /* @__PURE__ */ f("path", {
219
228
  strokeLinecap: "round",
220
229
  strokeLinejoin: "round",
221
230
  strokeWidth: 2,
222
231
  d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"
223
232
  })
224
233
  }),
225
- /* @__PURE__ */ d("dt", {
234
+ /* @__PURE__ */ f("dt", {
226
235
  className: "sr-only",
227
236
  children: "IP address"
228
237
  }),
229
- /* @__PURE__ */ d("dd", { children: e.ipAddress })
238
+ /* @__PURE__ */ f("dd", { children: e.ipAddress })
230
239
  ]
231
240
  }),
232
- e.location && /* @__PURE__ */ f("div", {
241
+ e.location && /* @__PURE__ */ p("div", {
233
242
  className: "flex items-center gap-1.5",
234
243
  children: [
235
- /* @__PURE__ */ f("svg", {
244
+ /* @__PURE__ */ p("svg", {
236
245
  className: "size-4",
237
246
  fill: "none",
238
247
  viewBox: "0 0 24 24",
239
248
  stroke: "currentColor",
240
249
  "aria-hidden": "true",
241
- children: [/* @__PURE__ */ d("path", {
250
+ children: [/* @__PURE__ */ f("path", {
242
251
  strokeLinecap: "round",
243
252
  strokeLinejoin: "round",
244
253
  strokeWidth: 2,
245
254
  d: "M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
246
- }), /* @__PURE__ */ d("path", {
255
+ }), /* @__PURE__ */ f("path", {
247
256
  strokeLinecap: "round",
248
257
  strokeLinejoin: "round",
249
258
  strokeWidth: 2,
250
259
  d: "M15 11a3 3 0 11-6 0 3 3 0 016 0z"
251
260
  })]
252
261
  }),
253
- /* @__PURE__ */ d("dt", {
262
+ /* @__PURE__ */ f("dt", {
254
263
  className: "sr-only",
255
264
  children: "Location"
256
265
  }),
257
- /* @__PURE__ */ d("dd", { children: e.location })
266
+ /* @__PURE__ */ f("dd", { children: e.location })
258
267
  ]
259
268
  }),
260
- /* @__PURE__ */ f("div", {
269
+ /* @__PURE__ */ p("div", {
261
270
  className: "flex items-center gap-1.5",
262
271
  children: [
263
- /* @__PURE__ */ d("svg", {
272
+ /* @__PURE__ */ f("svg", {
264
273
  className: "size-4",
265
274
  fill: "none",
266
275
  viewBox: "0 0 24 24",
267
276
  stroke: "currentColor",
268
277
  "aria-hidden": "true",
269
- children: /* @__PURE__ */ d("path", {
278
+ children: /* @__PURE__ */ f("path", {
270
279
  strokeLinecap: "round",
271
280
  strokeLinejoin: "round",
272
281
  strokeWidth: 2,
273
282
  d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
274
283
  })
275
284
  }),
276
- /* @__PURE__ */ d("dt", {
285
+ /* @__PURE__ */ f("dt", {
277
286
  className: "sr-only",
278
287
  children: "Last active"
279
288
  }),
280
- /* @__PURE__ */ f("dd", { children: [
281
- m("auth.sessions.lastActive", "Last active"),
289
+ /* @__PURE__ */ p("dd", { children: [
290
+ b("auth.sessions.lastActive", "Last active"),
282
291
  " ",
283
292
  i(e.lastActivityAt)
284
293
  ] })
@@ -288,70 +297,70 @@ function p() {
288
297
  })
289
298
  ]
290
299
  })]
291
- }), !e.isCurrent && /* @__PURE__ */ d("button", {
300
+ }), !e.isCurrent && /* @__PURE__ */ f("button", {
292
301
  type: "button",
293
- onClick: () => M(e.id),
294
- "aria-label": `${m("auth.sessions.revoke", "Revoke")} ${o(e.userAgent)} session`,
302
+ onClick: () => R(e.id),
303
+ "aria-label": `${b("auth.sessions.revoke", "Revoke")} ${o(e.userAgent)} session`,
295
304
  className: "ml-4 px-4 py-2 rounded-lg text-sm font-medium border border-status-error-border text-status-error-text bg-bg-surface hover:bg-status-error-bg-subtle transition-colors duration-200",
296
- children: m("auth.sessions.revoke", "Revoke")
305
+ children: b("auth.sessions.revoke", "Revoke")
297
306
  })]
298
307
  })
299
308
  }, e.id))
300
309
  }),
301
- !y && x > 1 && /* @__PURE__ */ f("div", {
310
+ !T && D > 1 && /* @__PURE__ */ p("div", {
302
311
  className: "flex items-center justify-between mt-6 pt-4 border-t border-border-subtle",
303
312
  children: [
304
- /* @__PURE__ */ f("button", {
313
+ /* @__PURE__ */ p("button", {
305
314
  type: "button",
306
- onClick: T,
307
- disabled: b === 0,
315
+ onClick: j,
316
+ disabled: E === 0,
308
317
  className: "flex items-center gap-2 px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface hover:bg-bg-sunken disabled:opacity-40 disabled:cursor-not-allowed transition-colors font-medium text-sm",
309
- "aria-label": m("auth.sessions.prevPage", "Previous page"),
310
- children: [/* @__PURE__ */ d("svg", {
318
+ "aria-label": b("auth.sessions.prevPage", "Previous page"),
319
+ children: [/* @__PURE__ */ f("svg", {
311
320
  className: "size-4",
312
321
  fill: "none",
313
322
  viewBox: "0 0 24 24",
314
323
  stroke: "currentColor",
315
324
  "aria-hidden": "true",
316
- children: /* @__PURE__ */ d("path", {
325
+ children: /* @__PURE__ */ f("path", {
317
326
  strokeLinecap: "round",
318
327
  strokeLinejoin: "round",
319
328
  strokeWidth: 2,
320
329
  d: "M15 19l-7-7 7-7"
321
330
  })
322
- }), m("auth.sessions.prev", "Previous")]
331
+ }), b("auth.sessions.prev", "Previous")]
323
332
  }),
324
- /* @__PURE__ */ f("span", {
333
+ /* @__PURE__ */ p("span", {
325
334
  className: "text-sm text-text-secondary",
326
335
  children: [
327
- m("auth.sessions.pageOf", "Page"),
336
+ b("auth.sessions.pageOf", "Page"),
328
337
  " ",
329
- /* @__PURE__ */ d("span", {
338
+ /* @__PURE__ */ f("span", {
330
339
  className: "font-medium text-text-primary",
331
- children: b + 1
340
+ children: E + 1
332
341
  }),
333
342
  " ",
334
- m("auth.sessions.of", "of"),
343
+ b("auth.sessions.of", "of"),
335
344
  " ",
336
- /* @__PURE__ */ d("span", {
345
+ /* @__PURE__ */ f("span", {
337
346
  className: "font-medium text-text-primary",
338
- children: x
347
+ children: D
339
348
  })
340
349
  ]
341
350
  }),
342
- /* @__PURE__ */ f("button", {
351
+ /* @__PURE__ */ p("button", {
343
352
  type: "button",
344
- onClick: w,
345
- disabled: !C,
353
+ onClick: A,
354
+ disabled: !k,
346
355
  className: "flex items-center gap-2 px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface hover:bg-bg-sunken disabled:opacity-40 disabled:cursor-not-allowed transition-colors font-medium text-sm",
347
- "aria-label": m("auth.sessions.nextPage", "Next page"),
348
- children: [m("auth.sessions.next", "Next"), /* @__PURE__ */ d("svg", {
356
+ "aria-label": b("auth.sessions.nextPage", "Next page"),
357
+ children: [b("auth.sessions.next", "Next"), /* @__PURE__ */ f("svg", {
349
358
  className: "size-4",
350
359
  fill: "none",
351
360
  viewBox: "0 0 24 24",
352
361
  stroke: "currentColor",
353
362
  "aria-hidden": "true",
354
- children: /* @__PURE__ */ d("path", {
363
+ children: /* @__PURE__ */ f("path", {
355
364
  strokeLinecap: "round",
356
365
  strokeLinejoin: "round",
357
366
  strokeWidth: 2,
@@ -360,33 +369,33 @@ function p() {
360
369
  })]
361
370
  })
362
371
  ]
372
+ }),
373
+ !T && M.length > 0 && /* @__PURE__ */ f(g, {
374
+ className: "mt-8",
375
+ storageKey: "auth-sessions",
376
+ steps: [{
377
+ id: "enable-mfa",
378
+ label: b("auth.sessions.nextEnableMfa", "Turn on two-factor authentication"),
379
+ description: b("auth.sessions.nextEnableMfaDesc", "Add a second sign-in step so a stolen password isn't enough."),
380
+ onClick: () => v("/auth/mfa")
381
+ }, {
382
+ id: "security-center",
383
+ label: b("auth.sessions.nextSecurityCenter", "Open the Security Center"),
384
+ description: b("auth.sessions.nextSecurityCenterDesc", "Review your password and overall account protection."),
385
+ onClick: () => v("/auth/security")
386
+ }]
363
387
  })
364
388
  ]
365
- }) : /* @__PURE__ */ d("div", {
389
+ }) : /* @__PURE__ */ f("div", {
366
390
  className: "max-w-4xl mx-auto p-6",
367
- children: /* @__PURE__ */ f("div", {
368
- className: "text-center py-16 border-2 border-dashed border-border-subtle rounded-xl",
369
- children: [
370
- /* @__PURE__ */ d("div", {
371
- className: "size-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center",
372
- children: /* @__PURE__ */ d(t, {
373
- className: "size-8 text-status-warning-text",
374
- "aria-hidden": "true"
375
- })
376
- }),
377
- /* @__PURE__ */ d("h2", {
378
- className: "text-xl font-semibold text-text-primary mb-2",
379
- children: m("auth.sessions.authRequired", "Authentication Required")
380
- }),
381
- /* @__PURE__ */ d("p", {
382
- className: "text-text-secondary",
383
- children: m("auth.sessions.signInToView", "Please sign in to view your active sessions")
384
- })
385
- ]
391
+ children: /* @__PURE__ */ f(h, {
392
+ illustration: "empty-generic",
393
+ title: b("auth.sessions.authRequired", "Authentication Required"),
394
+ description: b("auth.sessions.signInToView", "Please sign in to view your active sessions")
386
395
  })
387
396
  });
388
397
  }
389
398
  //#endregion
390
- export { p as SessionsPage };
399
+ export { v as SessionsPage };
391
400
 
392
401
  //# sourceMappingURL=SessionsPage.js.map