@hachej/boring-core 0.1.20 → 0.1.23

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.
@@ -131,7 +131,9 @@ var routes = {
131
131
  forgotPassword: "/auth/forgot-password",
132
132
  resetPassword: "/auth/reset-password",
133
133
  verifyEmail: "/auth/verify-email",
134
+ authError: "/auth/error",
134
135
  callbackGithub: "/auth/callback/github",
136
+ callbackGoogle: "/auth/callback/google",
135
137
  me: "/me",
136
138
  workspaceMembers: "/w/:id/members",
137
139
  workspaceInvites: "/w/:id/invites",
@@ -200,6 +202,9 @@ function useConfig() {
200
202
  throw new Error("useConfig must be used within a ConfigProvider");
201
203
  return ctx;
202
204
  }
205
+ function useOptionalConfig() {
206
+ return useContext(ConfigContext);
207
+ }
203
208
  function useConfigLoaded() {
204
209
  return useContext(ConfigContext) !== null;
205
210
  }
@@ -680,21 +685,67 @@ function useUser() {
680
685
  return useContext5(UserContext);
681
686
  }
682
687
 
683
- // src/front/auth/SignInPage.tsx
688
+ // src/front/auth/GoogleAuthButton.tsx
684
689
  import { useState as useState7 } from "react";
690
+ import { Button as Button2 } from "@hachej/boring-ui-kit";
691
+ import { jsx as jsx7 } from "react/jsx-runtime";
692
+ function GoogleAuthButton({
693
+ callbackURL = "/",
694
+ errorCallbackURL = callbackURL,
695
+ onError
696
+ }) {
697
+ const signIn = useSignIn();
698
+ const [isSubmitting, setIsSubmitting] = useState7(false);
699
+ async function handleClick() {
700
+ setIsSubmitting(true);
701
+ try {
702
+ const result = await signIn.social({ provider: "google", callbackURL, errorCallbackURL });
703
+ if (result?.error) {
704
+ onError?.(result.error.message);
705
+ }
706
+ } catch (error) {
707
+ onError?.(error instanceof Error ? error.message : void 0);
708
+ } finally {
709
+ setIsSubmitting(false);
710
+ }
711
+ }
712
+ return /* @__PURE__ */ jsx7(
713
+ Button2,
714
+ {
715
+ type: "button",
716
+ variant: "outline",
717
+ className: "w-full",
718
+ disabled: isSubmitting,
719
+ onClick: () => void handleClick(),
720
+ children: isSubmitting ? "Redirecting\u2026" : "Continue with Google"
721
+ }
722
+ );
723
+ }
724
+
725
+ // src/front/auth/SignInPage.tsx
726
+ import { useState as useState8 } from "react";
685
727
  import { useForm } from "react-hook-form";
686
728
  import { zodResolver } from "@hookform/resolvers/zod";
687
729
  import { z } from "zod";
688
- import { Button as Button2, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Input, Label } from "@hachej/boring-ui-kit";
689
- import { jsx as jsx7, jsxs } from "react/jsx-runtime";
730
+ import { Button as Button3, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Input, Label } from "@hachej/boring-ui-kit";
731
+ import { Fragment, jsx as jsx8, jsxs } from "react/jsx-runtime";
690
732
  var signInSchema = z.object({
691
733
  email: z.string().email("Please enter a valid email"),
692
734
  password: z.string().min(1, "Password is required")
693
735
  });
736
+ var DEFAULT_GOOGLE_SIGNIN_ERROR = "We could not complete Google sign in. Please try again or continue with email.";
737
+ function readGoogleAuthError() {
738
+ if (typeof window === "undefined") return null;
739
+ const error = new URLSearchParams(window.location.search).get("error");
740
+ return error ? DEFAULT_GOOGLE_SIGNIN_ERROR : null;
741
+ }
694
742
  function SignInPage() {
695
743
  const signIn = useSignIn();
696
- const [serverError, setServerError] = useState7(null);
697
- const [isSubmitting, setIsSubmitting] = useState7(false);
744
+ const config = useOptionalConfig();
745
+ const [serverError, setServerError] = useState8(null);
746
+ const [oauthError, setOauthError] = useState8(() => readGoogleAuthError());
747
+ const [isSubmitting, setIsSubmitting] = useState8(false);
748
+ const showGoogleAuth = config?.features.googleOauth === true;
698
749
  const {
699
750
  register,
700
751
  handleSubmit,
@@ -704,6 +755,7 @@ function SignInPage() {
704
755
  });
705
756
  async function onSubmit(data) {
706
757
  setServerError(null);
758
+ setOauthError(null);
707
759
  setIsSubmitting(true);
708
760
  try {
709
761
  const result = await signIn.email({
@@ -719,17 +771,30 @@ function SignInPage() {
719
771
  setIsSubmitting(false);
720
772
  }
721
773
  }
722
- return /* @__PURE__ */ jsx7("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
774
+ 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: [
723
775
  /* @__PURE__ */ jsxs(CardHeader, { children: [
724
- /* @__PURE__ */ jsx7(CardTitle, { children: "Sign in" }),
725
- /* @__PURE__ */ jsx7(CardDescription, { children: "Enter your credentials to continue" })
776
+ /* @__PURE__ */ jsx8(CardTitle, { children: "Sign in" }),
777
+ /* @__PURE__ */ jsx8(CardDescription, { children: "Enter your credentials to continue" })
726
778
  ] }),
727
779
  /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
728
780
  /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
729
- serverError && /* @__PURE__ */ jsx7("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
781
+ showGoogleAuth && /* @__PURE__ */ jsxs(Fragment, { children: [
782
+ /* @__PURE__ */ jsx8(
783
+ GoogleAuthButton,
784
+ {
785
+ errorCallbackURL: routes.signin,
786
+ onError: (message) => setOauthError(message || DEFAULT_GOOGLE_SIGNIN_ERROR)
787
+ }
788
+ ),
789
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
790
+ /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx8("span", { className: "w-full border-t" }) }),
791
+ /* @__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" }) })
792
+ ] })
793
+ ] }),
794
+ (serverError ?? oauthError) && /* @__PURE__ */ jsx8("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
730
795
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
731
- /* @__PURE__ */ jsx7(Label, { htmlFor: "email", children: "Email" }),
732
- /* @__PURE__ */ jsx7(
796
+ /* @__PURE__ */ jsx8(Label, { htmlFor: "email", children: "Email" }),
797
+ /* @__PURE__ */ jsx8(
733
798
  Input,
734
799
  {
735
800
  id: "email",
@@ -739,11 +804,11 @@ function SignInPage() {
739
804
  ...register("email")
740
805
  }
741
806
  ),
742
- errors.email && /* @__PURE__ */ jsx7("p", { className: "text-sm text-destructive", children: errors.email.message })
807
+ errors.email && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.email.message })
743
808
  ] }),
744
809
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
745
- /* @__PURE__ */ jsx7(Label, { htmlFor: "password", children: "Password" }),
746
- /* @__PURE__ */ jsx7(
810
+ /* @__PURE__ */ jsx8(Label, { htmlFor: "password", children: "Password" }),
811
+ /* @__PURE__ */ jsx8(
747
812
  Input,
748
813
  {
749
814
  id: "password",
@@ -752,14 +817,14 @@ function SignInPage() {
752
817
  ...register("password")
753
818
  }
754
819
  ),
755
- errors.password && /* @__PURE__ */ jsx7("p", { className: "text-sm text-destructive", children: errors.password.message })
820
+ errors.password && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.password.message })
756
821
  ] })
757
822
  ] }),
758
823
  /* @__PURE__ */ jsxs(CardFooter, { className: "flex flex-col gap-4", children: [
759
- /* @__PURE__ */ jsx7(Button2, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Signing in\u2026" : "Sign in" }),
824
+ /* @__PURE__ */ jsx8(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Signing in\u2026" : "Sign in" }),
760
825
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm w-full", children: [
761
- /* @__PURE__ */ jsx7("a", { href: routes.forgotPassword, className: "text-muted-foreground hover:underline", children: "Forgot password?" }),
762
- /* @__PURE__ */ jsx7("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Sign up" })
826
+ /* @__PURE__ */ jsx8("a", { href: routes.forgotPassword, className: "text-muted-foreground hover:underline", children: "Forgot password?" }),
827
+ /* @__PURE__ */ jsx8("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Sign up" })
763
828
  ] })
764
829
  ] })
765
830
  ] })
@@ -767,23 +832,32 @@ function SignInPage() {
767
832
  }
768
833
 
769
834
  // src/front/auth/SignUpPage.tsx
770
- import { useState as useState8 } from "react";
835
+ import { useState as useState9 } from "react";
771
836
  import { useForm as useForm2 } from "react-hook-form";
772
837
  import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
773
838
  import { z as z2 } from "zod";
774
- import { Button as Button3, 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";
775
- import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
839
+ 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";
840
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
776
841
  var signUpSchema = z2.object({
777
842
  name: z2.string().min(1, "Name is required"),
778
843
  email: z2.string().email("Please enter a valid email"),
779
844
  password: z2.string().min(8, "Password must be at least 8 characters")
780
845
  });
846
+ var DEFAULT_GOOGLE_SIGNUP_ERROR = "We could not complete Google sign up. Please try again or continue with email.";
847
+ function readGoogleAuthError2() {
848
+ if (typeof window === "undefined") return null;
849
+ const error = new URLSearchParams(window.location.search).get("error");
850
+ return error ? DEFAULT_GOOGLE_SIGNUP_ERROR : null;
851
+ }
781
852
  function SignUpPage() {
782
853
  const signUp = useSignUp();
783
- const [serverError, setServerError] = useState8(null);
784
- const [isSubmitting, setIsSubmitting] = useState8(false);
785
- const [success, setSuccess] = useState8(false);
854
+ const config = useOptionalConfig();
855
+ const [serverError, setServerError] = useState9(null);
856
+ const [oauthError, setOauthError] = useState9(() => readGoogleAuthError2());
857
+ const [isSubmitting, setIsSubmitting] = useState9(false);
858
+ const [success, setSuccess] = useState9(false);
786
859
  const inviteToken = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("invite_token") : null;
860
+ const showGoogleAuth = config?.features.googleOauth === true && !inviteToken;
787
861
  const {
788
862
  register,
789
863
  handleSubmit,
@@ -793,6 +867,7 @@ function SignUpPage() {
793
867
  });
794
868
  async function onSubmit(data) {
795
869
  setServerError(null);
870
+ setOauthError(null);
796
871
  setIsSubmitting(true);
797
872
  try {
798
873
  const fetchOptions = inviteToken ? { headers: { "x-invite-token": inviteToken } } : void 0;
@@ -812,25 +887,38 @@ function SignUpPage() {
812
887
  }
813
888
  }
814
889
  if (success) {
815
- return /* @__PURE__ */ jsx8("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
890
+ 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: [
816
891
  /* @__PURE__ */ jsxs2(CardHeader2, { children: [
817
- /* @__PURE__ */ jsx8(CardTitle2, { children: "Check your email" }),
818
- /* @__PURE__ */ jsx8(CardDescription2, { children: "We sent a verification link to your email address. Please check your inbox to continue." })
892
+ /* @__PURE__ */ jsx9(CardTitle2, { children: "Check your email" }),
893
+ /* @__PURE__ */ jsx9(CardDescription2, { children: "We sent a verification link to your email address. Please check your inbox to continue." })
819
894
  ] }),
820
- /* @__PURE__ */ jsx8(CardFooter2, { children: /* @__PURE__ */ jsx8("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
895
+ /* @__PURE__ */ jsx9(CardFooter2, { children: /* @__PURE__ */ jsx9("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
821
896
  ] }) });
822
897
  }
823
- return /* @__PURE__ */ jsx8("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
898
+ 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: [
824
899
  /* @__PURE__ */ jsxs2(CardHeader2, { children: [
825
- /* @__PURE__ */ jsx8(CardTitle2, { children: "Create an account" }),
826
- /* @__PURE__ */ jsx8(CardDescription2, { children: "Enter your details to get started" })
900
+ /* @__PURE__ */ jsx9(CardTitle2, { children: "Create an account" }),
901
+ /* @__PURE__ */ jsx9(CardDescription2, { children: "Enter your details to get started" })
827
902
  ] }),
828
903
  /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
829
904
  /* @__PURE__ */ jsxs2(CardContent2, { className: "space-y-4", children: [
830
- serverError && /* @__PURE__ */ jsx8("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
905
+ showGoogleAuth && /* @__PURE__ */ jsxs2(Fragment2, { children: [
906
+ /* @__PURE__ */ jsx9(
907
+ GoogleAuthButton,
908
+ {
909
+ errorCallbackURL: routes.signup,
910
+ onError: (message) => setOauthError(message || DEFAULT_GOOGLE_SIGNUP_ERROR)
911
+ }
912
+ ),
913
+ /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
914
+ /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx9("span", { className: "w-full border-t" }) }),
915
+ /* @__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" }) })
916
+ ] })
917
+ ] }),
918
+ (serverError ?? oauthError) && /* @__PURE__ */ jsx9("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
831
919
  /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
832
- /* @__PURE__ */ jsx8(Label2, { htmlFor: "name", children: "Name" }),
833
- /* @__PURE__ */ jsx8(
920
+ /* @__PURE__ */ jsx9(Label2, { htmlFor: "name", children: "Name" }),
921
+ /* @__PURE__ */ jsx9(
834
922
  Input2,
835
923
  {
836
924
  id: "name",
@@ -840,11 +928,11 @@ function SignUpPage() {
840
928
  ...register("name")
841
929
  }
842
930
  ),
843
- errors.name && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.name.message })
931
+ errors.name && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.name.message })
844
932
  ] }),
845
933
  /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
846
- /* @__PURE__ */ jsx8(Label2, { htmlFor: "email", children: "Email" }),
847
- /* @__PURE__ */ jsx8(
934
+ /* @__PURE__ */ jsx9(Label2, { htmlFor: "email", children: "Email" }),
935
+ /* @__PURE__ */ jsx9(
848
936
  Input2,
849
937
  {
850
938
  id: "email",
@@ -854,11 +942,11 @@ function SignUpPage() {
854
942
  ...register("email")
855
943
  }
856
944
  ),
857
- errors.email && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.email.message })
945
+ errors.email && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.email.message })
858
946
  ] }),
859
947
  /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
860
- /* @__PURE__ */ jsx8(Label2, { htmlFor: "password", children: "Password" }),
861
- /* @__PURE__ */ jsx8(
948
+ /* @__PURE__ */ jsx9(Label2, { htmlFor: "password", children: "Password" }),
949
+ /* @__PURE__ */ jsx9(
862
950
  Input2,
863
951
  {
864
952
  id: "password",
@@ -868,14 +956,14 @@ function SignUpPage() {
868
956
  ...register("password")
869
957
  }
870
958
  ),
871
- errors.password && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: errors.password.message })
959
+ errors.password && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.password.message })
872
960
  ] })
873
961
  ] }),
874
962
  /* @__PURE__ */ jsxs2(CardFooter2, { className: "flex flex-col gap-4", children: [
875
- /* @__PURE__ */ jsx8(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Creating account\u2026" : "Sign up" }),
963
+ /* @__PURE__ */ jsx9(Button4, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Creating account\u2026" : "Sign up" }),
876
964
  /* @__PURE__ */ jsxs2("div", { className: "text-sm text-center", children: [
877
- /* @__PURE__ */ jsx8("span", { className: "text-muted-foreground", children: "Already have an account? " }),
878
- /* @__PURE__ */ jsx8("a", { href: routes.signin, className: "hover:underline", children: "Sign in" })
965
+ /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground", children: "Already have an account? " }),
966
+ /* @__PURE__ */ jsx9("a", { href: routes.signin, className: "hover:underline", children: "Sign in" })
879
967
  ] })
880
968
  ] })
881
969
  ] })
@@ -883,19 +971,19 @@ function SignUpPage() {
883
971
  }
884
972
 
885
973
  // src/front/auth/ForgotPasswordPage.tsx
886
- import { useState as useState9 } from "react";
974
+ import { useState as useState10 } from "react";
887
975
  import { useForm as useForm3 } from "react-hook-form";
888
976
  import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
889
977
  import { z as z3 } from "zod";
