@petrarca/sonnet-shell 0.6.0 → 0.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.
@@ -1,6 +1,8 @@
1
1
  // src/auth/Login.tsx
2
2
  import { useState as useState2, useEffect, useCallback as useCallback2 } from "react";
3
3
  import { useNavigate, useLocation } from "react-router-dom";
4
+ import { Alert as Alert2 } from "@petrarca/sonnet-ui";
5
+ import { Button as Button2 } from "@petrarca/sonnet-ui";
4
6
  import { Input } from "@petrarca/sonnet-ui";
5
7
  import { Label } from "@petrarca/sonnet-ui";
6
8
  import { Spinner } from "@petrarca/sonnet-ui";
@@ -10,44 +12,55 @@ import { useState, useCallback } from "react";
10
12
  import { Check } from "lucide-react";
11
13
  import { Button } from "@petrarca/sonnet-ui";
12
14
  import { Alert } from "@petrarca/sonnet-ui";
13
- import { jsx, jsxs } from "react/jsx-runtime";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
16
  function OrgSelection({
15
17
  orgs,
16
18
  isLoading,
17
19
  error,
18
- onSelect
20
+ onSelect,
21
+ emptyAction
19
22
  }) {
20
23
  const [selectedId, setSelectedId] = useState(null);
24
+ const isEmpty = orgs.length === 0;
21
25
  const handleContinue = useCallback(() => {
22
26
  if (selectedId) onSelect(selectedId);
23
27
  }, [selectedId, onSelect]);
24
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen bg-slate-50 px-4", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm bg-white rounded-xl shadow-sm border border-slate-200 p-8", children: [
28
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen bg-muted px-4", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm bg-card rounded-lg shadow-sm border border-border p-8", children: [
25
29
  /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
26
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-slate-900 text-center", children: "Select organization" }),
27
- /* @__PURE__ */ jsx("p", { className: "text-center text-sm text-slate-500 mt-1", children: "Choose the organization you want to work in." })
30
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-foreground text-center", children: "Select organization" }),
31
+ /* @__PURE__ */ jsx("p", { className: "text-center text-sm text-muted-foreground mt-1", children: isEmpty ? "No organizations assigned to your account." : "Choose the organization you want to work in." })
28
32
  ] }),
29
- error ? /* @__PURE__ */ jsx(Alert, { className: "mb-4 border-red-200 bg-red-50 text-red-700 text-sm py-2.5 px-3", children: error }) : null,
30
- /* @__PURE__ */ jsx("div", { className: "space-y-2 mb-6 max-h-64 overflow-y-auto", children: orgs.map((org) => /* @__PURE__ */ jsxs(
31
- "button",
33
+ error ? /* @__PURE__ */ jsx(
34
+ Alert,
32
35
  {
33
- onClick: () => setSelectedId(org.id),
34
- className: `w-full flex items-center justify-between px-4 py-3 rounded-lg border text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-slate-400 ${selectedId === org.id ? "border-blue-500 bg-blue-50 text-blue-900" : "border-slate-200 hover:bg-slate-50 text-slate-700"}`,
35
- children: [
36
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: org.name }),
37
- selectedId === org.id ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-blue-500 shrink-0" }) : null
38
- ]
39
- },
40
- org.id
41
- )) }),
42
- /* @__PURE__ */ jsx(
43
- Button,
44
- {
45
- onClick: handleContinue,
46
- disabled: !selectedId || isLoading,
47
- className: "w-full h-10",
48
- children: isLoading ? "Loading..." : "Continue"
36
+ variant: "destructive",
37
+ className: "mb-4 bg-destructive/10 text-sm py-2.5 px-3",
38
+ children: error
49
39
  }
50
- )
40
+ ) : null,
41
+ isEmpty ? emptyAction ? /* @__PURE__ */ jsx("div", { className: "mt-2", children: emptyAction }) : null : /* @__PURE__ */ jsxs(Fragment, { children: [
42
+ /* @__PURE__ */ jsx("div", { className: "space-y-2 mb-6 max-h-64 overflow-y-auto", children: orgs.map((org) => /* @__PURE__ */ jsxs(
43
+ "button",
44
+ {
45
+ onClick: () => setSelectedId(org.id),
46
+ className: `w-full flex items-center justify-between px-4 py-3 rounded-md border text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${selectedId === org.id ? "border-primary bg-state-selected text-foreground" : "border-border hover:bg-state-hover text-foreground"}`,
47
+ children: [
48
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: org.name }),
49
+ selectedId === org.id ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-primary shrink-0" }) : null
50
+ ]
51
+ },
52
+ org.id
53
+ )) }),
54
+ /* @__PURE__ */ jsx(
55
+ Button,
56
+ {
57
+ onClick: handleContinue,
58
+ disabled: !selectedId || isLoading,
59
+ className: "w-full h-10",
60
+ children: isLoading ? "Loading..." : "Continue"
61
+ }
62
+ )
63
+ ] })
51
64
  ] }) });
