@hachej/boring-core 0.1.64 → 0.1.66

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.
@@ -142,6 +142,7 @@ var routes = {
142
142
  workspaceMembers: "/w/:id/members",
143
143
  workspaceInvites: "/w/:id/invites",
144
144
  workspaceSettings: "/w/:id/settings",
145
+ companyAdmin: "/w/:id/admin",
145
146
  inviteAccept: "/invites/:token"
146
147
  };
147
148
  function routeHref(name, params) {
@@ -301,8 +302,77 @@ function useTheme() {
301
302
  return ctx;
302
303
  }
303
304
 
305
+ // src/front/CompanyAdminProvider.tsx
306
+ import { createContext as createContext3, useContext as useContext3, useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
307
+ import { jsx as jsx4 } from "react/jsx-runtime";
308
+ var CompanyAdminContext = createContext3({
309
+ configured: false,
310
+ loading: false,
311
+ status: null,
312
+ error: null,
313
+ renderContent: null,
314
+ labels: {},
315
+ refresh: async () => {
316
+ }
317
+ });
318
+ function CompanyAdminProvider({ children, loadStatus, renderContent, labels, identityKey }) {
319
+ const [status, setStatus] = useState3(null);
320
+ const [loading, setLoading] = useState3(Boolean(loadStatus && identityKey !== null));
321
+ const [error, setError] = useState3(null);
322
+ async function refresh() {
323
+ if (!loadStatus) return;
324
+ setLoading(true);
325
+ setError(null);
326
+ try {
327
+ setStatus(await loadStatus());
328
+ } catch (err) {
329
+ setStatus(null);
330
+ setError(err instanceof Error ? err.message : String(err));
331
+ } finally {
332
+ setLoading(false);
333
+ }
334
+ }
335
+ useEffect3(() => {
336
+ let cancelled = false;
337
+ if (!loadStatus || identityKey === null) {
338
+ setStatus(null);
339
+ setError(null);
340
+ setLoading(false);
341
+ return;
342
+ }
343
+ setLoading(true);
344
+ setError(null);
345
+ loadStatus().then((next) => {
346
+ if (!cancelled) setStatus(next);
347
+ }).catch((err) => {
348
+ if (!cancelled) {
349
+ setStatus(null);
350
+ setError(err instanceof Error ? err.message : String(err));
351
+ }
352
+ }).finally(() => {
353
+ if (!cancelled) setLoading(false);
354
+ });
355
+ return () => {
356
+ cancelled = true;
357
+ };
358
+ }, [identityKey, loadStatus]);
359
+ const value = useMemo2(() => ({
360
+ configured: Boolean(loadStatus && renderContent),
361
+ loading,
362
+ status,
363
+ error,
364
+ renderContent: renderContent ?? null,
365
+ labels: labels ?? {},
366
+ refresh
367
+ }), [error, labels, loadStatus, loading, renderContent, status]);
368
+ return /* @__PURE__ */ jsx4(CompanyAdminContext.Provider, { value, children });
369
+ }
370
+ function useCompanyAdminStatus() {
371
+ return useContext3(CompanyAdminContext);
372
+ }
373
+
304
374
  // src/front/hooks/useKeyboardShortcuts.ts
305
- import { useEffect as useEffect3, useRef as useRef2 } from "react";
375
+ import { useEffect as useEffect4, useRef as useRef2 } from "react";
306
376
  var MAC_PLATFORM_RE = /Mac|iPod|iPhone|iPad/;
307
377
  function normalizeKey(key) {
308
378
  const lowered = key.toLowerCase();
@@ -351,7 +421,7 @@ function matchesBinding(event, parsed, macPlatform) {
351
421
  function useKeyboardShortcuts(bindings) {
352
422
  const bindingsRef = useRef2(bindings);
353
423
  bindingsRef.current = bindings;
354
- useEffect3(() => {
424
+ useEffect4(() => {
355
425
  if (typeof window === "undefined") return;
356
426
  const macPlatform = isMacPlatform();
357
427
  const parsedBindings = bindingsRef.current.map((binding) => ({
@@ -375,7 +445,7 @@ function useKeyboardShortcuts(bindings) {
375
445
  }
376
446
 
377
447
  // src/front/hooks/useViewportBreakpoint.ts
378
- import { useEffect as useEffect4, useState as useState3 } from "react";
448
+ import { useEffect as useEffect5, useState as useState4 } from "react";
379
449
  function getBreakpoint() {
380
450
  if (typeof window === "undefined") return "sm";
381
451
  if (typeof window.matchMedia !== "function") return "sm";
@@ -386,8 +456,8 @@ function getBreakpoint() {
386
456
  return "sm";
387
457
  }
388
458
  function useViewportBreakpoint() {
389
- const [breakpoint, setBreakpoint] = useState3(getBreakpoint);
390
- useEffect4(() => {
459
+ const [breakpoint, setBreakpoint] = useState4(getBreakpoint);
460
+ useEffect5(() => {
391
461
  if (typeof window === "undefined") return;
392
462
  const update = () => {
393
463
  setBreakpoint(getBreakpoint());
@@ -402,7 +472,7 @@ function useViewportBreakpoint() {
402
472
  }
403
473
 
404
474
  // src/front/hooks/useReducedMotion.ts
405
- import { useEffect as useEffect5, useState as useState4 } from "react";
475
+ import { useEffect as useEffect6, useState as useState5 } from "react";
406
476
  var QUERY = "(prefers-reduced-motion: reduce)";
407
477
  function prefersReducedMotion() {
408
478
  if (typeof window === "undefined") return false;
@@ -410,8 +480,8 @@ function prefersReducedMotion() {
410
480
  return window.matchMedia(QUERY).matches;
411
481
  }
412
482
  function useReducedMotion() {
413
- const [reducedMotion, setReducedMotion] = useState4(prefersReducedMotion);
414
- useEffect5(() => {
483
+ const [reducedMotion, setReducedMotion] = useState5(prefersReducedMotion);
484
+ useEffect6(() => {
415
485
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
416
486
  const media = window.matchMedia(QUERY);
417
487
  const update = (event) => {
@@ -431,10 +501,10 @@ function useReducedMotion() {
431
501
  }
432
502
 
433
503
  // src/front/hooks/useBlobUrl.ts
434
- import { useEffect as useEffect6, useState as useState5 } from "react";
504
+ import { useEffect as useEffect7, useState as useState6 } from "react";
435
505
  function useBlobUrl(blob) {
436
- const [blobUrl, setBlobUrl] = useState5(null);
437
- useEffect6(() => {
506
+ const [blobUrl, setBlobUrl] = useState6(null);
507
+ useEffect7(() => {
438
508
  if (!blob) {
439
509
  setBlobUrl(null);
440
510
  return;
@@ -475,12 +545,12 @@ function useWorkspaceMembers(workspaceId) {
475
545
  }
476
546
 
477
547
  // src/front/WorkspaceAuthProvider.tsx
478
- import { createContext as createContext4, useContext as useContext4 } from "react";
548
+ import { createContext as createContext5, useContext as useContext5 } from "react";
479
549
  import { useQuery as useQuery2, useQueryClient } from "@tanstack/react-query";
480
550
  import { matchPath, useLocation, useParams } from "react-router-dom";
481
551
 
482
552
  // src/front/auth/AuthProvider.tsx
483
- import { createContext as createContext3, useContext as useContext3, useCallback as useCallback2, useMemo as useMemo2 } from "react";
553
+ import { createContext as createContext4, useContext as useContext4, useCallback as useCallback2, useMemo as useMemo3 } from "react";
484
554
 
485
555
  // src/front/auth/authClient.ts
486
556
  import { createAuthClient } from "better-auth/react";
@@ -503,8 +573,8 @@ function getAuthClient(baseURL) {
503
573
  }
504
574
 
505
575
  // src/front/auth/AuthProvider.tsx
506
- import { jsx as jsx4 } from "react/jsx-runtime";
507
- var AuthContext = createContext3(null);
576
+ import { jsx as jsx5 } from "react/jsx-runtime";
577
+ var AuthContext = createContext4(null);
508
578
  function toISOString(value) {
509
579
  if (!value) return "";
510
580
  if (value instanceof Date) return value.toISOString();
@@ -527,20 +597,20 @@ function AuthProvider({
527
597
  queryClient,
528
598
  navigate
529
599
  }) {
530
- const client = useMemo2(() => getAuthClient(baseURL), [baseURL]);
600
+ const client = useMemo3(() => getAuthClient(baseURL), [baseURL]);
531
601
  const signOut = useCallback2(async () => {
532
602
  await client.signOut();
533
603
  queryClient?.clear();
534
604
  navigate?.(routes.signin);
535
605
  }, [client, queryClient, navigate]);
536
- const value = useMemo2(
606
+ const value = useMemo3(
537
607
  () => ({ client, signOut }),
538
608
  [client, signOut]
539
609
  );
540
- return /* @__PURE__ */ jsx4(AuthContext.Provider, { value, children });
610
+ return /* @__PURE__ */ jsx5(AuthContext.Provider, { value, children });
541
611
  }
542
612
  function useAuthContext() {
543
- const ctx = useContext3(AuthContext);
613
+ const ctx = useContext4(AuthContext);
544
614
  if (!ctx) throw new Error("useSession/signIn/signOut must be used within an AuthProvider");
545
615
  return ctx;
546
616
  }
@@ -606,8 +676,8 @@ function useSignOut() {
606
676
  }
607
677
 
608
678
  // src/front/WorkspaceAuthProvider.tsx
609
- import { jsx as jsx5 } from "react/jsx-runtime";
610
- var WorkspaceContext = createContext4({
679
+ import { jsx as jsx6 } from "react/jsx-runtime";
680
+ var WorkspaceContext = createContext5({
611
681
  workspace: null,
612
682
  role: null,
613
683
  routeStatus: { status: "idle", workspaceId: null }
@@ -699,22 +769,22 @@ function WorkspaceAuthProvider({
699
769
  if (workspace?.id === routeWorkspaceId) return { status: "matched", workspaceId: routeWorkspaceId, workspace };
700
770
  return { status: "mismatched", workspaceId: routeWorkspaceId, currentWorkspaceId: workspace?.id ?? null };
701
771
  })();
702
- return /* @__PURE__ */ jsx5(WorkspaceContext.Provider, { value: { workspace, role, routeStatus }, children });
772
+ return /* @__PURE__ */ jsx6(WorkspaceContext.Provider, { value: { workspace, role, routeStatus }, children });
703
773
  }
704
774
  function useCurrentWorkspace() {
705
- return useContext4(WorkspaceContext).workspace;
775
+ return useContext5(WorkspaceContext).workspace;
706
776
  }
707
777
  function useWorkspaceRole() {
708
- return useContext4(WorkspaceContext).role;
778
+ return useContext5(WorkspaceContext).role;
709
779
  }
710
780
  function useWorkspaceRouteStatus() {
711
- return useContext4(WorkspaceContext).routeStatus;
781
+ return useContext5(WorkspaceContext).routeStatus;
712
782
  }
713
783
 
714
784
  // src/front/auth/UserIdentityProvider.tsx
715
- import { createContext as createContext5, useContext as useContext5, useEffect as useEffect7, useState as useState6, useRef as useRef3 } from "react";
716
- import { jsx as jsx6 } from "react/jsx-runtime";
717
- var UserContext = createContext5(null);
785
+ import { createContext as createContext6, useContext as useContext6, useEffect as useEffect8, useState as useState7, useRef as useRef3 } from "react";
786
+ import { jsx as jsx7 } from "react/jsx-runtime";
787
+ var UserContext = createContext6(null);
718
788
  var STALE_MS = 6e4;
719
789
  function UserIdentityProvider({ children }) {
720
790
  const { data: session } = useSession();
@@ -723,10 +793,10 @@ function UserIdentityProvider({ children }) {
723
793
  session?.user,
724
794
  isRuntimeEmailVerificationEnabled(config)
725
795
  );
726
- const [identity, setIdentity] = useState6(null);
796
+ const [identity, setIdentity] = useState7(null);
727
797
  const fetchedForRef = useRef3(null);
728
798
  const lastFetchRef = useRef3(0);
729
- useEffect7(() => {
799
+ useEffect8(() => {
730
800
  if (!session?.user || !canFetchIdentity) {
731
801
  setIdentity(null);
732
802
  fetchedForRef.current = null;
@@ -751,23 +821,23 @@ function UserIdentityProvider({ children }) {
751
821
  cancelled = true;
752
822
  };
753
823
  }, [canFetchIdentity, session?.user?.id]);
754
- return /* @__PURE__ */ jsx6(UserContext.Provider, { value: identity, children });
824
+ return /* @__PURE__ */ jsx7(UserContext.Provider, { value: identity, children });
755
825
  }
756
826
  function useUser() {
757
- return useContext5(UserContext);
827
+ return useContext6(UserContext);
758
828
  }
759
829
 
760
830
  // src/front/auth/GoogleAuthButton.tsx
761
- import { useState as useState7 } from "react";
831
+ import { useState as useState8 } from "react";
762
832
  import { Button as Button2 } from "@hachej/boring-ui-kit";
763
- import { jsx as jsx7 } from "react/jsx-runtime";
833
+ import { jsx as jsx8 } from "react/jsx-runtime";
764
834
  function GoogleAuthButton({
765
835
  callbackURL = "/",
766
836
  errorCallbackURL = callbackURL,
767
837
  onError
768
838
  }) {
769
839
  const signIn = useSignIn();
770
- const [isSubmitting, setIsSubmitting] = useState7(false);
840
+ const [isSubmitting, setIsSubmitting] = useState8(false);
771
841
  async function handleClick() {
772
842
  setIsSubmitting(true);
773
843
  try {
@@ -781,7 +851,7 @@ function GoogleAuthButton({
781
851
  setIsSubmitting(false);
782
852
  }
783
853
  }
784
- return /* @__PURE__ */ jsx7(
854
+ return /* @__PURE__ */ jsx8(
785
855
  Button2,
786
856
  {
787
857
  type: "button",
@@ -795,12 +865,12 @@ function GoogleAuthButton({
795
865
  }
796
866
 
797
867
  // src/front/auth/SignInPage.tsx
798
- import { useState as useState8 } from "react";
868
+ import { useState as useState9 } from "react";
799
869
  import { useForm } from "react-hook-form";
800
870
  import { zodResolver } from "@hookform/resolvers/zod";
801
871
  import { z } from "zod";
802
872
  import { Button as Button3, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Input, Label } from "@hachej/boring-ui-kit";
803
- import { Fragment, jsx as jsx8, jsxs } from "react/jsx-runtime";
873
+ import { Fragment, jsx as jsx9, jsxs } from "react/jsx-runtime";
804
874
  var signInSchema = z.object({
805
875
  email: z.string().email("Please enter a valid email"),
806
876
  password: z.string().min(1, "Password is required")
@@ -814,9 +884,9 @@ function readGoogleAuthError() {
814
884
  function SignInPage() {
815
885
  const signIn = useSignIn();
816
886
  const config = useOptionalConfig();
817
- const [serverError, setServerError] = useState8(null);
818
- const [oauthError, setOauthError] = useState8(() => readGoogleAuthError());
819
- const [isSubmitting, setIsSubmitting] = useState8(false);
887
+ const [serverError, setServerError] = useState9(null);
888
+ const [oauthError, setOauthError] = useState9(() => readGoogleAuthError());
889
+ const [isSubmitting, setIsSubmitting] = useState9(false);
820
890
  const showGoogleAuth = config?.features.googleOauth === true;
821
891
  const {
822
892
  register,
@@ -843,15 +913,15 @@ function SignInPage() {
843
913
  setIsSubmitting(false);
844
914
  }
845
915
  }
846
- return /* @__PURE__ */ jsx8("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
916
+ return /* @__PURE__ */ jsx9("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
847
917
  /* @__PURE__ */ jsxs(CardHeader, { children: [
848
- /* @__PURE__ */ jsx8(CardTitle, { children: "Sign in" }),
849
- /* @__PURE__ */ jsx8(CardDescription, { children: "Enter your credentials to continue" })
918
+ /* @__PURE__ */ jsx9(CardTitle, { children: "Sign in" }),
919
+ /* @__PURE__ */ jsx9(CardDescription, { children: "Enter your credentials to continue" })
850
920
  ] }),
851
921
  /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
852
922
  /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
853
923
  showGoogleAuth && /* @__PURE__ */ jsxs(Fragment, { children: [
854
- /* @__PURE__ */ jsx8(
924
+ /* @__PURE__ */ jsx9(
855
925
  GoogleAuthButton,
856
926
  {
857
927
  errorCallbackURL: routes.signin,
@@ -859,14 +929,14 @@ function SignInPage() {
859
929
  }
860
930
  ),
861
931
  /* @__PURE__ */ jsxs("div", { className: "relative", children: [
862
- /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx8("span", { className: "w-full border-t" }) }),
863
- /* @__PURE__ */ jsx8("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx8("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with email" }) })
932
+ /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx9("span", { className: "w-full border-t" }) }),
933
+ /* @__PURE__ */ jsx9("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx9("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with email" }) })
864
934
  ] })
865
935
  ] }),
866
- (serverError ?? oauthError) && /* @__PURE__ */ jsx8("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
936
+ (serverError ?? oauthError) && /* @__PURE__ */ jsx9("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
867
937
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
868
- /* @__PURE__ */ jsx8(Label, { htmlFor: "email", children: "Email" }),
869
- /* @__PURE__ */ jsx8(
938
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "email", children: "Email" }),
939
+ /* @__PURE__ */ jsx9(
870
940
  Input,
871
941
  {
872
942
  id: "email",
@@ -876,11 +946,11 @@ function SignInPage() {
876
946
  ...register("email")
877
947
  }
878
948
  ),
879
- errors.email && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.email.message })
949
+ errors.email && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.email.message })
880
950
  ] }),
881
951
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
882
- /* @__PURE__ */ jsx8(Label, { htmlFor: "password", children: "Password" }),
883
- /* @__PURE__ */ jsx8(
952
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "password", children: "Password" }),
953
+ /* @__PURE__ */ jsx9(
884
954
  Input,
885
955
  {
886
956
  id: "password",
@@ -889,14 +959,14 @@ function SignInPage() {
889
959
  ...register("password")
890
960
  }
891
961
  ),
892
- errors.password && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.password.message })
962
+ errors.password && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.password.message })
893
963
  ] })
894
964
  ] }),
895
965
  /* @__PURE__ */ jsxs(CardFooter, { className: "flex flex-col gap-4", children: [
896
- /* @__PURE__ */ jsx8(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Signing in\u2026" : "Sign in" }),
966
+ /* @__PURE__ */ jsx9(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Signing in\u2026" : "Sign in" }),
897
967
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm w-full", children: [
898
- /* @__PURE__ */ jsx8("a", { href: routes.forgotPassword, className: "text-muted-foreground hover:underline", children: "Forgot password?" }),
899
- /* @__PURE__ */ jsx8("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Sign up" })
968
+ /* @__PURE__ */ jsx9("a", { href: routes.forgotPassword, className: "text-muted-foreground hover:underline", children: "Forgot password?" }),
969
+ /* @__PURE__ */ jsx9("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Sign up" })
900
970
  ] })
901
971
  ] })
902
972
  ] })
@@ -904,13 +974,13 @@ function SignInPage() {
904
974
  }
905
975
 
906
976
  // src/front/auth/SignUpPage.tsx
907
- import { useState as useState9 } from "react";
977
+ import { useState as useState10 } from "react";
908
978
  import { useForm as useForm2 } from "react-hook-form";
909
979
  import { useNavigate } from "react-router-dom";
910
980
  import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
911
981
  import { z as z2 } from "zod";
912
982
  import { Button as Button4, Card as Card2, CardContent as CardContent2, CardDescription as CardDescription2, CardFooter as CardFooter2, CardHeader as CardHeader2, CardTitle as CardTitle2, Input as Input2, Label as Label2 } from "@hachej/boring-ui-kit";
913
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
983
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
914
984
  var signUpSchema = z2.object({
915
985
  name: z2.string().min(1, "Name is required"),
916
986
  email: z2.string().email("Please enter a valid email"),
@@ -926,10 +996,10 @@ function SignUpPage() {
926
996
  const signUp = useSignUp();
927
997
  const navigate = useNavigate();
928
998
  const config = useOptionalConfig();
929
- const [serverError, setServerError] = useState9(null);
930
- const [oauthError, setOauthError] = useState9(() => readGoogleAuthError2());
931
- const [isSubmitting, setIsSubmitting] = useState9(false);
932
- const [success, setSuccess] = useState9(false);
999
+ const [serverError, setServerError] = useState10(null);
1000
+ const [oauthError, setOauthError] = useState10(() => readGoogleAuthError2());
1001
+ const [isSubmitting, setIsSubmitting] = useState10(false);
1002
+ const [success, setSuccess] = useState10(false);
933
1003
  const inviteToken = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("invite_token") : null;
934
1004
  const showGoogleAuth = config?.features.googleOauth === true && !inviteToken;
935
1005
  const {
@@ -963,23 +1033,23 @@ function SignUpPage() {
963
1033
  }
964
1034
  }
965
1035
  if (success) {
966
- return /* @__PURE__ */ jsx9("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
1036
+ return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
967
1037
  /* @__PURE__ */ jsxs2(CardHeader2, { children: [
968
- /* @__PURE__ */ jsx9(CardTitle2, { children: "Check your email" }),
969
- /* @__PURE__ */ jsx9(CardDescription2, { children: "We sent a verification link to your email address. Please check your inbox to continue." })
1038
+ /* @__PURE__ */ jsx10(CardTitle2, { children: "Check your email" }),
1039
+ /* @__PURE__ */ jsx10(CardDescription2, { children: "We sent a verification link to your email address. Please check your inbox to continue." })
970
1040
  ] }),
971
- /* @__PURE__ */ jsx9(CardFooter2, { children: /* @__PURE__ */ jsx9("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1041
+ /* @__PURE__ */ jsx10(CardFooter2, { children: /* @__PURE__ */ jsx10("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
972
1042
  ] }) });
973
1043
  }
974
- return /* @__PURE__ */ jsx9("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
1044
+ return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
975
1045
  /* @__PURE__ */ jsxs2(CardHeader2, { children: [
976
- /* @__PURE__ */ jsx9(CardTitle2, { children: "Create an account" }),
977
- /* @__PURE__ */ jsx9(CardDescription2, { children: "Enter your details to get started" })
1046
+ /* @__PURE__ */ jsx10(CardTitle2, { children: "Create an account" }),
1047
+ /* @__PURE__ */ jsx10(CardDescription2, { children: "Enter your details to get started" })
978
1048
  ] }),
979
1049
  /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
980
1050
  /* @__PURE__ */ jsxs2(CardContent2, { className: "space-y-4", children: [
981
1051
  showGoogleAuth && /* @__PURE__ */ jsxs2(Fragment2, { children: [
982
- /* @__PURE__ */ jsx9(
1052
+ /* @__PURE__ */ jsx10(
983
1053
  GoogleAuthButton,
984
1054
  {
985
1055
  errorCallbackURL: routes.signup,
@@ -987,14 +1057,14 @@ function SignUpPage() {
987
1057
  }
988
1058
  ),
989
1059
  /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
990
- /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx9("span", { className: "w-full border-t" }) }),
991
- /* @__PURE__ */ jsx9("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx9("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with email" }) })
1060
+ /* @__PURE__ */ jsx10("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx10("span", { className: "w-full border-t" }) }),
1061
+ /* @__PURE__ */ jsx10("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx10("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with email" }) })
992
1062
  ] })
993
1063
  ] }),
994
- (serverError ?? oauthError) && /* @__PURE__ */ jsx9("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
1064
+ (serverError ?? oauthError) && /* @__PURE__ */ jsx10("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
995
1065
  /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
996
- /* @__PURE__ */ jsx9(Label2, { htmlFor: "name", children: "Name" }),
997
- /* @__PURE__ */ jsx9(
1066
+ /* @__PURE__ */ jsx10(Label2, { htmlFor: "name", children: "Name" }),
1067
+ /* @__PURE__ */ jsx10(
998
1068
  Input2,
999
1069
  {
1000
1070
  id: "name",
@@ -1004,11 +1074,11 @@ function SignUpPage() {
1004
1074
  ...register("name")
1005
1075
  }
1006
1076
  ),
1007
- errors.name && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.name.message })
1077
+ errors.name && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.name.message })
1008
1078
  ] }),
1009
1079
  /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
1010
- /* @__PURE__ */ jsx9(Label2, { htmlFor: "email", children: "Email" }),
1011
- /* @__PURE__ */ jsx9(
1080
+ /* @__PURE__ */ jsx10(Label2, { htmlFor: "email", children: "Email" }),
1081
+ /* @__PURE__ */ jsx10(
1012
1082
  Input2,
1013
1083
  {
1014
1084
  id: "email",
@@ -1018,11 +1088,11 @@ function SignUpPage() {
1018
1088
  ...register("email")
1019
1089
  }
1020
1090
  ),
1021
- errors.email && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.email.message })
1091
+ errors.email && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.email.message })
1022
1092
  ] }),
1023
1093
  /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
1024
- /* @__PURE__ */ jsx9(Label2, { htmlFor: "password", children: "Password" }),
1025
- /* @__PURE__ */ jsx9(
1094
+ /* @__PURE__ */ jsx10(Label2, { htmlFor: "password", children: "Password" }),
1095
+ /* @__PURE__ */ jsx10(
1026
1096
  Input2,
1027
1097
  {
1028
1098
  id: "password",
@@ -1032,14 +1102,14 @@ function SignUpPage() {
1032
1102
  ...register("password")
1033
1103
  }
1034
1104
  ),
1035
- errors.password && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.password.message })
1105
+ errors.password && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.password.message })
1036
1106
  ] })
1037
1107
  ] }),
1038
1108
  /* @__PURE__ */ jsxs2(CardFooter2, { className: "flex flex-col gap-4", children: [
1039
- /* @__PURE__ */ jsx9(Button4, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Creating account\u2026" : "Sign up" }),
1109
+ /* @__PURE__ */ jsx10(Button4, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Creating account\u2026" : "Sign up" }),
1040
1110
  /* @__PURE__ */ jsxs2("div", { className: "text-sm text-center", children: [
1041
- /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground", children: "Already have an account? " }),
1042
- /* @__PURE__ */ jsx9("a", { href: routes.signin, className: "hover:underline", children: "Sign in" })
1111
+ /* @__PURE__ */ jsx10("span", { className: "text-muted-foreground", children: "Already have an account? " }),
1112
+ /* @__PURE__ */ jsx10("a", { href: routes.signin, className: "hover:underline", children: "Sign in" })
1043
1113
  ] })
1044
1114
  ] })
1045
1115
  ] })
@@ -1047,19 +1117,19 @@ function SignUpPage() {
1047
1117
  }
1048
1118
 
1049
1119
  // src/front/auth/ForgotPasswordPage.tsx
1050
- import { useState as useState10 } from "react";
1120
+ import { useState as useState11 } from "react";
1051
1121
  import { useForm as useForm3 } from "react-hook-form";
1052
1122
  import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
1053
1123
  import { z as z3 } from "zod";
1054
1124
  import { Button as Button5, Card as Card3, CardContent as CardContent3, CardDescription as CardDescription3, CardFooter as CardFooter3, CardHeader as CardHeader3, CardTitle as CardTitle3, Input as Input3, Label as Label3 } from "@hachej/boring-ui-kit";
1055
- import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
1125
+ import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
1056
1126
  var forgotSchema = z3.object({
1057
1127
  email: z3.string().email("Please enter a valid email")
1058
1128
  });
1059
1129
  function ForgotPasswordPage() {
1060
1130
  const forgetPassword = useForgetPassword();
1061
- const [isSubmitting, setIsSubmitting] = useState10(false);
1062
- const [submitted, setSubmitted] = useState10(false);
1131
+ const [isSubmitting, setIsSubmitting] = useState11(false);
1132
+ const [submitted, setSubmitted] = useState11(false);
1063
1133
  const redirect = typeof window === "undefined" ? null : new URLSearchParams(window.location.search).get("redirect");
1064
1134
  const signinHref = redirect ? `${routes.signin}?redirect=${encodeURIComponent(redirect)}` : routes.signin;
1065
1135
  const {
@@ -1080,23 +1150,23 @@ function ForgotPasswordPage() {
1080
1150
  }
1081
1151
  }
1082
1152
  if (submitted) {
1083
- return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
1153
+ return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
1084
1154
  /* @__PURE__ */ jsxs3(CardHeader3, { children: [
1085
- /* @__PURE__ */ jsx10(CardTitle3, { children: "Check your inbox" }),
1086
- /* @__PURE__ */ jsx10(CardDescription3, { children: "If an account exists with that email, we sent a password reset link. Check your inbox and follow the instructions." })
1155
+ /* @__PURE__ */ jsx11(CardTitle3, { children: "Check your inbox" }),
1156
+ /* @__PURE__ */ jsx11(CardDescription3, { children: "If an account exists with that email, we sent a password reset link. Check your inbox and follow the instructions." })
1087
1157
  ] }),
1088
- /* @__PURE__ */ jsx10(CardFooter3, { children: /* @__PURE__ */ jsx10("a", { href: signinHref, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1158
+ /* @__PURE__ */ jsx11(CardFooter3, { children: /* @__PURE__ */ jsx11("a", { href: signinHref, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1089
1159
  ] }) });
1090
1160
  }
1091
- return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
1161
+ return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
1092
1162
  /* @__PURE__ */ jsxs3(CardHeader3, { children: [
1093
- /* @__PURE__ */ jsx10(CardTitle3, { children: "Forgot password" }),
1094
- /* @__PURE__ */ jsx10(CardDescription3, { children: "Enter your email and we'll send you a reset link" })
1163
+ /* @__PURE__ */ jsx11(CardTitle3, { children: "Forgot password" }),
1164
+ /* @__PURE__ */ jsx11(CardDescription3, { children: "Enter your email and we'll send you a reset link" })
1095
1165
  ] }),
1096
1166
  /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
1097
- /* @__PURE__ */ jsx10(CardContent3, { className: "space-y-4", children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
1098
- /* @__PURE__ */ jsx10(Label3, { htmlFor: "email", children: "Email" }),
1099
- /* @__PURE__ */ jsx10(
1167
+ /* @__PURE__ */ jsx11(CardContent3, { className: "space-y-4", children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
1168
+ /* @__PURE__ */ jsx11(Label3, { htmlFor: "email", children: "Email" }),
1169
+ /* @__PURE__ */ jsx11(
1100
1170
  Input3,
1101
1171
  {
1102
1172
  id: "email",
@@ -1106,23 +1176,23 @@ function ForgotPasswordPage() {
1106
1176
  ...register("email")
1107
1177
  }
1108
1178
  ),
1109
- errors.email && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.email.message })
1179
+ errors.email && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: errors.email.message })
1110
1180
  ] }) }),
1111
1181
  /* @__PURE__ */ jsxs3(CardFooter3, { className: "flex flex-col gap-4", children: [
1112
- /* @__PURE__ */ jsx10(Button5, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Sending\u2026" : "Send reset link" }),
1113
- /* @__PURE__ */ jsx10("a", { href: signinHref, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" })
1182
+ /* @__PURE__ */ jsx11(Button5, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Sending\u2026" : "Send reset link" }),
1183
+ /* @__PURE__ */ jsx11("a", { href: signinHref, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" })
1114
1184
  ] })
1115
1185
  ] })
1116
1186
  ] }) });
1117
1187
  }
1118
1188
 
1119
1189
  // src/front/auth/ResetPasswordPage.tsx
1120
- import { useState as useState11 } from "react";
1190
+ import { useState as useState12 } from "react";
1121
1191
  import { useForm as useForm4 } from "react-hook-form";
1122
1192
  import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
1123
1193
  import { z as z4 } from "zod";
1124
1194
  import { Button as Button6, Card as Card4, CardContent as CardContent4, CardDescription as CardDescription4, CardFooter as CardFooter4, CardHeader as CardHeader4, CardTitle as CardTitle4, Input as Input4, Label as Label4 } from "@hachej/boring-ui-kit";
1125
- import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
1195
+ import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
1126
1196
  var resetSchema = z4.object({
1127
1197
  password: z4.string().min(8, "Password must be at least 8 characters"),
1128
1198
  confirmPassword: z4.string()
@@ -1132,9 +1202,9 @@ var resetSchema = z4.object({
1132
1202
  });
1133
1203
  function ResetPasswordPage() {
1134
1204
  const resetPassword = useResetPassword();
1135
- const [serverError, setServerError] = useState11(null);
1136
- const [isSubmitting, setIsSubmitting] = useState11(false);
1137
- const [expired, setExpired] = useState11(false);
1205
+ const [serverError, setServerError] = useState12(null);
1206
+ const [isSubmitting, setIsSubmitting] = useState12(false);
1207
+ const [expired, setExpired] = useState12(false);
1138
1208
  const token = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null;
1139
1209
  const {
1140
1210
  register,
@@ -1172,25 +1242,25 @@ function ResetPasswordPage() {
1172
1242
  }
1173
1243
  }
1174
1244
  if (!token || expired) {
1175
- return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
1245
+ return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
1176
1246
  /* @__PURE__ */ jsxs4(CardHeader4, { children: [
1177
- /* @__PURE__ */ jsx11(CardTitle4, { children: "Link expired" }),
1178
- /* @__PURE__ */ jsx11(CardDescription4, { children: "This reset link is no longer valid. Please request a new one." })
1247
+ /* @__PURE__ */ jsx12(CardTitle4, { children: "Link expired" }),
1248
+ /* @__PURE__ */ jsx12(CardDescription4, { children: "This reset link is no longer valid. Please request a new one." })
1179
1249
  ] }),
1180
- /* @__PURE__ */ jsx11(CardFooter4, { children: /* @__PURE__ */ jsx11("a", { href: routes.forgotPassword, children: /* @__PURE__ */ jsx11(Button6, { variant: "outline", children: "Request new link" }) }) })
1250
+ /* @__PURE__ */ jsx12(CardFooter4, { children: /* @__PURE__ */ jsx12("a", { href: routes.forgotPassword, children: /* @__PURE__ */ jsx12(Button6, { variant: "outline", children: "Request new link" }) }) })
1181
1251
  ] }) });
1182
1252
  }
1183
- return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
1253
+ return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
1184
1254
  /* @__PURE__ */ jsxs4(CardHeader4, { children: [
1185
- /* @__PURE__ */ jsx11(CardTitle4, { children: "Reset password" }),
1186
- /* @__PURE__ */ jsx11(CardDescription4, { children: "Enter your new password below" })
1255
+ /* @__PURE__ */ jsx12(CardTitle4, { children: "Reset password" }),
1256
+ /* @__PURE__ */ jsx12(CardDescription4, { children: "Enter your new password below" })
1187
1257
  ] }),
1188
1258
  /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
1189
1259
  /* @__PURE__ */ jsxs4(CardContent4, { className: "space-y-4", children: [
1190
- serverError && /* @__PURE__ */ jsx11("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
1260
+ serverError && /* @__PURE__ */ jsx12("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
1191
1261
  /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1192
- /* @__PURE__ */ jsx11(Label4, { htmlFor: "password", children: "New password" }),
1193
- /* @__PURE__ */ jsx11(
1262
+ /* @__PURE__ */ jsx12(Label4, { htmlFor: "password", children: "New password" }),
1263
+ /* @__PURE__ */ jsx12(
1194
1264
  Input4,
1195
1265
  {
1196
1266
  id: "password",
@@ -1200,11 +1270,11 @@ function ResetPasswordPage() {
1200
1270
  ...register("password")
1201
1271
  }
1202
1272
  ),
1203
- errors.password && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: errors.password.message })
1273
+ errors.password && /* @__PURE__ */ jsx12("p", { className: "text-sm text-destructive", children: errors.password.message })
1204
1274
  ] }),
1205
1275
  /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1206
- /* @__PURE__ */ jsx11(Label4, { htmlFor: "confirmPassword", children: "Confirm password" }),
1207
- /* @__PURE__ */ jsx11(
1276
+ /* @__PURE__ */ jsx12(Label4, { htmlFor: "confirmPassword", children: "Confirm password" }),
1277
+ /* @__PURE__ */ jsx12(
1208
1278
  Input4,
1209
1279
  {
1210
1280
  id: "confirmPassword",
@@ -1213,18 +1283,18 @@ function ResetPasswordPage() {
1213
1283
  ...register("confirmPassword")
1214
1284
  }
1215
1285
  ),
1216
- errors.confirmPassword && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
1286
+ errors.confirmPassword && /* @__PURE__ */ jsx12("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
1217
1287
  ] })
1218
1288
  ] }),
1219
- /* @__PURE__ */ jsx11(CardFooter4, { children: /* @__PURE__ */ jsx11(Button6, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Resetting\u2026" : "Reset password" }) })
1289
+ /* @__PURE__ */ jsx12(CardFooter4, { children: /* @__PURE__ */ jsx12(Button6, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Resetting\u2026" : "Reset password" }) })
1220
1290
  ] })
1221
1291
  ] }) });
1222
1292
  }
1223
1293
 
1224
1294
  // src/front/auth/VerifyEmailPage.tsx
1225
- import { useCallback as useCallback3, useEffect as useEffect8, useRef as useRef4, useState as useState12 } from "react";
1295
+ import { useCallback as useCallback3, useEffect as useEffect9, useRef as useRef4, useState as useState13 } from "react";
1226
1296
  import { Button as Button7, Card as Card5, CardContent as CardContent5, CardDescription as CardDescription5, CardFooter as CardFooter5, CardHeader as CardHeader5, CardTitle as CardTitle5, Input as Input5, Label as Label5 } from "@hachej/boring-ui-kit";
1227
- import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
1297
+ import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1228
1298
  function getCookie(name) {
1229
1299
  const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
1230
1300
  return match ? decodeURIComponent(match[1]) : null;
@@ -1243,22 +1313,22 @@ function VerifyEmailPage() {
1243
1313
  const sendVerificationEmail = useSendVerificationEmail();
1244
1314
  const signOut = useSignOut();
1245
1315
  const token = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null;
1246
- const [status, setStatus] = useState12(token ? "verifying" : "no-token");
1247
- const [inviteWarning, setInviteWarning] = useState12(null);
1248
- const [cooldown, setCooldown] = useState12(0);
1249
- const [resendEmail, setResendEmail] = useState12("");
1250
- const [resendSent, setResendSent] = useState12(false);
1251
- const [isSigningOut, setIsSigningOut] = useState12(false);
1316
+ const [status, setStatus] = useState13(token ? "verifying" : "no-token");
1317
+ const [inviteWarning, setInviteWarning] = useState13(null);
1318
+ const [cooldown, setCooldown] = useState13(0);
1319
+ const [resendEmail, setResendEmail] = useState13("");
1320
+ const [resendSent, setResendSent] = useState13(false);
1321
+ const [isSigningOut, setIsSigningOut] = useState13(false);
1252
1322
  const verifiedRef = useRef4(false);
1253
1323
  const sessionEmail = session.data?.user?.email ?? null;
1254
- useEffect8(() => {
1324
+ useEffect9(() => {
1255
1325
  const cookie = getCookie("boring_invite_failed");
1256
1326
  if (cookie) {
1257
1327
  setInviteWarning(cookie || "Your invite link was invalid; you\u2019re signed in.");
1258
1328
  deleteCookie("boring_invite_failed");
1259
1329
  }
1260
1330
  }, []);
1261
- useEffect8(() => {
1331
+ useEffect9(() => {
1262
1332
  if (!token || verifiedRef.current) return;
1263
1333
  verifiedRef.current = true;
1264
1334
  (async () => {
@@ -1280,7 +1350,7 @@ function VerifyEmailPage() {
1280
1350
  }
1281
1351
  })();
1282
1352
  }, [token, verifyEmail]);
1283
- useEffect8(() => {
1353
+ useEffect9(() => {
1284
1354
  if (cooldown <= 0) return;
1285
1355
  const id = setInterval(() => {
1286
1356
  setCooldown((c) => {
@@ -1312,7 +1382,7 @@ function VerifyEmailPage() {
1312
1382
  navigateToSignIn();
1313
1383
  }
1314
1384
  }, [isSigningOut, signOut]);
1315
- const resendButton = /* @__PURE__ */ jsx12(
1385
+ const resendButton = /* @__PURE__ */ jsx13(
1316
1386
  Button7,
1317
1387
  {
1318
1388
  variant: "outline",
@@ -1324,8 +1394,8 @@ function VerifyEmailPage() {
1324
1394
  );
1325
1395
  const resendSection = /* @__PURE__ */ jsxs5("div", { className: "space-y-3", children: [
1326
1396
  !sessionEmail && /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
1327
- /* @__PURE__ */ jsx12(Label5, { htmlFor: "resend-email", children: "Email" }),
1328
- /* @__PURE__ */ jsx12(
1397
+ /* @__PURE__ */ jsx13(Label5, { htmlFor: "resend-email", children: "Email" }),
1398
+ /* @__PURE__ */ jsx13(
1329
1399
  Input5,
1330
1400
  {
1331
1401
  id: "resend-email",
@@ -1337,33 +1407,33 @@ function VerifyEmailPage() {
1337
1407
  )
1338
1408
  ] }),
1339
1409
  resendButton,
1340
- resendSent && /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground text-center", children: "If an account exists with that email, we sent a new verification link." })
1410
+ resendSent && /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground text-center", children: "If an account exists with that email, we sent a new verification link." })
1341
1411
  ] });
1342
1412
  if (status === "verifying") {
1343
- return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx12(Card5, { className: "w-full max-w-sm", children: /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1344
- /* @__PURE__ */ jsx12(CardTitle5, { children: "Verifying your email" }),
1345
- /* @__PURE__ */ jsx12(CardDescription5, { children: "Please wait\u2026" })
1413
+ return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx13(Card5, { className: "w-full max-w-sm", children: /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1414
+ /* @__PURE__ */ jsx13(CardTitle5, { children: "Verifying your email" }),
1415
+ /* @__PURE__ */ jsx13(CardDescription5, { children: "Please wait\u2026" })
1346
1416
  ] }) }) });
1347
1417
  }
1348
1418
  if (status === "verified") {
1349
- return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1350
- inviteWarning && /* @__PURE__ */ jsx12("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx12("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1419
+ return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1420
+ inviteWarning && /* @__PURE__ */ jsx13("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx13("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1351
1421
  /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1352
- /* @__PURE__ */ jsx12(CardTitle5, { children: "Email verified" }),
1353
- /* @__PURE__ */ jsx12(CardDescription5, { children: "Your email has been verified. You can now continue." })
1422
+ /* @__PURE__ */ jsx13(CardTitle5, { children: "Email verified" }),
1423
+ /* @__PURE__ */ jsx13(CardDescription5, { children: "Your email has been verified. You can now continue." })
1354
1424
  ] }),
1355
- /* @__PURE__ */ jsx12(CardFooter5, { children: /* @__PURE__ */ jsx12("a", { href: "/", className: "w-full", children: /* @__PURE__ */ jsx12(Button7, { className: "w-full", children: "Continue" }) }) })
1425
+ /* @__PURE__ */ jsx13(CardFooter5, { children: /* @__PURE__ */ jsx13("a", { href: "/", className: "w-full", children: /* @__PURE__ */ jsx13(Button7, { className: "w-full", children: "Continue" }) }) })
1356
1426
  ] }) });
1357
1427
  }
1358
1428
  if (status === "expired") {
1359
- return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1360
- inviteWarning && /* @__PURE__ */ jsx12("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx12("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1429
+ return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1430
+ inviteWarning && /* @__PURE__ */ jsx13("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx13("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1361
1431
  /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1362
- /* @__PURE__ */ jsx12(CardTitle5, { children: "Link expired" }),
1363
- /* @__PURE__ */ jsx12(CardDescription5, { children: "This verification link is no longer valid. Request a new one below." })
1432
+ /* @__PURE__ */ jsx13(CardTitle5, { children: "Link expired" }),
1433
+ /* @__PURE__ */ jsx13(CardDescription5, { children: "This verification link is no longer valid. Request a new one below." })
1364
1434
  ] }),
1365
- /* @__PURE__ */ jsx12(CardContent5, { children: resendSection }),
1366
- /* @__PURE__ */ jsx12(CardFooter5, { children: /* @__PURE__ */ jsx12(
1435
+ /* @__PURE__ */ jsx13(CardContent5, { children: resendSection }),
1436
+ /* @__PURE__ */ jsx13(CardFooter5, { children: /* @__PURE__ */ jsx13(
1367
1437
  Button7,
1368
1438
  {
1369
1439
  type: "button",
@@ -1377,14 +1447,14 @@ function VerifyEmailPage() {
1377
1447
  ] }) });
1378
1448
  }
1379
1449
  const isWaitingForEmailClick = status === "no-token" && Boolean(sessionEmail);
1380
- return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1381
- inviteWarning && /* @__PURE__ */ jsx12("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx12("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1450
+ return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1451
+ inviteWarning && /* @__PURE__ */ jsx13("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx13("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1382
1452
  /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1383
- /* @__PURE__ */ jsx12(CardTitle5, { children: isWaitingForEmailClick ? "Check your email" : "Invalid verification link" }),
1384
- /* @__PURE__ */ jsx12(CardDescription5, { children: isWaitingForEmailClick ? "We sent a verification link to your email address. Please check your inbox to continue." : status === "no-token" ? "No verification token found. Check the link in your email." : "This verification link is invalid. Request a new one below." })
1453
+ /* @__PURE__ */ jsx13(CardTitle5, { children: isWaitingForEmailClick ? "Check your email" : "Invalid verification link" }),
1454
+ /* @__PURE__ */ jsx13(CardDescription5, { children: isWaitingForEmailClick ? "We sent a verification link to your email address. Please check your inbox to continue." : status === "no-token" ? "No verification token found. Check the link in your email." : "This verification link is invalid. Request a new one below." })
1385
1455
  ] }),
1386
- /* @__PURE__ */ jsx12(CardContent5, { children: resendSection }),
1387
- /* @__PURE__ */ jsx12(CardFooter5, { children: /* @__PURE__ */ jsx12(
1456
+ /* @__PURE__ */ jsx13(CardContent5, { children: resendSection }),
1457
+ /* @__PURE__ */ jsx13(CardFooter5, { children: /* @__PURE__ */ jsx13(
1388
1458
  Button7,
1389
1459
  {
1390
1460
  type: "button",
@@ -1399,7 +1469,7 @@ function VerifyEmailPage() {
1399
1469
  }
1400
1470
 
1401
1471
  // src/front/auth/UserSettingsPage.tsx
1402
- import { useCallback as useCallback4, useState as useState13 } from "react";
1472
+ import { useCallback as useCallback4, useState as useState14 } from "react";
1403
1473
  import { useForm as useForm5 } from "react-hook-form";
1404
1474
  import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1405
1475
  import { z as z5 } from "zod";
@@ -1431,7 +1501,7 @@ import {
1431
1501
  Trash2,
1432
1502
  UserRound
1433
1503
  } from "lucide-react";
1434
- import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
1504
+ import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
1435
1505
  var changePasswordSchema = z5.object({
1436
1506
  currentPassword: z5.string().min(1, "Current password is required"),
1437
1507
  newPassword: z5.string().min(8, "Password must be at least 8 characters"),
@@ -1457,7 +1527,7 @@ function SettingsTopBar() {
1457
1527
  const config = useOptionalConfig();
1458
1528
  const appTitle = config?.appName ?? "Boring UI";
1459
1529
  const appInitial = (appTitle.trim().charAt(0) || "B").toUpperCase();
1460
- return /* @__PURE__ */ jsx13(
1530
+ return /* @__PURE__ */ jsx14(
1461
1531
  "header",
1462
1532
  {
1463
1533
  className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
@@ -1470,7 +1540,7 @@ function SettingsTopBar() {
1470
1540
  "aria-label": `${appTitle} home`,
1471
1541
  className: "flex min-w-0 items-center gap-2.5 rounded-md outline-none transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-ring",
1472
1542
  children: [
1473
- /* @__PURE__ */ jsx13(
1543
+ /* @__PURE__ */ jsx14(
1474
1544
  "div",
1475
1545
  {
1476
1546
  "aria-hidden": "true",
@@ -1478,12 +1548,12 @@ function SettingsTopBar() {
1478
1548
  children: appInitial
1479
1549
  }
1480
1550
  ),
1481
- /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle })
1551
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle })
1482
1552
  ]
1483
1553
  }
1484
1554
  ),
1485
- /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
1486
- /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] text-muted-foreground", children: "Account settings" })
1555
+ /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
1556
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-[13px] text-muted-foreground", children: "Account settings" })
1487
1557
  ] })
1488
1558
  }
1489
1559
  );
@@ -1495,7 +1565,7 @@ function SettingsPageHeader({
1495
1565
  }) {
1496
1566
  return /* @__PURE__ */ jsxs6("header", { className: "boring-settings-page-header", children: [
1497
1567
  /* @__PURE__ */ jsxs6("div", { className: "boring-settings-context", children: [
1498
- /* @__PURE__ */ jsx13("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: initials }),
1568
+ /* @__PURE__ */ jsx14("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: initials }),
1499
1569
  /* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
1500
1570
  /* @__PURE__ */ jsxs6("p", { className: "truncate text-[13px] font-medium text-foreground", children: [
1501
1571
  "Signed in as ",
@@ -1508,9 +1578,9 @@ function SettingsPageHeader({
1508
1578
  ] })
1509
1579
  ] }),
1510
1580
  /* @__PURE__ */ jsxs6("div", { className: "max-w-2xl", children: [
1511
- /* @__PURE__ */ jsx13("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Account" }),
1512
- /* @__PURE__ */ jsx13("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Account settings" }),
1513
- /* @__PURE__ */ jsx13("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Review your profile, change your password, and manage account-level actions." })
1581
+ /* @__PURE__ */ jsx14("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Account" }),
1582
+ /* @__PURE__ */ jsx14("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Account settings" }),
1583
+ /* @__PURE__ */ jsx14("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Review your profile, change your password, and manage account-level actions." })
1514
1584
  ] })
1515
1585
  ] });
1516
1586
  }
@@ -1525,13 +1595,13 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1525
1595
  const signOut = useSignOut();
1526
1596
  const changePassword = useChangePassword();
1527
1597
  const user = identity?.user ?? session.data?.user ?? null;
1528
- const [passwordError, setPasswordError] = useState13(null);
1529
- const [passwordSuccess, setPasswordSuccess] = useState13(false);
1530
- const [isChangingPassword, setIsChangingPassword] = useState13(false);
1531
- const [deleteConfirm, setDeleteConfirm] = useState13("");
1532
- const [deleteError, setDeleteError] = useState13(null);
1533
- const [isDeleting, setIsDeleting] = useState13(false);
1534
- const [deleteDialogOpen, setDeleteDialogOpen] = useState13(false);
1598
+ const [passwordError, setPasswordError] = useState14(null);
1599
+ const [passwordSuccess, setPasswordSuccess] = useState14(false);
1600
+ const [isChangingPassword, setIsChangingPassword] = useState14(false);
1601
+ const [deleteConfirm, setDeleteConfirm] = useState14("");
1602
+ const [deleteError, setDeleteError] = useState14(null);
1603
+ const [isDeleting, setIsDeleting] = useState14(false);
1604
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState14(false);
1535
1605
  const {
1536
1606
  register,
1537
1607
  handleSubmit,
@@ -1589,21 +1659,21 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1589
1659
  setIsDeleting(false);
1590
1660
  }
1591
1661
  }, [user?.email, signOut]);
1592
- const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx13(SettingsTopBar, {}) : topBar;
1662
+ const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx14(SettingsTopBar, {}) : topBar;
1593
1663
  if (!user) {
1594
1664
  return /* @__PURE__ */ jsxs6("main", { className: "boring-settings-shell", children: [
1595
1665
  topBarNode,
1596
- /* @__PURE__ */ jsx13("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsx13("div", { className: "mx-auto flex min-h-full w-full max-w-5xl items-center justify-center px-4", children: /* @__PURE__ */ jsxs6("div", { className: "w-full max-w-sm rounded-lg border border-border/60 bg-background p-4", children: [
1597
- /* @__PURE__ */ jsx13("h1", { className: "text-[13px] font-medium", children: "Account settings" }),
1598
- /* @__PURE__ */ jsx13("p", { className: "mt-1 text-[12px] text-muted-foreground", children: "Loading your account..." })
1666
+ /* @__PURE__ */ jsx14("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsx14("div", { className: "mx-auto flex min-h-full w-full max-w-5xl items-center justify-center px-4", children: /* @__PURE__ */ jsxs6("div", { className: "w-full max-w-sm rounded-lg border border-border/60 bg-background p-4", children: [
1667
+ /* @__PURE__ */ jsx14("h1", { className: "text-[13px] font-medium", children: "Account settings" }),
1668
+ /* @__PURE__ */ jsx14("p", { className: "mt-1 text-[12px] text-muted-foreground", children: "Loading your account..." })
1599
1669
  ] }) }) })
1600
1670
  ] });
1601
1671
  }
1602
1672
  const initials = initialsFor(user.name, user.email);
1603
1673
  return /* @__PURE__ */ jsxs6("main", { className: "boring-settings-shell", children: [
1604
1674
  topBarNode,
1605
- /* @__PURE__ */ jsx13("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs6("div", { className: "boring-settings-layout", children: [
1606
- /* @__PURE__ */ jsx13("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx13(
1675
+ /* @__PURE__ */ jsx14("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs6("div", { className: "boring-settings-layout", children: [
1676
+ /* @__PURE__ */ jsx14("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx14(
1607
1677
  UiSettingsNav,
1608
1678
  {
1609
1679
  label: "Account settings",
@@ -1615,7 +1685,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1615
1685
  }
1616
1686
  ) }),
1617
1687
  /* @__PURE__ */ jsxs6("div", { className: "boring-settings-content space-y-4", children: [
1618
- /* @__PURE__ */ jsx13(
1688
+ /* @__PURE__ */ jsx14(
1619
1689
  SettingsPageHeader,
1620
1690
  {
1621
1691
  initials,
@@ -1623,65 +1693,65 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1623
1693
  email: user.email
1624
1694
  }
1625
1695
  ),
1626
- /* @__PURE__ */ jsx13(
1696
+ /* @__PURE__ */ jsx14(
1627
1697
  UiSettingsPanel,
1628
1698
  {
1629
1699
  id: "profile",
1630
- icon: /* @__PURE__ */ jsx13(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1700
+ icon: /* @__PURE__ */ jsx14(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1631
1701
  title: "Profile",
1632
1702
  description: "The identity shown inside this app.",
1633
1703
  children: /* @__PURE__ */ jsxs6(DetailList, { children: [
1634
- /* @__PURE__ */ jsx13(
1704
+ /* @__PURE__ */ jsx14(
1635
1705
  UiDetailLine,
1636
1706
  {
1637
- icon: /* @__PURE__ */ jsx13(Mail, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1707
+ icon: /* @__PURE__ */ jsx14(Mail, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1638
1708
  label: "Email",
1639
- children: /* @__PURE__ */ jsx13("p", { className: "truncate", children: user.email })
1709
+ children: /* @__PURE__ */ jsx14("p", { className: "truncate", children: user.email })
1640
1710
  }
1641
1711
  ),
1642
- /* @__PURE__ */ jsx13(
1712
+ /* @__PURE__ */ jsx14(
1643
1713
  UiDetailLine,
1644
1714
  {
1645
- icon: /* @__PURE__ */ jsx13(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1715
+ icon: /* @__PURE__ */ jsx14(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1646
1716
  label: "Name",
1647
- children: /* @__PURE__ */ jsx13("p", { className: "truncate", children: user.name ?? "Not set" })
1717
+ children: /* @__PURE__ */ jsx14("p", { className: "truncate", children: user.name ?? "Not set" })
1648
1718
  }
1649
1719
  ),
1650
- /* @__PURE__ */ jsx13(
1720
+ /* @__PURE__ */ jsx14(
1651
1721
  UiDetailLine,
1652
1722
  {
1653
- icon: /* @__PURE__ */ jsx13(CalendarDays, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1723
+ icon: /* @__PURE__ */ jsx14(CalendarDays, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1654
1724
  label: "Member since",
1655
- children: /* @__PURE__ */ jsx13("p", { children: formatMemberSince(user.createdAt) })
1725
+ children: /* @__PURE__ */ jsx14("p", { children: formatMemberSince(user.createdAt) })
1656
1726
  }
1657
1727
  ),
1658
- /* @__PURE__ */ jsx13(
1728
+ /* @__PURE__ */ jsx14(
1659
1729
  UiDetailLine,
1660
1730
  {
1661
- icon: /* @__PURE__ */ jsx13(CheckCircle2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1731
+ icon: /* @__PURE__ */ jsx14(CheckCircle2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1662
1732
  label: "Email status",
1663
- children: /* @__PURE__ */ jsx13("p", { children: user.emailVerified ? "Verified" : "Not verified" })
1733
+ children: /* @__PURE__ */ jsx14("p", { children: user.emailVerified ? "Verified" : "Not verified" })
1664
1734
  }
1665
1735
  )
1666
1736
  ] })
1667
1737
  }
1668
1738
  ),
1669
- extraSections.map((section) => /* @__PURE__ */ jsx13("div", { children: section.content }, section.id)),
1670
- /* @__PURE__ */ jsx13("form", { onSubmit: handleSubmit(onChangePassword), noValidate: true, children: /* @__PURE__ */ jsx13(
1739
+ extraSections.map((section) => /* @__PURE__ */ jsx14("div", { children: section.content }, section.id)),
1740
+ /* @__PURE__ */ jsx14("form", { onSubmit: handleSubmit(onChangePassword), noValidate: true, children: /* @__PURE__ */ jsx14(
1671
1741
  UiSettingsPanel,
1672
1742
  {
1673
1743
  id: "password",
1674
- icon: /* @__PURE__ */ jsx13(KeyRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1744
+ icon: /* @__PURE__ */ jsx14(KeyRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1675
1745
  title: "Change password",
1676
1746
  description: "Update the password used for email sign-in.",
1677
- footer: /* @__PURE__ */ jsx13(Button8, { type: "submit", size: "sm", disabled: isChangingPassword, children: isChangingPassword ? "Changing..." : "Change password" }),
1747
+ footer: /* @__PURE__ */ jsx14(Button8, { type: "submit", size: "sm", disabled: isChangingPassword, children: isChangingPassword ? "Changing..." : "Change password" }),
1678
1748
  children: /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
1679
- passwordError && /* @__PURE__ */ jsx13(Notice, { role: "alert", tone: "error", description: passwordError }),
1680
- passwordSuccess && /* @__PURE__ */ jsx13(Notice, { role: "status", tone: "success", description: "Password changed successfully." }),
1749
+ passwordError && /* @__PURE__ */ jsx14(Notice, { role: "alert", tone: "error", description: passwordError }),
1750
+ passwordSuccess && /* @__PURE__ */ jsx14(Notice, { role: "status", tone: "success", description: "Password changed successfully." }),
1681
1751
  /* @__PURE__ */ jsxs6("div", { className: "grid gap-3 sm:grid-cols-2", children: [
1682
1752
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2 sm:col-span-2", children: [
1683
- /* @__PURE__ */ jsx13(Label6, { htmlFor: "currentPassword", className: "text-[12px]", children: "Current password" }),
1684
- /* @__PURE__ */ jsx13(
1753
+ /* @__PURE__ */ jsx14(Label6, { htmlFor: "currentPassword", className: "text-[12px]", children: "Current password" }),
1754
+ /* @__PURE__ */ jsx14(
1685
1755
  Input6,
1686
1756
  {
1687
1757
  id: "currentPassword",
@@ -1692,11 +1762,11 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1692
1762
  ...register("currentPassword")
1693
1763
  }
1694
1764
  ),
1695
- errors.currentPassword && /* @__PURE__ */ jsx13("p", { className: "text-[12px] text-destructive", children: errors.currentPassword.message })
1765
+ errors.currentPassword && /* @__PURE__ */ jsx14("p", { className: "text-[12px] text-destructive", children: errors.currentPassword.message })
1696
1766
  ] }),
1697
1767
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1698
- /* @__PURE__ */ jsx13(Label6, { htmlFor: "newPassword", className: "text-[12px]", children: "New password" }),
1699
- /* @__PURE__ */ jsx13(
1768
+ /* @__PURE__ */ jsx14(Label6, { htmlFor: "newPassword", className: "text-[12px]", children: "New password" }),
1769
+ /* @__PURE__ */ jsx14(
1700
1770
  Input6,
1701
1771
  {
1702
1772
  id: "newPassword",
@@ -1708,11 +1778,11 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1708
1778
  ...register("newPassword")
1709
1779
  }
1710
1780
  ),
1711
- errors.newPassword && /* @__PURE__ */ jsx13("p", { className: "text-[12px] text-destructive", children: errors.newPassword.message })
1781
+ errors.newPassword && /* @__PURE__ */ jsx14("p", { className: "text-[12px] text-destructive", children: errors.newPassword.message })
1712
1782
  ] }),
1713
1783
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1714
- /* @__PURE__ */ jsx13(Label6, { htmlFor: "confirmPassword", className: "text-[12px]", children: "Confirm new password" }),
1715
- /* @__PURE__ */ jsx13(
1784
+ /* @__PURE__ */ jsx14(Label6, { htmlFor: "confirmPassword", className: "text-[12px]", children: "Confirm new password" }),
1785
+ /* @__PURE__ */ jsx14(
1716
1786
  Input6,
1717
1787
  {
1718
1788
  id: "confirmPassword",
@@ -1723,44 +1793,44 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1723
1793
  ...register("confirmPassword")
1724
1794
  }
1725
1795
  ),
1726
- errors.confirmPassword && /* @__PURE__ */ jsx13("p", { className: "text-[12px] text-destructive", children: errors.confirmPassword.message })
1796
+ errors.confirmPassword && /* @__PURE__ */ jsx14("p", { className: "text-[12px] text-destructive", children: errors.confirmPassword.message })
1727
1797
  ] })
1728
1798
  ] })
1729
1799
  ] })
1730
1800
  }
1731
1801
  ) }),
1732
- /* @__PURE__ */ jsx13(
1802
+ /* @__PURE__ */ jsx14(
1733
1803
  UiSettingsPanel,
1734
1804
  {
1735
1805
  id: "danger-zone",
1736
- icon: /* @__PURE__ */ jsx13(ShieldAlert, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1806
+ icon: /* @__PURE__ */ jsx14(ShieldAlert, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1737
1807
  title: "Danger zone",
1738
1808
  description: "Permanently delete this account and remove its workspace access.",
1739
1809
  danger: true,
1740
- children: /* @__PURE__ */ jsx13(
1810
+ children: /* @__PURE__ */ jsx14(
1741
1811
  UiSettingsActionRow,
1742
1812
  {
1743
1813
  title: "Delete account",
1744
1814
  description: "Delete your account, user settings, and workspace memberships after confirmation.",
1745
1815
  action: /* @__PURE__ */ jsxs6(AlertDialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
1746
- /* @__PURE__ */ jsx13(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button8, { variant: "destructive", size: "sm", children: [
1747
- /* @__PURE__ */ jsx13(Trash2, { className: "h-4 w-4", "aria-hidden": "true" }),
1816
+ /* @__PURE__ */ jsx14(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button8, { variant: "destructive", size: "sm", children: [
1817
+ /* @__PURE__ */ jsx14(Trash2, { className: "h-4 w-4", "aria-hidden": "true" }),
1748
1818
  "Delete account"
1749
1819
  ] }) }),
1750
1820
  /* @__PURE__ */ jsxs6(AlertDialogContent, { children: [
1751
1821
  /* @__PURE__ */ jsxs6(AlertDialogHeader, { children: [
1752
- /* @__PURE__ */ jsx13(AlertDialogTitle, { children: "Delete your account?" }),
1753
- /* @__PURE__ */ jsx13(AlertDialogDescription, { children: "This action cannot be undone. All your data, workspaces, and settings will be permanently deleted." })
1822
+ /* @__PURE__ */ jsx14(AlertDialogTitle, { children: "Delete your account?" }),
1823
+ /* @__PURE__ */ jsx14(AlertDialogDescription, { children: "This action cannot be undone. All your data, workspaces, and settings will be permanently deleted." })
1754
1824
  ] }),
1755
1825
  /* @__PURE__ */ jsxs6("div", { className: "space-y-3 py-2", children: [
1756
- deleteError && /* @__PURE__ */ jsx13(Notice, { role: "alert", tone: "error", description: deleteError }),
1826
+ deleteError && /* @__PURE__ */ jsx14(Notice, { role: "alert", tone: "error", description: deleteError }),
1757
1827
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1758
1828
  /* @__PURE__ */ jsxs6(Label6, { htmlFor: "delete-confirm", children: [
1759
1829
  "Type ",
1760
- /* @__PURE__ */ jsx13("span", { className: "font-mono font-bold", children: "DELETE" }),
1830
+ /* @__PURE__ */ jsx14("span", { className: "font-mono font-bold", children: "DELETE" }),
1761
1831
  " to confirm"
1762
1832
  ] }),
1763
- /* @__PURE__ */ jsx13(
1833
+ /* @__PURE__ */ jsx14(
1764
1834
  Input6,
1765
1835
  {
1766
1836
  id: "delete-confirm",
@@ -1774,7 +1844,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1774
1844
  ] })
1775
1845
  ] }),
1776
1846
  /* @__PURE__ */ jsxs6(AlertDialogFooter, { children: [
1777
- /* @__PURE__ */ jsx13(
1847
+ /* @__PURE__ */ jsx14(
1778
1848
  AlertDialogCancel,
1779
1849
  {
1780
1850
  onClick: () => {
@@ -1784,7 +1854,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1784
1854
  children: "Cancel"
1785
1855
  }
1786
1856
  ),
1787
- /* @__PURE__ */ jsx13(
1857
+ /* @__PURE__ */ jsx14(
1788
1858
  Button8,
1789
1859
  {
1790
1860
  variant: "destructive",
@@ -1807,7 +1877,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
1807
1877
  }
1808
1878
 
1809
1879
  // src/front/auth/InviteAcceptPage.tsx
1810
- import { useCallback as useCallback5, useState as useState14 } from "react";
1880
+ import { useCallback as useCallback5, useState as useState15 } from "react";
1811
1881
  import { useParams as useParams2, useNavigate as useNavigate2 } from "react-router-dom";
1812
1882
  import { useQuery as useQuery3, useMutation, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1813
1883
  import {
@@ -1821,13 +1891,13 @@ import {
1821
1891
  LoadingState,
1822
1892
  Notice as Notice2
1823
1893
  } from "@hachej/boring-ui-kit";
1824
- import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1894
+ import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1825
1895
  function InviteAcceptPage() {
1826
1896
  const { token } = useParams2();
1827
1897
  const session = useSession();
1828
1898
  const navigate = useNavigate2();
1829
1899
  const queryClient = useQueryClient2();
1830
- const [acceptError, setAcceptError] = useState14(null);
1900
+ const [acceptError, setAcceptError] = useState15(null);
1831
1901
  const isSignedIn = Boolean(session.data);
1832
1902
  const isSessionPending = session.isPending;
1833
1903
  const resolveQuery = useQuery3({
@@ -1871,20 +1941,20 @@ function InviteAcceptPage() {
1871
1941
  navigate("/");
1872
1942
  }, [navigate]);
1873
1943
  if (isSessionPending) {
1874
- return /* @__PURE__ */ jsx14("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx14(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx14(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx14(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
1944
+ return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx15(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx15(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx15(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
1875
1945
  }
1876
1946
  if (!isSignedIn) {
1877
1947
  const signinUrl = `${routes.signin}?redirect=${encodeURIComponent(`/invites/${token}`)}`;
1878
- return /* @__PURE__ */ jsx14("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1948
+ return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1879
1949
  /* @__PURE__ */ jsxs7(CardHeader6, { children: [
1880
- /* @__PURE__ */ jsx14(CardTitle6, { children: "Sign in to accept this invite" }),
1881
- /* @__PURE__ */ jsx14(CardDescription6, { children: "You need to sign in before you can accept a workspace invite." })
1950
+ /* @__PURE__ */ jsx15(CardTitle6, { children: "Sign in to accept this invite" }),
1951
+ /* @__PURE__ */ jsx15(CardDescription6, { children: "You need to sign in before you can accept a workspace invite." })
1882
1952
  ] }),
1883
- /* @__PURE__ */ jsx14(CardFooter6, { children: /* @__PURE__ */ jsx14(Button9, { className: "w-full", onClick: () => navigate(signinUrl), "data-testid": "signin-redirect", children: "Sign in" }) })
1953
+ /* @__PURE__ */ jsx15(CardFooter6, { children: /* @__PURE__ */ jsx15(Button9, { className: "w-full", onClick: () => navigate(signinUrl), "data-testid": "signin-redirect", children: "Sign in" }) })
1884
1954
  ] }) });
1885
1955
  }
1886
1956
  if (resolveQuery.isLoading) {
1887
- return /* @__PURE__ */ jsx14("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx14(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx14(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx14(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
1957
+ return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx15(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx15(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx15(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
1888
1958
  }
1889
1959
  if (resolveQuery.error) {
1890
1960
  const detail = getHttpErrorDetail(resolveQuery.error);
@@ -1898,26 +1968,26 @@ function InviteAcceptPage() {
1898
1968
  } else {
1899
1969
  message = detail.message;
1900
1970
  }
1901
- return /* @__PURE__ */ jsx14("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1902
- /* @__PURE__ */ jsx14(CardHeader6, { children: /* @__PURE__ */ jsx14(CardTitle6, { children: "Invite unavailable" }) }),
1903
- /* @__PURE__ */ jsx14(CardContent6, { children: /* @__PURE__ */ jsx14(Notice2, { "data-testid": "resolve-error", tone: "error", description: message }) }),
1904
- /* @__PURE__ */ jsx14(CardFooter6, { children: /* @__PURE__ */ jsx14(Button9, { variant: "outline", className: "w-full", onClick: () => navigate("/"), children: "Go home" }) })
1971
+ return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1972
+ /* @__PURE__ */ jsx15(CardHeader6, { children: /* @__PURE__ */ jsx15(CardTitle6, { children: "Invite unavailable" }) }),
1973
+ /* @__PURE__ */ jsx15(CardContent6, { children: /* @__PURE__ */ jsx15(Notice2, { "data-testid": "resolve-error", tone: "error", description: message }) }),
1974
+ /* @__PURE__ */ jsx15(CardFooter6, { children: /* @__PURE__ */ jsx15(Button9, { variant: "outline", className: "w-full", onClick: () => navigate("/"), children: "Go home" }) })
1905
1975
  ] }) });
1906
1976
  }
1907
1977
  const preview = resolveQuery.data;
1908
1978
  if (!preview) return null;
1909
- return /* @__PURE__ */ jsx14("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1979
+ return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1910
1980
  /* @__PURE__ */ jsxs7(CardHeader6, { children: [
1911
- /* @__PURE__ */ jsx14(CardTitle6, { children: "You've been invited" }),
1981
+ /* @__PURE__ */ jsx15(CardTitle6, { children: "You've been invited" }),
1912
1982
  /* @__PURE__ */ jsxs7(CardDescription6, { children: [
1913
1983
  "Join ",
1914
- /* @__PURE__ */ jsx14("strong", { children: preview.workspaceName }),
1984
+ /* @__PURE__ */ jsx15("strong", { children: preview.workspaceName }),
1915
1985
  " as ",
1916
- /* @__PURE__ */ jsx14("strong", { children: preview.role })
1986
+ /* @__PURE__ */ jsx15("strong", { children: preview.role })
1917
1987
  ] })
1918
1988
  ] }),
1919
1989
  /* @__PURE__ */ jsxs7(CardContent6, { className: "space-y-3", children: [
1920
- acceptError && /* @__PURE__ */ jsx14(Notice2, { role: "alert", "data-testid": "accept-error", tone: "error", description: acceptError }),
1990
+ acceptError && /* @__PURE__ */ jsx15(Notice2, { role: "alert", "data-testid": "accept-error", tone: "error", description: acceptError }),
1921
1991
  /* @__PURE__ */ jsxs7("div", { className: "text-sm text-muted-foreground", children: [
1922
1992
  "This invite expires on",
1923
1993
  " ",
@@ -1929,7 +1999,7 @@ function InviteAcceptPage() {
1929
1999
  ] })
1930
2000
  ] }),
1931
2001
  /* @__PURE__ */ jsxs7(CardFooter6, { className: "flex gap-3", children: [
1932
- /* @__PURE__ */ jsx14(
2002
+ /* @__PURE__ */ jsx15(
1933
2003
  Button9,
1934
2004
  {
1935
2005
  variant: "outline",
@@ -1939,7 +2009,7 @@ function InviteAcceptPage() {
1939
2009
  children: "Decline"
1940
2010
  }
1941
2011
  ),
1942
- /* @__PURE__ */ jsx14(
2012
+ /* @__PURE__ */ jsx15(
1943
2013
  Button9,
1944
2014
  {
1945
2015
  className: "flex-1",
@@ -1954,9 +2024,9 @@ function InviteAcceptPage() {
1954
2024
  }
1955
2025
 
1956
2026
  // src/front/AuthGate.tsx
1957
- import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef5 } from "react";
2027
+ import { useEffect as useEffect10, useMemo as useMemo4, useRef as useRef5 } from "react";
1958
2028
  import { matchPath as matchPath2 } from "react-router-dom";
1959
- import { Fragment as Fragment3, jsx as jsx15 } from "react/jsx-runtime";
2029
+ import { Fragment as Fragment3, jsx as jsx16 } from "react/jsx-runtime";
1960
2030
  var DEFAULT_GRACE_MS = 3e4;
1961
2031
  var UNSAFE_REDIRECT_RE = /[\0\r\n<>"'`]/;
1962
2032
  var UNVERIFIED_ALLOWED_PATHS = /* @__PURE__ */ new Set([
@@ -2039,19 +2109,19 @@ function AuthGate({
2039
2109
  const readNow = now ?? Date.now;
2040
2110
  const currentLocation = location ?? defaultLocation();
2041
2111
  const goTo = navigate ?? defaultNavigate;
2042
- const normalizedPublicPaths = useMemo3(
2112
+ const normalizedPublicPaths = useMemo4(
2043
2113
  () => publicPaths.map(normalizePublicPath),
2044
2114
  [publicPaths]
2045
2115
  );
2046
2116
  const isEmailVerified = session.data?.user?.emailVerified ?? false;
2047
- useEffect9(() => {
2117
+ useEffect10(() => {
2048
2118
  return () => {
2049
2119
  if (!redirectTimerRef.current) return;
2050
2120
  clearTimeout(redirectTimerRef.current);
2051
2121
  redirectTimerRef.current = null;
2052
2122
  };
2053
2123
  }, []);
2054
- useEffect9(() => {
2124
+ useEffect10(() => {
2055
2125
  if (redirectTimerRef.current) {
2056
2126
  clearTimeout(redirectTimerRef.current);
2057
2127
  redirectTimerRef.current = null;
@@ -2098,17 +2168,17 @@ function AuthGate({
2098
2168
  const pathname = normalizePath(currentLocation.pathname);
2099
2169
  if (shouldBlockUnverifiedUser(pathname, Boolean(session.data), requireEmailVerification, isEmailVerified)) return null;
2100
2170
  if (session.isPending && !isPublicPath(pathname, normalizedPublicPaths)) return null;
2101
- return /* @__PURE__ */ jsx15(Fragment3, { children });
2171
+ return /* @__PURE__ */ jsx16(Fragment3, { children });
2102
2172
  }
2103
2173
 
2104
2174
  // src/front/CoreFront.tsx
2105
- import { Suspense, useCallback as useCallback9, useMemo as useMemo7 } from "react";
2175
+ import { Suspense, useCallback as useCallback9, useEffect as useEffect12, useMemo as useMemo8 } from "react";
2106
2176
  import { BrowserRouter, Routes, Route, useLocation as useLocation2, useNavigate as useNavigate6 } from "react-router-dom";
2107
2177
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2108
2178
  import { Helmet, HelmetProvider } from "react-helmet-async";
2109
2179
 
2110
2180
  // src/front/components/UserMenu.tsx
2111
- import { useMemo as useMemo4, useState as useState15 } from "react";
2181
+ import { useMemo as useMemo5, useState as useState16 } from "react";
2112
2182
  import {
2113
2183
  Button as Button10,
2114
2184
  DropdownMenu,
@@ -2126,10 +2196,11 @@ import {
2126
2196
  Monitor,
2127
2197
  Moon,
2128
2198
  Settings,
2199
+ ShieldCheck,
2129
2200
  Sun
2130
2201
  } from "lucide-react";
2131
2202
  import { useNavigate as useNavigate3 } from "react-router-dom";
2132
- import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
2203
+ import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
2133
2204
  var THEME_ORDER = ["light", "dark", "system"];
2134
2205
  function labelForTheme(preference) {
2135
2206
  if (preference === "light") return "Light";
@@ -2152,11 +2223,17 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2152
2223
  const signOut = useSignOut();
2153
2224
  const navigate = useNavigate3();
2154
2225
  const { preference, setTheme } = useTheme();
2155
- const [isSigningOut, setIsSigningOut] = useState15(false);
2226
+ const workspace = useCurrentWorkspace();
2227
+ const companyAdmin = useCompanyAdminStatus();
2228
+ const [isSigningOut, setIsSigningOut] = useState16(false);
2156
2229
  const user = identity?.user;
2230
+ const adminMenuLabel = companyAdmin.labels.menuLabel ?? "Admin";
2231
+ const companyAdminStatusPending = companyAdmin.configured && companyAdmin.loading && !companyAdmin.status;
2232
+ const canOpenCompanyAdmin = companyAdmin.configured && (companyAdminStatusPending || Boolean(companyAdmin.error) || companyAdmin.status?.enabled === true && companyAdmin.status.admin === true);
2233
+ const companyAdminWorkspaceId = canOpenCompanyAdmin ? workspace?.id ?? null : null;
2157
2234
  const userName = user?.name ?? "Unknown user";
2158
2235
  const userEmail = user?.email ?? "unknown@example.com";
2159
- const initials = useMemo4(() => initialsFor2(user?.name ?? null, userEmail), [user?.name, userEmail]);
2236
+ const initials = useMemo5(() => initialsFor2(user?.name ?? null, userEmail), [user?.name, userEmail]);
2160
2237
  async function handleSignOut() {
2161
2238
  if (isSigningOut) return;
2162
2239
  setIsSigningOut(true);
@@ -2168,7 +2245,7 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2168
2245
  }
2169
2246
  }
2170
2247
  return /* @__PURE__ */ jsxs8(DropdownMenu, { children: [
2171
- /* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: variant === "bar" ? /* @__PURE__ */ jsxs8(
2248
+ /* @__PURE__ */ jsx17(DropdownMenuTrigger, { asChild: true, children: variant === "bar" ? /* @__PURE__ */ jsxs8(
2172
2249
  Button10,
2173
2250
  {
2174
2251
  type: "button",
@@ -2176,12 +2253,12 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2176
2253
  "aria-label": "Account menu",
2177
2254
  className: "h-10 w-full justify-start gap-2.5 rounded-lg border border-transparent bg-transparent px-2 text-left text-foreground shadow-none hover:bg-foreground/[0.06] focus-visible:ring-1 focus-visible:ring-ring",
2178
2255
  children: [
2179
- /* @__PURE__ */ jsx16("span", { className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/60 bg-foreground/[0.12] text-[10px] font-semibold text-foreground", children: initials }),
2256
+ /* @__PURE__ */ jsx17("span", { className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/60 bg-foreground/[0.12] text-[10px] font-semibold text-foreground", children: initials }),
2180
2257
  /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5 leading-snug", children: [
2181
- /* @__PURE__ */ jsx16("span", { className: "truncate text-[13px] font-medium text-foreground", children: userName }),
2182
- /* @__PURE__ */ jsx16("span", { className: "truncate text-[11px] text-muted-foreground/80", children: userEmail })
2258
+ /* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-medium text-foreground", children: userName }),
2259
+ /* @__PURE__ */ jsx17("span", { className: "truncate text-[11px] text-muted-foreground/80", children: userEmail })
2183
2260
  ] }),
2184
- /* @__PURE__ */ jsx16(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2261
+ /* @__PURE__ */ jsx17(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2185
2262
  ]
2186
2263
  }
2187
2264
  ) : /* @__PURE__ */ jsxs8(
@@ -2192,8 +2269,8 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2192
2269
  "aria-label": "User menu",
2193
2270
  className: "h-8 rounded-md border border-transparent bg-transparent px-1 pr-1.5 text-foreground shadow-none hover:bg-foreground/5 focus-visible:ring-1 focus-visible:ring-ring",
2194
2271
  children: [
2195
- /* @__PURE__ */ jsx16("span", { className: "inline-flex h-7 w-7 items-center justify-center rounded-md bg-foreground text-[11px] font-semibold text-background", children: initials }),
2196
- /* @__PURE__ */ jsx16(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground", "aria-hidden": "true" })
2272
+ /* @__PURE__ */ jsx17("span", { className: "inline-flex h-7 w-7 items-center justify-center rounded-md bg-foreground text-[11px] font-semibold text-background", children: initials }),
2273
+ /* @__PURE__ */ jsx17(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground", "aria-hidden": "true" })
2197
2274
  ]
2198
2275
  }
2199
2276
  ) }),
@@ -2205,15 +2282,15 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2205
2282
  sideOffset: 8,
2206
2283
  className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
2207
2284
  children: [
2208
- /* @__PURE__ */ jsx16(DropdownMenuLabel, { className: "p-2", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
2209
- /* @__PURE__ */ jsx16("span", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: initials }),
2285
+ /* @__PURE__ */ jsx17(DropdownMenuLabel, { className: "p-2", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
2286
+ /* @__PURE__ */ jsx17("span", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: initials }),
2210
2287
  /* @__PURE__ */ jsxs8("span", { className: "min-w-0 space-y-1", children: [
2211
- /* @__PURE__ */ jsx16("span", { className: "block truncate text-sm font-medium leading-none", children: userName }),
2212
- /* @__PURE__ */ jsx16("span", { className: "block truncate text-xs font-normal text-muted-foreground", children: userEmail })
2288
+ /* @__PURE__ */ jsx17("span", { className: "block truncate text-sm font-medium leading-none", children: userName }),
2289
+ /* @__PURE__ */ jsx17("span", { className: "block truncate text-xs font-normal text-muted-foreground", children: userEmail })
2213
2290
  ] })
2214
2291
  ] }) }),
2215
- /* @__PURE__ */ jsx16(DropdownMenuSeparator, { className: "-mx-2" }),
2216
- /* @__PURE__ */ jsx16(DropdownMenuLabel, { className: "px-2 pb-1 pt-2 text-[11px] font-medium text-muted-foreground", children: "Theme" }),
2292
+ /* @__PURE__ */ jsx17(DropdownMenuSeparator, { className: "-mx-2" }),
2293
+ /* @__PURE__ */ jsx17(DropdownMenuLabel, { className: "px-2 pb-1 pt-2 text-[11px] font-medium text-muted-foreground", children: "Theme" }),
2217
2294
  THEME_ORDER.map((theme) => {
2218
2295
  const Icon = iconForTheme(theme);
2219
2296
  const selected = preference === theme;
@@ -2228,15 +2305,15 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2228
2305
  },
2229
2306
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2230
2307
  children: [
2231
- /* @__PURE__ */ jsx16(Icon, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }),
2232
- /* @__PURE__ */ jsx16("span", { className: "flex-1", children: labelForTheme(theme) }),
2233
- selected ? /* @__PURE__ */ jsx16(Check, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
2308
+ /* @__PURE__ */ jsx17(Icon, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }),
2309
+ /* @__PURE__ */ jsx17("span", { className: "flex-1", children: labelForTheme(theme) }),
2310
+ selected ? /* @__PURE__ */ jsx17(Check, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
2234
2311
  ]
2235
2312
  },
2236
2313
  theme
2237
2314
  );
2238
2315
  }),
2239
- /* @__PURE__ */ jsx16(DropdownMenuSeparator, { className: "-mx-2" }),
2316
+ /* @__PURE__ */ jsx17(DropdownMenuSeparator, { className: "-mx-2" }),
2240
2317
  /* @__PURE__ */ jsxs8(
2241
2318
  DropdownMenuItem,
2242
2319
  {
@@ -2244,15 +2321,30 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2244
2321
  onSelect: () => navigate(routes.me),
2245
2322
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2246
2323
  children: [
2247
- /* @__PURE__ */ jsx16(Settings, { className: "h-4 w-4", "aria-hidden": "true" }),
2324
+ /* @__PURE__ */ jsx17(Settings, { className: "h-4 w-4", "aria-hidden": "true" }),
2248
2325
  /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-col", children: [
2249
- /* @__PURE__ */ jsx16("span", { children: "User settings" }),
2250
- /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: "Password and account controls" })
2326
+ /* @__PURE__ */ jsx17("span", { children: "User settings" }),
2327
+ /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Password and account controls" })
2251
2328
  ] })
2252
2329
  ]
2253
2330
  }
2254
2331
  ),
2255
- /* @__PURE__ */ jsx16(DropdownMenuSeparator, { className: "-mx-2" }),
2332
+ companyAdminWorkspaceId ? /* @__PURE__ */ jsxs8(
2333
+ DropdownMenuItem,
2334
+ {
2335
+ "aria-label": adminMenuLabel,
2336
+ onSelect: () => navigate(routeHref("companyAdmin", { id: companyAdminWorkspaceId })),
2337
+ className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2338
+ children: [
2339
+ /* @__PURE__ */ jsx17(ShieldCheck, { className: "h-4 w-4", "aria-hidden": "true" }),
2340
+ /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-col", children: [
2341
+ /* @__PURE__ */ jsx17("span", { children: adminMenuLabel }),
2342
+ /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Admin controls" })
2343
+ ] })
2344
+ ]
2345
+ }
2346
+ ) : null,
2347
+ /* @__PURE__ */ jsx17(DropdownMenuSeparator, { className: "-mx-2" }),
2256
2348
  /* @__PURE__ */ jsxs8(
2257
2349
  DropdownMenuItem,
2258
2350
  {
@@ -2264,7 +2356,7 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2264
2356
  disabled: isSigningOut,
2265
2357
  className: "gap-3 rounded-md py-2 text-[13px]",
2266
2358
  children: [
2267
- /* @__PURE__ */ jsx16(LogOut, { className: "h-4 w-4", "aria-hidden": "true" }),
2359
+ /* @__PURE__ */ jsx17(LogOut, { className: "h-4 w-4", "aria-hidden": "true" }),
2268
2360
  isSigningOut ? "Signing out..." : "Sign out"
2269
2361
  ]
2270
2362
  }
@@ -2276,7 +2368,7 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
2276
2368
  }
2277
2369
 
2278
2370
  // src/front/components/WorkspaceSwitcher.tsx
2279
- import { useMemo as useMemo5, useState as useState16 } from "react";
2371
+ import { useMemo as useMemo6, useState as useState17 } from "react";
2280
2372
  import { useQuery as useQuery4, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
2281
2373
  import {
2282
2374
  Button as Button11,
@@ -2299,7 +2391,7 @@ import {
2299
2391
  import { ChevronsUpDown as ChevronsUpDown2, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
2300
2392
  import { useNavigate as useNavigate4 } from "react-router-dom";
2301
2393
  import { z as z6 } from "zod";
2302
- import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
2394
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
2303
2395
  var workspaceNameSchema = z6.object({
2304
2396
  name: z6.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
2305
2397
  });
@@ -2337,9 +2429,9 @@ function workspaceInitial(name) {
2337
2429
  }
2338
2430
  function OpenInNewTabIcon({ className }) {
2339
2431
  return /* @__PURE__ */ jsxs9("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
2340
- /* @__PURE__ */ jsx17("path", { d: "M15 3h6v6" }),
2341
- /* @__PURE__ */ jsx17("path", { d: "M10 14 21 3" }),
2342
- /* @__PURE__ */ jsx17("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
2432
+ /* @__PURE__ */ jsx18("path", { d: "M15 3h6v6" }),
2433
+ /* @__PURE__ */ jsx18("path", { d: "M10 14 21 3" }),
2434
+ /* @__PURE__ */ jsx18("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
2343
2435
  ] });
2344
2436
  }
2345
2437
  function WorkspaceSwitcher({
@@ -2355,12 +2447,12 @@ function WorkspaceSwitcher({
2355
2447
  const currentWorkspace = useCurrentWorkspace();
2356
2448
  const workspacesQuery = useWorkspaces();
2357
2449
  const workspaces = workspacesQuery.data ?? [];
2358
- const [isModalOpen, setIsModalOpen] = useState16(false);
2359
- const [name, setName] = useState16("");
2360
- const [attemptedSubmit, setAttemptedSubmit] = useState16(false);
2361
- const [isSubmitting, setIsSubmitting] = useState16(false);
2362
- const [serverError, setServerError] = useState16(null);
2363
- const nameValidation = useMemo5(() => validateWorkspaceName(name), [name]);
2450
+ const [isModalOpen, setIsModalOpen] = useState17(false);
2451
+ const [name, setName] = useState17("");
2452
+ const [attemptedSubmit, setAttemptedSubmit] = useState17(false);
2453
+ const [isSubmitting, setIsSubmitting] = useState17(false);
2454
+ const [serverError, setServerError] = useState17(null);
2455
+ const nameValidation = useMemo6(() => validateWorkspaceName(name), [name]);
2364
2456
  const shouldShowNameError = name.length > 100 || attemptedSubmit && nameValidation.message !== null;
2365
2457
  const nameError = shouldShowNameError ? nameValidation.message : null;
2366
2458
  function openCreateWorkspace() {
@@ -2431,7 +2523,7 @@ function WorkspaceSwitcher({
2431
2523
  onClick: openCreateWorkspace,
2432
2524
  className: "-ml-1 h-8 gap-2 rounded-md px-1 pr-2.5 hover:bg-foreground/5 focus-visible:ring-1 focus-visible:ring-ring",
2433
2525
  children: [
2434
- /* @__PURE__ */ jsx17(
2526
+ /* @__PURE__ */ jsx18(
2435
2527
  "span",
2436
2528
  {
2437
2529
  "aria-hidden": "true",
@@ -2439,11 +2531,11 @@ function WorkspaceSwitcher({
2439
2531
  children: resolvedAppTitle.charAt(0).toUpperCase()
2440
2532
  }
2441
2533
  ),
2442
- /* @__PURE__ */ jsx17("span", { className: "text-[13px] font-medium text-foreground", children: "Create your first workspace" })
2534
+ /* @__PURE__ */ jsx18("span", { className: "text-[13px] font-medium text-foreground", children: "Create your first workspace" })
2443
2535
  ]
2444
2536
  }
2445
2537
  ) : /* @__PURE__ */ jsxs9(DropdownMenu2, { children: [
2446
- /* @__PURE__ */ jsx17(DropdownMenuTrigger2, { asChild: true, children: displayMode === "workspace" ? /* @__PURE__ */ jsxs9(
2538
+ /* @__PURE__ */ jsx18(DropdownMenuTrigger2, { asChild: true, children: displayMode === "workspace" ? /* @__PURE__ */ jsxs9(
2447
2539
  Button11,
2448
2540
  {
2449
2541
  type: "button",
@@ -2451,8 +2543,8 @@ function WorkspaceSwitcher({
2451
2543
  "aria-label": `Workspace menu: ${switcherLabel}`,
2452
2544
  className: "h-8 w-full min-w-0 justify-start gap-1.5 rounded-lg border border-transparent px-2 text-left hover:bg-foreground/[0.06] focus-visible:ring-1 focus-visible:ring-ring",
2453
2545
  children: [
2454
- /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-[13px] font-medium text-foreground/85", children: switcherLabel }),
2455
- /* @__PURE__ */ jsx17(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
2546
+ /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-[13px] font-medium text-foreground/85", children: switcherLabel }),
2547
+ /* @__PURE__ */ jsx18(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
2456
2548
  ]
2457
2549
  }
2458
2550
  ) : /* @__PURE__ */ jsxs9(
@@ -2463,7 +2555,7 @@ function WorkspaceSwitcher({
2463
2555
  "aria-label": `Workspace menu: ${switcherLabel}`,
2464
2556
  className: "-ml-1 h-8 min-w-0 justify-start gap-2.5 border border-transparent px-1 py-1 text-left",
2465
2557
  children: [
2466
- /* @__PURE__ */ jsx17(
2558
+ /* @__PURE__ */ jsx18(
2467
2559
  "span",
2468
2560
  {
2469
2561
  "aria-hidden": "true",
@@ -2471,8 +2563,8 @@ function WorkspaceSwitcher({
2471
2563
  children: workspaceInitial(switcherLabel)
2472
2564
  }
2473
2565
  ),
2474
- /* @__PURE__ */ jsx17("span", { className: "min-w-0 truncate text-[13px] font-medium text-foreground", children: switcherLabel }),
2475
- /* @__PURE__ */ jsx17(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2566
+ /* @__PURE__ */ jsx18("span", { className: "min-w-0 truncate text-[13px] font-medium text-foreground", children: switcherLabel }),
2567
+ /* @__PURE__ */ jsx18(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2476
2568
  ]
2477
2569
  }
2478
2570
  ) }),
@@ -2483,11 +2575,11 @@ function WorkspaceSwitcher({
2483
2575
  sideOffset: 8,
2484
2576
  className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
2485
2577
  children: [
2486
- /* @__PURE__ */ jsx17(DropdownMenuLabel2, { className: "px-2 pb-2 pt-1", children: /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-2 text-xs font-medium text-muted-foreground", children: [
2487
- /* @__PURE__ */ jsx17(LayoutGrid, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2578
+ /* @__PURE__ */ jsx18(DropdownMenuLabel2, { className: "px-2 pb-2 pt-1", children: /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-2 text-xs font-medium text-muted-foreground", children: [
2579
+ /* @__PURE__ */ jsx18(LayoutGrid, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2488
2580
  "Workspaces"
2489
2581
  ] }) }),
2490
- /* @__PURE__ */ jsx17("div", { className: "max-h-72 overflow-y-auto pr-1", children: workspaces.map((workspace) => {
2582
+ /* @__PURE__ */ jsx18("div", { className: "max-h-72 overflow-y-auto pr-1", children: workspaces.map((workspace) => {
2491
2583
  const isCurrent = currentWorkspace?.id === workspace.id;
2492
2584
  return /* @__PURE__ */ jsxs9("div", { className: "group relative w-full", children: [
2493
2585
  /* @__PURE__ */ jsxs9(
@@ -2499,12 +2591,12 @@ function WorkspaceSwitcher({
2499
2591
  style: { paddingRight: 72 },
2500
2592
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2501
2593
  children: [
2502
- /* @__PURE__ */ jsx17("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-border/60 bg-background text-xs font-semibold text-muted-foreground", children: workspaceInitial(workspace.name) }),
2503
- /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm", children: workspace.name })
2594
+ /* @__PURE__ */ jsx18("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-border/60 bg-background text-xs font-semibold text-muted-foreground", children: workspaceInitial(workspace.name) }),
2595
+ /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-sm", children: workspace.name })
2504
2596
  ]
2505
2597
  }
2506
2598
  ),
2507
- /* @__PURE__ */ jsx17(
2599
+ /* @__PURE__ */ jsx18(
2508
2600
  "button",
2509
2601
  {
2510
2602
  type: "button",
@@ -2522,12 +2614,12 @@ function WorkspaceSwitcher({
2522
2614
  },
2523
2615
  style: { right: 4, top: "50%", transform: "translateY(-50%)" },
2524
2616
  className: "absolute z-10 flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground opacity-0 transition hover:bg-foreground/10 hover:text-foreground focus:opacity-100 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100",
2525
- children: /* @__PURE__ */ jsx17(OpenInNewTabIcon, { className: "h-3.5 w-3.5" })
2617
+ children: /* @__PURE__ */ jsx18(OpenInNewTabIcon, { className: "h-3.5 w-3.5" })
2526
2618
  }
2527
2619
  )
2528
2620
  ] }, workspace.id);
2529
2621
  }) }),
2530
- /* @__PURE__ */ jsx17(DropdownMenuSeparator2, { className: "-mx-2" }),
2622
+ /* @__PURE__ */ jsx18(DropdownMenuSeparator2, { className: "-mx-2" }),
2531
2623
  /* @__PURE__ */ jsxs9(
2532
2624
  DropdownMenuItem2,
2533
2625
  {
@@ -2538,10 +2630,10 @@ function WorkspaceSwitcher({
2538
2630
  },
2539
2631
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2540
2632
  children: [
2541
- /* @__PURE__ */ jsx17(Plus, { className: "h-4 w-4", "aria-hidden": "true" }),
2633
+ /* @__PURE__ */ jsx18(Plus, { className: "h-4 w-4", "aria-hidden": "true" }),
2542
2634
  /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-col", children: [
2543
- /* @__PURE__ */ jsx17("span", { children: "Create workspace" }),
2544
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Start a clean project space" })
2635
+ /* @__PURE__ */ jsx18("span", { children: "Create workspace" }),
2636
+ /* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground", children: "Start a clean project space" })
2545
2637
  ] })
2546
2638
  ]
2547
2639
  }
@@ -2553,10 +2645,10 @@ function WorkspaceSwitcher({
2553
2645
  onSelect: () => navigate(hrefForWorkspace(workspacePathPrefix, currentWorkspace.id, "/settings")),
2554
2646
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2555
2647
  children: [
2556
- /* @__PURE__ */ jsx17(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }),
2648
+ /* @__PURE__ */ jsx18(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }),
2557
2649
  /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-col", children: [
2558
- /* @__PURE__ */ jsx17("span", { children: "Workspace settings" }),
2559
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Rename, runtime, deletion" })
2650
+ /* @__PURE__ */ jsx18("span", { children: "Workspace settings" }),
2651
+ /* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground", children: "Rename, runtime, deletion" })
2560
2652
  ] })
2561
2653
  ]
2562
2654
  }
@@ -2565,21 +2657,21 @@ function WorkspaceSwitcher({
2565
2657
  }
2566
2658
  )
2567
2659
  ] }),
2568
- /* @__PURE__ */ jsx17(Dialog, { open: isModalOpen, onOpenChange: onModalChange, children: /* @__PURE__ */ jsxs9(DialogContent, { children: [
2660
+ /* @__PURE__ */ jsx18(Dialog, { open: isModalOpen, onOpenChange: onModalChange, children: /* @__PURE__ */ jsxs9(DialogContent, { children: [
2569
2661
  /* @__PURE__ */ jsxs9(DialogHeader, { children: [
2570
- /* @__PURE__ */ jsx17(DialogTitle, { children: "Create workspace" }),
2571
- /* @__PURE__ */ jsx17(DialogDescription, { children: "Choose a name for your new workspace." })
2662
+ /* @__PURE__ */ jsx18(DialogTitle, { children: "Create workspace" }),
2663
+ /* @__PURE__ */ jsx18(DialogDescription, { children: "Choose a name for your new workspace." })
2572
2664
  ] }),
2573
2665
  /* @__PURE__ */ jsxs9("form", { onSubmit: (event) => void handleCreateWorkspace(event), className: "space-y-4", children: [
2574
2666
  /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2575
2667
  /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
2576
- /* @__PURE__ */ jsx17(Label7, { htmlFor: "workspace-name", children: "Name" }),
2668
+ /* @__PURE__ */ jsx18(Label7, { htmlFor: "workspace-name", children: "Name" }),
2577
2669
  /* @__PURE__ */ jsxs9("span", { className: "text-xs text-muted-foreground", children: [
2578
2670
  name.length,
2579
2671
  "/100"
2580
2672
  ] })
2581
2673
  ] }),
2582
- /* @__PURE__ */ jsx17(
2674
+ /* @__PURE__ */ jsx18(
2583
2675
  Input7,
2584
2676
  {
2585
2677
  id: "workspace-name",
@@ -2595,11 +2687,11 @@ function WorkspaceSwitcher({
2595
2687
  autoFocus: true
2596
2688
  }
2597
2689
  ),
2598
- nameError ? /* @__PURE__ */ jsx17("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2599
- serverError ? /* @__PURE__ */ jsx17("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2690
+ nameError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2691
+ serverError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2600
2692
  ] }),
2601
2693
  /* @__PURE__ */ jsxs9(DialogFooter, { children: [
2602
- /* @__PURE__ */ jsx17(
2694
+ /* @__PURE__ */ jsx18(
2603
2695
  Button11,
2604
2696
  {
2605
2697
  type: "button",
@@ -2609,7 +2701,7 @@ function WorkspaceSwitcher({
2609
2701
  children: "Cancel"
2610
2702
  }
2611
2703
  ),
2612
- /* @__PURE__ */ jsx17(
2704
+ /* @__PURE__ */ jsx18(
2613
2705
  Button11,
2614
2706
  {
2615
2707
  type: "submit",
@@ -2624,7 +2716,7 @@ function WorkspaceSwitcher({
2624
2716
  }
2625
2717
 
2626
2718
  // src/front/components/CreateWorkspaceDialog.tsx
2627
- import { useMemo as useMemo6, useState as useState17 } from "react";
2719
+ import { useMemo as useMemo7, useState as useState18 } from "react";
2628
2720
  import { useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2629
2721
  import {
2630
2722
  Button as Button12,
@@ -2639,7 +2731,7 @@ import {
2639
2731
  useToast as useToast2
2640
2732
  } from "@hachej/boring-ui-kit";
2641
2733
  import { z as z7 } from "zod";
2642
- import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
2734
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
2643
2735
  var workspaceNameSchema2 = z7.object({
2644
2736
  name: z7.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
2645
2737
  });
@@ -2653,11 +2745,11 @@ function CreateWorkspaceDialog({
2653
2745
  }) {
2654
2746
  const queryClient = useQueryClient4();
2655
2747
  const { toast } = useToast2();
2656
- const [name, setName] = useState17("");
2657
- const [attemptedSubmit, setAttemptedSubmit] = useState17(false);
2658
- const [isSubmitting, setIsSubmitting] = useState17(false);
2659
- const [serverError, setServerError] = useState17(null);
2660
- const validation = useMemo6(() => workspaceNameSchema2.safeParse({ name }), [name]);
2748
+ const [name, setName] = useState18("");
2749
+ const [attemptedSubmit, setAttemptedSubmit] = useState18(false);
2750
+ const [isSubmitting, setIsSubmitting] = useState18(false);
2751
+ const [serverError, setServerError] = useState18(null);
2752
+ const validation = useMemo7(() => workspaceNameSchema2.safeParse({ name }), [name]);
2661
2753
  const shouldShowNameError = name.length > 100 || attemptedSubmit && !validation.success;
2662
2754
  const nameError = shouldShowNameError && !validation.success ? validation.error.issues[0]?.message ?? "Invalid workspace name" : null;
2663
2755
  function reset() {
@@ -2707,21 +2799,21 @@ function CreateWorkspaceDialog({
2707
2799
  setIsSubmitting(false);
2708
2800
  }
2709
2801
  }
2710
- return /* @__PURE__ */ jsx18(Dialog2, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent2, { children: [
2802
+ return /* @__PURE__ */ jsx19(Dialog2, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent2, { children: [
2711
2803
  /* @__PURE__ */ jsxs10(DialogHeader2, { children: [
2712
- /* @__PURE__ */ jsx18(DialogTitle2, { children: title }),
2713
- /* @__PURE__ */ jsx18(DialogDescription2, { children: description })
2804
+ /* @__PURE__ */ jsx19(DialogTitle2, { children: title }),
2805
+ /* @__PURE__ */ jsx19(DialogDescription2, { children: description })
2714
2806
  ] }),
2715
2807
  /* @__PURE__ */ jsxs10("form", { onSubmit: (event) => void handleSubmit(event), className: "space-y-4", children: [
2716
2808
  /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2717
2809
  /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3", children: [
2718
- /* @__PURE__ */ jsx18(Label8, { htmlFor: "create-workspace-name", children: "Name" }),
2810
+ /* @__PURE__ */ jsx19(Label8, { htmlFor: "create-workspace-name", children: "Name" }),
2719
2811
  /* @__PURE__ */ jsxs10("span", { className: "text-xs text-muted-foreground", children: [
2720
2812
  name.length,
2721
2813
  "/100"
2722
2814
  ] })
2723
2815
  ] }),
2724
- /* @__PURE__ */ jsx18(
2816
+ /* @__PURE__ */ jsx19(
2725
2817
  Input8,
2726
2818
  {
2727
2819
  id: "create-workspace-name",
@@ -2737,12 +2829,12 @@ function CreateWorkspaceDialog({
2737
2829
  autoFocus: true
2738
2830
  }
2739
2831
  ),
2740
- nameError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2741
- serverError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2832
+ nameError ? /* @__PURE__ */ jsx19("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2833
+ serverError ? /* @__PURE__ */ jsx19("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2742
2834
  ] }),
2743
2835
  /* @__PURE__ */ jsxs10(DialogFooter2, { children: [
2744
- /* @__PURE__ */ jsx18(Button12, { type: "button", variant: "ghost", onClick: () => handleOpenChange(false), disabled: isSubmitting, children: "Cancel" }),
2745
- /* @__PURE__ */ jsx18(Button12, { type: "submit", disabled: isSubmitting || !validation.success, children: isSubmitting ? "Creating..." : title })
2836
+ /* @__PURE__ */ jsx19(Button12, { type: "button", variant: "ghost", onClick: () => handleOpenChange(false), disabled: isSubmitting, children: "Cancel" }),
2837
+ /* @__PURE__ */ jsx19(Button12, { type: "submit", disabled: isSubmitting || !validation.success, children: isSubmitting ? "Creating..." : title })
2746
2838
  ] })
2747
2839
  ] })
2748
2840
  ] }) });
@@ -2782,31 +2874,31 @@ function ThemeToggle() {
2782
2874
 
2783
2875
  // src/front/auth/AuthErrorPage.tsx
2784
2876
  import { Card as Card7, CardContent as CardContent7, CardDescription as CardDescription7, CardFooter as CardFooter7, CardHeader as CardHeader7, CardTitle as CardTitle7 } from "@hachej/boring-ui-kit";
2785
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2877
+ import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
2786
2878
  function readAuthErrorCode() {
2787
2879
  if (typeof window === "undefined") return null;
2788
2880
  return new URLSearchParams(window.location.search).get("error");
2789
2881
  }
2790
2882
  function AuthErrorPage() {
2791
2883
  const errorCode = readAuthErrorCode();
2792
- return /* @__PURE__ */ jsx19("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12(Card7, { className: "w-full max-w-sm", children: [
2884
+ return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12(Card7, { className: "w-full max-w-sm", children: [
2793
2885
  /* @__PURE__ */ jsxs12(CardHeader7, { children: [
2794
- /* @__PURE__ */ jsx19(CardTitle7, { children: "Authentication error" }),
2795
- /* @__PURE__ */ jsx19(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
2886
+ /* @__PURE__ */ jsx20(CardTitle7, { children: "Authentication error" }),
2887
+ /* @__PURE__ */ jsx20(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
2796
2888
  ] }),
2797
- errorCode && /* @__PURE__ */ jsx19(CardContent7, { children: /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground break-all", children: [
2889
+ errorCode && /* @__PURE__ */ jsx20(CardContent7, { children: /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground break-all", children: [
2798
2890
  "Error: ",
2799
2891
  errorCode
2800
2892
  ] }) }),
2801
2893
  /* @__PURE__ */ jsxs12(CardFooter7, { className: "flex justify-between gap-4 text-sm", children: [
2802
- /* @__PURE__ */ jsx19("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
2803
- /* @__PURE__ */ jsx19("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
2894
+ /* @__PURE__ */ jsx20("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
2895
+ /* @__PURE__ */ jsx20("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
2804
2896
  ] })
2805
2897
  ] }) });
2806
2898
  }
2807
2899
 
2808
2900
  // src/front/workspace/InvitesPage.tsx
2809
- import { useCallback as useCallback6, useState as useState18 } from "react";
2901
+ import { useCallback as useCallback6, useState as useState19 } from "react";
2810
2902
  import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
2811
2903
  import {
2812
2904
  Button as Button14,
@@ -2827,7 +2919,7 @@ import {
2827
2919
  SelectValue,
2828
2920
  StatusBadge
2829
2921
  } from "@hachej/boring-ui-kit";
2830
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
2922
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
2831
2923
  function invitesQueryKey(workspaceId) {
2832
2924
  return ["invites", workspaceId];
2833
2925
  }
@@ -2848,10 +2940,10 @@ function InvitesPage() {
2848
2940
  const workspace = useCurrentWorkspace();
2849
2941
  const role = useWorkspaceRole();
2850
2942
  const queryClient = useQueryClient5();
2851
- const [email, setEmail] = useState18("");
2852
- const [inviteRole, setInviteRole] = useState18("editor");
2853
- const [formError, setFormError] = useState18(null);
2854
- const [successMessage, setSuccessMessage] = useState18(null);
2943
+ const [email, setEmail] = useState19("");
2944
+ const [inviteRole, setInviteRole] = useState19("editor");
2945
+ const [formError, setFormError] = useState19(null);
2946
+ const [successMessage, setSuccessMessage] = useState19(null);
2855
2947
  const workspaceId = workspace?.id ?? "";
2856
2948
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
2857
2949
  const invitesQuery = useQuery5({
@@ -2887,7 +2979,7 @@ function InvitesPage() {
2887
2979
  setFormError(detail.message);
2888
2980
  }
2889
2981
  });
2890
- const [revokeError, setRevokeError] = useState18(null);
2982
+ const [revokeError, setRevokeError] = useState19(null);
2891
2983
  const revokeMutation = useMutation2({
2892
2984
  mutationFn: async (inviteId) => {
2893
2985
  await apiFetch(
@@ -2919,15 +3011,15 @@ function InvitesPage() {
2919
3011
  [email, inviteRole, createMutation]
2920
3012
  );
2921
3013
  if (role !== "owner") {
2922
- return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx20(Card8, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs13(CardHeader8, { children: [
2923
- /* @__PURE__ */ jsx20(CardTitle8, { children: "Access denied" }),
2924
- /* @__PURE__ */ jsx20(CardDescription8, { children: "Only workspace owners can manage invites." })
3014
+ return /* @__PURE__ */ jsx21("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx21(Card8, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs13(CardHeader8, { children: [
3015
+ /* @__PURE__ */ jsx21(CardTitle8, { children: "Access denied" }),
3016
+ /* @__PURE__ */ jsx21(CardDescription8, { children: "Only workspace owners can manage invites." })
2925
3017
  ] }) }) });
2926
3018
  }
2927
- return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-2xl space-y-6", children: [
3019
+ return /* @__PURE__ */ jsx21("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-2xl space-y-6", children: [
2928
3020
  /* @__PURE__ */ jsxs13(Card8, { children: [
2929
3021
  /* @__PURE__ */ jsxs13(CardHeader8, { children: [
2930
- /* @__PURE__ */ jsx20(CardTitle8, { children: "Invite a member" }),
3022
+ /* @__PURE__ */ jsx21(CardTitle8, { children: "Invite a member" }),
2931
3023
  /* @__PURE__ */ jsxs13(CardDescription8, { children: [
2932
3024
  "Send an invite to join ",
2933
3025
  workspace?.name ?? "this workspace",
@@ -2936,11 +3028,11 @@ function InvitesPage() {
2936
3028
  ] }),
2937
3029
  /* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
2938
3030
  /* @__PURE__ */ jsxs13(CardContent8, { className: "space-y-4", children: [
2939
- formError && /* @__PURE__ */ jsx20(Notice3, { role: "alert", tone: "error", description: formError }),
2940
- successMessage && /* @__PURE__ */ jsx20(Notice3, { role: "status", tone: "success", description: successMessage }),
3031
+ formError && /* @__PURE__ */ jsx21(Notice3, { role: "alert", tone: "error", description: formError }),
3032
+ successMessage && /* @__PURE__ */ jsx21(Notice3, { role: "status", tone: "success", description: successMessage }),
2941
3033
  /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
2942
- /* @__PURE__ */ jsx20(Label9, { htmlFor: "invite-email", children: "Email address" }),
2943
- /* @__PURE__ */ jsx20(
3034
+ /* @__PURE__ */ jsx21(Label9, { htmlFor: "invite-email", children: "Email address" }),
3035
+ /* @__PURE__ */ jsx21(
2944
3036
  Input9,
2945
3037
  {
2946
3038
  id: "invite-email",
@@ -2953,18 +3045,18 @@ function InvitesPage() {
2953
3045
  )
2954
3046
  ] }),
2955
3047
  /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
2956
- /* @__PURE__ */ jsx20(Label9, { htmlFor: "invite-role", children: "Role" }),
3048
+ /* @__PURE__ */ jsx21(Label9, { htmlFor: "invite-role", children: "Role" }),
2957
3049
  /* @__PURE__ */ jsxs13(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
2958
- /* @__PURE__ */ jsx20(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx20(SelectValue, { placeholder: "Select role" }) }),
3050
+ /* @__PURE__ */ jsx21(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx21(SelectValue, { placeholder: "Select role" }) }),
2959
3051
  /* @__PURE__ */ jsxs13(SelectContent, { children: [
2960
- /* @__PURE__ */ jsx20(SelectItem, { value: "editor", children: "Editor" }),
2961
- /* @__PURE__ */ jsx20(SelectItem, { value: "viewer", children: "Viewer" }),
2962
- /* @__PURE__ */ jsx20(SelectItem, { value: "owner", children: "Owner" })
3052
+ /* @__PURE__ */ jsx21(SelectItem, { value: "editor", children: "Editor" }),
3053
+ /* @__PURE__ */ jsx21(SelectItem, { value: "viewer", children: "Viewer" }),
3054
+ /* @__PURE__ */ jsx21(SelectItem, { value: "owner", children: "Owner" })
2963
3055
  ] })
2964
3056
  ] })
2965
3057
  ] })
2966
3058
  ] }),
2967
- /* @__PURE__ */ jsx20(CardFooter8, { children: /* @__PURE__ */ jsx20(
3059
+ /* @__PURE__ */ jsx21(CardFooter8, { children: /* @__PURE__ */ jsx21(
2968
3060
  Button14,
2969
3061
  {
2970
3062
  type: "submit",
@@ -2977,14 +3069,14 @@ function InvitesPage() {
2977
3069
  ] }),
2978
3070
  /* @__PURE__ */ jsxs13(Card8, { children: [
2979
3071
  /* @__PURE__ */ jsxs13(CardHeader8, { children: [
2980
- /* @__PURE__ */ jsx20(CardTitle8, { children: "Pending invites" }),
2981
- /* @__PURE__ */ jsx20(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
3072
+ /* @__PURE__ */ jsx21(CardTitle8, { children: "Pending invites" }),
3073
+ /* @__PURE__ */ jsx21(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
2982
3074
  ] }),
2983
3075
  /* @__PURE__ */ jsxs13(CardContent8, { children: [
2984
- revokeError && /* @__PURE__ */ jsx20(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
2985
- invitesQuery.isLoading && /* @__PURE__ */ jsx20(LoadingState2, {}),
2986
- invitesQuery.isError && /* @__PURE__ */ jsx20(Notice3, { tone: "error", description: "Failed to load invites." }),
2987
- invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx20("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
3076
+ revokeError && /* @__PURE__ */ jsx21(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
3077
+ invitesQuery.isLoading && /* @__PURE__ */ jsx21(LoadingState2, {}),
3078
+ invitesQuery.isError && /* @__PURE__ */ jsx21(Notice3, { tone: "error", description: "Failed to load invites." }),
3079
+ invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx21("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
2988
3080
  const status = getInviteStatus(invite);
2989
3081
  return /* @__PURE__ */ jsxs13(
2990
3082
  "div",
@@ -2993,10 +3085,10 @@ function InvitesPage() {
2993
3085
  "data-testid": `invite-row-${invite.id}`,
2994
3086
  children: [
2995
3087
  /* @__PURE__ */ jsxs13("div", { className: "space-y-1", children: [
2996
- /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium", children: invite.email }),
3088
+ /* @__PURE__ */ jsx21("p", { className: "text-sm font-medium", children: invite.email }),
2997
3089
  /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2998
- /* @__PURE__ */ jsx20("span", { children: invite.role }),
2999
- /* @__PURE__ */ jsx20(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
3090
+ /* @__PURE__ */ jsx21("span", { children: invite.role }),
3091
+ /* @__PURE__ */ jsx21(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
3000
3092
  /* @__PURE__ */ jsxs13("span", { children: [
3001
3093
  "expires",
3002
3094
  " ",
@@ -3004,7 +3096,7 @@ function InvitesPage() {
3004
3096
  ] })
3005
3097
  ] })
3006
3098
  ] }),
3007
- status === "pending" && /* @__PURE__ */ jsx20(
3099
+ status === "pending" && /* @__PURE__ */ jsx21(
3008
3100
  Button14,
3009
3101
  {
3010
3102
  variant: "destructive",
@@ -3026,7 +3118,7 @@ function InvitesPage() {
3026
3118
  }
3027
3119
 
3028
3120
  // src/front/workspace/MembersPage.tsx
3029
- import { useCallback as useCallback7, useState as useState19 } from "react";
3121
+ import { useCallback as useCallback7, useState as useState20 } from "react";
3030
3122
  import { useMutation as useMutation3, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
3031
3123
  import {
3032
3124
  AlertDialog as AlertDialog2,
@@ -3051,7 +3143,7 @@ import {
3051
3143
  LoadingState as LoadingState3,
3052
3144
  Notice as Notice4
3053
3145
  } from "@hachej/boring-ui-kit";
3054
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
3146
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
3055
3147
  var ROLE_OPTIONS = ["owner", "editor", "viewer"];
3056
3148
  function MembersPage() {
3057
3149
  const workspace = useCurrentWorkspace();
@@ -3062,8 +3154,8 @@ function MembersPage() {
3062
3154
  const currentUserId = session.data?.user?.id ?? "";
3063
3155
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
3064
3156
  const membersQuery = useWorkspaceMembers(workspaceId);
3065
- const [toast, setToast] = useState19(null);
3066
- const [confirmTarget, setConfirmTarget] = useState19(null);
3157
+ const [toast, setToast] = useState20(null);
3158
+ const [confirmTarget, setConfirmTarget] = useState20(null);
3067
3159
  const showToast = useCallback7((msg) => {
3068
3160
  setToast(msg);
3069
3161
  setTimeout(() => setToast(null), 4e3);
@@ -3124,10 +3216,10 @@ function MembersPage() {
3124
3216
  removeMutation.mutate(confirmTarget.userId);
3125
3217
  }, [confirmTarget, removeMutation]);
3126
3218
  const isOwner = myRole === "owner";
3127
- return /* @__PURE__ */ jsx21("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs14("div", { className: "w-full max-w-2xl space-y-6", children: [
3219
+ return /* @__PURE__ */ jsx22("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs14("div", { className: "w-full max-w-2xl space-y-6", children: [
3128
3220
  /* @__PURE__ */ jsxs14(Card9, { children: [
3129
3221
  /* @__PURE__ */ jsxs14(CardHeader9, { children: [
3130
- /* @__PURE__ */ jsx21(CardTitle9, { children: "Members" }),
3222
+ /* @__PURE__ */ jsx22(CardTitle9, { children: "Members" }),
3131
3223
  /* @__PURE__ */ jsxs14(CardDescription9, { children: [
3132
3224
  workspace?.name ?? "Workspace",
3133
3225
  " \xB7",
@@ -3138,10 +3230,10 @@ function MembersPage() {
3138
3230
  ] })
3139
3231
  ] }),
3140
3232
  /* @__PURE__ */ jsxs14(CardContent9, { children: [
3141
- toast && /* @__PURE__ */ jsx21(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
3142
- membersQuery.isLoading && /* @__PURE__ */ jsx21(LoadingState3, {}),
3143
- membersQuery.isError && /* @__PURE__ */ jsx21(Notice4, { tone: "error", description: "Failed to load members." }),
3144
- membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx21("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
3233
+ toast && /* @__PURE__ */ jsx22(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
3234
+ membersQuery.isLoading && /* @__PURE__ */ jsx22(LoadingState3, {}),
3235
+ membersQuery.isError && /* @__PURE__ */ jsx22(Notice4, { tone: "error", description: "Failed to load members." }),
3236
+ membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx22("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
3145
3237
  const isSelf = member.userId === currentUserId;
3146
3238
  const canChangeRole = isOwner && !isSelf;
3147
3239
  const canRemove = isOwner || isSelf;
@@ -3152,13 +3244,13 @@ function MembersPage() {
3152
3244
  "data-testid": `member-row-${member.userId}`,
3153
3245
  children: [
3154
3246
  /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3", children: [
3155
- /* @__PURE__ */ jsx21(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
3247
+ /* @__PURE__ */ jsx22(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
3156
3248
  /* @__PURE__ */ jsxs14("div", { children: [
3157
3249
  /* @__PURE__ */ jsxs14("p", { className: "text-sm font-medium", children: [
3158
3250
  member.user.name ?? member.user.email,
3159
- isSelf && /* @__PURE__ */ jsx21("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
3251
+ isSelf && /* @__PURE__ */ jsx22("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
3160
3252
  ] }),
3161
- /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: member.user.email })
3253
+ /* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: member.user.email })
3162
3254
  ] })
3163
3255
  ] }),
3164
3256
  /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
@@ -3169,12 +3261,12 @@ function MembersPage() {
3169
3261
  disabled: !canChangeRole,
3170
3262
  onValueChange: (value) => handleRoleChange(member.userId, value),
3171
3263
  children: [
3172
- /* @__PURE__ */ jsx21(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx21(SelectValue2, { placeholder: "Role" }) }),
3173
- /* @__PURE__ */ jsx21(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx21(SelectItem2, { value: r, children: r }, r)) })
3264
+ /* @__PURE__ */ jsx22(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx22(SelectValue2, { placeholder: "Role" }) }),
3265
+ /* @__PURE__ */ jsx22(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx22(SelectItem2, { value: r, children: r }, r)) })
3174
3266
  ]
3175
3267
  }
3176
3268
  ),
3177
- canRemove && /* @__PURE__ */ jsx21(
3269
+ canRemove && /* @__PURE__ */ jsx22(
3178
3270
  Button15,
3179
3271
  {
3180
3272
  variant: "destructive",
@@ -3192,7 +3284,7 @@ function MembersPage() {
3192
3284
  }) })
3193
3285
  ] })
3194
3286
  ] }),
3195
- /* @__PURE__ */ jsx21(
3287
+ /* @__PURE__ */ jsx22(
3196
3288
  AlertDialog2,
3197
3289
  {
3198
3290
  open: confirmTarget !== null,
@@ -3201,12 +3293,12 @@ function MembersPage() {
3201
3293
  },
3202
3294
  children: /* @__PURE__ */ jsxs14(AlertDialogContent2, { children: [
3203
3295
  /* @__PURE__ */ jsxs14(AlertDialogHeader2, { children: [
3204
- /* @__PURE__ */ jsx21(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
3205
- /* @__PURE__ */ jsx21(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
3296
+ /* @__PURE__ */ jsx22(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
3297
+ /* @__PURE__ */ jsx22(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
3206
3298
  ] }),
3207
3299
  /* @__PURE__ */ jsxs14(AlertDialogFooter2, { children: [
3208
- /* @__PURE__ */ jsx21(AlertDialogCancel2, { children: "Cancel" }),
3209
- /* @__PURE__ */ jsx21(
3300
+ /* @__PURE__ */ jsx22(AlertDialogCancel2, { children: "Cancel" }),
3301
+ /* @__PURE__ */ jsx22(
3210
3302
  Button15,
3211
3303
  {
3212
3304
  variant: "destructive",
@@ -3224,7 +3316,7 @@ function MembersPage() {
3224
3316
  }
3225
3317
 
3226
3318
  // src/front/workspace/WorkspaceSettingsPage.tsx
3227
- import { useCallback as useCallback8, useEffect as useEffect10, useState as useState20 } from "react";
3319
+ import { useCallback as useCallback8, useEffect as useEffect11, useState as useState21 } from "react";
3228
3320
  import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
3229
3321
  import { useNavigate as useNavigate5 } from "react-router-dom";
3230
3322
  import {
@@ -3254,7 +3346,7 @@ import {
3254
3346
  ShieldAlert as ShieldAlert2,
3255
3347
  Trash2 as Trash22
3256
3348
  } from "lucide-react";
3257
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
3349
+ import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
3258
3350
  var STATE_TONES = {
3259
3351
  pending: "info",
3260
3352
  ready: "success",
@@ -3266,13 +3358,13 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
3266
3358
  const appInitial = (appTitle.trim().charAt(0) || "B").toUpperCase();
3267
3359
  const navigate = useNavigate5();
3268
3360
  const workspaceHref = workspaceId ? `/workspace/${encodeURIComponent(workspaceId)}` : "/";
3269
- return /* @__PURE__ */ jsx22(
3361
+ return /* @__PURE__ */ jsx23(
3270
3362
  "header",
3271
3363
  {
3272
3364
  className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
3273
3365
  "aria-label": "App top bar",
3274
3366
  children: /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
3275
- /* @__PURE__ */ jsx22(
3367
+ /* @__PURE__ */ jsx23(
3276
3368
  IconButton,
3277
3369
  {
3278
3370
  type: "button",
@@ -3285,11 +3377,11 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
3285
3377
  children: appInitial
3286
3378
  }
3287
3379
  ),
3288
- /* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
3289
- /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3290
- /* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
3291
- /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3292
- /* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
3380
+ /* @__PURE__ */ jsx23("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
3381
+ /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3382
+ /* @__PURE__ */ jsx23("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
3383
+ /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3384
+ /* @__PURE__ */ jsx23("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
3293
3385
  ] })
3294
3386
  }
3295
3387
  );
@@ -3302,24 +3394,24 @@ function SettingsPageHeader2({
3302
3394
  }) {
3303
3395
  return /* @__PURE__ */ jsxs15("header", { className: "boring-settings-page-header", children: [
3304
3396
  /* @__PURE__ */ jsxs15("div", { className: "boring-settings-context", children: [
3305
- /* @__PURE__ */ jsx22("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: workspaceInitial2 }),
3397
+ /* @__PURE__ */ jsx23("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: workspaceInitial2 }),
3306
3398
  /* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
3307
- /* @__PURE__ */ jsx22("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
3399
+ /* @__PURE__ */ jsx23("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
3308
3400
  /* @__PURE__ */ jsxs15("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
3309
- /* @__PURE__ */ jsx22("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
3310
- isDefault ? /* @__PURE__ */ jsx22("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
3401
+ /* @__PURE__ */ jsx23("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
3402
+ isDefault ? /* @__PURE__ */ jsx23("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
3311
3403
  ] })
3312
3404
  ] })
3313
3405
  ] }),
3314
3406
  /* @__PURE__ */ jsxs15("div", { className: "max-w-2xl", children: [
3315
- /* @__PURE__ */ jsx22("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
3316
- /* @__PURE__ */ jsx22("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
3317
- /* @__PURE__ */ jsx22("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
3407
+ /* @__PURE__ */ jsx23("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
3408
+ /* @__PURE__ */ jsx23("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
3409
+ /* @__PURE__ */ jsx23("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
3318
3410
  ] })
3319
3411
  ] });
3320
3412
  }
3321
3413
  function FieldNote({ children }) {
3322
- return /* @__PURE__ */ jsx22("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
3414
+ return /* @__PURE__ */ jsx23("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
3323
3415
  }
3324
3416
  function roleLabel(role) {
3325
3417
  if (!role) return "Loading role";
@@ -3337,14 +3429,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3337
3429
  const queryClient = useQueryClient7();
3338
3430
  const navigate = useNavigate5();
3339
3431
  const workspaceId = workspace?.id ?? "";
3340
- const [nameValue, setNameValue] = useState20(null);
3341
- const [nameError, setNameError] = useState20(null);
3342
- const [retryError, setRetryError] = useState20(null);
3343
- const [deleteConfirmName, setDeleteConfirmName] = useState20("");
3344
- const [deleteDialogOpen, setDeleteDialogOpen] = useState20(false);
3345
- const [deleteError, setDeleteError] = useState20(null);
3346
- const [imageUploadDirValue, setImageUploadDirValue] = useState20(null);
3347
- const [fileSettingsError, setFileSettingsError] = useState20(null);
3432
+ const [nameValue, setNameValue] = useState21(null);
3433
+ const [nameError, setNameError] = useState21(null);
3434
+ const [retryError, setRetryError] = useState21(null);
3435
+ const [deleteConfirmName, setDeleteConfirmName] = useState21("");
3436
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState21(false);
3437
+ const [deleteError, setDeleteError] = useState21(null);
3438
+ const [imageUploadDirValue, setImageUploadDirValue] = useState21(null);
3439
+ const [fileSettingsError, setFileSettingsError] = useState21(null);
3348
3440
  const displayName = nameValue ?? workspace?.name ?? "";
3349
3441
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
3350
3442
  const requestHeaders = workspaceId ? { "x-boring-workspace-id": workspaceId } : void 0;
@@ -3382,7 +3474,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3382
3474
  enabled: workspaceId.length > 0,
3383
3475
  retry: false
3384
3476
  });
3385
- useEffect10(() => {
3477
+ useEffect11(() => {
3386
3478
  const next = fileSettingsQuery.data?.markdown?.imageUploadDir;
3387
3479
  if (typeof next === "string") setImageUploadDirValue(next);
3388
3480
  }, [fileSettingsQuery.data?.markdown?.imageUploadDir]);
@@ -3490,7 +3582,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3490
3582
  const canDeleteWorkspace = role === "owner" || role === null;
3491
3583
  const workspaceName = workspace?.name ?? "Workspace";
3492
3584
  const workspaceInitial2 = (workspace?.name?.trim()?.[0] ?? "W").toUpperCase();
3493
- const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx22(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
3585
+ const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx23(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
3494
3586
  const navItems = WORKSPACE_NAV_ITEMS.filter((item) => {
3495
3587
  if (item.href === "#runtime") return hasRuntime;
3496
3588
  if (item.href === "#files") return hasFileSettings;
@@ -3498,10 +3590,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3498
3590
  });
3499
3591
  return /* @__PURE__ */ jsxs15("main", { className: "boring-settings-shell", children: [
3500
3592
  topBarNode,
3501
- /* @__PURE__ */ jsx22("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs15("div", { className: "boring-settings-layout", children: [
3502
- /* @__PURE__ */ jsx22("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx22(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
3593
+ /* @__PURE__ */ jsx23("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs15("div", { className: "boring-settings-layout", children: [
3594
+ /* @__PURE__ */ jsx23("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx23(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
3503
3595
  /* @__PURE__ */ jsxs15("div", { className: "boring-settings-content space-y-4", children: [
3504
- /* @__PURE__ */ jsx22(
3596
+ /* @__PURE__ */ jsx23(
3505
3597
  SettingsPageHeader2,
3506
3598
  {
3507
3599
  workspaceName,
@@ -3510,15 +3602,15 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3510
3602
  isDefault: Boolean(workspace?.isDefault)
3511
3603
  }
3512
3604
  ),
3513
- /* @__PURE__ */ jsx22(
3605
+ /* @__PURE__ */ jsx23(
3514
3606
  UiSettingsPanel2,
3515
3607
  {
3516
3608
  id: "general",
3517
- icon: /* @__PURE__ */ jsx22(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3609
+ icon: /* @__PURE__ */ jsx23(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3518
3610
  title: "General",
3519
3611
  description: "Keep the workspace name clear enough to scan in menus.",
3520
3612
  footer: /* @__PURE__ */ jsxs15(Fragment5, { children: [
3521
- nameChanged ? /* @__PURE__ */ jsx22(
3613
+ nameChanged ? /* @__PURE__ */ jsx23(
3522
3614
  Button16,
3523
3615
  {
3524
3616
  type: "button",
@@ -3532,7 +3624,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3532
3624
  children: "Reset"
3533
3625
  }
3534
3626
  ) : null,
3535
- /* @__PURE__ */ jsx22(
3627
+ /* @__PURE__ */ jsx23(
3536
3628
  Button16,
3537
3629
  {
3538
3630
  "data-testid": "save-name",
@@ -3544,10 +3636,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3544
3636
  )
3545
3637
  ] }),
3546
3638
  children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3547
- nameError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
3639
+ nameError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
3548
3640
  /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
3549
- /* @__PURE__ */ jsx22(Label10, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
3550
- /* @__PURE__ */ jsx22(
3641
+ /* @__PURE__ */ jsx23(Label10, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
3642
+ /* @__PURE__ */ jsx23(
3551
3643
  Input10,
3552
3644
  {
3553
3645
  id: "workspace-name",
@@ -3559,23 +3651,23 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3559
3651
  "aria-invalid": nameError ? "true" : "false"
3560
3652
  }
3561
3653
  ),
3562
- /* @__PURE__ */ jsx22(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
3654
+ /* @__PURE__ */ jsx23(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
3563
3655
  ] })
3564
3656
  ] })
3565
3657
  }
3566
3658
  ),
3567
- hasRuntime && /* @__PURE__ */ jsx22(
3659
+ hasRuntime && /* @__PURE__ */ jsx23(
3568
3660
  UiSettingsPanel2,
3569
3661
  {
3570
3662
  id: "runtime",
3571
3663
  testId: "runtime-card",
3572
- icon: /* @__PURE__ */ jsx22(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3664
+ icon: /* @__PURE__ */ jsx23(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3573
3665
  title: "Runtime",
3574
3666
  description: "Provisioning status for this workspace.",
3575
3667
  children: /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
3576
3668
  /* @__PURE__ */ jsxs15("div", { className: "flex min-h-10 flex-wrap items-center justify-between gap-3 rounded-md border border-border/50 bg-muted/10 px-3 py-2", children: [
3577
- /* @__PURE__ */ jsx22("span", { className: "text-[13px] font-medium", children: "State" }),
3578
- /* @__PURE__ */ jsx22(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
3669
+ /* @__PURE__ */ jsx23("span", { className: "text-[13px] font-medium", children: "State" }),
3670
+ /* @__PURE__ */ jsx23(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
3579
3671
  ] }),
3580
3672
  runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs15(
3581
3673
  "div",
@@ -3583,8 +3675,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3583
3675
  "data-testid": "volume-path",
3584
3676
  className: "space-y-1 rounded-md border border-border/50 bg-muted/10 px-3 py-2",
3585
3677
  children: [
3586
- /* @__PURE__ */ jsx22("p", { className: "text-[13px] font-medium", children: "Volume" }),
3587
- /* @__PURE__ */ jsx22("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
3678
+ /* @__PURE__ */ jsx23("p", { className: "text-[13px] font-medium", children: "Volume" }),
3679
+ /* @__PURE__ */ jsx23("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
3588
3680
  ]
3589
3681
  }
3590
3682
  ),
@@ -3595,7 +3687,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3595
3687
  role: "alert",
3596
3688
  className: "flex gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[13px] leading-5 text-destructive",
3597
3689
  children: [
3598
- /* @__PURE__ */ jsx22(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
3690
+ /* @__PURE__ */ jsx23(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
3599
3691
  runtime.lastError
3600
3692
  ]
3601
3693
  }
@@ -3610,14 +3702,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3610
3702
  disabled: retryMutation.isPending,
3611
3703
  onClick: () => retryMutation.mutate(),
3612
3704
  children: [
3613
- /* @__PURE__ */ jsx22(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
3705
+ /* @__PURE__ */ jsx23(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
3614
3706
  retryMutation.isPending ? "Retrying..." : "Retry provisioning"
3615
3707
  ]
3616
3708
  }
3617
3709
  ),
3618
- retryError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
3710
+ retryError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
3619
3711
  ] }),
3620
- runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx22(
3712
+ runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx23(
3621
3713
  "p",
3622
3714
  {
3623
3715
  "data-testid": "destroy-guidance",
@@ -3628,15 +3720,15 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3628
3720
  ] })
3629
3721
  }
3630
3722
  ),
3631
- hasFileSettings && /* @__PURE__ */ jsx22(
3723
+ hasFileSettings && /* @__PURE__ */ jsx23(
3632
3724
  UiSettingsPanel2,
3633
3725
  {
3634
3726
  id: "files",
3635
3727
  testId: "file-settings-card",
3636
- icon: /* @__PURE__ */ jsx22(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3728
+ icon: /* @__PURE__ */ jsx23(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3637
3729
  title: "Files",
3638
3730
  description: "Configure where markdown editor image uploads are stored. Direct/local workspaces can also edit .boring/settings.",
3639
- footer: /* @__PURE__ */ jsx22(
3731
+ footer: /* @__PURE__ */ jsx23(
3640
3732
  Button16,
3641
3733
  {
3642
3734
  "data-testid": "save-file-settings",
@@ -3647,10 +3739,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3647
3739
  }
3648
3740
  ),
3649
3741
  children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3650
- fileSettingsError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
3742
+ fileSettingsError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
3651
3743
  /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
3652
- /* @__PURE__ */ jsx22(Label10, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
3653
- /* @__PURE__ */ jsx22(
3744
+ /* @__PURE__ */ jsx23(Label10, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
3745
+ /* @__PURE__ */ jsx23(
3654
3746
  Input10,
3655
3747
  {
3656
3748
  id: "markdown-image-upload-dir",
@@ -3663,26 +3755,26 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3663
3755
  ),
3664
3756
  /* @__PURE__ */ jsxs15(FieldNote, { children: [
3665
3757
  "Relative workspace path used by markdown image uploads. Stored in ",
3666
- /* @__PURE__ */ jsx22("code", { children: ".boring/settings" }),
3758
+ /* @__PURE__ */ jsx23("code", { children: ".boring/settings" }),
3667
3759
  "."
3668
3760
  ] })
3669
3761
  ] })
3670
3762
  ] })
3671
3763
  }
3672
3764
  ),
3673
- /* @__PURE__ */ jsx22(
3765
+ /* @__PURE__ */ jsx23(
3674
3766
  UiSettingsPanel2,
3675
3767
  {
3676
3768
  id: "danger-zone",
3677
3769
  testId: "danger-zone",
3678
- icon: /* @__PURE__ */ jsx22(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3770
+ icon: /* @__PURE__ */ jsx23(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3679
3771
  title: "Danger zone",
3680
3772
  description: "Permanently delete this workspace and all provisioned data.",
3681
3773
  danger: true,
3682
3774
  children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3683
- deleteError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
3684
- !canDeleteWorkspace ? /* @__PURE__ */ jsx22("div", { className: "rounded-md border border-border/50 bg-muted/10 px-3 py-2 text-[13px] leading-5 text-muted-foreground", children: "Only workspace owners can delete this workspace." }) : null,
3685
- /* @__PURE__ */ jsx22(
3775
+ deleteError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
3776
+ !canDeleteWorkspace ? /* @__PURE__ */ jsx23("div", { className: "rounded-md border border-border/50 bg-muted/10 px-3 py-2 text-[13px] leading-5 text-muted-foreground", children: "Only workspace owners can delete this workspace." }) : null,
3777
+ /* @__PURE__ */ jsx23(
3686
3778
  UiSettingsActionRow2,
3687
3779
  {
3688
3780
  title: "Delete workspace",
@@ -3700,21 +3792,21 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3700
3792
  setDeleteConfirmName("");
3701
3793
  },
3702
3794
  children: [
3703
- /* @__PURE__ */ jsx22(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
3795
+ /* @__PURE__ */ jsx23(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
3704
3796
  "Delete workspace"
3705
3797
  ]
3706
3798
  }
3707
3799
  ),
3708
3800
  /* @__PURE__ */ jsxs15(AlertDialogContent3, { children: [
3709
3801
  /* @__PURE__ */ jsxs15(AlertDialogHeader3, { children: [
3710
- /* @__PURE__ */ jsx22(AlertDialogTitle3, { children: "Delete workspace?" }),
3802
+ /* @__PURE__ */ jsx23(AlertDialogTitle3, { children: "Delete workspace?" }),
3711
3803
  /* @__PURE__ */ jsxs15(AlertDialogDescription3, { children: [
3712
3804
  "This action cannot be undone. Type ",
3713
- /* @__PURE__ */ jsx22("strong", { children: workspace?.name }),
3805
+ /* @__PURE__ */ jsx23("strong", { children: workspace?.name }),
3714
3806
  " to confirm."
3715
3807
  ] })
3716
3808
  ] }),
3717
- /* @__PURE__ */ jsx22("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx22(
3809
+ /* @__PURE__ */ jsx23("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx23(
3718
3810
  Input10,
3719
3811
  {
3720
3812
  "data-testid": "delete-confirm-input",
@@ -3726,8 +3818,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3726
3818
  }
3727
3819
  ) }),
3728
3820
  /* @__PURE__ */ jsxs15(AlertDialogFooter3, { children: [
3729
- /* @__PURE__ */ jsx22(AlertDialogCancel3, { children: "Cancel" }),
3730
- /* @__PURE__ */ jsx22(
3821
+ /* @__PURE__ */ jsx23(AlertDialogCancel3, { children: "Cancel" }),
3822
+ /* @__PURE__ */ jsx23(
3731
3823
  Button16,
3732
3824
  {
3733
3825
  variant: "destructive",
@@ -3751,11 +3843,65 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3751
3843
  ] });
3752
3844
  }
3753
3845
 
3846
+ // src/front/workspace/CompanyAdminPage.tsx
3847
+ import { Navigate } from "react-router-dom";
3848
+ import { Button as Button17 } from "@hachej/boring-ui-kit";
3849
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
3850
+ var DEFAULT_PAGE_TITLE = "Admin";
3851
+ var DEFAULT_DENIED_MESSAGE = "You do not have access to this page.";
3852
+ function CompanyAdminPage() {
3853
+ const currentWorkspace = useCurrentWorkspace();
3854
+ const routeStatus = useWorkspaceRouteStatus();
3855
+ const companyAdmin = useCompanyAdminStatus();
3856
+ const pageTitle = companyAdmin.labels.pageTitle ?? DEFAULT_PAGE_TITLE;
3857
+ const deniedMessage = companyAdmin.labels.deniedMessage ?? DEFAULT_DENIED_MESSAGE;
3858
+ if (!companyAdmin.configured) return /* @__PURE__ */ jsx24(Navigate, { to: "/", replace: true });
3859
+ if (routeStatus.status === "loading") {
3860
+ return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsx24("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", "aria-busy": "true", children: /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading admin\u2026" }) }) });
3861
+ }
3862
+ if (companyAdmin.configured && companyAdmin.loading && !companyAdmin.status) {
3863
+ return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsx24("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", "aria-busy": "true", children: /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading admin status\u2026" }) }) });
3864
+ }
3865
+ if (companyAdmin.error) {
3866
+ const workspace2 = routeStatus.status === "matched" ? routeStatus.workspace : currentWorkspace;
3867
+ const workspaceId2 = routeStatus.workspaceId ?? workspace2?.id ?? null;
3868
+ return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsxs16("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", children: [
3869
+ /* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-destructive", children: "Admin unavailable" }),
3870
+ /* @__PURE__ */ jsx24("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: pageTitle }),
3871
+ /* @__PURE__ */ jsx24("p", { className: "mt-2 text-sm text-muted-foreground", children: companyAdmin.error }),
3872
+ workspaceId2 ? /* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: routeHref("workspaceSettings", { id: workspaceId2 }), children: "Back to workspace settings" }) }) : /* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: "/", children: "Back to workspace" }) })
3873
+ ] }) });
3874
+ }
3875
+ if (!companyAdmin.status || companyAdmin.status.enabled !== true) return /* @__PURE__ */ jsx24(Navigate, { to: "/", replace: true });
3876
+ if (routeStatus.status === "not-found" || routeStatus.status === "switch-failed" || routeStatus.status === "mismatched") {
3877
+ const message = routeStatus.status === "mismatched" ? "The requested workspace could not be loaded." : routeStatus.message;
3878
+ return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsxs16("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", children: [
3879
+ /* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-destructive", children: "Workspace unavailable" }),
3880
+ /* @__PURE__ */ jsx24("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: pageTitle }),
3881
+ /* @__PURE__ */ jsx24("p", { className: "mt-2 text-sm text-muted-foreground", children: message }),
3882
+ /* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: "/", children: "Back to workspace" }) })
3883
+ ] }) });
3884
+ }
3885
+ const workspace = routeStatus.status === "matched" ? routeStatus.workspace : currentWorkspace;
3886
+ const workspaceId = routeStatus.workspaceId ?? workspace?.id ?? null;
3887
+ if (!workspaceId) return /* @__PURE__ */ jsx24(Navigate, { to: "/", replace: true });
3888
+ if (routeStatus.status === "forbidden" || companyAdmin.status.admin !== true) {
3889
+ return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsxs16("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", children: [
3890
+ /* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-destructive", children: "Access required" }),
3891
+ /* @__PURE__ */ jsx24("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: pageTitle }),
3892
+ /* @__PURE__ */ jsx24("p", { className: "mt-2 text-sm text-muted-foreground", children: deniedMessage }),
3893
+ /* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: routeHref("workspaceSettings", { id: workspaceId }), children: "Back to workspace settings" }) })
3894
+ ] }) });
3895
+ }
3896
+ const renderedAppContent = companyAdmin.renderContent ? companyAdmin.renderContent(companyAdmin.status) : null;
3897
+ return renderedAppContent ? /* @__PURE__ */ jsx24(Fragment6, { children: renderedAppContent }) : null;
3898
+ }
3899
+
3754
3900
  // src/front/CoreFront.tsx
3755
- import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
3901
+ import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
3756
3902
  var CSP_NONCE_META_NAME = "boring-csp-nonce";
3757
3903
  function PlaceholderPage({ name }) {
3758
- return /* @__PURE__ */ jsxs16("div", { "data-testid": `placeholder-${name}`, children: [
3904
+ return /* @__PURE__ */ jsxs17("div", { "data-testid": `placeholder-${name}`, children: [
3759
3905
  name,
3760
3906
  " (not yet implemented)"
3761
3907
  ] });
@@ -3766,6 +3912,22 @@ function readCspNonceFromDom() {
3766
3912
  const value = meta?.getAttribute("content")?.trim();
3767
3913
  return value ? value : void 0;
3768
3914
  }
3915
+ function CspNonceScript({ nonce }) {
3916
+ useEffect12(() => {
3917
+ const selector = 'script[data-boring-csp-nonce="true"]';
3918
+ const existing = document.head.querySelector(selector);
3919
+ const script = existing ?? document.createElement("script");
3920
+ script.type = "application/json";
3921
+ script.setAttribute("nonce", nonce);
3922
+ script.dataset.boringCspNonce = "true";
3923
+ script.textContent = JSON.stringify({ nonce });
3924
+ if (!existing) document.head.appendChild(script);
3925
+ return () => {
3926
+ script.remove();
3927
+ };
3928
+ }, [nonce]);
3929
+ return null;
3930
+ }
3769
3931
  function createDefaultQueryClient() {
3770
3932
  return new QueryClient({
3771
3933
  defaultOptions: {
@@ -3776,11 +3938,25 @@ function createDefaultQueryClient() {
3776
3938
  }
3777
3939
  });
3778
3940
  }
3941
+ function CompanyAdminScopedProvider({ children, companyAdmin }) {
3942
+ const session = useSession();
3943
+ const identityKey = session.data?.user?.id ?? null;
3944
+ return /* @__PURE__ */ jsx25(
3945
+ CompanyAdminProvider,
3946
+ {
3947
+ loadStatus: companyAdmin?.loadStatus,
3948
+ renderContent: companyAdmin?.renderContent,
3949
+ labels: companyAdmin?.labels,
3950
+ identityKey,
3951
+ children
3952
+ }
3953
+ );
3954
+ }
3779
3955
  function RouterAuthGate({ children, publicPaths }) {
3780
3956
  const config = useConfig();
3781
3957
  const location = useLocation2();
3782
3958
  const navigate = useNavigate6();
3783
- const authLocation = useMemo7(
3959
+ const authLocation = useMemo8(
3784
3960
  () => ({ pathname: location.pathname, search: location.search, hash: location.hash }),
3785
3961
  [location.hash, location.pathname, location.search]
3786
3962
  );
@@ -3790,7 +3966,7 @@ function RouterAuthGate({ children, publicPaths }) {
3790
3966
  },
3791
3967
  [navigate]
3792
3968
  );
3793
- return /* @__PURE__ */ jsx23(
3969
+ return /* @__PURE__ */ jsx25(
3794
3970
  AuthGate,
3795
3971
  {
3796
3972
  location: authLocation,
@@ -3801,9 +3977,9 @@ function RouterAuthGate({ children, publicPaths }) {
3801
3977
  }
3802
3978
  );
3803
3979
  }
3804
- function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdParam, publicPaths }) {
3805
- const queryClient = useMemo7(createDefaultQueryClient, []);
3806
- const resolvedCspNonce = useMemo7(
3980
+ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdParam, publicPaths, companyAdmin }) {
3981
+ const queryClient = useMemo8(createDefaultQueryClient, []);
3982
+ const resolvedCspNonce = useMemo8(
3807
3983
  () => cspNonce ?? readCspNonceFromDom(),
3808
3984
  [cspNonce]
3809
3985
  );
@@ -3814,43 +3990,35 @@ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdP
3814
3990
  const VerifyEmailPage2 = authPages?.verifyEmail ?? VerifyEmailPage;
3815
3991
  const AuthErrorPage2 = authPages?.authError ?? AuthErrorPage;
3816
3992
  const UserSettingsPage2 = authPages?.userSettings ?? UserSettingsPage;
3817
- return /* @__PURE__ */ jsx23(HelmetProvider, { children: /* @__PURE__ */ jsx23(AppErrorBoundary, { children: /* @__PURE__ */ jsx23(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx23(ConfigProvider, { children: /* @__PURE__ */ jsx23(ThemeProvider, { children: /* @__PURE__ */ jsx23(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx23(UserIdentityProvider, { children: /* @__PURE__ */ jsx23(BrowserRouter, { children: /* @__PURE__ */ jsx23(WorkspaceAuthProvider, { workspaceRoute, workspaceIdParam, children: /* @__PURE__ */ jsxs16(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx23(UserMenu, {}), children: [
3818
- /* @__PURE__ */ jsx23(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsxs16(Fragment6, { children: [
3819
- /* @__PURE__ */ jsx23("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }),
3820
- /* @__PURE__ */ jsx23(
3821
- "script",
3822
- {
3823
- type: "application/json",
3824
- nonce: resolvedCspNonce,
3825
- "data-boring-csp-nonce": "true",
3826
- children: JSON.stringify({ nonce: resolvedCspNonce })
3827
- }
3828
- )
3829
- ] }) : null }),
3830
- /* @__PURE__ */ jsx23(RouterAuthGate, { publicPaths: ["/invites", ...publicPaths ?? []], children: /* @__PURE__ */ jsx23(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs16(Routes, { children: [
3831
- /* @__PURE__ */ jsx23(Route, { path: routes.signin, element: /* @__PURE__ */ jsx23(SignInPage2, {}) }),
3832
- /* @__PURE__ */ jsx23(Route, { path: routes.signup, element: /* @__PURE__ */ jsx23(SignUpPage2, {}) }),
3833
- /* @__PURE__ */ jsx23(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx23(ForgotPasswordPage2, {}) }),
3834
- /* @__PURE__ */ jsx23(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx23(ResetPasswordPage2, {}) }),
3835
- /* @__PURE__ */ jsx23(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx23(VerifyEmailPage2, {}) }),
3836
- /* @__PURE__ */ jsx23(Route, { path: routes.authError, element: /* @__PURE__ */ jsx23(AuthErrorPage2, {}) }),
3837
- /* @__PURE__ */ jsx23(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx23(PlaceholderPage, { name: "github-callback" }) }),
3838
- /* @__PURE__ */ jsx23(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx23(PlaceholderPage, { name: "google-callback" }) }),
3839
- /* @__PURE__ */ jsx23(Route, { path: routes.me, element: /* @__PURE__ */ jsx23(UserSettingsPage2, {}) }),
3840
- /* @__PURE__ */ jsx23(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx23(MembersPage, {}) }),
3841
- /* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx23(MembersPage, {}) }),
3842
- /* @__PURE__ */ jsx23(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx23(InvitesPage, {}) }),
3843
- /* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx23(InvitesPage, {}) }),
3844
- /* @__PURE__ */ jsx23(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx23(WorkspaceSettingsPage, {}) }),
3845
- /* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx23(WorkspaceSettingsPage, {}) }),
3846
- /* @__PURE__ */ jsx23(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx23(InviteAcceptPage, {}) }),
3993
+ return /* @__PURE__ */ jsx25(HelmetProvider, { children: /* @__PURE__ */ jsx25(AppErrorBoundary, { children: /* @__PURE__ */ jsx25(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx25(ConfigProvider, { children: /* @__PURE__ */ jsx25(ThemeProvider, { children: /* @__PURE__ */ jsx25(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx25(UserIdentityProvider, { children: /* @__PURE__ */ jsx25(BrowserRouter, { children: /* @__PURE__ */ jsx25(CompanyAdminScopedProvider, { companyAdmin, children: /* @__PURE__ */ jsx25(WorkspaceAuthProvider, { workspaceRoute, workspaceIdParam, children: /* @__PURE__ */ jsxs17(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx25(UserMenu, {}), children: [
3994
+ /* @__PURE__ */ jsx25(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsx25("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }) : null }),
3995
+ resolvedCspNonce ? /* @__PURE__ */ jsx25(CspNonceScript, { nonce: resolvedCspNonce }) : null,
3996
+ /* @__PURE__ */ jsx25(RouterAuthGate, { publicPaths: ["/invites", ...publicPaths ?? []], children: /* @__PURE__ */ jsx25(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs17(Routes, { children: [
3997
+ /* @__PURE__ */ jsx25(Route, { path: routes.signin, element: /* @__PURE__ */ jsx25(SignInPage2, {}) }),
3998
+ /* @__PURE__ */ jsx25(Route, { path: routes.signup, element: /* @__PURE__ */ jsx25(SignUpPage2, {}) }),
3999
+ /* @__PURE__ */ jsx25(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx25(ForgotPasswordPage2, {}) }),
4000
+ /* @__PURE__ */ jsx25(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx25(ResetPasswordPage2, {}) }),
4001
+ /* @__PURE__ */ jsx25(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx25(VerifyEmailPage2, {}) }),
4002
+ /* @__PURE__ */ jsx25(Route, { path: routes.authError, element: /* @__PURE__ */ jsx25(AuthErrorPage2, {}) }),
4003
+ /* @__PURE__ */ jsx25(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx25(PlaceholderPage, { name: "github-callback" }) }),
4004
+ /* @__PURE__ */ jsx25(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx25(PlaceholderPage, { name: "google-callback" }) }),
4005
+ /* @__PURE__ */ jsx25(Route, { path: routes.me, element: /* @__PURE__ */ jsx25(UserSettingsPage2, {}) }),
4006
+ /* @__PURE__ */ jsx25(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx25(MembersPage, {}) }),
4007
+ /* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx25(MembersPage, {}) }),
4008
+ /* @__PURE__ */ jsx25(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx25(InvitesPage, {}) }),
4009
+ /* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx25(InvitesPage, {}) }),
4010
+ /* @__PURE__ */ jsx25(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx25(WorkspaceSettingsPage, {}) }),
4011
+ /* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx25(WorkspaceSettingsPage, {}) }),
4012
+ /* @__PURE__ */ jsx25(Route, { path: routes.companyAdmin, element: /* @__PURE__ */ jsx25(CompanyAdminPage, {}) }),
4013
+ /* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/admin", element: /* @__PURE__ */ jsx25(CompanyAdminPage, {}) }),
4014
+ /* @__PURE__ */ jsx25(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx25(InviteAcceptPage, {}) }),
3847
4015
  children
3848
4016
  ] }) }) })
3849
- ] }) }) }) }) }) }) }) }) }) });
4017
+ ] }) }) }) }) }) }) }) }) }) }) });
3850
4018
  }
3851
4019
 
3852
4020
  // src/front/commands/CoreCommandContributions.tsx
3853
- import { useMemo as useMemo8, useState as useState21 } from "react";
4021
+ import { useMemo as useMemo9, useState as useState22 } from "react";
3854
4022
  import { useNavigate as useNavigate7 } from "react-router-dom";
3855
4023
 
3856
4024
  // src/front/workspace/commands.ts
@@ -3892,8 +4060,8 @@ function useCoreCommands() {
3892
4060
  const navigate = useNavigate7();
3893
4061
  const signOut = useSignOut();
3894
4062
  const workspace = useCurrentWorkspace();
3895
- const [isSigningOut, setIsSigningOut] = useState21(false);
3896
- return useMemo8(() => {
4063
+ const [isSigningOut, setIsSigningOut] = useState22(false);
4064
+ return useMemo9(() => {
3897
4065
  const result = [
3898
4066
  {
3899
4067
  id: "user:settings",
@@ -4007,6 +4175,8 @@ export {
4007
4175
  useConfigLoaded,
4008
4176
  ThemeProvider,
4009
4177
  useTheme,
4178
+ CompanyAdminProvider,
4179
+ useCompanyAdminStatus,
4010
4180
  useKeyboardShortcuts,
4011
4181
  useViewportBreakpoint,
4012
4182
  useReducedMotion,
@@ -4044,6 +4214,7 @@ export {
4044
4214
  InvitesPage,
4045
4215
  MembersPage,
4046
4216
  WorkspaceSettingsPage,
4217
+ CompanyAdminPage,
4047
4218
  CoreFront,
4048
4219
  getWorkspaceCommands,
4049
4220
  useCoreCommands,