890
- import { Button as Button4, 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";
891
- import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
978
+ 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";
979
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
892
980
  var forgotSchema = z3.object({
893
981
  email: z3.string().email("Please enter a valid email")
894
982
  });
895
983
  function ForgotPasswordPage() {
896
984
  const forgetPassword = useForgetPassword();
897
- const [isSubmitting, setIsSubmitting] = useState9(false);
898
- const [submitted, setSubmitted] = useState9(false);
985
+ const [isSubmitting, setIsSubmitting] = useState10(false);
986
+ const [submitted, setSubmitted] = useState10(false);
899
987
  const {
900
988
  register,
901
989
  handleSubmit,
@@ -914,23 +1002,23 @@ function ForgotPasswordPage() {
914
1002
  }
915
1003
  }
916
1004
  if (submitted) {
917
- return /* @__PURE__ */ jsx9("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
1005
+ 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: [
918
1006
  /* @__PURE__ */ jsxs3(CardHeader3, { children: [
919
- /* @__PURE__ */ jsx9(CardTitle3, { children: "Check your inbox" }),
920
- /* @__PURE__ */ jsx9(CardDescription3, { children: "If an account exists with that email, we sent a password reset link. Check your inbox and follow the instructions." })
1007
+ /* @__PURE__ */ jsx10(CardTitle3, { children: "Check your inbox" }),
1008
+ /* @__PURE__ */ jsx10(CardDescription3, { children: "If an account exists with that email, we sent a password reset link. Check your inbox and follow the instructions." })
921
1009
  ] }),
922
- /* @__PURE__ */ jsx9(CardFooter3, { children: /* @__PURE__ */ jsx9("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1010
+ /* @__PURE__ */ jsx10(CardFooter3, { children: /* @__PURE__ */ jsx10("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
923
1011
  ] }) });
924
1012
  }
925
- return /* @__PURE__ */ jsx9("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
1013
+ 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: [
926
1014
  /* @__PURE__ */ jsxs3(CardHeader3, { children: [
927
- /* @__PURE__ */ jsx9(CardTitle3, { children: "Forgot password" }),
928
- /* @__PURE__ */ jsx9(CardDescription3, { children: "Enter your email and we'll send you a reset link" })
1015
+ /* @__PURE__ */ jsx10(CardTitle3, { children: "Forgot password" }),
1016
+ /* @__PURE__ */ jsx10(CardDescription3, { children: "Enter your email and we'll send you a reset link" })
929
1017
  ] }),
930
1018
  /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
931
- /* @__PURE__ */ jsx9(CardContent3, { className: "space-y-4", children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
932
- /* @__PURE__ */ jsx9(Label3, { htmlFor: "email", children: "Email" }),
933
- /* @__PURE__ */ jsx9(
1019
+ /* @__PURE__ */ jsx10(CardContent3, { className: "space-y-4", children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
1020
+ /* @__PURE__ */ jsx10(Label3, { htmlFor: "email", children: "Email" }),
1021
+ /* @__PURE__ */ jsx10(
934
1022
  Input3,
935
1023
  {
936
1024
  id: "email",
@@ -940,23 +1028,23 @@ function ForgotPasswordPage() {
940
1028
  ...register("email")
941
1029
  }
942
1030
  ),
943
- errors.email && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.email.message })
1031
+ errors.email && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.email.message })
944
1032
  ] }) }),
945
1033
  /* @__PURE__ */ jsxs3(CardFooter3, { className: "flex flex-col gap-4", children: [
946
- /* @__PURE__ */ jsx9(Button4, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Sending\u2026" : "Send reset link" }),
947
- /* @__PURE__ */ jsx9("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" })
1034
+ /* @__PURE__ */ jsx10(Button5, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Sending\u2026" : "Send reset link" }),
1035
+ /* @__PURE__ */ jsx10("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" })
948
1036
  ] })
949
1037
  ] })
950
1038
  ] }) });
951
1039
  }
952
1040
 
953
1041
  // src/front/auth/ResetPasswordPage.tsx
954
- import { useState as useState10 } from "react";
1042
+ import { useState as useState11 } from "react";
955
1043
  import { useForm as useForm4 } from "react-hook-form";
956
1044
  import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
957
1045
  import { z as z4 } from "zod";
958
- import { Button as Button5, 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";
959
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
1046
+ 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";
1047
+ import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
960
1048
  var resetSchema = z4.object({
961
1049
  password: z4.string().min(8, "Password must be at least 8 characters"),
962
1050
  confirmPassword: z4.string()
@@ -966,9 +1054,9 @@ var resetSchema = z4.object({
966
1054
  });
967
1055
  function ResetPasswordPage() {
968
1056
  const resetPassword = useResetPassword();
969
- const [serverError, setServerError] = useState10(null);
970
- const [isSubmitting, setIsSubmitting] = useState10(false);
971
- const [expired, setExpired] = useState10(false);
1057
+ const [serverError, setServerError] = useState11(null);
1058
+ const [isSubmitting, setIsSubmitting] = useState11(false);
1059
+ const [expired, setExpired] = useState11(false);
972
1060
  const token = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null;
973
1061
  const {
974
1062
  register,
@@ -1006,25 +1094,25 @@ function ResetPasswordPage() {
1006
1094
  }
1007
1095
  }
1008
1096
  if (!token || expired) {
1009
- return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
1097
+ 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: [
1010
1098
  /* @__PURE__ */ jsxs4(CardHeader4, { children: [
1011
- /* @__PURE__ */ jsx10(CardTitle4, { children: "Link expired" }),
1012
- /* @__PURE__ */ jsx10(CardDescription4, { children: "This reset link is no longer valid. Please request a new one." })
1099
+ /* @__PURE__ */ jsx11(CardTitle4, { children: "Link expired" }),
1100
+ /* @__PURE__ */ jsx11(CardDescription4, { children: "This reset link is no longer valid. Please request a new one." })
1013
1101
  ] }),
1014
- /* @__PURE__ */ jsx10(CardFooter4, { children: /* @__PURE__ */ jsx10("a", { href: routes.forgotPassword, children: /* @__PURE__ */ jsx10(Button5, { variant: "outline", children: "Request new link" }) }) })
1102
+ /* @__PURE__ */ jsx11(CardFooter4, { children: /* @__PURE__ */ jsx11("a", { href: routes.forgotPassword, children: /* @__PURE__ */ jsx11(Button6, { variant: "outline", children: "Request new link" }) }) })
1015
1103
  ] }) });
1016
1104
  }
1017
- return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
1105
+ 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: [
1018
1106
  /* @__PURE__ */ jsxs4(CardHeader4, { children: [
1019
- /* @__PURE__ */ jsx10(CardTitle4, { children: "Reset password" }),
1020
- /* @__PURE__ */ jsx10(CardDescription4, { children: "Enter your new password below" })
1107
+ /* @__PURE__ */ jsx11(CardTitle4, { children: "Reset password" }),
1108
+ /* @__PURE__ */ jsx11(CardDescription4, { children: "Enter your new password below" })
1021
1109
  ] }),
1022
1110
  /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
1023
1111
  /* @__PURE__ */ jsxs4(CardContent4, { className: "space-y-4", children: [
1024
- serverError && /* @__PURE__ */ jsx10("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
1112
+ serverError && /* @__PURE__ */ jsx11("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
1025
1113
  /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1026
- /* @__PURE__ */ jsx10(Label4, { htmlFor: "password", children: "New password" }),
1027
- /* @__PURE__ */ jsx10(
1114
+ /* @__PURE__ */ jsx11(Label4, { htmlFor: "password", children: "New password" }),
1115
+ /* @__PURE__ */ jsx11(
1028
1116
  Input4,
1029
1117
  {
1030
1118
  id: "password",
@@ -1034,11 +1122,11 @@ function ResetPasswordPage() {
1034
1122
  ...register("password")
1035
1123
  }
1036
1124
  ),
1037
- errors.password && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.password.message })
1125
+ errors.password && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: errors.password.message })
1038
1126
  ] }),
1039
1127
  /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1040
- /* @__PURE__ */ jsx10(Label4, { htmlFor: "confirmPassword", children: "Confirm password" }),
1041
- /* @__PURE__ */ jsx10(
1128
+ /* @__PURE__ */ jsx11(Label4, { htmlFor: "confirmPassword", children: "Confirm password" }),
1129
+ /* @__PURE__ */ jsx11(
1042
1130
  Input4,
1043
1131
  {
1044
1132
  id: "confirmPassword",
@@ -1047,18 +1135,18 @@ function ResetPasswordPage() {
1047
1135
  ...register("confirmPassword")
1048
1136
  }
1049
1137
  ),
1050
- errors.confirmPassword && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
1138
+ errors.confirmPassword && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
1051
1139
  ] })
1052
1140
  ] }),
1053
- /* @__PURE__ */ jsx10(CardFooter4, { children: /* @__PURE__ */ jsx10(Button5, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Resetting\u2026" : "Reset password" }) })
1141
+ /* @__PURE__ */ jsx11(CardFooter4, { children: /* @__PURE__ */ jsx11(Button6, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Resetting\u2026" : "Reset password" }) })
1054
1142
  ] })
1055
1143
  ] }) });
1056
1144
  }
1057
1145
 
1058
1146
  // src/front/auth/VerifyEmailPage.tsx
1059
- import { useCallback as useCallback3, useEffect as useEffect8, useRef as useRef4, useState as useState11 } from "react";
1060
- import { Button as Button6, 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";
1061
- import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
1147
+ import { useCallback as useCallback3, useEffect as useEffect8, useRef as useRef4, useState as useState12 } from "react";
1148
+ 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";
1149
+ import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
1062
1150
  function getCookie(name) {
1063
1151
  const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
1064
1152
  return match ? decodeURIComponent(match[1]) : null;
@@ -1071,11 +1159,11 @@ function VerifyEmailPage() {
1071
1159
  const verifyEmail = useVerifyEmail();
1072
1160
  const sendVerificationEmail = useSendVerificationEmail();
1073
1161
  const token = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null;
1074
- const [status, setStatus] = useState11(token ? "verifying" : "no-token");
1075
- const [inviteWarning, setInviteWarning] = useState11(null);
1076
- const [cooldown, setCooldown] = useState11(0);
1077
- const [resendEmail, setResendEmail] = useState11("");
1078
- const [resendSent, setResendSent] = useState11(false);
1162
+ const [status, setStatus] = useState12(token ? "verifying" : "no-token");
1163
+ const [inviteWarning, setInviteWarning] = useState12(null);
1164
+ const [cooldown, setCooldown] = useState12(0);
1165
+ const [resendEmail, setResendEmail] = useState12("");
1166
+ const [resendSent, setResendSent] = useState12(false);
1079
1167
  const verifiedRef = useRef4(false);
1080
1168
  const sessionEmail = session.data?.user?.email ?? null;
1081
1169
  useEffect8(() => {
@@ -1130,8 +1218,8 @@ function VerifyEmailPage() {
1130
1218
  setResendSent(true);
1131
1219
  setCooldown(60);
1132
1220
  }, [sessionEmail, resendEmail, cooldown, sendVerificationEmail]);
1133
- const resendButton = /* @__PURE__ */ jsx11(
1134
- Button6,
1221
+ const resendButton = /* @__PURE__ */ jsx12(
1222
+ Button7,
1135
1223
  {
1136
1224
  variant: "outline",
1137
1225
  className: "w-full",
@@ -1142,8 +1230,8 @@ function VerifyEmailPage() {
1142
1230
  );
1143
1231
  const resendSection = /* @__PURE__ */ jsxs5("div", { className: "space-y-3", children: [
1144
1232
  !sessionEmail && /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
1145
- /* @__PURE__ */ jsx11(Label5, { htmlFor: "resend-email", children: "Email" }),
1146
- /* @__PURE__ */ jsx11(
1233
+ /* @__PURE__ */ jsx12(Label5, { htmlFor: "resend-email", children: "Email" }),
1234
+ /* @__PURE__ */ jsx12(
1147
1235
  Input5,
1148
1236
  {
1149
1237
  id: "resend-email",
@@ -1155,48 +1243,48 @@ function VerifyEmailPage() {
1155
1243
  )
1156
1244
  ] }),
1157
1245
  resendButton,
1158
- resendSent && /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground text-center", children: "If an account exists with that email, we sent a new verification link." })
1246
+ 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." })
1159
1247
  ] });
1160
1248
  if (status === "verifying") {
1161
- return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx11(Card5, { className: "w-full max-w-sm", children: /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1162
- /* @__PURE__ */ jsx11(CardTitle5, { children: "Verifying your email" }),
1163
- /* @__PURE__ */ jsx11(CardDescription5, { children: "Please wait\u2026" })
1249
+ 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: [
1250
+ /* @__PURE__ */ jsx12(CardTitle5, { children: "Verifying your email" }),
1251
+ /* @__PURE__ */ jsx12(CardDescription5, { children: "Please wait\u2026" })
1164
1252
  ] }) }) });
1165
1253
  }
1166
1254
  if (status === "verified") {
1167
- return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1168
- inviteWarning && /* @__PURE__ */ jsx11("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx11("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1255
+ 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: [
1256
+ 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 }) }),
1169
1257
  /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1170
- /* @__PURE__ */ jsx11(CardTitle5, { children: "Email verified" }),
1171
- /* @__PURE__ */ jsx11(CardDescription5, { children: "Your email has been verified. You can now continue." })
1258
+ /* @__PURE__ */ jsx12(CardTitle5, { children: "Email verified" }),
1259
+ /* @__PURE__ */ jsx12(CardDescription5, { children: "Your email has been verified. You can now continue." })
1172
1260
  ] }),
1173
- /* @__PURE__ */ jsx11(CardFooter5, { children: /* @__PURE__ */ jsx11("a", { href: "/", className: "w-full", children: /* @__PURE__ */ jsx11(Button6, { className: "w-full", children: "Continue" }) }) })
1261
+ /* @__PURE__ */ jsx12(CardFooter5, { children: /* @__PURE__ */ jsx12("a", { href: "/", className: "w-full", children: /* @__PURE__ */ jsx12(Button7, { className: "w-full", children: "Continue" }) }) })
1174
1262
  ] }) });
1175
1263
  }
1176
1264
  if (status === "expired") {
1177
- return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1178
- inviteWarning && /* @__PURE__ */ jsx11("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx11("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1265
+ 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: [
1266
+ 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 }) }),
1179
1267
  /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1180
- /* @__PURE__ */ jsx11(CardTitle5, { children: "Link expired" }),
1181
- /* @__PURE__ */ jsx11(CardDescription5, { children: "This verification link is no longer valid. Request a new one below." })
1268
+ /* @__PURE__ */ jsx12(CardTitle5, { children: "Link expired" }),
1269
+ /* @__PURE__ */ jsx12(CardDescription5, { children: "This verification link is no longer valid. Request a new one below." })
1182
1270
  ] }),
1183
- /* @__PURE__ */ jsx11(CardContent5, { children: resendSection }),
1184
- /* @__PURE__ */ jsx11(CardFooter5, { children: /* @__PURE__ */ jsx11("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1271
+ /* @__PURE__ */ jsx12(CardContent5, { children: resendSection }),
1272
+ /* @__PURE__ */ jsx12(CardFooter5, { children: /* @__PURE__ */ jsx12("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1185
1273
  ] }) });
1186
1274
  }
1187
- return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
1188
- inviteWarning && /* @__PURE__ */ jsx11("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx11("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
1275
+ 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: [
1276
+ 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 }) }),
1189
1277
  /* @__PURE__ */ jsxs5(CardHeader5, { children: [
1190
- /* @__PURE__ */ jsx11(CardTitle5, { children: "Invalid verification link" }),
1191
- /* @__PURE__ */ jsx11(CardDescription5, { children: status === "no-token" ? "No verification token found. Check the link in your email." : "This verification link is invalid. Request a new one below." })
1278
+ /* @__PURE__ */ jsx12(CardTitle5, { children: "Invalid verification link" }),
1279
+ /* @__PURE__ */ jsx12(CardDescription5, { children: status === "no-token" ? "No verification token found. Check the link in your email." : "This verification link is invalid. Request a new one below." })
1192
1280
  ] }),
1193
- /* @__PURE__ */ jsx11(CardContent5, { children: resendSection }),
1194
- /* @__PURE__ */ jsx11(CardFooter5, { children: /* @__PURE__ */ jsx11("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1281
+ /* @__PURE__ */ jsx12(CardContent5, { children: resendSection }),
1282
+ /* @__PURE__ */ jsx12(CardFooter5, { children: /* @__PURE__ */ jsx12("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
1195
1283
  ] }) });
1196
1284
  }
1197
1285
 
1198
1286
  // src/front/auth/UserSettingsPage.tsx