52
65
  }
53
66
 
@@ -65,13 +78,15 @@ function useLoginFlow(props) {
65
78
  onSelectOrg,
66
79
  onClearError,
67
80
  onDiscover,
68
- onExternalLogin
81
+ onExternalLogin,
82
+ requiresOrgSelection = true
69
83
  } = props;
70
84
  const navigate = useNavigate();
71
85
  const location = useLocation();
72
86
  const locationState = location.state;
73
87
  const identifierFirst = Boolean(onDiscover);
74
- const initial = locationState?.step ?? (identifierFirst ? "identifier" : "credentials");
88
+ const requestedStep = requiresOrgSelection && locationState?.step ? locationState.step : void 0;
89
+ const initial = requestedStep ?? (identifierFirst ? "identifier" : "credentials");
75
90
  const [redirectTo] = useState2(() => locationState?.from?.pathname ?? "/");
76
91
  const [step, setStep] = useState2(initial);
77
92
  const [identifier, setIdentifier] = useState2("");
@@ -81,10 +96,17 @@ function useLoginFlow(props) {
81
96
  const [isRedirecting, setIsRedirecting] = useState2(false);
82
97
  const [orgError, setOrgError] = useState2(null);
83
98
  useEffect(() => {
84
- if (isAuthenticated && activeTenantId)
99
+ if (isAuthenticated && (activeTenantId || !requiresOrgSelection))
85
100
  navigate(redirectTo, { replace: true });
86
- }, [isAuthenticated, activeTenantId, navigate, redirectTo]);
101
+ }, [
102
+ isAuthenticated,
103
+ activeTenantId,
104
+ requiresOrgSelection,
105
+ navigate,
106
+ redirectTo
107
+ ]);
87
108
  useEffect(() => {
109
+ if (!requiresOrgSelection) return;
88
110
  if (!isAuthenticated || !orgs || activeTenantId) return;
89
111
  if (orgs.length === 1) {
90
112
  onSelectOrg(orgs[0].id).catch((err) => {
@@ -96,7 +118,13 @@ function useLoginFlow(props) {
96
118
  } else if (orgs.length > 1) {
97
119
  setStep("org-selection");
98
120
  }
99
- }, [isAuthenticated, orgs, activeTenantId, onSelectOrg]);
121
+ }, [
122
+ requiresOrgSelection,
123
+ isAuthenticated,
124
+ orgs,
125
+ activeTenantId,
126
+ onSelectOrg
127
+ ]);
100
128
  useEffect(() => {
101
129
  if (config?.ui.direct_redirect)
102
130
  window.location.href = config.ui.direct_redirect;
@@ -178,19 +206,47 @@ function useLoginFlow(props) {
178
206
  goBack
179
207
  };
180
208
  }
209
+ function resolveScreen(args) {
210
+ if (args.directRedirect || args.isRedirecting) return "redirecting";
211
+ const canShowOrgPicker = args.requiresOrgSelection && args.step === "org-selection" && args.orgsLoaded;
212
+ if (args.isAuthenticated && !args.activeTenantId && !canShowOrgPicker)
213
+ return "redirecting";
214
+ return canShowOrgPicker ? "org-selection" : "form";
215
+ }
181
216
  function Login(props) {
182
- const { config, isLoading, isDiscovering, error, orgs, appName, logoUrl } = props;
217
+ const {
218
+ config,
219
+ isAuthenticated,
220
+ activeTenantId,
221
+ isLoading,
222
+ isDiscovering,
223
+ error,
224
+ orgs,
225
+ appName,
226
+ logoUrl,
227
+ orgEmptyAction,
228
+ requiresOrgSelection = true
229
+ } = props;
183
230
  const flow = useLoginFlow(props);
184
- if (config?.ui.direct_redirect || flow.isRedirecting)
185
- return /* @__PURE__ */ jsx2(RedirectingMessage, {});
186
- if (flow.step === "org-selection" && orgs) {
231
+ const screen = resolveScreen({
232
+ isRedirecting: flow.isRedirecting,
233
+ directRedirect: Boolean(config?.ui.direct_redirect),
234
+ isAuthenticated,
235
+ activeTenantId,
236
+ requiresOrgSelection,
237
+ step: flow.step,
238
+ orgsLoaded: orgs !== null
239
+ });
240
+ if (screen === "redirecting") return /* @__PURE__ */ jsx2(RedirectingMessage, {});
241
+ if (screen === "org-selection") {
187
242
  return /* @__PURE__ */ jsx2(
188
243
  OrgSelection,
189
244
  {
190
- orgs,
245
+ orgs: orgs ?? [],
191
246
  isLoading,
192
247
  error: flow.orgError,
193
- onSelect: flow.handleOrgSelect
248
+ onSelect: flow.handleOrgSelect,
249
+ emptyAction: orgEmptyAction
194
250
  }
195
251
  );
196
252
  }
@@ -242,26 +298,17 @@ function Login(props) {
242
298
  ] }) });