1199
- import { useCallback as useCallback4, useState as useState12 } from "react";
1287
+ import { useCallback as useCallback4, useState as useState13 } from "react";
1200
1288
  import { useForm as useForm5 } from "react-hook-form";
1201
1289
  import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1202
1290
  import { z as z5 } from "zod";
@@ -1209,7 +1297,7 @@ import {
1209
1297
  AlertDialogHeader,
1210
1298
  AlertDialogTitle,
1211
1299
  AlertDialogTrigger,
1212
- Button as Button7,
1300
+ Button as Button8,
1213
1301
  DetailLine as UiDetailLine,
1214
1302
  DetailList,
1215
1303
  Input as Input6,
@@ -1228,7 +1316,7 @@ import {
1228
1316
  Trash2,
1229
1317
  UserRound
1230
1318
  } from "lucide-react";
1231
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1319
+ import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
1232
1320
  var changePasswordSchema = z5.object({
1233
1321
  currentPassword: z5.string().min(1, "Current password is required"),
1234
1322
  newPassword: z5.string().min(8, "Password must be at least 8 characters"),
@@ -1251,13 +1339,13 @@ function formatMemberSince(value) {
1251
1339
  });
1252
1340
  }
1253
1341
  function SettingsTopBar() {
1254
- return /* @__PURE__ */ jsx12(
1342
+ return /* @__PURE__ */ jsx13(
1255
1343
  "header",
1256
1344
  {
1257
1345
  className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
1258
1346
  "aria-label": "App top bar",
1259
1347
  children: /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
1260
- /* @__PURE__ */ jsx12(
1348
+ /* @__PURE__ */ jsx13(
1261
1349
  "div",
1262
1350
  {
1263
1351
  "aria-hidden": "true",
@@ -1265,9 +1353,9 @@ function SettingsTopBar() {
1265
1353
  children: "B"
1266
1354
  }
1267
1355
  ),
1268
- /* @__PURE__ */ jsx12("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: "Boring" }),
1269
- /* @__PURE__ */ jsx12("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
1270
- /* @__PURE__ */ jsx12("span", { className: "truncate text-[13px] text-muted-foreground", children: "Account settings" })
1356
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: "Boring" }),
1357
+ /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
1358
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] text-muted-foreground", children: "Account settings" })
1271
1359
  ] })
1272
1360
  }
1273
1361
  );
@@ -1279,7 +1367,7 @@ function SettingsPageHeader({
1279
1367
  }) {
1280
1368
  return /* @__PURE__ */ jsxs6("header", { className: "boring-settings-page-header", children: [
1281
1369
  /* @__PURE__ */ jsxs6("div", { className: "boring-settings-context", children: [
1282
- /* @__PURE__ */ jsx12("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 }),
1370
+ /* @__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 }),
1283
1371
  /* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
1284
1372
  /* @__PURE__ */ jsxs6("p", { className: "truncate text-[13px] font-medium text-foreground", children: [
1285
1373
  "Signed in as ",
@@ -1292,9 +1380,9 @@ function SettingsPageHeader({
1292
1380
  ] })
1293
1381
  ] }),
1294
1382
  /* @__PURE__ */ jsxs6("div", { className: "max-w-2xl", children: [
1295
- /* @__PURE__ */ jsx12("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Account" }),
1296
- /* @__PURE__ */ jsx12("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Account settings" }),
1297
- /* @__PURE__ */ jsx12("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Review your profile, change your password, and manage account-level actions." })
1383
+ /* @__PURE__ */ jsx13("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Account" }),
1384
+ /* @__PURE__ */ jsx13("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Account settings" }),
1385
+ /* @__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." })
1298
1386
  ] })
1299
1387
  ] });
1300
1388
  }
@@ -1309,13 +1397,13 @@ function UserSettingsPage({ topBar } = {}) {
1309
1397
  const signOut = useSignOut();
1310
1398
  const changePassword = useChangePassword();
1311
1399
  const user = identity?.user ?? session.data?.user ?? null;
1312
- const [passwordError, setPasswordError] = useState12(null);
1313
- const [passwordSuccess, setPasswordSuccess] = useState12(false);
1314
- const [isChangingPassword, setIsChangingPassword] = useState12(false);
1315
- const [deleteConfirm, setDeleteConfirm] = useState12("");
1316
- const [deleteError, setDeleteError] = useState12(null);
1317
- const [isDeleting, setIsDeleting] = useState12(false);
1318
- const [deleteDialogOpen, setDeleteDialogOpen] = useState12(false);
1400
+ const [passwordError, setPasswordError] = useState13(null);
1401
+ const [passwordSuccess, setPasswordSuccess] = useState13(false);
1402
+ const [isChangingPassword, setIsChangingPassword] = useState13(false);
1403
+ const [deleteConfirm, setDeleteConfirm] = useState13("");
1404
+ const [deleteError, setDeleteError] = useState13(null);
1405
+ const [isDeleting, setIsDeleting] = useState13(false);
1406
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState13(false);
1319
1407
  const {
1320
1408
  register,
1321
1409
  handleSubmit,
@@ -1373,23 +1461,23 @@ function UserSettingsPage({ topBar } = {}) {
1373
1461
  setIsDeleting(false);
1374
1462
  }
1375
1463
  }, [user?.email, signOut]);
1376
- const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx12(SettingsTopBar, {}) : topBar;
1464
+ const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx13(SettingsTopBar, {}) : topBar;
1377
1465
  if (!user) {
1378
1466
  return /* @__PURE__ */ jsxs6("main", { className: "boring-settings-shell", children: [
1379
1467
  topBarNode,
1380
- /* @__PURE__ */ jsx12("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsx12("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: [
1381
- /* @__PURE__ */ jsx12("h1", { className: "text-[13px] font-medium", children: "Account settings" }),
1382
- /* @__PURE__ */ jsx12("p", { className: "mt-1 text-[12px] text-muted-foreground", children: "Loading your account..." })
1468
+ /* @__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: [
1469
+ /* @__PURE__ */ jsx13("h1", { className: "text-[13px] font-medium", children: "Account settings" }),
1470
+ /* @__PURE__ */ jsx13("p", { className: "mt-1 text-[12px] text-muted-foreground", children: "Loading your account..." })
1383
1471
  ] }) }) })
1384
1472
  ] });
1385
1473
  }
1386
1474
  const initials = initialsFor(user.name, user.email);
1387
1475
  return /* @__PURE__ */ jsxs6("main", { className: "boring-settings-shell", children: [
1388
1476
  topBarNode,
1389
- /* @__PURE__ */ jsx12("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs6("div", { className: "boring-settings-layout", children: [
1390
- /* @__PURE__ */ jsx12("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx12(UiSettingsNav, { label: "Account settings", items: ACCOUNT_NAV_ITEMS }) }),
1477
+ /* @__PURE__ */ jsx13("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs6("div", { className: "boring-settings-layout", children: [
1478
+ /* @__PURE__ */ jsx13("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx13(UiSettingsNav, { label: "Account settings", items: ACCOUNT_NAV_ITEMS }) }),
1391
1479
  /* @__PURE__ */ jsxs6("div", { className: "boring-settings-content space-y-4", children: [
1392
- /* @__PURE__ */ jsx12(
1480
+ /* @__PURE__ */ jsx13(
1393
1481
  SettingsPageHeader,
1394
1482
  {
1395
1483
  initials,
@@ -1397,64 +1485,64 @@ function UserSettingsPage({ topBar } = {}) {
1397
1485
  email: user.email
1398
1486
  }
1399
1487
  ),
1400
- /* @__PURE__ */ jsx12(
1488
+ /* @__PURE__ */ jsx13(
1401
1489
  UiSettingsPanel,
1402
1490
  {
1403
1491
  id: "profile",
1404
- icon: /* @__PURE__ */ jsx12(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1492
+ icon: /* @__PURE__ */ jsx13(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1405
1493
  title: "Profile",
1406
1494
  description: "The identity shown inside this app.",
1407
1495
  children: /* @__PURE__ */ jsxs6(DetailList, { children: [
1408
- /* @__PURE__ */ jsx12(
1496
+ /* @__PURE__ */ jsx13(
1409
1497
  UiDetailLine,
1410
1498
  {
1411
- icon: /* @__PURE__ */ jsx12(Mail, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1499
+ icon: /* @__PURE__ */ jsx13(Mail, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1412
1500
  label: "Email",
1413
- children: /* @__PURE__ */ jsx12("p", { className: "truncate", children: user.email })
1501
+ children: /* @__PURE__ */ jsx13("p", { className: "truncate", children: user.email })
1414
1502
  }
1415
1503
  ),
1416
- /* @__PURE__ */ jsx12(
1504
+ /* @__PURE__ */ jsx13(
1417
1505
  UiDetailLine,
1418
1506
  {
1419
- icon: /* @__PURE__ */ jsx12(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1507
+ icon: /* @__PURE__ */ jsx13(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1420
1508
  label: "Name",
1421
- children: /* @__PURE__ */ jsx12("p", { className: "truncate", children: user.name ?? "Not set" })
1509
+ children: /* @__PURE__ */ jsx13("p", { className: "truncate", children: user.name ?? "Not set" })
1422
1510
  }
1423
1511
  ),
1424
- /* @__PURE__ */ jsx12(
1512
+ /* @__PURE__ */ jsx13(
1425
1513
  UiDetailLine,
1426
1514
  {
1427
- icon: /* @__PURE__ */ jsx12(CalendarDays, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1515
+ icon: /* @__PURE__ */ jsx13(CalendarDays, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1428
1516
  label: "Member since",
1429
- children: /* @__PURE__ */ jsx12("p", { children: formatMemberSince(user.createdAt) })
1517
+ children: /* @__PURE__ */ jsx13("p", { children: formatMemberSince(user.createdAt) })
1430
1518
  }
1431
1519
  ),
1432
- /* @__PURE__ */ jsx12(
1520
+ /* @__PURE__ */ jsx13(
1433
1521
  UiDetailLine,
1434
1522
  {
1435
- icon: /* @__PURE__ */ jsx12(CheckCircle2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1523
+ icon: /* @__PURE__ */ jsx13(CheckCircle2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1436
1524
  label: "Email status",
1437
- children: /* @__PURE__ */ jsx12("p", { children: user.emailVerified ? "Verified" : "Not verified" })
1525
+ children: /* @__PURE__ */ jsx13("p", { children: user.emailVerified ? "Verified" : "Not verified" })
1438
1526
  }
1439
1527
  )
1440
1528
  ] })
1441
1529
  }
1442
1530
  ),
1443
- /* @__PURE__ */ jsx12("form", { onSubmit: handleSubmit(onChangePassword), noValidate: true, children: /* @__PURE__ */ jsx12(
1531
+ /* @__PURE__ */ jsx13("form", { onSubmit: handleSubmit(onChangePassword), noValidate: true, children: /* @__PURE__ */ jsx13(
1444
1532
  UiSettingsPanel,
1445
1533
  {
1446
1534
  id: "password",
1447
- icon: /* @__PURE__ */ jsx12(KeyRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1535
+ icon: /* @__PURE__ */ jsx13(KeyRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1448
1536
  title: "Change password",
1449
1537
  description: "Update the password used for email sign-in.",
1450
- footer: /* @__PURE__ */ jsx12(Button7, { type: "submit", size: "sm", disabled: isChangingPassword, children: isChangingPassword ? "Changing..." : "Change password" }),
1538
+ footer: /* @__PURE__ */ jsx13(Button8, { type: "submit", size: "sm", disabled: isChangingPassword, children: isChangingPassword ? "Changing..." : "Change password" }),
1451
1539
  children: /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
1452
- passwordError && /* @__PURE__ */ jsx12(Notice, { role: "alert", tone: "error", description: passwordError }),
1453
- passwordSuccess && /* @__PURE__ */ jsx12(Notice, { role: "status", tone: "success", description: "Password changed successfully." }),
1540
+ passwordError && /* @__PURE__ */ jsx13(Notice, { role: "alert", tone: "error", description: passwordError }),
1541
+ passwordSuccess && /* @__PURE__ */ jsx13(Notice, { role: "status", tone: "success", description: "Password changed successfully." }),
1454
1542
  /* @__PURE__ */ jsxs6("div", { className: "grid gap-3 sm:grid-cols-2", children: [
1455
1543
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2 sm:col-span-2", children: [
1456
- /* @__PURE__ */ jsx12(Label6, { htmlFor: "currentPassword", className: "text-[12px]", children: "Current password" }),
1457
- /* @__PURE__ */ jsx12(
1544
+ /* @__PURE__ */ jsx13(Label6, { htmlFor: "currentPassword", className: "text-[12px]", children: "Current password" }),
1545
+ /* @__PURE__ */ jsx13(
1458
1546
  Input6,
1459
1547
  {
1460
1548
  id: "currentPassword",
@@ -1465,11 +1553,11 @@ function UserSettingsPage({ topBar } = {}) {
1465
1553
  ...register("currentPassword")
1466
1554
  }
1467
1555
  ),
1468
- errors.currentPassword && /* @__PURE__ */ jsx12("p", { className: "text-[12px] text-destructive", children: errors.currentPassword.message })
1556
+ errors.currentPassword && /* @__PURE__ */ jsx13("p", { className: "text-[12px] text-destructive", children: errors.currentPassword.message })
1469
1557
  ] }),
1470
1558
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1471
- /* @__PURE__ */ jsx12(Label6, { htmlFor: "newPassword", className: "text-[12px]", children: "New password" }),
1472
- /* @__PURE__ */ jsx12(
1559
+ /* @__PURE__ */ jsx13(Label6, { htmlFor: "newPassword", className: "text-[12px]", children: "New password" }),
1560
+ /* @__PURE__ */ jsx13(
1473
1561
  Input6,
1474
1562
  {
1475
1563
  id: "newPassword",
@@ -1481,11 +1569,11 @@ function UserSettingsPage({ topBar } = {}) {
1481
1569
  ...register("newPassword")
1482
1570
  }
1483
1571
  ),
1484
- errors.newPassword && /* @__PURE__ */ jsx12("p", { className: "text-[12px] text-destructive", children: errors.newPassword.message })
1572
+ errors.newPassword && /* @__PURE__ */ jsx13("p", { className: "text-[12px] text-destructive", children: errors.newPassword.message })
1485
1573
  ] }),
1486
1574
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1487
- /* @__PURE__ */ jsx12(Label6, { htmlFor: "confirmPassword", className: "text-[12px]", children: "Confirm new password" }),
1488
- /* @__PURE__ */ jsx12(
1575
+ /* @__PURE__ */ jsx13(Label6, { htmlFor: "confirmPassword", className: "text-[12px]", children: "Confirm new password" }),
1576
+ /* @__PURE__ */ jsx13(
1489
1577
  Input6,
1490
1578
  {
1491
1579
  id: "confirmPassword",
@@ -1496,44 +1584,44 @@ function UserSettingsPage({ topBar } = {}) {
1496
1584
  ...register("confirmPassword")
1497
1585
  }
1498
1586
  ),
1499
- errors.confirmPassword && /* @__PURE__ */ jsx12("p", { className: "text-[12px] text-destructive", children: errors.confirmPassword.message })
1587
+ errors.confirmPassword && /* @__PURE__ */ jsx13("p", { className: "text-[12px] text-destructive", children: errors.confirmPassword.message })
1500
1588
  ] })
1501
1589
  ] })
1502
1590
  ] })
1503
1591
  }
1504
1592
  ) }),
1505
- /* @__PURE__ */ jsx12(
1593
+ /* @__PURE__ */ jsx13(
1506
1594
  UiSettingsPanel,
1507
1595
  {
1508
1596
  id: "danger-zone",
1509
- icon: /* @__PURE__ */ jsx12(ShieldAlert, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1597
+ icon: /* @__PURE__ */ jsx13(ShieldAlert, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1510
1598
  title: "Danger zone",
1511
1599
  description: "Permanently delete this account and remove its workspace access.",
1512
1600
  danger: true,
1513
- children: /* @__PURE__ */ jsx12(
1601
+ children: /* @__PURE__ */ jsx13(
1514
1602
  UiSettingsActionRow,
1515
1603
  {
1516
1604
  title: "Delete account",
1517
1605
  description: "Delete your account, user settings, and workspace memberships after confirmation.",
1518
1606
  action: /* @__PURE__ */ jsxs6(AlertDialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
1519
- /* @__PURE__ */ jsx12(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button7, { variant: "destructive", size: "sm", children: [
1520
- /* @__PURE__ */ jsx12(Trash2, { className: "h-4 w-4", "aria-hidden": "true" }),
1607
+ /* @__PURE__ */ jsx13(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button8, { variant: "destructive", size: "sm", children: [
1608
+ /* @__PURE__ */ jsx13(Trash2, { className: "h-4 w-4", "aria-hidden": "true" }),
1521
1609
  "Delete account"
1522
1610
  ] }) }),
1523
1611
  /* @__PURE__ */ jsxs6(AlertDialogContent, { children: [
1524
1612
  /* @__PURE__ */ jsxs6(AlertDialogHeader, { children: [
1525
- /* @__PURE__ */ jsx12(AlertDialogTitle, { children: "Delete your account?" }),
1526
- /* @__PURE__ */ jsx12(AlertDialogDescription, { children: "This action cannot be undone. All your data, workspaces, and settings will be permanently deleted." })
1613
+ /* @__PURE__ */ jsx13(AlertDialogTitle, { children: "Delete your account?" }),
1614
+ /* @__PURE__ */ jsx13(AlertDialogDescription, { children: "This action cannot be undone. All your data, workspaces, and settings will be permanently deleted." })
1527
1615
  ] }),
1528
1616
  /* @__PURE__ */ jsxs6("div", { className: "space-y-3 py-2", children: [
1529
- deleteError && /* @__PURE__ */ jsx12(Notice, { role: "alert", tone: "error", description: deleteError }),
1617
+ deleteError && /* @__PURE__ */ jsx13(Notice, { role: "alert", tone: "error", description: deleteError }),
1530
1618
  /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1531
1619
  /* @__PURE__ */ jsxs6(Label6, { htmlFor: "delete-confirm", children: [
1532
1620
  "Type ",
1533
- /* @__PURE__ */ jsx12("span", { className: "font-mono font-bold", children: "DELETE" }),
1621
+ /* @__PURE__ */ jsx13("span", { className: "font-mono font-bold", children: "DELETE" }),
1534
1622
  " to confirm"
1535
1623
  ] }),
1536
- /* @__PURE__ */ jsx12(
1624
+ /* @__PURE__ */ jsx13(
1537
1625
  Input6,
1538
1626
  {
1539
1627
  id: "delete-confirm",
@@ -1547,7 +1635,7 @@ function UserSettingsPage({ topBar } = {}) {
1547
1635
  ] })
1548
1636
  ] }),
1549
1637
  /* @__PURE__ */ jsxs6(AlertDialogFooter, { children: [
1550
- /* @__PURE__ */ jsx12(
1638
+ /* @__PURE__ */ jsx13(
1551
1639
  AlertDialogCancel,
1552
1640
  {
1553
1641
  onClick: () => {
@@ -1557,8 +1645,8 @@ function UserSettingsPage({ topBar } = {}) {
1557
1645
  children: "Cancel"
1558
1646
  }
1559
1647
  ),
1560
- /* @__PURE__ */ jsx12(
1561
- Button7,
1648
+ /* @__PURE__ */ jsx13(
1649
+ Button8,
1562
1650
  {
1563
1651
  variant: "destructive",
1564
1652
  size: "sm",
@@ -1580,11 +1668,11 @@ function UserSettingsPage({ topBar } = {}) {
1580
1668
  }
1581
1669
 
1582
1670
  // src/front/auth/InviteAcceptPage.tsx
1583
- import { useCallback as useCallback5, useState as useState13 } from "react";
1671
+ import { useCallback as useCallback5, useState as useState14 } from "react";
1584
1672
  import { useParams as useParams2, useNavigate } from "react-router-dom";
1585
1673
  import { useQuery as useQuery3, useMutation, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1586
1674
  import {
1587
- Button as Button8,
1675
+ Button as Button9,
1588
1676
  Card as Card6,
1589
1677
  CardContent as CardContent6,
1590
1678
  CardDescription as CardDescription6,
@@ -1594,13 +1682,13 @@ import {
1594
1682
  LoadingState,
1595
1683
  Notice as Notice2
1596
1684
  } from "@hachej/boring-ui-kit";
1597
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1685
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1598
1686
  function InviteAcceptPage() {
1599
1687
  const { token } = useParams2();
1600
1688
  const session = useSession();
1601
1689
  const navigate = useNavigate();
1602
1690
  const queryClient = useQueryClient2();
1603
- const [acceptError, setAcceptError] = useState13(null);
1691
+ const [acceptError, setAcceptError] = useState14(null);
1604
1692
  const isSignedIn = Boolean(session.data);
1605
1693
  const isSessionPending = session.isPending;
1606
1694
  const resolveQuery = useQuery3({
@@ -1644,20 +1732,20 @@ function InviteAcceptPage() {
1644
1732
  navigate("/");
1645
1733
  }, [navigate]);
1646
1734
  if (isSessionPending) {
1647
- return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx13(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx13(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx13(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
1735
+ 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" }) }) }) });
1648
1736
  }
1649
1737
  if (!isSignedIn) {
1650
1738
  const signinUrl = `${routes.signin}?redirect=${encodeURIComponent(`/invites/${token}`)}`;
1651
- return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1739
+ 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: [
1652
1740
  /* @__PURE__ */ jsxs7(CardHeader6, { children: [
1653
- /* @__PURE__ */ jsx13(CardTitle6, { children: "Sign in to accept this invite" }),
1654
- /* @__PURE__ */ jsx13(CardDescription6, { children: "You need to sign in before you can accept a workspace invite." })
1741
+ /* @__PURE__ */ jsx14(CardTitle6, { children: "Sign in to accept this invite" }),
1742
+ /* @__PURE__ */ jsx14(CardDescription6, { children: "You need to sign in before you can accept a workspace invite." })
1655
1743
  ] }),
1656
- /* @__PURE__ */ jsx13(CardFooter6, { children: /* @__PURE__ */ jsx13(Button8, { className: "w-full", onClick: () => navigate(signinUrl), "data-testid": "signin-redirect", children: "Sign in" }) })
1744
+ /* @__PURE__ */ jsx14(CardFooter6, { children: /* @__PURE__ */ jsx14(Button9, { className: "w-full", onClick: () => navigate(signinUrl), "data-testid": "signin-redirect", children: "Sign in" }) })
1657
1745
  ] }) });
1658
1746
  }
1659
1747
  if (resolveQuery.isLoading) {
1660
- return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx13(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx13(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx13(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
1748
+ 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" }) }) }) });
1661
1749
  }
1662
1750
  if (resolveQuery.error) {
1663
1751
  const detail = getHttpErrorDetail(resolveQuery.error);
@@ -1671,26 +1759,26 @@ function InviteAcceptPage() {
1671
1759
  } else {
1672
1760
  message = detail.message;
1673
1761
  }
1674
- return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1675
- /* @__PURE__ */ jsx13(CardHeader6, { children: /* @__PURE__ */ jsx13(CardTitle6, { children: "Invite unavailable" }) }),
1676
- /* @__PURE__ */ jsx13(CardContent6, { children: /* @__PURE__ */ jsx13(Notice2, { "data-testid": "resolve-error", tone: "error", description: message }) }),
1677
- /* @__PURE__ */ jsx13(CardFooter6, { children: /* @__PURE__ */ jsx13(Button8, { variant: "outline", className: "w-full", onClick: () => navigate("/"), children: "Go home" }) })
1762
+ 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: [
1763
+ /* @__PURE__ */ jsx14(CardHeader6, { children: /* @__PURE__ */ jsx14(CardTitle6, { children: "Invite unavailable" }) }),
1764
+ /* @__PURE__ */ jsx14(CardContent6, { children: /* @__PURE__ */ jsx14(Notice2, { "data-testid": "resolve-error", tone: "error", description: message }) }),
1765
+ /* @__PURE__ */ jsx14(CardFooter6, { children: /* @__PURE__ */ jsx14(Button9, { variant: "outline", className: "w-full", onClick: () => navigate("/"), children: "Go home" }) })
1678
1766
  ] }) });
1679
1767
  }
1680
1768
  const preview = resolveQuery.data;
1681
1769
  if (!preview) return null;
1682
- return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
1770
+ 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: [
1683
1771
  /* @__PURE__ */ jsxs7(CardHeader6, { children: [
1684
- /* @__PURE__ */ jsx13(CardTitle6, { children: "You've been invited" }),
1772
+ /* @__PURE__ */ jsx14(CardTitle6, { children: "You've been invited" }),
1685
1773
  /* @__PURE__ */ jsxs7(CardDescription6, { children: [
1686
1774
  "Join ",
1687
- /* @__PURE__ */ jsx13("strong", { children: preview.workspaceName }),
1775
+ /* @__PURE__ */ jsx14("strong", { children: preview.workspaceName }),
1688
1776
  " as ",
1689
- /* @__PURE__ */ jsx13("strong", { children: preview.role })
1777
+ /* @__PURE__ */ jsx14("strong", { children: preview.role })
1690
1778
  ] })
1691
1779
  ] }),
1692
1780
  /* @__PURE__ */ jsxs7(CardContent6, { className: "space-y-3", children: [
1693
- acceptError && /* @__PURE__ */ jsx13(Notice2, { role: "alert", "data-testid": "accept-error", tone: "error", description: acceptError }),
1781
+ acceptError && /* @__PURE__ */ jsx14(Notice2, { role: "alert", "data-testid": "accept-error", tone: "error", description: acceptError }),
1694
1782
  /* @__PURE__ */ jsxs7("div", { className: "text-sm text-muted-foreground", children: [
1695
1783
  "This invite expires on",
1696
1784
  " ",
@@ -1702,8 +1790,8 @@ function InviteAcceptPage() {
1702
1790
  ] })
1703
1791
  ] }),
1704
1792
  /* @__PURE__ */ jsxs7(CardFooter6, { className: "flex gap-3", children: [
1705
- /* @__PURE__ */ jsx13(
1706
- Button8,
1793
+ /* @__PURE__ */ jsx14(
1794
+ Button9,
1707
1795
  {
1708
1796
  variant: "outline",
1709
1797
  className: "flex-1",
@@ -1712,8 +1800,8 @@ function InviteAcceptPage() {
1712
1800
  children: "Decline"
1713
1801
  }
1714
1802
  ),
1715
- /* @__PURE__ */ jsx13(
1716
- Button8,
1803
+ /* @__PURE__ */ jsx14(
1804
+ Button9,
1717
1805
  {
1718
1806
  className: "flex-1",
1719
1807
  disabled: acceptMutation.isPending,
@@ -1728,7 +1816,7 @@ function InviteAcceptPage() {
1728
1816
 
1729
1817
  // src/front/AuthGate.tsx
1730
1818
  import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef5 } from "react";
1731
- import { Fragment, jsx as jsx14 } from "react/jsx-runtime";
1819
+ import { Fragment as Fragment3, jsx as jsx15 } from "react/jsx-runtime";
1732
1820
  var DEFAULT_GRACE_MS = 3e4;
1733
1821
  var UNSAFE_REDIRECT_RE = /[\0\r\n<>"'`]/;
1734
1822
  function normalizePath(pathname) {
@@ -1846,7 +1934,7 @@ function AuthGate({
1846
1934
  }, [currentLocation, goTo, graceMs, normalizedPublicPaths, readNow, session.data, session.isPending]);
1847
1935
  const pathname = normalizePath(currentLocation.pathname);
1848
1936
  if (session.isPending && !isPublicPath(pathname, normalizedPublicPaths)) return null;
1849
- return /* @__PURE__ */ jsx14(Fragment, { children });
1937
+ return /* @__PURE__ */ jsx15(Fragment3, { children });
1850
1938
  }
1851
1939
 
1852
1940
  // src/front/CoreFront.tsx
@@ -1856,9 +1944,9 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
1856
1944
  import { Helmet, HelmetProvider } from "react-helmet-async";
1857
1945
 
1858
1946
  // src/front/components/UserMenu.tsx
1859
- import { useMemo as useMemo4, useState as useState14 } from "react";
1947
+ import { useMemo as useMemo4, useState as useState15 } from "react";
1860
1948
  import {
1861
- Button as Button9,
1949
+ Button as Button10,
1862
1950
  DropdownMenu,
1863
1951
  DropdownMenuContent,
1864
1952
  DropdownMenuItem,
@@ -1876,7 +1964,7 @@ import {
1876
1964
  Sun
1877
1965
  } from "lucide-react";
1878
1966
  import { useNavigate as useNavigate2 } from "react-router-dom";
1879
- import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1967
+ import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
1880
1968
  var THEME_ORDER = ["light", "dark", "system"];
1881
1969
  function labelForTheme(preference) {
1882
1970
  if (preference === "light") return "Light";
@@ -1899,7 +1987,7 @@ function UserMenu() {
1899
1987
  const signOut = useSignOut();
1900
1988
  const navigate = useNavigate2();
1901
1989
  const { preference, setTheme } = useTheme();
1902
- const [isSigningOut, setIsSigningOut] = useState14(false);
1990
+ const [isSigningOut, setIsSigningOut] = useState15(false);
1903
1991
  const user = identity?.user;
1904
1992
  const userName = user?.name ?? "Unknown user";
1905
1993
  const userEmail = user?.email ?? "unknown@example.com";
@@ -1915,16 +2003,16 @@ function UserMenu() {
1915
2003
  }
1916
2004
  }
1917
2005
  return /* @__PURE__ */ jsxs8(DropdownMenu, { children: [
1918
- /* @__PURE__ */ jsx15(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
1919
- Button9,
2006
+ /* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
2007
+ Button10,
1920
2008
  {
1921
2009
  type: "button",
1922
2010
  variant: "ghost",
1923
2011
  "aria-label": "User menu",
1924
2012
  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",
1925
2013
  children: [
1926
- /* @__PURE__ */ jsx15("span", { className: "inline-flex h-7 w-7 items-center justify-center rounded-md bg-foreground text-[11px] font-semibold text-background", children: initials }),
1927
- /* @__PURE__ */ jsx15(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground", "aria-hidden": "true" })
2014
+ /* @__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 }),
2015
+ /* @__PURE__ */ jsx16(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground", "aria-hidden": "true" })
1928
2016
  ]
1929
2017
  }
1930
2018
  ) }),
@@ -1935,15 +2023,15 @@ function UserMenu() {
1935
2023
  sideOffset: 8,
1936
2024
  className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
1937
2025
  children: [
1938
- /* @__PURE__ */ jsx15(DropdownMenuLabel, { className: "p-2", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
1939
- /* @__PURE__ */ jsx15("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 }),
2026
+ /* @__PURE__ */ jsx16(DropdownMenuLabel, { className: "p-2", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
2027
+ /* @__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 }),
1940
2028
  /* @__PURE__ */ jsxs8("span", { className: "min-w-0 space-y-1", children: [
1941
- /* @__PURE__ */ jsx15("span", { className: "block truncate text-sm font-medium leading-none", children: userName }),
1942
- /* @__PURE__ */ jsx15("span", { className: "block truncate text-xs font-normal text-muted-foreground", children: userEmail })
2029
+ /* @__PURE__ */ jsx16("span", { className: "block truncate text-sm font-medium leading-none", children: userName }),
2030
+ /* @__PURE__ */ jsx16("span", { className: "block truncate text-xs font-normal text-muted-foreground", children: userEmail })
1943
2031
  ] })
1944
2032
  ] }) }),
1945
- /* @__PURE__ */ jsx15(DropdownMenuSeparator, { className: "-mx-2" }),
1946
- /* @__PURE__ */ jsx15(DropdownMenuLabel, { className: "px-2 pb-1 pt-2 text-[11px] font-medium text-muted-foreground", children: "Theme" }),
2033
+ /* @__PURE__ */ jsx16(DropdownMenuSeparator, { className: "-mx-2" }),
2034
+ /* @__PURE__ */ jsx16(DropdownMenuLabel, { className: "px-2 pb-1 pt-2 text-[11px] font-medium text-muted-foreground", children: "Theme" }),
1947
2035
  THEME_ORDER.map((theme) => {
1948
2036
  const Icon = iconForTheme(theme);
1949
2037
  const selected = preference === theme;
@@ -1958,15 +2046,15 @@ function UserMenu() {
1958
2046
  },
1959
2047
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
1960
2048
  children: [
1961
- /* @__PURE__ */ jsx15(Icon, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }),
1962
- /* @__PURE__ */ jsx15("span", { className: "flex-1", children: labelForTheme(theme) }),
1963
- selected ? /* @__PURE__ */ jsx15(Check, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
2049
+ /* @__PURE__ */ jsx16(Icon, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }),
2050
+ /* @__PURE__ */ jsx16("span", { className: "flex-1", children: labelForTheme(theme) }),
2051
+ selected ? /* @__PURE__ */ jsx16(Check, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
1964
2052
  ]
1965
2053
  },
1966
2054
  theme
1967
2055
  );
1968
2056
  }),
1969
- /* @__PURE__ */ jsx15(DropdownMenuSeparator, { className: "-mx-2" }),
2057
+ /* @__PURE__ */ jsx16(DropdownMenuSeparator, { className: "-mx-2" }),
1970
2058
  /* @__PURE__ */ jsxs8(
1971
2059
  DropdownMenuItem,
1972
2060
  {
@@ -1974,15 +2062,15 @@ function UserMenu() {
1974
2062
  onSelect: () => navigate(routes.me),
1975
2063
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
1976
2064
  children: [
1977
- /* @__PURE__ */ jsx15(Settings, { className: "h-4 w-4", "aria-hidden": "true" }),
2065
+ /* @__PURE__ */ jsx16(Settings, { className: "h-4 w-4", "aria-hidden": "true" }),
1978
2066
  /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-col", children: [
1979
- /* @__PURE__ */ jsx15("span", { children: "User settings" }),
1980
- /* @__PURE__ */ jsx15("span", { className: "text-xs text-muted-foreground", children: "Password and account controls" })
2067
+ /* @__PURE__ */ jsx16("span", { children: "User settings" }),
2068
+ /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: "Password and account controls" })
1981
2069
  ] })
1982
2070
  ]
1983
2071
  }
1984
2072
  ),
1985
- /* @__PURE__ */ jsx15(DropdownMenuSeparator, { className: "-mx-2" }),
2073
+ /* @__PURE__ */ jsx16(DropdownMenuSeparator, { className: "-mx-2" }),
1986
2074
  /* @__PURE__ */ jsxs8(
1987
2075
  DropdownMenuItem,
1988
2076
  {
@@ -1994,7 +2082,7 @@ function UserMenu() {
1994
2082
  disabled: isSigningOut,
1995
2083
  className: "gap-3 rounded-md py-2 text-[13px]",
1996
2084
  children: [
1997
- /* @__PURE__ */ jsx15(LogOut, { className: "h-4 w-4", "aria-hidden": "true" }),
2085
+ /* @__PURE__ */ jsx16(LogOut, { className: "h-4 w-4", "aria-hidden": "true" }),
1998
2086
  isSigningOut ? "Signing out..." : "Sign out"
1999
2087
  ]
2000
2088
  }
@@ -2006,10 +2094,10 @@ function UserMenu() {
2006
2094
  }
2007
2095
 
2008
2096
  // src/front/components/WorkspaceSwitcher.tsx
2009
- import { useMemo as useMemo5, useState as useState15 } from "react";
2097
+ import { useMemo as useMemo5, useState as useState16 } from "react";
2010
2098
  import { useQuery as useQuery4, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
2011
2099
  import {
2012
- Button as Button10,
2100
+ Button as Button11,
2013
2101
  Dialog,
2014
2102
  DialogContent,
2015
2103
  DialogDescription,
@@ -2029,7 +2117,7 @@ import {
2029
2117
  import { Check as Check2, ChevronsUpDown, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
2030
2118
  import { useNavigate as useNavigate3 } from "react-router-dom";
2031
2119
  import { z as z6 } from "zod";
2032
- import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
2120
+ import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
2033
2121
  var workspaceNameSchema = z6.object({
2034
2122
  name: z6.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
2035
2123
  });
@@ -2075,11 +2163,11 @@ function WorkspaceSwitcher({
2075
2163
  const currentWorkspace = useCurrentWorkspace();
2076
2164
  const workspacesQuery = useWorkspaces();
2077
2165
  const workspaces = workspacesQuery.data ?? [];
2078
- const [isModalOpen, setIsModalOpen] = useState15(false);
2079
- const [name, setName] = useState15("");
2080
- const [attemptedSubmit, setAttemptedSubmit] = useState15(false);
2081
- const [isSubmitting, setIsSubmitting] = useState15(false);
2082
- const [serverError, setServerError] = useState15(null);
2166
+ const [isModalOpen, setIsModalOpen] = useState16(false);
2167
+ const [name, setName] = useState16("");
2168
+ const [attemptedSubmit, setAttemptedSubmit] = useState16(false);
2169
+ const [isSubmitting, setIsSubmitting] = useState16(false);
2170
+ const [serverError, setServerError] = useState16(null);
2083
2171
  const nameValidation = useMemo5(() => validateWorkspaceName(name), [name]);
2084
2172
  const shouldShowNameError = name.length > 100 || attemptedSubmit && nameValidation.message !== null;
2085
2173
  const nameError = shouldShowNameError ? nameValidation.message : null;
@@ -2136,16 +2224,16 @@ function WorkspaceSwitcher({
2136
2224
  }
2137
2225
  }
2138
2226
  const switcherLabel = currentWorkspace?.name ?? "Select workspace";
2139
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
2227
+ return /* @__PURE__ */ jsxs9(Fragment4, { children: [
2140
2228
  workspaces.length === 0 ? /* @__PURE__ */ jsxs9(
2141
- Button10,
2229
+ Button11,
2142
2230
  {
2143
2231
  type: "button",
2144
2232
  variant: "ghost",
2145
2233
  onClick: openCreateWorkspace,
2146
2234
  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",
2147
2235
  children: [
2148
- /* @__PURE__ */ jsx16(
2236
+ /* @__PURE__ */ jsx17(
2149
2237
  "span",
2150
2238
  {
2151
2239
  "aria-hidden": "true",
@@ -2153,19 +2241,19 @@ function WorkspaceSwitcher({
2153
2241
  children: appTitle.charAt(0).toUpperCase()
2154
2242
  }
2155
2243
  ),
2156
- /* @__PURE__ */ jsx16("span", { className: "text-[13px] font-medium text-foreground", children: "Create your first workspace" })
2244
+ /* @__PURE__ */ jsx17("span", { className: "text-[13px] font-medium text-foreground", children: "Create your first workspace" })
2157
2245
  ]
2158
2246
  }
2159
2247
  ) : /* @__PURE__ */ jsxs9(DropdownMenu2, { children: [
2160
- /* @__PURE__ */ jsx16(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs9(
2161
- Button10,
2248
+ /* @__PURE__ */ jsx17(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs9(
2249
+ Button11,
2162
2250
  {
2163
2251
  type: "button",
2164
2252
  variant: "ghost",
2165
2253
  "aria-label": `Workspace menu: ${switcherLabel}`,
2166
2254
  className: "-ml-1 h-8 min-w-0 justify-start gap-2.5 border border-transparent px-1 py-1 text-left",
2167
2255
  children: [
2168
- /* @__PURE__ */ jsx16(
2256
+ /* @__PURE__ */ jsx17(
2169
2257
  "span",
2170
2258
  {
2171
2259
  "aria-hidden": "true",
@@ -2174,11 +2262,11 @@ function WorkspaceSwitcher({
2174
2262
  }
2175
2263
  ),
2176
2264
  /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 items-center gap-1.5", children: [
2177
- /* @__PURE__ */ jsx16("span", { className: "truncate text-[13px] font-medium text-foreground", children: appTitle }),
2178
- /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2179
- /* @__PURE__ */ jsx16("span", { className: "truncate text-[13px] font-normal text-muted-foreground", children: switcherLabel })
2265
+ /* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-medium text-foreground", children: appTitle }),
2266
+ /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2267
+ /* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-normal text-muted-foreground", children: switcherLabel })
2180
2268
  ] }),
2181
- /* @__PURE__ */ jsx16(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2269
+ /* @__PURE__ */ jsx17(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2182
2270
  ]
2183
2271
  }
2184
2272
  ) }),
@@ -2189,11 +2277,11 @@ function WorkspaceSwitcher({
2189
2277
  sideOffset: 8,
2190
2278
  className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
2191
2279
  children: [
2192
- /* @__PURE__ */ jsx16(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: [
2193
- /* @__PURE__ */ jsx16(LayoutGrid, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2280
+ /* @__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: [
2281
+ /* @__PURE__ */ jsx17(LayoutGrid, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2194
2282
  "Workspaces"
2195
2283
  ] }) }),
2196
- /* @__PURE__ */ jsx16("div", { className: "max-h-72 overflow-y-auto pr-1", children: workspaces.map((workspace) => {
2284
+ /* @__PURE__ */ jsx17("div", { className: "max-h-72 overflow-y-auto pr-1", children: workspaces.map((workspace) => {
2197
2285
  const isCurrent = currentWorkspace?.id === workspace.id;
2198
2286
  return /* @__PURE__ */ jsxs9(
2199
2287
  DropdownMenuItem2,
@@ -2203,15 +2291,15 @@ function WorkspaceSwitcher({
2203
2291
  onSelect: () => navigate(hrefForWorkspace(workspacePathPrefix, workspace.id)),
2204
2292
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2205
2293
  children: [
2206
- /* @__PURE__ */ jsx16("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) }),
2207
- /* @__PURE__ */ jsx16("span", { className: "min-w-0 flex-1 truncate text-sm", children: workspace.name }),
2208
- isCurrent ? /* @__PURE__ */ jsx16(Check2, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
2294
+ /* @__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) }),
2295
+ /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm", children: workspace.name }),
2296
+ isCurrent ? /* @__PURE__ */ jsx17(Check2, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
2209
2297
  ]
2210
2298
  },
2211
2299
  workspace.id
2212
2300
  );
2213
2301
  }) }),
2214
- /* @__PURE__ */ jsx16(DropdownMenuSeparator2, { className: "-mx-2" }),
2302
+ /* @__PURE__ */ jsx17(DropdownMenuSeparator2, { className: "-mx-2" }),
2215
2303
  /* @__PURE__ */ jsxs9(
2216
2304
  DropdownMenuItem2,
2217
2305
  {
@@ -2222,10 +2310,10 @@ function WorkspaceSwitcher({
2222
2310
  },
2223
2311
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2224
2312
  children: [
2225
- /* @__PURE__ */ jsx16(Plus, { className: "h-4 w-4", "aria-hidden": "true" }),
2313
+ /* @__PURE__ */ jsx17(Plus, { className: "h-4 w-4", "aria-hidden": "true" }),
2226
2314
  /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-col", children: [
2227
- /* @__PURE__ */ jsx16("span", { children: "Create workspace" }),
2228
- /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: "Start a clean project space" })
2315
+ /* @__PURE__ */ jsx17("span", { children: "Create workspace" }),
2316
+ /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Start a clean project space" })
2229
2317
  ] })
2230
2318
  ]
2231
2319
  }
@@ -2237,10 +2325,10 @@ function WorkspaceSwitcher({
2237
2325
  onSelect: () => navigate(hrefForWorkspace(workspacePathPrefix, currentWorkspace.id, "/settings")),
2238
2326
  className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
2239
2327
  children: [
2240
- /* @__PURE__ */ jsx16(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }),
2328
+ /* @__PURE__ */ jsx17(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }),
2241
2329
  /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-col", children: [
2242
- /* @__PURE__ */ jsx16("span", { children: "Workspace settings" }),
2243
- /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: "Rename, runtime, deletion" })
2330
+ /* @__PURE__ */ jsx17("span", { children: "Workspace settings" }),
2331
+ /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Rename, runtime, deletion" })
2244
2332
  ] })
2245
2333
  ]
2246
2334
  }
@@ -2249,21 +2337,21 @@ function WorkspaceSwitcher({
2249
2337
  }
2250
2338
  )
2251
2339
  ] }),
2252
- /* @__PURE__ */ jsx16(Dialog, { open: isModalOpen, onOpenChange: onModalChange, children: /* @__PURE__ */ jsxs9(DialogContent, { children: [
2340
+ /* @__PURE__ */ jsx17(Dialog, { open: isModalOpen, onOpenChange: onModalChange, children: /* @__PURE__ */ jsxs9(DialogContent, { children: [
2253
2341
  /* @__PURE__ */ jsxs9(DialogHeader, { children: [
2254
- /* @__PURE__ */ jsx16(DialogTitle, { children: "Create workspace" }),
2255
- /* @__PURE__ */ jsx16(DialogDescription, { children: "Choose a name for your new workspace." })
2342
+ /* @__PURE__ */ jsx17(DialogTitle, { children: "Create workspace" }),
2343
+ /* @__PURE__ */ jsx17(DialogDescription, { children: "Choose a name for your new workspace." })
2256
2344
  ] }),
2257
2345
  /* @__PURE__ */ jsxs9("form", { onSubmit: (event) => void handleCreateWorkspace(event), className: "space-y-4", children: [
2258
2346
  /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2259
2347
  /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
2260
- /* @__PURE__ */ jsx16(Label7, { htmlFor: "workspace-name", children: "Name" }),
2348
+ /* @__PURE__ */ jsx17(Label7, { htmlFor: "workspace-name", children: "Name" }),
2261
2349
  /* @__PURE__ */ jsxs9("span", { className: "text-xs text-muted-foreground", children: [
2262
2350
  name.length,
2263
2351
  "/100"
2264
2352
  ] })
2265
2353
  ] }),
2266
- /* @__PURE__ */ jsx16(
2354
+ /* @__PURE__ */ jsx17(
2267
2355
  Input7,
2268
2356
  {
2269
2357
  id: "workspace-name",
@@ -2279,12 +2367,12 @@ function WorkspaceSwitcher({
2279
2367
  autoFocus: true
2280
2368
  }
2281
2369
  ),
2282
- nameError ? /* @__PURE__ */ jsx16("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2283
- serverError ? /* @__PURE__ */ jsx16("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2370
+ nameError ? /* @__PURE__ */ jsx17("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2371
+ serverError ? /* @__PURE__ */ jsx17("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2284
2372
  ] }),
2285
2373
  /* @__PURE__ */ jsxs9(DialogFooter, { children: [
2286
- /* @__PURE__ */ jsx16(
2287
- Button10,
2374
+ /* @__PURE__ */ jsx17(
2375
+ Button11,
2288
2376
  {
2289
2377
  type: "button",
2290
2378
  variant: "ghost",
@@ -2293,8 +2381,8 @@ function WorkspaceSwitcher({
2293
2381
  children: "Cancel"
2294
2382
  }
2295
2383
  ),
2296
- /* @__PURE__ */ jsx16(
2297
- Button10,
2384
+ /* @__PURE__ */ jsx17(
2385
+ Button11,
2298
2386
  {
2299
2387
  type: "submit",
2300
2388
  disabled: isSubmitting || nameValidation.parsedName === null,
@@ -2308,7 +2396,7 @@ function WorkspaceSwitcher({
2308
2396
  }
2309
2397
 
2310
2398
  // src/front/components/ThemeToggle.tsx
2311
- import { Button as Button11 } from "@hachej/boring-ui-kit";
2399
+ import { Button as Button12 } from "@hachej/boring-ui-kit";
2312
2400
  import { jsxs as jsxs10 } from "react/jsx-runtime";
2313
2401
  var THEME_ORDER2 = ["light", "dark", "system"];
2314
2402
  function nextTheme(preference) {
@@ -2324,7 +2412,7 @@ function labelForTheme2(preference) {
2324
2412
  function ThemeToggle() {
2325
2413
  const { preference, setTheme } = useTheme();
2326
2414
  return /* @__PURE__ */ jsxs10(
2327
- Button11,
2415
+ Button12,
2328
2416
  {
2329
2417
  type: "button",
2330
2418
  variant: "outline",
@@ -2339,17 +2427,42 @@ function ThemeToggle() {
2339
2427
  );
2340
2428
  }
2341
2429
 
2430
+ // src/front/auth/AuthErrorPage.tsx
2431
+ import { Card as Card7, CardContent as CardContent7, CardDescription as CardDescription7, CardFooter as CardFooter7, CardHeader as CardHeader7, CardTitle as CardTitle7 } from "@hachej/boring-ui-kit";
2432
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
2433
+ function readAuthErrorCode() {
2434
+ if (typeof window === "undefined") return null;
2435
+ return new URLSearchParams(window.location.search).get("error");
2436
+ }
2437
+ function AuthErrorPage() {
2438
+ const errorCode = readAuthErrorCode();
2439
+ return /* @__PURE__ */ jsx18("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs11(Card7, { className: "w-full max-w-sm", children: [
2440
+ /* @__PURE__ */ jsxs11(CardHeader7, { children: [
2441
+ /* @__PURE__ */ jsx18(CardTitle7, { children: "Authentication error" }),
2442
+ /* @__PURE__ */ jsx18(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
2443
+ ] }),
2444
+ errorCode && /* @__PURE__ */ jsx18(CardContent7, { children: /* @__PURE__ */ jsxs11("p", { className: "text-sm text-muted-foreground break-all", children: [
2445
+ "Error: ",
2446
+ errorCode
2447
+ ] }) }),
2448
+ /* @__PURE__ */ jsxs11(CardFooter7, { className: "flex justify-between gap-4 text-sm", children: [
2449
+ /* @__PURE__ */ jsx18("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
2450
+ /* @__PURE__ */ jsx18("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
2451
+ ] })
2452
+ ] }) });
2453
+ }
2454
+
2342
2455
  // src/front/workspace/InvitesPage.tsx
2343
- import { useCallback as useCallback6, useState as useState16 } from "react";
2456
+ import { useCallback as useCallback6, useState as useState17 } from "react";
2344
2457
  import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2345
2458
  import {
2346
- Button as Button12,
2347
- Card as Card7,
2348
- CardContent as CardContent7,
2349
- CardDescription as CardDescription7,
2350
- CardFooter as CardFooter7,
2351
- CardHeader as CardHeader7,
2352
- CardTitle as CardTitle7,
2459
+ Button as Button13,
2460
+ Card as Card8,
2461
+ CardContent as CardContent8,
2462
+ CardDescription as CardDescription8,
2463
+ CardFooter as CardFooter8,
2464
+ CardHeader as CardHeader8,
2465
+ CardTitle as CardTitle8,
2353
2466
  Input as Input8,
2354
2467
  Label as Label8,
2355
2468
  LoadingState as LoadingState2,
@@ -2361,7 +2474,7 @@ import {
2361
2474
  SelectValue,
2362
2475
  StatusBadge
2363
2476
  } from "@hachej/boring-ui-kit";
2364
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2477
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2365
2478
  function invitesQueryKey(workspaceId) {
2366
2479
  return ["invites", workspaceId];
2367
2480
  }
@@ -2382,10 +2495,10 @@ function InvitesPage() {
2382
2495
  const workspace = useCurrentWorkspace();
2383
2496
  const role = useWorkspaceRole();
2384
2497
  const queryClient = useQueryClient4();
2385
- const [email, setEmail] = useState16("");
2386
- const [inviteRole, setInviteRole] = useState16("editor");
2387
- const [formError, setFormError] = useState16(null);
2388
- const [successMessage, setSuccessMessage] = useState16(null);
2498
+ const [email, setEmail] = useState17("");
2499
+ const [inviteRole, setInviteRole] = useState17("editor");
2500
+ const [formError, setFormError] = useState17(null);
2501
+ const [successMessage, setSuccessMessage] = useState17(null);
2389
2502
  const workspaceId = workspace?.id ?? "";
2390
2503
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
2391
2504
  const invitesQuery = useQuery5({
@@ -2421,7 +2534,7 @@ function InvitesPage() {
2421
2534
  setFormError(detail.message);
2422
2535
  }
2423
2536
  });
2424
- const [revokeError, setRevokeError] = useState16(null);
2537
+ const [revokeError, setRevokeError] = useState17(null);
2425
2538
  const revokeMutation = useMutation2({
2426
2539
  mutationFn: async (inviteId) => {
2427
2540
  await apiFetch(
@@ -2453,28 +2566,28 @@ function InvitesPage() {
2453
2566
  [email, inviteRole, createMutation]
2454
2567
  );
2455
2568
  if (role !== "owner") {
2456
- return /* @__PURE__ */ jsx17("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx17(Card7, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs11(CardHeader7, { children: [
2457
- /* @__PURE__ */ jsx17(CardTitle7, { children: "Access denied" }),
2458
- /* @__PURE__ */ jsx17(CardDescription7, { children: "Only workspace owners can manage invites." })
2569
+ return /* @__PURE__ */ jsx19("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx19(Card8, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs12(CardHeader8, { children: [
2570
+ /* @__PURE__ */ jsx19(CardTitle8, { children: "Access denied" }),
2571
+ /* @__PURE__ */ jsx19(CardDescription8, { children: "Only workspace owners can manage invites." })
2459
2572
  ] }) }) });
2460
2573
  }
2461
- return /* @__PURE__ */ jsx17("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs11("div", { className: "w-full max-w-2xl space-y-6", children: [
2462
- /* @__PURE__ */ jsxs11(Card7, { children: [
2463
- /* @__PURE__ */ jsxs11(CardHeader7, { children: [
2464
- /* @__PURE__ */ jsx17(CardTitle7, { children: "Invite a member" }),
2465
- /* @__PURE__ */ jsxs11(CardDescription7, { children: [
2574
+ return /* @__PURE__ */ jsx19("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12("div", { className: "w-full max-w-2xl space-y-6", children: [
2575
+ /* @__PURE__ */ jsxs12(Card8, { children: [
2576
+ /* @__PURE__ */ jsxs12(CardHeader8, { children: [
2577
+ /* @__PURE__ */ jsx19(CardTitle8, { children: "Invite a member" }),
2578
+ /* @__PURE__ */ jsxs12(CardDescription8, { children: [
2466
2579
  "Send an invite to join ",
2467
2580
  workspace?.name ?? "this workspace",
2468
2581
  "."
2469
2582
  ] })
2470
2583
  ] }),
2471
- /* @__PURE__ */ jsxs11("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
2472
- /* @__PURE__ */ jsxs11(CardContent7, { className: "space-y-4", children: [
2473
- formError && /* @__PURE__ */ jsx17(Notice3, { role: "alert", tone: "error", description: formError }),
2474
- successMessage && /* @__PURE__ */ jsx17(Notice3, { role: "status", tone: "success", description: successMessage }),
2475
- /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
2476
- /* @__PURE__ */ jsx17(Label8, { htmlFor: "invite-email", children: "Email address" }),
2477
- /* @__PURE__ */ jsx17(
2584
+ /* @__PURE__ */ jsxs12("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
2585
+ /* @__PURE__ */ jsxs12(CardContent8, { className: "space-y-4", children: [
2586
+ formError && /* @__PURE__ */ jsx19(Notice3, { role: "alert", tone: "error", description: formError }),
2587
+ successMessage && /* @__PURE__ */ jsx19(Notice3, { role: "status", tone: "success", description: successMessage }),
2588
+ /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
2589
+ /* @__PURE__ */ jsx19(Label8, { htmlFor: "invite-email", children: "Email address" }),
2590
+ /* @__PURE__ */ jsx19(
2478
2591
  Input8,
2479
2592
  {
2480
2593
  id: "invite-email",
@@ -2486,20 +2599,20 @@ function InvitesPage() {
2486
2599
  }
2487
2600
  )
2488
2601
  ] }),
2489
- /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
2490
- /* @__PURE__ */ jsx17(Label8, { htmlFor: "invite-role", children: "Role" }),
2491
- /* @__PURE__ */ jsxs11(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
2492
- /* @__PURE__ */ jsx17(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx17(SelectValue, { placeholder: "Select role" }) }),
2493
- /* @__PURE__ */ jsxs11(SelectContent, { children: [
2494
- /* @__PURE__ */ jsx17(SelectItem, { value: "editor", children: "Editor" }),
2495
- /* @__PURE__ */ jsx17(SelectItem, { value: "viewer", children: "Viewer" }),
2496
- /* @__PURE__ */ jsx17(SelectItem, { value: "owner", children: "Owner" })
2602
+ /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
2603
+ /* @__PURE__ */ jsx19(Label8, { htmlFor: "invite-role", children: "Role" }),
2604
+ /* @__PURE__ */ jsxs12(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
2605
+ /* @__PURE__ */ jsx19(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx19(SelectValue, { placeholder: "Select role" }) }),
2606
+ /* @__PURE__ */ jsxs12(SelectContent, { children: [
2607
+ /* @__PURE__ */ jsx19(SelectItem, { value: "editor", children: "Editor" }),
2608
+ /* @__PURE__ */ jsx19(SelectItem, { value: "viewer", children: "Viewer" }),
2609
+ /* @__PURE__ */ jsx19(SelectItem, { value: "owner", children: "Owner" })
2497
2610
  ] })
2498
2611
  ] })
2499
2612
  ] })
2500
2613
  ] }),
2501
- /* @__PURE__ */ jsx17(CardFooter7, { children: /* @__PURE__ */ jsx17(
2502
- Button12,
2614
+ /* @__PURE__ */ jsx19(CardFooter8, { children: /* @__PURE__ */ jsx19(
2615
+ Button13,
2503
2616
  {
2504
2617
  type: "submit",
2505
2618
  className: "w-full",
@@ -2509,37 +2622,37 @@ function InvitesPage() {
2509
2622
  ) })
2510
2623
  ] })
2511
2624
  ] }),
2512
- /* @__PURE__ */ jsxs11(Card7, { children: [
2513
- /* @__PURE__ */ jsxs11(CardHeader7, { children: [
2514
- /* @__PURE__ */ jsx17(CardTitle7, { children: "Pending invites" }),
2515
- /* @__PURE__ */ jsx17(CardDescription7, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
2625
+ /* @__PURE__ */ jsxs12(Card8, { children: [
2626
+ /* @__PURE__ */ jsxs12(CardHeader8, { children: [
2627
+ /* @__PURE__ */ jsx19(CardTitle8, { children: "Pending invites" }),
2628
+ /* @__PURE__ */ jsx19(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
2516
2629
  ] }),
2517
- /* @__PURE__ */ jsxs11(CardContent7, { children: [
2518
- revokeError && /* @__PURE__ */ jsx17(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
2519
- invitesQuery.isLoading && /* @__PURE__ */ jsx17(LoadingState2, {}),
2520
- invitesQuery.isError && /* @__PURE__ */ jsx17(Notice3, { tone: "error", description: "Failed to load invites." }),
2521
- invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx17("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
2630
+ /* @__PURE__ */ jsxs12(CardContent8, { children: [
2631
+ revokeError && /* @__PURE__ */ jsx19(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
2632
+ invitesQuery.isLoading && /* @__PURE__ */ jsx19(LoadingState2, {}),
2633
+ invitesQuery.isError && /* @__PURE__ */ jsx19(Notice3, { tone: "error", description: "Failed to load invites." }),
2634
+ invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx19("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
2522
2635
  const status = getInviteStatus(invite);
2523
- return /* @__PURE__ */ jsxs11(
2636
+ return /* @__PURE__ */ jsxs12(
2524
2637
  "div",
2525
2638
  {
2526
2639
  className: "flex items-center justify-between py-3",
2527
2640
  "data-testid": `invite-row-${invite.id}`,
2528
2641
  children: [
2529
- /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
2530
- /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium", children: invite.email }),
2531
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2532
- /* @__PURE__ */ jsx17("span", { children: invite.role }),
2533
- /* @__PURE__ */ jsx17(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
2534
- /* @__PURE__ */ jsxs11("span", { children: [
2642
+ /* @__PURE__ */ jsxs12("div", { className: "space-y-1", children: [
2643
+ /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium", children: invite.email }),
2644
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2645
+ /* @__PURE__ */ jsx19("span", { children: invite.role }),
2646
+ /* @__PURE__ */ jsx19(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
2647
+ /* @__PURE__ */ jsxs12("span", { children: [
2535
2648
  "expires",
2536
2649
  " ",
2537
2650
  new Date(invite.expiresAt).toLocaleDateString()
2538
2651
  ] })
2539
2652
  ] })
2540
2653
  ] }),
2541
- status === "pending" && /* @__PURE__ */ jsx17(
2542
- Button12,
2654
+ status === "pending" && /* @__PURE__ */ jsx19(
2655
+ Button13,
2543
2656
  {
2544
2657
  variant: "destructive",
2545
2658
  size: "sm",
@@ -2560,7 +2673,7 @@ function InvitesPage() {
2560
2673
  }
2561
2674
 
2562
2675
  // src/front/workspace/MembersPage.tsx
2563
- import { useCallback as useCallback7, useState as useState17 } from "react";
2676
+ import { useCallback as useCallback7, useState as useState18 } from "react";
2564
2677
  import { useMutation as useMutation3, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
2565
2678
  import {
2566
2679
  AlertDialog as AlertDialog2,
@@ -2570,12 +2683,12 @@ import {
2570
2683
  AlertDialogFooter as AlertDialogFooter2,
2571
2684
  AlertDialogHeader as AlertDialogHeader2,
2572
2685
  AlertDialogTitle as AlertDialogTitle2,
2573
- Button as Button13,
2574
- Card as Card8,
2575
- CardContent as CardContent8,
2576
- CardDescription as CardDescription8,
2577
- CardHeader as CardHeader8,
2578
- CardTitle as CardTitle8,
2686
+ Button as Button14,
2687
+ Card as Card9,
2688
+ CardContent as CardContent9,
2689
+ CardDescription as CardDescription9,
2690
+ CardHeader as CardHeader9,
2691
+ CardTitle as CardTitle9,
2579
2692
  Select as Select2,
2580
2693
  SelectContent as SelectContent2,
2581
2694
  SelectItem as SelectItem2,
@@ -2585,7 +2698,7 @@ import {
2585
2698
  LoadingState as LoadingState3,
2586
2699
  Notice as Notice4
2587
2700
  } from "@hachej/boring-ui-kit";
2588
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
2701
+ import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
2589
2702
  var ROLE_OPTIONS = ["owner", "editor", "viewer"];
2590
2703
  function MembersPage() {
2591
2704
  const workspace = useCurrentWorkspace();
@@ -2596,8 +2709,8 @@ function MembersPage() {
2596
2709
  const currentUserId = session.data?.user?.id ?? "";
2597
2710
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
2598
2711
  const membersQuery = useWorkspaceMembers(workspaceId);
2599
- const [toast, setToast] = useState17(null);
2600
- const [confirmTarget, setConfirmTarget] = useState17(null);
2712
+ const [toast, setToast] = useState18(null);
2713
+ const [confirmTarget, setConfirmTarget] = useState18(null);
2601
2714
  const showToast = useCallback7((msg) => {
2602
2715
  setToast(msg);
2603
2716
  setTimeout(() => setToast(null), 4e3);
@@ -2658,11 +2771,11 @@ function MembersPage() {
2658
2771
  removeMutation.mutate(confirmTarget.userId);
2659
2772
  }, [confirmTarget, removeMutation]);
2660
2773
  const isOwner = myRole === "owner";
2661
- return /* @__PURE__ */ jsx18("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12("div", { className: "w-full max-w-2xl space-y-6", children: [
2662
- /* @__PURE__ */ jsxs12(Card8, { children: [
2663
- /* @__PURE__ */ jsxs12(CardHeader8, { children: [
2664
- /* @__PURE__ */ jsx18(CardTitle8, { children: "Members" }),
2665
- /* @__PURE__ */ jsxs12(CardDescription8, { children: [
2774
+ 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: [
2775
+ /* @__PURE__ */ jsxs13(Card9, { children: [
2776
+ /* @__PURE__ */ jsxs13(CardHeader9, { children: [
2777
+ /* @__PURE__ */ jsx20(CardTitle9, { children: "Members" }),
2778
+ /* @__PURE__ */ jsxs13(CardDescription9, { children: [
2666
2779
  workspace?.name ?? "Workspace",
2667
2780
  " \xB7",
2668
2781
  " ",
@@ -2671,45 +2784,45 @@ function MembersPage() {
2671
2784
  (membersQuery.data?.length ?? 0) !== 1 ? "s" : ""
2672
2785
  ] })
2673
2786
  ] }),
2674
- /* @__PURE__ */ jsxs12(CardContent8, { children: [
2675
- toast && /* @__PURE__ */ jsx18(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
2676
- membersQuery.isLoading && /* @__PURE__ */ jsx18(LoadingState3, {}),
2677
- membersQuery.isError && /* @__PURE__ */ jsx18(Notice4, { tone: "error", description: "Failed to load members." }),
2678
- membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx18("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
2787
+ /* @__PURE__ */ jsxs13(CardContent9, { children: [
2788
+ toast && /* @__PURE__ */ jsx20(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
2789
+ membersQuery.isLoading && /* @__PURE__ */ jsx20(LoadingState3, {}),
2790
+ membersQuery.isError && /* @__PURE__ */ jsx20(Notice4, { tone: "error", description: "Failed to load members." }),
2791
+ membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx20("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
2679
2792
  const isSelf = member.userId === currentUserId;
2680
2793
  const canChangeRole = isOwner && !isSelf;
2681
2794
  const canRemove = isOwner || isSelf;
2682
- return /* @__PURE__ */ jsxs12(
2795
+ return /* @__PURE__ */ jsxs13(
2683
2796
  "div",
2684
2797
  {
2685
2798
  className: "flex items-center justify-between py-3",
2686
2799
  "data-testid": `member-row-${member.userId}`,
2687
2800
  children: [
2688
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
2689
- /* @__PURE__ */ jsx18(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
2690
- /* @__PURE__ */ jsxs12("div", { children: [
2691
- /* @__PURE__ */ jsxs12("p", { className: "text-sm font-medium", children: [
2801
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-3", children: [
2802
+ /* @__PURE__ */ jsx20(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
2803
+ /* @__PURE__ */ jsxs13("div", { children: [
2804
+ /* @__PURE__ */ jsxs13("p", { className: "text-sm font-medium", children: [
2692
2805
  member.user.name ?? member.user.email,
2693
- isSelf && /* @__PURE__ */ jsx18("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
2806
+ isSelf && /* @__PURE__ */ jsx20("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
2694
2807
  ] }),
2695
- /* @__PURE__ */ jsx18("p", { className: "text-xs text-muted-foreground", children: member.user.email })
2808
+ /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: member.user.email })
2696
2809
  ] })
2697
2810
  ] }),
2698
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
2699
- /* @__PURE__ */ jsxs12(
2811
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
2812
+ /* @__PURE__ */ jsxs13(
2700
2813
  Select2,
2701
2814
  {
2702
2815
  value: member.role,
2703
2816
  disabled: !canChangeRole,
2704
2817
  onValueChange: (value) => handleRoleChange(member.userId, value),
2705
2818
  children: [
2706
- /* @__PURE__ */ jsx18(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx18(SelectValue2, { placeholder: "Role" }) }),
2707
- /* @__PURE__ */ jsx18(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx18(SelectItem2, { value: r, children: r }, r)) })
2819
+ /* @__PURE__ */ jsx20(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx20(SelectValue2, { placeholder: "Role" }) }),
2820
+ /* @__PURE__ */ jsx20(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx20(SelectItem2, { value: r, children: r }, r)) })
2708
2821
  ]
2709
2822
  }
2710
2823
  ),
2711
- canRemove && /* @__PURE__ */ jsx18(
2712
- Button13,
2824
+ canRemove && /* @__PURE__ */ jsx20(
2825
+ Button14,
2713
2826
  {
2714
2827
  variant: "destructive",
2715
2828
  size: "sm",
@@ -2726,22 +2839,22 @@ function MembersPage() {
2726
2839
  }) })
2727
2840
  ] })
2728
2841
  ] }),
2729
- /* @__PURE__ */ jsx18(
2842
+ /* @__PURE__ */ jsx20(
2730
2843
  AlertDialog2,
2731
2844
  {
2732
2845
  open: confirmTarget !== null,
2733
2846
  onOpenChange: (open) => {
2734
2847
  if (!open) setConfirmTarget(null);
2735
2848
  },
2736
- children: /* @__PURE__ */ jsxs12(AlertDialogContent2, { children: [
2737
- /* @__PURE__ */ jsxs12(AlertDialogHeader2, { children: [
2738
- /* @__PURE__ */ jsx18(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
2739
- /* @__PURE__ */ jsx18(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
2849
+ children: /* @__PURE__ */ jsxs13(AlertDialogContent2, { children: [
2850
+ /* @__PURE__ */ jsxs13(AlertDialogHeader2, { children: [
2851
+ /* @__PURE__ */ jsx20(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
2852
+ /* @__PURE__ */ jsx20(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
2740
2853
  ] }),
2741
- /* @__PURE__ */ jsxs12(AlertDialogFooter2, { children: [
2742
- /* @__PURE__ */ jsx18(AlertDialogCancel2, { children: "Cancel" }),
2743
- /* @__PURE__ */ jsx18(
2744
- Button13,
2854
+ /* @__PURE__ */ jsxs13(AlertDialogFooter2, { children: [
2855
+ /* @__PURE__ */ jsx20(AlertDialogCancel2, { children: "Cancel" }),
2856
+ /* @__PURE__ */ jsx20(
2857
+ Button14,
2745
2858
  {
2746
2859
  variant: "destructive",
2747
2860
  disabled: removeMutation.isPending,
@@ -2758,7 +2871,7 @@ function MembersPage() {
2758
2871
  }
2759
2872
 
2760
2873
  // src/front/workspace/WorkspaceSettingsPage.tsx
2761
- import { useCallback as useCallback8, useEffect as useEffect10, useState as useState18 } from "react";
2874
+ import { useCallback as useCallback8, useEffect as useEffect10, useState as useState19 } from "react";
2762
2875
  import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
2763
2876
  import { useNavigate as useNavigate4 } from "react-router-dom";
2764
2877
  import {
@@ -2769,7 +2882,7 @@ import {
2769
2882
  AlertDialogFooter as AlertDialogFooter3,
2770
2883
  AlertDialogHeader as AlertDialogHeader3,
2771
2884
  AlertDialogTitle as AlertDialogTitle3,
2772
- Button as Button14,
2885
+ Button as Button15,
2773
2886
  IconButton,
2774
2887
  SettingsActionRow as UiSettingsActionRow2,
2775
2888
  SettingsNav as UiSettingsNav2,
@@ -2788,7 +2901,7 @@ import {
2788
2901
  ShieldAlert as ShieldAlert2,
2789
2902
  Trash2 as Trash22
2790
2903
  } from "lucide-react";
2791
- import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
2904
+ import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
2792
2905
  var STATE_TONES = {
2793
2906
  pending: "info",
2794
2907
  ready: "success",
@@ -2797,13 +2910,13 @@ var STATE_TONES = {
2797
2910
  function SettingsTopBar2({ workspaceId, workspaceName }) {
2798
2911
  const navigate = useNavigate4();
2799
2912
  const workspaceHref = workspaceId ? `/workspace/${encodeURIComponent(workspaceId)}` : "/";
2800
- return /* @__PURE__ */ jsx19(
2913
+ return /* @__PURE__ */ jsx21(
2801
2914
  "header",
2802
2915
  {
2803
2916
  className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
2804
2917
  "aria-label": "App top bar",
2805
- children: /* @__PURE__ */ jsxs13("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
2806
- /* @__PURE__ */ jsx19(
2918
+ children: /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
2919
+ /* @__PURE__ */ jsx21(
2807
2920
  IconButton,
2808
2921
  {
2809
2922
  type: "button",
@@ -2816,11 +2929,11 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
2816
2929
  children: "B"
2817
2930
  }
2818
2931
  ),
2819
- /* @__PURE__ */ jsx19("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: "Boring" }),
2820
- /* @__PURE__ */ jsx19("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2821
- /* @__PURE__ */ jsx19("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
2822
- /* @__PURE__ */ jsx19("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2823
- /* @__PURE__ */ jsx19("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
2932
+ /* @__PURE__ */ jsx21("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: "Boring" }),
2933
+ /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2934
+ /* @__PURE__ */ jsx21("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
2935
+ /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2936
+ /* @__PURE__ */ jsx21("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
2824
2937
  ] })
2825
2938
  }
2826
2939
  );
@@ -2831,26 +2944,26 @@ function SettingsPageHeader2({
2831
2944
  role,
2832
2945
  isDefault
2833
2946
  }) {
2834
- return /* @__PURE__ */ jsxs13("header", { className: "boring-settings-page-header", children: [
2835
- /* @__PURE__ */ jsxs13("div", { className: "boring-settings-context", children: [
2836
- /* @__PURE__ */ jsx19("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 }),
2837
- /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
2838
- /* @__PURE__ */ jsx19("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
2839
- /* @__PURE__ */ jsxs13("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
2840
- /* @__PURE__ */ jsx19("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
2841
- isDefault ? /* @__PURE__ */ jsx19("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
2947
+ return /* @__PURE__ */ jsxs14("header", { className: "boring-settings-page-header", children: [
2948
+ /* @__PURE__ */ jsxs14("div", { className: "boring-settings-context", children: [
2949
+ /* @__PURE__ */ jsx21("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 }),
2950
+ /* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
2951
+ /* @__PURE__ */ jsx21("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
2952
+ /* @__PURE__ */ jsxs14("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
2953
+ /* @__PURE__ */ jsx21("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
2954
+ isDefault ? /* @__PURE__ */ jsx21("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
2842
2955
  ] })
2843
2956
  ] })
2844
2957
  ] }),
2845
- /* @__PURE__ */ jsxs13("div", { className: "max-w-2xl", children: [
2846
- /* @__PURE__ */ jsx19("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
2847
- /* @__PURE__ */ jsx19("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
2848
- /* @__PURE__ */ jsx19("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
2958
+ /* @__PURE__ */ jsxs14("div", { className: "max-w-2xl", children: [
2959
+ /* @__PURE__ */ jsx21("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
2960
+ /* @__PURE__ */ jsx21("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
2961
+ /* @__PURE__ */ jsx21("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
2849
2962
  ] })
2850
2963
  ] });
2851
2964
  }
2852
2965
  function FieldNote({ children }) {
2853
- return /* @__PURE__ */ jsx19("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
2966
+ return /* @__PURE__ */ jsx21("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
2854
2967
  }
2855
2968
  function roleLabel(role) {
2856
2969
  if (!role) return "Loading role";
@@ -2868,14 +2981,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
2868
2981
  const queryClient = useQueryClient6();
2869
2982
  const navigate = useNavigate4();
2870
2983
  const workspaceId = workspace?.id ?? "";
2871
- const [nameValue, setNameValue] = useState18(null);
2872
- const [nameError, setNameError] = useState18(null);
2873
- const [retryError, setRetryError] = useState18(null);
2874
- const [deleteConfirmName, setDeleteConfirmName] = useState18("");
2875
- const [deleteDialogOpen, setDeleteDialogOpen] = useState18(false);
2876
- const [deleteError, setDeleteError] = useState18(null);
2877
- const [imageUploadDirValue, setImageUploadDirValue] = useState18(null);
2878
- const [fileSettingsError, setFileSettingsError] = useState18(null);
2984
+ const [nameValue, setNameValue] = useState19(null);
2985
+ const [nameError, setNameError] = useState19(null);
2986
+ const [retryError, setRetryError] = useState19(null);
2987
+ const [deleteConfirmName, setDeleteConfirmName] = useState19("");
2988
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState19(false);
2989
+ const [deleteError, setDeleteError] = useState19(null);
2990
+ const [imageUploadDirValue, setImageUploadDirValue] = useState19(null);
2991
+ const [fileSettingsError, setFileSettingsError] = useState19(null);
2879
2992
  const displayName = nameValue ?? workspace?.name ?? "";
2880
2993
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
2881
2994
  const requestHeaders = workspaceId ? { "x-boring-workspace-id": workspaceId } : void 0;
@@ -3021,18 +3134,18 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3021
3134
  const canDeleteWorkspace = role === "owner" || role === null;
3022
3135
  const workspaceName = workspace?.name ?? "Workspace";
3023
3136
  const workspaceInitial2 = (workspace?.name?.trim()?.[0] ?? "W").toUpperCase();
3024
- const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx19(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
3137
+ const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx21(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
3025
3138
  const navItems = WORKSPACE_NAV_ITEMS.filter((item) => {
3026
3139
  if (item.href === "#runtime") return hasRuntime;
3027
3140
  if (item.href === "#files") return hasFileSettings;
3028
3141
  return true;
3029
3142
  });
3030
- return /* @__PURE__ */ jsxs13("main", { className: "boring-settings-shell", children: [
3143
+ return /* @__PURE__ */ jsxs14("main", { className: "boring-settings-shell", children: [
3031
3144
  topBarNode,
3032
- /* @__PURE__ */ jsx19("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs13("div", { className: "boring-settings-layout", children: [
3033
- /* @__PURE__ */ jsx19("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx19(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
3034
- /* @__PURE__ */ jsxs13("div", { className: "boring-settings-content space-y-4", children: [
3035
- /* @__PURE__ */ jsx19(
3145
+ /* @__PURE__ */ jsx21("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs14("div", { className: "boring-settings-layout", children: [
3146
+ /* @__PURE__ */ jsx21("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx21(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
3147
+ /* @__PURE__ */ jsxs14("div", { className: "boring-settings-content space-y-4", children: [
3148
+ /* @__PURE__ */ jsx21(
3036
3149
  SettingsPageHeader2,
3037
3150
  {
3038
3151
  workspaceName,
@@ -3041,16 +3154,16 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3041
3154
  isDefault: Boolean(workspace?.isDefault)
3042
3155
  }
3043
3156
  ),
3044
- /* @__PURE__ */ jsx19(
3157
+ /* @__PURE__ */ jsx21(
3045
3158
  UiSettingsPanel2,
3046
3159
  {
3047
3160
  id: "general",
3048
- icon: /* @__PURE__ */ jsx19(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3161
+ icon: /* @__PURE__ */ jsx21(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3049
3162
  title: "General",
3050
3163
  description: "Keep the workspace name clear enough to scan in menus.",
3051
- footer: /* @__PURE__ */ jsxs13(Fragment3, { children: [
3052
- nameChanged ? /* @__PURE__ */ jsx19(
3053
- Button14,
3164
+ footer: /* @__PURE__ */ jsxs14(Fragment5, { children: [
3165
+ nameChanged ? /* @__PURE__ */ jsx21(
3166
+ Button15,
3054
3167
  {
3055
3168
  type: "button",
3056
3169
  variant: "ghost",
@@ -3063,8 +3176,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3063
3176
  children: "Reset"
3064
3177
  }
3065
3178
  ) : null,
3066
- /* @__PURE__ */ jsx19(
3067
- Button14,
3179
+ /* @__PURE__ */ jsx21(
3180
+ Button15,
3068
3181
  {
3069
3182
  "data-testid": "save-name",
3070
3183
  size: "sm",
@@ -3074,11 +3187,11 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3074
3187
  }
3075
3188
  )
3076
3189
  ] }),
3077
- children: /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
3078
- nameError && /* @__PURE__ */ jsx19(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
3079
- /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3080
- /* @__PURE__ */ jsx19(Label9, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
3081
- /* @__PURE__ */ jsx19(
3190
+ children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3191
+ nameError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
3192
+ /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
3193
+ /* @__PURE__ */ jsx21(Label9, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
3194
+ /* @__PURE__ */ jsx21(
3082
3195
  Input9,
3083
3196
  {
3084
3197
  id: "workspace-name",
@@ -3090,50 +3203,50 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3090
3203
  "aria-invalid": nameError ? "true" : "false"
3091
3204
  }
3092
3205
  ),
3093
- /* @__PURE__ */ jsx19(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
3206
+ /* @__PURE__ */ jsx21(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
3094
3207
  ] })
3095
3208
  ] })
3096
3209
  }
3097
3210
  ),
3098
- hasRuntime && /* @__PURE__ */ jsx19(
3211
+ hasRuntime && /* @__PURE__ */ jsx21(
3099
3212
  UiSettingsPanel2,
3100
3213
  {
3101
3214
  id: "runtime",
3102
3215
  testId: "runtime-card",
3103
- icon: /* @__PURE__ */ jsx19(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3216
+ icon: /* @__PURE__ */ jsx21(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3104
3217
  title: "Runtime",
3105
3218
  description: "Provisioning status for this workspace.",
3106
- children: /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
3107
- /* @__PURE__ */ jsxs13("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: [
3108
- /* @__PURE__ */ jsx19("span", { className: "text-[13px] font-medium", children: "State" }),
3109
- /* @__PURE__ */ jsx19(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
3219
+ children: /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
3220
+ /* @__PURE__ */ jsxs14("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: [
3221
+ /* @__PURE__ */ jsx21("span", { className: "text-[13px] font-medium", children: "State" }),
3222
+ /* @__PURE__ */ jsx21(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
3110
3223
  ] }),
3111
- runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs13(
3224
+ runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs14(
3112
3225
  "div",
3113
3226
  {
3114
3227
  "data-testid": "volume-path",
3115
3228
  className: "space-y-1 rounded-md border border-border/50 bg-muted/10 px-3 py-2",
3116
3229
  children: [
3117
- /* @__PURE__ */ jsx19("p", { className: "text-[13px] font-medium", children: "Volume" }),
3118
- /* @__PURE__ */ jsx19("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
3230
+ /* @__PURE__ */ jsx21("p", { className: "text-[13px] font-medium", children: "Volume" }),
3231
+ /* @__PURE__ */ jsx21("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
3119
3232
  ]
3120
3233
  }
3121
3234
  ),
3122
- runtime.state === "error" && runtime.lastError && /* @__PURE__ */ jsxs13(
3235
+ runtime.state === "error" && runtime.lastError && /* @__PURE__ */ jsxs14(
3123
3236
  "div",
3124
3237
  {
3125
3238
  "data-testid": "runtime-error",
3126
3239
  role: "alert",
3127
3240
  className: "flex gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[13px] leading-5 text-destructive",
3128
3241
  children: [
3129
- /* @__PURE__ */ jsx19(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
3242
+ /* @__PURE__ */ jsx21(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
3130
3243
  runtime.lastError
3131
3244
  ]
3132
3245
  }
3133
3246
  ),
3134
- runtime.state === "error" && runtime.lastErrorOp === "provision" && /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
3135
- /* @__PURE__ */ jsxs13(
3136
- Button14,
3247
+ runtime.state === "error" && runtime.lastErrorOp === "provision" && /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
3248
+ /* @__PURE__ */ jsxs14(
3249
+ Button15,
3137
3250
  {
3138
3251
  "data-testid": "retry-provision",
3139
3252
  variant: "outline",
@@ -3141,14 +3254,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3141
3254
  disabled: retryMutation.isPending,
3142
3255
  onClick: () => retryMutation.mutate(),
3143
3256
  children: [
3144
- /* @__PURE__ */ jsx19(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
3257
+ /* @__PURE__ */ jsx21(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
3145
3258
  retryMutation.isPending ? "Retrying..." : "Retry provisioning"
3146
3259
  ]
3147
3260
  }
3148
3261
  ),
3149
- retryError && /* @__PURE__ */ jsx19(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
3262
+ retryError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
3150
3263
  ] }),
3151
- runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx19(
3264
+ runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx21(
3152
3265
  "p",
3153
3266
  {
3154
3267
  "data-testid": "destroy-guidance",
@@ -3159,16 +3272,16 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3159
3272
  ] })
3160
3273
  }
3161
3274
  ),
3162
- hasFileSettings && /* @__PURE__ */ jsx19(
3275
+ hasFileSettings && /* @__PURE__ */ jsx21(
3163
3276
  UiSettingsPanel2,
3164
3277
  {
3165
3278
  id: "files",
3166
3279
  testId: "file-settings-card",
3167
- icon: /* @__PURE__ */ jsx19(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3280
+ icon: /* @__PURE__ */ jsx21(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3168
3281
  title: "Files",
3169
3282
  description: "Configure where markdown editor image uploads are stored. Direct/local workspaces can also edit .boring/settings.",
3170
- footer: /* @__PURE__ */ jsx19(
3171
- Button14,
3283
+ footer: /* @__PURE__ */ jsx21(
3284
+ Button15,
3172
3285
  {
3173
3286
  "data-testid": "save-file-settings",
3174
3287
  size: "sm",
@@ -3177,11 +3290,11 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3177
3290
  children: fileSettingsMutation.isPending ? "Saving..." : "Save file settings"
3178
3291
  }
3179
3292
  ),
3180
- children: /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
3181
- fileSettingsError && /* @__PURE__ */ jsx19(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
3182
- /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3183
- /* @__PURE__ */ jsx19(Label9, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
3184
- /* @__PURE__ */ jsx19(
3293
+ children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3294
+ fileSettingsError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
3295
+ /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
3296
+ /* @__PURE__ */ jsx21(Label9, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
3297
+ /* @__PURE__ */ jsx21(
3185
3298
  Input9,
3186
3299
  {
3187
3300
  id: "markdown-image-upload-dir",
@@ -3192,35 +3305,35 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3192
3305
  disabled: !canEditName
3193
3306
  }
3194
3307
  ),
3195
- /* @__PURE__ */ jsxs13(FieldNote, { children: [
3308
+ /* @__PURE__ */ jsxs14(FieldNote, { children: [
3196
3309
  "Relative workspace path used by markdown image uploads. Stored in ",
3197
- /* @__PURE__ */ jsx19("code", { children: ".boring/settings" }),
3310
+ /* @__PURE__ */ jsx21("code", { children: ".boring/settings" }),
3198
3311
  "."
3199
3312
  ] })
3200
3313
  ] })
3201
3314
  ] })
3202
3315
  }
3203
3316
  ),
3204
- /* @__PURE__ */ jsx19(
3317
+ /* @__PURE__ */ jsx21(
3205
3318
  UiSettingsPanel2,
3206
3319
  {
3207
3320
  id: "danger-zone",
3208
3321
  testId: "danger-zone",
3209
- icon: /* @__PURE__ */ jsx19(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3322
+ icon: /* @__PURE__ */ jsx21(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3210
3323
  title: "Danger zone",
3211
3324
  description: "Permanently delete this workspace and all provisioned data.",
3212
3325
  danger: true,
3213
- children: /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
3214
- deleteError && /* @__PURE__ */ jsx19(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
3215
- !canDeleteWorkspace ? /* @__PURE__ */ jsx19("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,
3216
- /* @__PURE__ */ jsx19(
3326
+ children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3327
+ deleteError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
3328
+ !canDeleteWorkspace ? /* @__PURE__ */ jsx21("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,
3329
+ /* @__PURE__ */ jsx21(
3217
3330
  UiSettingsActionRow2,
3218
3331
  {
3219
3332
  title: "Delete workspace",
3220
3333
  description: "Delete the workspace record and re-issue cleanup for provisioned runtime data.",
3221
- action: /* @__PURE__ */ jsxs13(AlertDialog3, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
3222
- /* @__PURE__ */ jsxs13(
3223
- Button14,
3334
+ action: /* @__PURE__ */ jsxs14(AlertDialog3, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
3335
+ /* @__PURE__ */ jsxs14(
3336
+ Button15,
3224
3337
  {
3225
3338
  variant: "destructive",
3226
3339
  size: "sm",
@@ -3231,21 +3344,21 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3231
3344
  setDeleteConfirmName("");
3232
3345
  },
3233
3346
  children: [
3234
- /* @__PURE__ */ jsx19(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
3347
+ /* @__PURE__ */ jsx21(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
3235
3348
  "Delete workspace"
3236
3349
  ]
3237
3350
  }
3238
3351
  ),
3239
- /* @__PURE__ */ jsxs13(AlertDialogContent3, { children: [
3240
- /* @__PURE__ */ jsxs13(AlertDialogHeader3, { children: [
3241
- /* @__PURE__ */ jsx19(AlertDialogTitle3, { children: "Delete workspace?" }),
3242
- /* @__PURE__ */ jsxs13(AlertDialogDescription3, { children: [
3352
+ /* @__PURE__ */ jsxs14(AlertDialogContent3, { children: [
3353
+ /* @__PURE__ */ jsxs14(AlertDialogHeader3, { children: [
3354
+ /* @__PURE__ */ jsx21(AlertDialogTitle3, { children: "Delete workspace?" }),
3355
+ /* @__PURE__ */ jsxs14(AlertDialogDescription3, { children: [
3243
3356
  "This action cannot be undone. Type ",
3244
- /* @__PURE__ */ jsx19("strong", { children: workspace?.name }),
3357
+ /* @__PURE__ */ jsx21("strong", { children: workspace?.name }),
3245
3358
  " to confirm."
3246
3359
  ] })
3247
3360
  ] }),
3248
- /* @__PURE__ */ jsx19("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx19(
3361
+ /* @__PURE__ */ jsx21("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx21(
3249
3362
  Input9,
3250
3363
  {
3251
3364
  "data-testid": "delete-confirm-input",
@@ -3256,10 +3369,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3256
3369
  autoComplete: "off"
3257
3370
  }
3258
3371
  ) }),
3259
- /* @__PURE__ */ jsxs13(AlertDialogFooter3, { children: [
3260
- /* @__PURE__ */ jsx19(AlertDialogCancel3, { children: "Cancel" }),
3261
- /* @__PURE__ */ jsx19(
3262
- Button14,
3372
+ /* @__PURE__ */ jsxs14(AlertDialogFooter3, { children: [
3373
+ /* @__PURE__ */ jsx21(AlertDialogCancel3, { children: "Cancel" }),
3374
+ /* @__PURE__ */ jsx21(
3375
+ Button15,
3263
3376
  {
3264
3377
  variant: "destructive",
3265
3378
  size: "sm",
@@ -3283,10 +3396,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3283
3396
  }
3284
3397
 
3285
3398
  // src/front/CoreFront.tsx
3286
- import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
3399
+ import { Fragment as Fragment6, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
3287
3400
  var CSP_NONCE_META_NAME = "boring-csp-nonce";
3288
3401
  function PlaceholderPage({ name }) {
3289
- return /* @__PURE__ */ jsxs14("div", { "data-testid": `placeholder-${name}`, children: [
3402
+ return /* @__PURE__ */ jsxs15("div", { "data-testid": `placeholder-${name}`, children: [
3290
3403
  name,
3291
3404
  " (not yet implemented)"
3292
3405
  ] });
@@ -3318,11 +3431,12 @@ function CoreFront({ children, authPages, cspNonce }) {
3318
3431
  const ForgotPasswordPage2 = authPages?.forgotPassword ?? ForgotPasswordPage;
3319
3432
  const ResetPasswordPage2 = authPages?.resetPassword ?? ResetPasswordPage;
3320
3433
  const VerifyEmailPage2 = authPages?.verifyEmail ?? VerifyEmailPage;
3434
+ const AuthErrorPage2 = authPages?.authError ?? AuthErrorPage;
3321
3435
  const UserSettingsPage2 = authPages?.userSettings ?? UserSettingsPage;
3322
- return /* @__PURE__ */ jsx20(HelmetProvider, { children: /* @__PURE__ */ jsx20(AppErrorBoundary, { children: /* @__PURE__ */ jsx20(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx20(ConfigProvider, { children: /* @__PURE__ */ jsx20(ThemeProvider, { children: /* @__PURE__ */ jsx20(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx20(UserIdentityProvider, { children: /* @__PURE__ */ jsx20(BrowserRouter, { children: /* @__PURE__ */ jsx20(WorkspaceAuthProvider, { children: /* @__PURE__ */ jsxs14(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx20(UserMenu, {}), children: [
3323
- /* @__PURE__ */ jsx20(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
3324
- /* @__PURE__ */ jsx20("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }),
3325
- /* @__PURE__ */ jsx20(
3436
+ return /* @__PURE__ */ jsx22(HelmetProvider, { children: /* @__PURE__ */ jsx22(AppErrorBoundary, { children: /* @__PURE__ */ jsx22(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx22(ConfigProvider, { children: /* @__PURE__ */ jsx22(ThemeProvider, { children: /* @__PURE__ */ jsx22(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx22(UserIdentityProvider, { children: /* @__PURE__ */ jsx22(BrowserRouter, { children: /* @__PURE__ */ jsx22(WorkspaceAuthProvider, { children: /* @__PURE__ */ jsxs15(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx22(UserMenu, {}), children: [
3437
+ /* @__PURE__ */ jsx22(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsxs15(Fragment6, { children: [
3438
+ /* @__PURE__ */ jsx22("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }),
3439
+ /* @__PURE__ */ jsx22(
3326
3440
  "script",
3327
3441
  {
3328
3442
  type: "application/json",
@@ -3332,28 +3446,30 @@ function CoreFront({ children, authPages, cspNonce }) {
3332
3446
  }
3333
3447
  )
3334
3448
  ] }) : null }),
3335
- /* @__PURE__ */ jsx20(AuthGate, { publicPaths: ["/invites"], children: /* @__PURE__ */ jsx20(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs14(Routes, { children: [
3336
- /* @__PURE__ */ jsx20(Route, { path: routes.signin, element: /* @__PURE__ */ jsx20(SignInPage2, {}) }),
3337
- /* @__PURE__ */ jsx20(Route, { path: routes.signup, element: /* @__PURE__ */ jsx20(SignUpPage2, {}) }),
3338
- /* @__PURE__ */ jsx20(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx20(ForgotPasswordPage2, {}) }),
3339
- /* @__PURE__ */ jsx20(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx20(ResetPasswordPage2, {}) }),
3340
- /* @__PURE__ */ jsx20(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx20(VerifyEmailPage2, {}) }),
3341
- /* @__PURE__ */ jsx20(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx20(PlaceholderPage, { name: "github-callback" }) }),
3342
- /* @__PURE__ */ jsx20(Route, { path: routes.me, element: /* @__PURE__ */ jsx20(UserSettingsPage2, {}) }),
3343
- /* @__PURE__ */ jsx20(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx20(MembersPage, {}) }),
3344
- /* @__PURE__ */ jsx20(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx20(MembersPage, {}) }),
3345
- /* @__PURE__ */ jsx20(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx20(InvitesPage, {}) }),
3346
- /* @__PURE__ */ jsx20(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx20(InvitesPage, {}) }),
3347
- /* @__PURE__ */ jsx20(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx20(WorkspaceSettingsPage, {}) }),
3348
- /* @__PURE__ */ jsx20(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx20(WorkspaceSettingsPage, {}) }),
3349
- /* @__PURE__ */ jsx20(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx20(InviteAcceptPage, {}) }),
3449
+ /* @__PURE__ */ jsx22(AuthGate, { publicPaths: ["/invites"], children: /* @__PURE__ */ jsx22(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs15(Routes, { children: [
3450
+ /* @__PURE__ */ jsx22(Route, { path: routes.signin, element: /* @__PURE__ */ jsx22(SignInPage2, {}) }),
3451
+ /* @__PURE__ */ jsx22(Route, { path: routes.signup, element: /* @__PURE__ */ jsx22(SignUpPage2, {}) }),
3452
+ /* @__PURE__ */ jsx22(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx22(ForgotPasswordPage2, {}) }),
3453
+ /* @__PURE__ */ jsx22(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx22(ResetPasswordPage2, {}) }),
3454
+ /* @__PURE__ */ jsx22(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx22(VerifyEmailPage2, {}) }),
3455
+ /* @__PURE__ */ jsx22(Route, { path: routes.authError, element: /* @__PURE__ */ jsx22(AuthErrorPage2, {}) }),
3456
+ /* @__PURE__ */ jsx22(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx22(PlaceholderPage, { name: "github-callback" }) }),
3457
+ /* @__PURE__ */ jsx22(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx22(PlaceholderPage, { name: "google-callback" }) }),
3458
+ /* @__PURE__ */ jsx22(Route, { path: routes.me, element: /* @__PURE__ */ jsx22(UserSettingsPage2, {}) }),
3459
+ /* @__PURE__ */ jsx22(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx22(MembersPage, {}) }),
3460
+ /* @__PURE__ */ jsx22(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx22(MembersPage, {}) }),
3461
+ /* @__PURE__ */ jsx22(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx22(InvitesPage, {}) }),
3462
+ /* @__PURE__ */ jsx22(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx22(InvitesPage, {}) }),
3463
+ /* @__PURE__ */ jsx22(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx22(WorkspaceSettingsPage, {}) }),
3464
+ /* @__PURE__ */ jsx22(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx22(WorkspaceSettingsPage, {}) }),
3465
+ /* @__PURE__ */ jsx22(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx22(InviteAcceptPage, {}) }),
3350
3466
  children
3351
3467
  ] }) }) })
3352
3468
  ] }) }) }) }) }) }) }) }) }) });
3353
3469
  }
3354
3470
 
3355
3471
  // src/front/commands/CoreCommandContributions.tsx
3356
- import { useMemo as useMemo7, useState as useState19 } from "react";
3472
+ import { useMemo as useMemo7, useState as useState20 } from "react";
3357
3473
  import { useNavigate as useNavigate5 } from "react-router-dom";
3358
3474
 
3359
3475
  // src/front/workspace/commands.ts
@@ -3395,7 +3511,7 @@ function useCoreCommands() {
3395
3511
  const navigate = useNavigate5();
3396
3512
  const signOut = useSignOut();
3397
3513
  const workspace = useCurrentWorkspace();
3398
- const [isSigningOut, setIsSigningOut] = useState19(false);
3514
+ const [isSigningOut, setIsSigningOut] = useState20(false);
3399
3515
  return useMemo7(() => {
3400
3516
  const result = [
3401
3517
  {
@@ -3530,6 +3646,7 @@ export {
3530
3646
  useSignOut,
3531
3647
  UserIdentityProvider,
3532
3648
  useUser,
3649
+ GoogleAuthButton,
3533
3650
  SignInPage,
3534
3651
  SignUpPage,
3535
3652
  ForgotPasswordPage,