243
299
  }
244
300
  function PageShell({ children }) {
245
- return /* @__PURE__ */ jsx2("div", { className: "flex flex-col items-center justify-center min-h-screen bg-gray-100 px-4", children });
301
+ return /* @__PURE__ */ jsx2("div", { className: "flex flex-col items-center justify-center min-h-screen bg-muted px-4", children });
246
302
  }
247
303
  function Card({ children }) {
248
- return /* @__PURE__ */ jsx2(
249
- "div",
250
- {
251
- className: "w-full max-w-sm bg-white rounded-xl border border-gray-200 p-8",
252
- style: {
253
- boxShadow: "0 24px 48px rgba(15,23,42,0.10), 0 2px 4px rgba(15,23,42,0.06)"
254
- },
255
- children
256
- }
257
- );
304
+ return /* @__PURE__ */ jsx2("div", { className: "w-full max-w-sm bg-card rounded-lg border border-border shadow-sm p-8", children });
258
305
  }
259
306
  function BrandHeader({
260
307
  appName,
261
308
  logoUrl
262
309
  }) {
263
310
  if (!appName && !logoUrl) return null;
264
- return /* @__PURE__ */ jsx2("div", { className: "flex flex-col items-center mb-6", children: logoUrl ? /* @__PURE__ */ jsx2("img", { src: logoUrl, alt: appName ?? "Logo", className: "h-10 w-auto" }) : /* @__PURE__ */ jsx2("span", { className: "text-lg font-semibold text-slate-500 tracking-wide", children: appName }) });
311
+ return /* @__PURE__ */ jsx2("div", { className: "flex flex-col items-center mb-6", children: logoUrl ? /* @__PURE__ */ jsx2("img", { src: logoUrl, alt: appName ?? "Logo", className: "h-10 w-auto" }) : /* @__PURE__ */ jsx2("span", { className: "text-lg font-semibold text-muted-foreground tracking-wide", children: appName }) });
265
312
  }
266
313
  function IdentifierStep({
267
314
  appName,
@@ -275,19 +322,12 @@ function IdentifierStep({
275
322
  return /* @__PURE__ */ jsxs2("form", { onSubmit, className: "space-y-6", children: [
276
323
  /* @__PURE__ */ jsx2(BrandHeader, { appName, logoUrl }),
277
324
  /* @__PURE__ */ jsxs2("div", { className: "text-center", children: [
278
- /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold text-slate-900 leading-tight", children: "Welcome" }),
279
- /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-gray-500", children: "Enter your email or username to continue." })
325
+ /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold text-foreground leading-tight", children: "Welcome" }),
326
+ /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: "Enter your email or username to continue." })
280
327
  ] }),
281
328
  error ? /* @__PURE__ */ jsx2(ErrorAlert, { message: error }) : null,
282
329
  /* @__PURE__ */ jsxs2("div", { children: [
283
- /* @__PURE__ */ jsx2(
284
- Label,
285
- {
286
- htmlFor: "identifier",
287
- className: "block text-sm font-medium text-gray-700 mb-1.5",
288
- children: "Email or username"
289
- }
290
- ),
330
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "identifier", className: "mb-1.5 block", children: "Email or username" }),
291
331
  /* @__PURE__ */ jsx2(
292
332
  Input,
293
333
  {
@@ -298,8 +338,7 @@ function IdentifierStep({
298
338
  required: true,
299
339
  autoFocus: true,
300
340
  autoComplete: "email",
301
- placeholder: "you@company.com",
302
- className: "h-10 rounded-lg border-gray-300 text-sm placeholder:text-gray-400 focus:ring-indigo-500 focus:border-indigo-500"
341
+ placeholder: "you@company.com"
303
342
  }
304
343
  )
305
344
  ] }),
@@ -339,27 +378,20 @@ function AuthStep({
339
378
  {
340
379
  type: "button",
341
380
  onClick: onBack,
342
- className: "flex items-center gap-1.5 text-sm text-gray-500 hover:text-gray-700 transition-colors mb-4",
381
+ className: "flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors mb-4",
343
382
  children: [
344
383
  /* @__PURE__ */ jsx2("span", { "aria-hidden": true, children: "\u2190" }),
345
384
  " Back"
346
385
  ]
347
386
  }
348
387
  ),
349
- /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold text-slate-900 leading-tight", children: "Welcome back" }),
350
- /* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-gray-500", children: identifier })
388
+ /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold text-foreground leading-tight", children: "Welcome back" }),
389
+ /* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-muted-foreground", children: identifier })
351
390
  ] }),
352
391
  error ? /* @__PURE__ */ jsx2(ErrorAlert, { message: error }) : null,
353
392
  hasLocal ? /* @__PURE__ */ jsxs2("form", { onSubmit: onCredentialSubmit, className: "space-y-4", children: [
354
393
  /* @__PURE__ */ jsxs2("div", { children: [
355
- /* @__PURE__ */ jsx2(
356
- Label,
357
- {
358
- htmlFor: "password",
359
- className: "block text-sm font-medium text-gray-700 mb-1.5",
360
- children: "Password"
361
- }
362
- ),
394
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "password", className: "mb-1.5 block", children: "Password" }),
363
395
  /* @__PURE__ */ jsx2(
364
396
  Input,
365
397
  {
@@ -370,8 +402,7 @@ function AuthStep({
370
402
  required: true,
371
403
  autoFocus: true,
372
404
  autoComplete: "current-password",
373
- placeholder: "Enter your password",
374
- className: "h-10 rounded-lg border-gray-300 text-sm placeholder:text-gray-400 focus:ring-indigo-500 focus:border-indigo-500"
405
+ placeholder: "Enter your password"
375
406
  }
376
407
  )
377
408
  ] }),
@@ -395,7 +426,7 @@ function AuthStep({
395
426
  },
396
427
  p.name
397
428
  )) }) : null,
398
- providers.length === 0 ? /* @__PURE__ */ jsx2("p", { className: "text-sm text-gray-500 text-center py-2", children: "No login methods available." }) : null
429
+ providers.length === 0 ? /* @__PURE__ */ jsx2("p", { className: "text-sm text-muted-foreground text-center py-2", children: "No login methods available." }) : null
399
430
  ] });
400
431
  }
401
432
  function resolveOAuthProviders(config) {
@@ -418,18 +449,11 @@ function CredentialsStep({
418
449
  const hasBoth = config?.features.local_auth && oauthProviders.length > 0;
419
450
  return /* @__PURE__ */ jsxs2("div", { className: "space-y-6", children: [
420
451
  /* @__PURE__ */ jsx2(BrandHeader, { appName, logoUrl }),
421
- /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold text-slate-900 leading-tight text-center", children: "Welcome" }),
452
+ /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-semibold text-foreground leading-tight text-center", children: "Welcome" }),
422
453
  error ? /* @__PURE__ */ jsx2(ErrorAlert, { message: error }) : null,
423
454
  config?.features.local_auth ? /* @__PURE__ */ jsxs2("form", { onSubmit, className: "space-y-4", children: [
424
455
  /* @__PURE__ */ jsxs2("div", { children: [
425
- /* @__PURE__ */ jsx2(
426
- Label,
427
- {
428
- htmlFor: "identifier",
429
- className: "block text-sm font-medium text-gray-700 mb-1.5",
430
- children: "Email or username"
431
- }
432
- ),
456
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "identifier", className: "mb-1.5 block", children: "Email or username" }),
433
457
  /* @__PURE__ */ jsx2(
434
458
  Input,
435
459
  {
@@ -440,20 +464,12 @@ function CredentialsStep({
440
464
  required: true,
441
465
  autoFocus: true,
442
466
  autoComplete: "email",
443
- placeholder: "you@company.com",
444
- className: "h-10 rounded-lg border-gray-300 text-sm placeholder:text-gray-400 focus:ring-indigo-500 focus:border-indigo-500"
467
+ placeholder: "you@company.com"
445
468
  }
446
469
  )
447
470
  ] }),
448
471
  /* @__PURE__ */ jsxs2("div", { children: [
449
- /* @__PURE__ */ jsx2(
450
- Label,
451
- {
452
- htmlFor: "password",
453
- className: "block text-sm font-medium text-gray-700 mb-1.5",
454
- children: "Password"
455
- }
456
- ),
472
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "password", className: "mb-1.5 block", children: "Password" }),
457
473
  /* @__PURE__ */ jsx2(
458
474
  Input,
459
475
  {
@@ -463,8 +479,7 @@ function CredentialsStep({
463
479
  onChange: (e) => onPasswordChange(e.target.value),
464
480
  required: true,
465
481
  autoComplete: "current-password",
466
- placeholder: "Enter your password",
467
- className: "h-10 rounded-lg border-gray-300 text-sm placeholder:text-gray-400 focus:ring-indigo-500 focus:border-indigo-500"
482
+ placeholder: "Enter your password"
468
483
  }
469
484
  )
470
485
  ] }),
@@ -491,18 +506,25 @@ function CredentialsStep({
491
506
  ] });
492
507
  }
493
508
  function RedirectingMessage() {
494
- return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center min-h-screen bg-gray-100 gap-3 text-gray-500", children: [
509
+ return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center min-h-screen bg-muted gap-3 text-muted-foreground", children: [
495
510
  /* @__PURE__ */ jsx2(Spinner, { size: "lg" }),
496
511
  /* @__PURE__ */ jsx2("p", { className: "text-sm", children: "Redirecting..." })
497
512
  ] });
498
513
  }
499
514
  function ErrorAlert({ message }) {
500
- return /* @__PURE__ */ jsx2("div", { className: "rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 text-sm text-red-700", children: message });
515
+ return /* @__PURE__ */ jsx2(
516
+ Alert2,
517
+ {
518
+ variant: "destructive",
519
+ className: "bg-destructive/10 px-3 py-2.5 text-sm",
520
+ children: message
521
+ }
522
+ );
501
523
  }
502
524
  function Separator() {
503
525
  return /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
504
- /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx2("div", { className: "w-full border-t border-gray-200" }) }),
505
- /* @__PURE__ */ jsx2("div", { className: "relative flex justify-center text-xs", children: /* @__PURE__ */ jsx2("span", { className: "bg-white px-2 text-gray-400", children: "or continue with" }) })
526
+ /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx2("div", { className: "w-full border-t border-border" }) }),
527
+ /* @__PURE__ */ jsx2("div", { className: "relative flex justify-center text-xs", children: /* @__PURE__ */ jsx2("span", { className: "bg-card px-2 text-muted-foreground", children: "or continue with" }) })
506
528
  ] });
507
529
  }
508
530
  function PrimaryButton({
@@ -514,17 +536,15 @@ function PrimaryButton({
514
536
  onClick
515
537
  }) {
516
538
  return /* @__PURE__ */ jsxs2(
517
- "button",
539
+ Button2,
518
540
  {
519
541
  type,
542
+ size: "lg",
520
543
  disabled,
521
544
  onClick,
522
- className: "w-full inline-flex items-center justify-center rounded-full bg-indigo-600 px-5 py-2.5 text-sm font-semibold text-white shadow-md transition duration-150 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed",
523
- style: {
524
- boxShadow: disabled ? void 0 : "0 4px 14px rgba(79,70,229,0.30)"
525
- },
545
+ className: "w-full",
526
546
  children: [
527
- loading ? /* @__PURE__ */ jsx2(Spinner, { size: "sm", className: "mr-2" }) : null,
547
+ loading ? /* @__PURE__ */ jsx2(Spinner, { size: "sm" }) : null,
528
548
  loading && loadingText ? loadingText : children
529
549
  ]
530
550
  }
@@ -532,11 +552,13 @@ function PrimaryButton({
532
552
  }
533
553
  function SsoButton({ label, onClick }) {
534
554
  return /* @__PURE__ */ jsx2(
535
- "button",
555
+ Button2,
536
556
  {
537
557
  type: "button",
558
+ variant: "outline",
559
+ size: "lg",
538
560
  onClick,
539
- className: "w-full flex items-center justify-center gap-2.5 h-10 px-4 rounded-lg border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 hover:border-gray-400 transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2",
561
+ className: "w-full",
540
562
  children: label
541
563
  }
542
564
  );
@@ -546,7 +568,7 @@ function SsoButton({ label, onClick }) {
546
568
  import { Navigate, useLocation as useLocation2 } from "react-router-dom";
547
569
  import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
548
570
  import { Spinner as Spinner2 } from "@petrarca/sonnet-ui";
549
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
571
+ import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
550
572
  function ProtectedRoute({
551
573
  children,
552
574
  authEnabled,
@@ -554,7 +576,8 @@ function ProtectedRoute({
554
576
  isAuthenticated,
555
577
  accessToken,
556
578
  activeTenantId,
557
- initializeAuth
579
+ initializeAuth,
580
+ requiresOrgSelection = true
558
581
  }) {
559
582
  const location = useLocation2();
560
583
  const [initializing, setInitializing] = useState3(true);
@@ -566,7 +589,7 @@ function ProtectedRoute({
566
589
  return /* @__PURE__ */ jsx3("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsx3(Spinner2, { size: "lg" }) });
567
590
  }
568
591
  if (!authEnabled) {
569
- return /* @__PURE__ */ jsx3(Fragment, { children });
592
+ return /* @__PURE__ */ jsx3(Fragment2, { children });
570
593
  }
571
594
  if (!isAuthenticated || !accessToken) {
572
595
  return /* @__PURE__ */ jsx3(
@@ -578,17 +601,17 @@ function ProtectedRoute({
578
601
  }
579
602
  );
580
603
  }
581
- if (!activeTenantId) {
604
+ if (requiresOrgSelection && !activeTenantId) {
582
605
  return /* @__PURE__ */ jsx3(
583
606
  Navigate,
584
607
  {
585
608
  to: "/login",
586
- state: { from: location, step: "tenant-selection" },
609
+ state: { from: location, step: "org-selection" },
587
610
  replace: true
588
611
  }
589
612
  );
590
613
  }
591
- return /* @__PURE__ */ jsx3(Fragment, { children });
614
+ return /* @__PURE__ */ jsx3(Fragment2, { children });
592
615
  }
593
616
  export {
594
617
  Login,