@hachej/boring-core 0.1.58 → 0.1.60

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.
@@ -2102,7 +2102,7 @@ function AuthGate({
2102
2102
  }
2103
2103
 
2104
2104
  // src/front/CoreFront.tsx
2105
- import { Suspense, useCallback as useCallback9, useMemo as useMemo6 } from "react";
2105
+ import { Suspense, useCallback as useCallback9, useMemo as useMemo7 } from "react";
2106
2106
  import { BrowserRouter, Routes, Route, useLocation as useLocation2, useNavigate as useNavigate6 } from "react-router-dom";
2107
2107
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2108
2108
  import { Helmet, HelmetProvider } from "react-helmet-async";
@@ -2120,6 +2120,7 @@ import {
2120
2120
  } from "@hachej/boring-ui-kit";
2121
2121
  import {
2122
2122
  ChevronDown,
2123
+ ChevronsUpDown,
2123
2124
  Check,
2124
2125
  LogOut,
2125
2126
  Monitor,
@@ -2146,7 +2147,7 @@ function initialsFor2(name, email) {
2146
2147
  }
2147
2148
  return email.slice(0, 2).toUpperCase();
2148
2149
  }
2149
- function UserMenu() {
2150
+ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "compact" } = {}) {
2150
2151
  const identity = useUser();
2151
2152
  const signOut = useSignOut();
2152
2153
  const navigate = useNavigate3();
@@ -2167,7 +2168,23 @@ function UserMenu() {
2167
2168
  }
2168
2169
  }
2169
2170
  return /* @__PURE__ */ jsxs8(DropdownMenu, { children: [
2170
- /* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
2171
+ /* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: variant === "bar" ? /* @__PURE__ */ jsxs8(
2172
+ Button10,
2173
+ {
2174
+ type: "button",
2175
+ variant: "ghost",
2176
+ "aria-label": "Account menu",
2177
+ className: "h-10 w-full justify-start gap-2.5 rounded-lg border border-transparent bg-transparent px-2 text-left text-foreground shadow-none hover:bg-foreground/[0.06] focus-visible:ring-1 focus-visible:ring-ring",
2178
+ children: [
2179
+ /* @__PURE__ */ jsx16("span", { className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/60 bg-foreground/[0.12] text-[10px] font-semibold text-foreground", children: initials }),
2180
+ /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5 leading-snug", children: [
2181
+ /* @__PURE__ */ jsx16("span", { className: "truncate text-[13px] font-medium text-foreground", children: userName }),
2182
+ /* @__PURE__ */ jsx16("span", { className: "truncate text-[11px] text-muted-foreground/80", children: userEmail })
2183
+ ] }),
2184
+ /* @__PURE__ */ jsx16(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2185
+ ]
2186
+ }
2187
+ ) : /* @__PURE__ */ jsxs8(
2171
2188
  Button10,
2172
2189
  {
2173
2190
  type: "button",
@@ -2183,7 +2200,8 @@ function UserMenu() {
2183
2200
  /* @__PURE__ */ jsxs8(
2184
2201
  DropdownMenuContent,
2185
2202
  {
2186
- align: "end",
2203
+ align: contentAlign,
2204
+ side: contentSide,
2187
2205
  sideOffset: 8,
2188
2206
  className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
2189
2207
  children: [
@@ -2278,7 +2296,7 @@ import {
2278
2296
  Label as Label7,
2279
2297
  useToast
2280
2298
  } from "@hachej/boring-ui-kit";
2281
- import { ChevronsUpDown, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
2299
+ import { ChevronsUpDown as ChevronsUpDown2, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
2282
2300
  import { useNavigate as useNavigate4 } from "react-router-dom";
2283
2301
  import { z as z6 } from "zod";
2284
2302
  import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
@@ -2326,7 +2344,8 @@ function OpenInNewTabIcon({ className }) {
2326
2344
  }
2327
2345
  function WorkspaceSwitcher({
2328
2346
  appTitle,
2329
- workspacePathPrefix = "/workspace"
2347
+ workspacePathPrefix = "/workspace",
2348
+ displayMode = "full"
2330
2349
  }) {
2331
2350
  const config = useOptionalConfig();
2332
2351
  const resolvedAppTitle = appTitle ?? config?.appName ?? "Boring UI";
@@ -2424,7 +2443,19 @@ function WorkspaceSwitcher({
2424
2443
  ]
2425
2444
  }
2426
2445
  ) : /* @__PURE__ */ jsxs9(DropdownMenu2, { children: [
2427
- /* @__PURE__ */ jsx17(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs9(
2446
+ /* @__PURE__ */ jsx17(DropdownMenuTrigger2, { asChild: true, children: displayMode === "workspace" ? /* @__PURE__ */ jsxs9(
2447
+ Button11,
2448
+ {
2449
+ type: "button",
2450
+ variant: "ghost",
2451
+ "aria-label": `Workspace menu: ${switcherLabel}`,
2452
+ className: "h-8 w-full min-w-0 justify-start gap-1.5 rounded-lg border border-transparent px-2 text-left hover:bg-foreground/[0.06] focus-visible:ring-1 focus-visible:ring-ring",
2453
+ children: [
2454
+ /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-[13px] font-medium text-foreground/85", children: switcherLabel }),
2455
+ /* @__PURE__ */ jsx17(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
2456
+ ]
2457
+ }
2458
+ ) : /* @__PURE__ */ jsxs9(
2428
2459
  Button11,
2429
2460
  {
2430
2461
  type: "button",
@@ -2437,15 +2468,11 @@ function WorkspaceSwitcher({
2437
2468
  {
2438
2469
  "aria-hidden": "true",
2439
2470
  className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background",
2440
- children: resolvedAppTitle.charAt(0).toUpperCase()
2471
+ children: workspaceInitial(switcherLabel)
2441
2472
  }
2442
2473
  ),
2443
- /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 items-center gap-1.5", children: [
2444
- /* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-medium text-foreground", children: resolvedAppTitle }),
2445
- /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
2446
- /* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-normal text-muted-foreground", children: switcherLabel })
2447
- ] }),
2448
- /* @__PURE__ */ jsx17(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2474
+ /* @__PURE__ */ jsx17("span", { className: "min-w-0 truncate text-[13px] font-medium text-foreground", children: switcherLabel }),
2475
+ /* @__PURE__ */ jsx17(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
2449
2476
  ]
2450
2477
  }
2451
2478
  ) }),
@@ -2596,9 +2623,134 @@ function WorkspaceSwitcher({
2596
2623
  ] });
2597
2624
  }
2598
2625
 
2626
+ // src/front/components/CreateWorkspaceDialog.tsx
2627
+ import { useMemo as useMemo6, useState as useState17 } from "react";
2628
+ import { useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2629
+ import {
2630
+ Button as Button12,
2631
+ Dialog as Dialog2,
2632
+ DialogContent as DialogContent2,
2633
+ DialogDescription as DialogDescription2,
2634
+ DialogFooter as DialogFooter2,
2635
+ DialogHeader as DialogHeader2,
2636
+ DialogTitle as DialogTitle2,
2637
+ Input as Input8,
2638
+ Label as Label8,
2639
+ useToast as useToast2
2640
+ } from "@hachej/boring-ui-kit";
2641
+ import { z as z7 } from "zod";
2642
+ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
2643
+ var workspaceNameSchema2 = z7.object({
2644
+ name: z7.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
2645
+ });
2646
+ function CreateWorkspaceDialog({
2647
+ open,
2648
+ onOpenChange,
2649
+ onCreated,
2650
+ title = "Create workspace",
2651
+ description = "Choose a name for your new workspace.",
2652
+ entityNoun = "workspace"
2653
+ }) {
2654
+ const queryClient = useQueryClient4();
2655
+ const { toast } = useToast2();
2656
+ const [name, setName] = useState17("");
2657
+ const [attemptedSubmit, setAttemptedSubmit] = useState17(false);
2658
+ const [isSubmitting, setIsSubmitting] = useState17(false);
2659
+ const [serverError, setServerError] = useState17(null);
2660
+ const validation = useMemo6(() => workspaceNameSchema2.safeParse({ name }), [name]);
2661
+ const shouldShowNameError = name.length > 100 || attemptedSubmit && !validation.success;
2662
+ const nameError = shouldShowNameError && !validation.success ? validation.error.issues[0]?.message ?? "Invalid workspace name" : null;
2663
+ function reset() {
2664
+ setName("");
2665
+ setAttemptedSubmit(false);
2666
+ setIsSubmitting(false);
2667
+ setServerError(null);
2668
+ }
2669
+ function handleOpenChange(next) {
2670
+ onOpenChange(next);
2671
+ if (!next) reset();
2672
+ }
2673
+ async function handleSubmit(event) {
2674
+ event.preventDefault();
2675
+ setAttemptedSubmit(true);
2676
+ setServerError(null);
2677
+ const parsed = workspaceNameSchema2.safeParse({ name });
2678
+ if (!parsed.success) return;
2679
+ setIsSubmitting(true);
2680
+ try {
2681
+ const data = await apiFetchJson("/api/v1/workspaces", {
2682
+ method: "POST",
2683
+ headers: { "content-type": "application/json" },
2684
+ body: JSON.stringify({ name: parsed.data.name })
2685
+ });
2686
+ queryClient.setQueryData(workspaceQueryKey(data.workspace.id), data);
2687
+ queryClient.setQueryData(WORKSPACES_QUERY_KEY, (current = []) => {
2688
+ if (current.some((workspace) => workspace.id === data.workspace.id)) return current;
2689
+ return [...current, data.workspace];
2690
+ });
2691
+ handleOpenChange(false);
2692
+ onCreated?.(data.workspace);
2693
+ void queryClient.invalidateQueries({ queryKey: WORKSPACES_QUERY_KEY });
2694
+ void queryClient.invalidateQueries({ queryKey: workspaceQueryKey(data.workspace.id) });
2695
+ } catch (error) {
2696
+ const detail = getHttpErrorDetail(error);
2697
+ if (typeof detail.status === "number" && detail.status >= 400 && detail.status < 500) {
2698
+ toast({
2699
+ title: `Unable to create ${entityNoun}`,
2700
+ description: detail.message,
2701
+ variant: "destructive"
2702
+ });
2703
+ } else {
2704
+ setServerError(detail.message);
2705
+ }
2706
+ } finally {
2707
+ setIsSubmitting(false);
2708
+ }
2709
+ }
2710
+ return /* @__PURE__ */ jsx18(Dialog2, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent2, { children: [
2711
+ /* @__PURE__ */ jsxs10(DialogHeader2, { children: [
2712
+ /* @__PURE__ */ jsx18(DialogTitle2, { children: title }),
2713
+ /* @__PURE__ */ jsx18(DialogDescription2, { children: description })
2714
+ ] }),
2715
+ /* @__PURE__ */ jsxs10("form", { onSubmit: (event) => void handleSubmit(event), className: "space-y-4", children: [
2716
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2717
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3", children: [
2718
+ /* @__PURE__ */ jsx18(Label8, { htmlFor: "create-workspace-name", children: "Name" }),
2719
+ /* @__PURE__ */ jsxs10("span", { className: "text-xs text-muted-foreground", children: [
2720
+ name.length,
2721
+ "/100"
2722
+ ] })
2723
+ ] }),
2724
+ /* @__PURE__ */ jsx18(
2725
+ Input8,
2726
+ {
2727
+ id: "create-workspace-name",
2728
+ name: "name",
2729
+ value: name,
2730
+ maxLength: 101,
2731
+ onChange: (event) => {
2732
+ setName(event.target.value);
2733
+ if (serverError) setServerError(null);
2734
+ },
2735
+ placeholder: "Default workspace",
2736
+ "aria-invalid": nameError ? "true" : "false",
2737
+ autoFocus: true
2738
+ }
2739
+ ),
2740
+ nameError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
2741
+ serverError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
2742
+ ] }),
2743
+ /* @__PURE__ */ jsxs10(DialogFooter2, { children: [
2744
+ /* @__PURE__ */ jsx18(Button12, { type: "button", variant: "ghost", onClick: () => handleOpenChange(false), disabled: isSubmitting, children: "Cancel" }),
2745
+ /* @__PURE__ */ jsx18(Button12, { type: "submit", disabled: isSubmitting || !validation.success, children: isSubmitting ? "Creating..." : title })
2746
+ ] })
2747
+ ] })
2748
+ ] }) });
2749
+ }
2750
+
2599
2751
  // src/front/components/ThemeToggle.tsx
2600
- import { Button as Button12 } from "@hachej/boring-ui-kit";
2601
- import { jsxs as jsxs10 } from "react/jsx-runtime";
2752
+ import { Button as Button13 } from "@hachej/boring-ui-kit";
2753
+ import { jsxs as jsxs11 } from "react/jsx-runtime";
2602
2754
  var THEME_ORDER2 = ["light", "dark", "system"];
2603
2755
  function nextTheme(preference) {
2604
2756
  const index = THEME_ORDER2.indexOf(preference);
@@ -2612,8 +2764,8 @@ function labelForTheme2(preference) {
2612
2764
  }
2613
2765
  function ThemeToggle() {
2614
2766
  const { preference, setTheme } = useTheme();
2615
- return /* @__PURE__ */ jsxs10(
2616
- Button12,
2767
+ return /* @__PURE__ */ jsxs11(
2768
+ Button13,
2617
2769
  {
2618
2770
  type: "button",
2619
2771
  variant: "outline",
@@ -2630,42 +2782,42 @@ function ThemeToggle() {
2630
2782
 
2631
2783
  // src/front/auth/AuthErrorPage.tsx
2632
2784
  import { Card as Card7, CardContent as CardContent7, CardDescription as CardDescription7, CardFooter as CardFooter7, CardHeader as CardHeader7, CardTitle as CardTitle7 } from "@hachej/boring-ui-kit";
2633
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
2785
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2634
2786
  function readAuthErrorCode() {
2635
2787
  if (typeof window === "undefined") return null;
2636
2788
  return new URLSearchParams(window.location.search).get("error");
2637
2789
  }
2638
2790
  function AuthErrorPage() {
2639
2791
  const errorCode = readAuthErrorCode();
2640
- 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: [
2641
- /* @__PURE__ */ jsxs11(CardHeader7, { children: [
2642
- /* @__PURE__ */ jsx18(CardTitle7, { children: "Authentication error" }),
2643
- /* @__PURE__ */ jsx18(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
2792
+ return /* @__PURE__ */ jsx19("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12(Card7, { className: "w-full max-w-sm", children: [
2793
+ /* @__PURE__ */ jsxs12(CardHeader7, { children: [
2794
+ /* @__PURE__ */ jsx19(CardTitle7, { children: "Authentication error" }),
2795
+ /* @__PURE__ */ jsx19(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
2644
2796
  ] }),
2645
- errorCode && /* @__PURE__ */ jsx18(CardContent7, { children: /* @__PURE__ */ jsxs11("p", { className: "text-sm text-muted-foreground break-all", children: [
2797
+ errorCode && /* @__PURE__ */ jsx19(CardContent7, { children: /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground break-all", children: [
2646
2798
  "Error: ",
2647
2799
  errorCode
2648
2800
  ] }) }),
2649
- /* @__PURE__ */ jsxs11(CardFooter7, { className: "flex justify-between gap-4 text-sm", children: [
2650
- /* @__PURE__ */ jsx18("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
2651
- /* @__PURE__ */ jsx18("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
2801
+ /* @__PURE__ */ jsxs12(CardFooter7, { className: "flex justify-between gap-4 text-sm", children: [
2802
+ /* @__PURE__ */ jsx19("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
2803
+ /* @__PURE__ */ jsx19("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
2652
2804
  ] })
2653
2805
  ] }) });
2654
2806
  }
2655
2807
 
2656
2808
  // src/front/workspace/InvitesPage.tsx
2657
- import { useCallback as useCallback6, useState as useState17 } from "react";
2658
- import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2809
+ import { useCallback as useCallback6, useState as useState18 } from "react";
2810
+ import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
2659
2811
  import {
2660
- Button as Button13,
2812
+ Button as Button14,
2661
2813
  Card as Card8,
2662
2814
  CardContent as CardContent8,
2663
2815
  CardDescription as CardDescription8,
2664
2816
  CardFooter as CardFooter8,
2665
2817
  CardHeader as CardHeader8,
2666
2818
  CardTitle as CardTitle8,
2667
- Input as Input8,
2668
- Label as Label8,
2819
+ Input as Input9,
2820
+ Label as Label9,
2669
2821
  LoadingState as LoadingState2,
2670
2822
  Notice as Notice3,
2671
2823
  Select,
@@ -2675,7 +2827,7 @@ import {
2675
2827
  SelectValue,
2676
2828
  StatusBadge
2677
2829
  } from "@hachej/boring-ui-kit";
2678
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2830
+ import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
2679
2831
  function invitesQueryKey(workspaceId) {
2680
2832
  return ["invites", workspaceId];
2681
2833
  }
@@ -2695,11 +2847,11 @@ var STATUS_TONES = {
2695
2847
  function InvitesPage() {
2696
2848
  const workspace = useCurrentWorkspace();
2697
2849
  const role = useWorkspaceRole();
2698
- const queryClient = useQueryClient4();
2699
- const [email, setEmail] = useState17("");
2700
- const [inviteRole, setInviteRole] = useState17("editor");
2701
- const [formError, setFormError] = useState17(null);
2702
- const [successMessage, setSuccessMessage] = useState17(null);
2850
+ const queryClient = useQueryClient5();
2851
+ const [email, setEmail] = useState18("");
2852
+ const [inviteRole, setInviteRole] = useState18("editor");
2853
+ const [formError, setFormError] = useState18(null);
2854
+ const [successMessage, setSuccessMessage] = useState18(null);
2703
2855
  const workspaceId = workspace?.id ?? "";
2704
2856
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
2705
2857
  const invitesQuery = useQuery5({
@@ -2735,7 +2887,7 @@ function InvitesPage() {
2735
2887
  setFormError(detail.message);
2736
2888
  }
2737
2889
  });
2738
- const [revokeError, setRevokeError] = useState17(null);
2890
+ const [revokeError, setRevokeError] = useState18(null);
2739
2891
  const revokeMutation = useMutation2({
2740
2892
  mutationFn: async (inviteId) => {
2741
2893
  await apiFetch(
@@ -2767,29 +2919,29 @@ function InvitesPage() {
2767
2919
  [email, inviteRole, createMutation]
2768
2920
  );
2769
2921
  if (role !== "owner") {
2770
- 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: [
2771
- /* @__PURE__ */ jsx19(CardTitle8, { children: "Access denied" }),
2772
- /* @__PURE__ */ jsx19(CardDescription8, { children: "Only workspace owners can manage invites." })
2922
+ return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx20(Card8, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs13(CardHeader8, { children: [
2923
+ /* @__PURE__ */ jsx20(CardTitle8, { children: "Access denied" }),
2924
+ /* @__PURE__ */ jsx20(CardDescription8, { children: "Only workspace owners can manage invites." })
2773
2925
  ] }) }) });
2774
2926
  }
2775
- 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: [
2776
- /* @__PURE__ */ jsxs12(Card8, { children: [
2777
- /* @__PURE__ */ jsxs12(CardHeader8, { children: [
2778
- /* @__PURE__ */ jsx19(CardTitle8, { children: "Invite a member" }),
2779
- /* @__PURE__ */ jsxs12(CardDescription8, { children: [
2927
+ return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-2xl space-y-6", children: [
2928
+ /* @__PURE__ */ jsxs13(Card8, { children: [
2929
+ /* @__PURE__ */ jsxs13(CardHeader8, { children: [
2930
+ /* @__PURE__ */ jsx20(CardTitle8, { children: "Invite a member" }),
2931
+ /* @__PURE__ */ jsxs13(CardDescription8, { children: [
2780
2932
  "Send an invite to join ",
2781
2933
  workspace?.name ?? "this workspace",
2782
2934
  "."
2783
2935
  ] })
2784
2936
  ] }),
2785
- /* @__PURE__ */ jsxs12("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
2786
- /* @__PURE__ */ jsxs12(CardContent8, { className: "space-y-4", children: [
2787
- formError && /* @__PURE__ */ jsx19(Notice3, { role: "alert", tone: "error", description: formError }),
2788
- successMessage && /* @__PURE__ */ jsx19(Notice3, { role: "status", tone: "success", description: successMessage }),
2789
- /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
2790
- /* @__PURE__ */ jsx19(Label8, { htmlFor: "invite-email", children: "Email address" }),
2791
- /* @__PURE__ */ jsx19(
2792
- Input8,
2937
+ /* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
2938
+ /* @__PURE__ */ jsxs13(CardContent8, { className: "space-y-4", children: [
2939
+ formError && /* @__PURE__ */ jsx20(Notice3, { role: "alert", tone: "error", description: formError }),
2940
+ successMessage && /* @__PURE__ */ jsx20(Notice3, { role: "status", tone: "success", description: successMessage }),
2941
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
2942
+ /* @__PURE__ */ jsx20(Label9, { htmlFor: "invite-email", children: "Email address" }),
2943
+ /* @__PURE__ */ jsx20(
2944
+ Input9,
2793
2945
  {
2794
2946
  id: "invite-email",
2795
2947
  type: "email",
@@ -2800,20 +2952,20 @@ function InvitesPage() {
2800
2952
  }
2801
2953
  )
2802
2954
  ] }),
2803
- /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
2804
- /* @__PURE__ */ jsx19(Label8, { htmlFor: "invite-role", children: "Role" }),
2805
- /* @__PURE__ */ jsxs12(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
2806
- /* @__PURE__ */ jsx19(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx19(SelectValue, { placeholder: "Select role" }) }),
2807
- /* @__PURE__ */ jsxs12(SelectContent, { children: [
2808
- /* @__PURE__ */ jsx19(SelectItem, { value: "editor", children: "Editor" }),
2809
- /* @__PURE__ */ jsx19(SelectItem, { value: "viewer", children: "Viewer" }),
2810
- /* @__PURE__ */ jsx19(SelectItem, { value: "owner", children: "Owner" })
2955
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
2956
+ /* @__PURE__ */ jsx20(Label9, { htmlFor: "invite-role", children: "Role" }),
2957
+ /* @__PURE__ */ jsxs13(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
2958
+ /* @__PURE__ */ jsx20(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx20(SelectValue, { placeholder: "Select role" }) }),
2959
+ /* @__PURE__ */ jsxs13(SelectContent, { children: [
2960
+ /* @__PURE__ */ jsx20(SelectItem, { value: "editor", children: "Editor" }),
2961
+ /* @__PURE__ */ jsx20(SelectItem, { value: "viewer", children: "Viewer" }),
2962
+ /* @__PURE__ */ jsx20(SelectItem, { value: "owner", children: "Owner" })
2811
2963
  ] })
2812
2964
  ] })
2813
2965
  ] })
2814
2966
  ] }),
2815
- /* @__PURE__ */ jsx19(CardFooter8, { children: /* @__PURE__ */ jsx19(
2816
- Button13,
2967
+ /* @__PURE__ */ jsx20(CardFooter8, { children: /* @__PURE__ */ jsx20(
2968
+ Button14,
2817
2969
  {
2818
2970
  type: "submit",
2819
2971
  className: "w-full",
@@ -2823,37 +2975,37 @@ function InvitesPage() {
2823
2975
  ) })
2824
2976
  ] })
2825
2977
  ] }),
2826
- /* @__PURE__ */ jsxs12(Card8, { children: [
2827
- /* @__PURE__ */ jsxs12(CardHeader8, { children: [
2828
- /* @__PURE__ */ jsx19(CardTitle8, { children: "Pending invites" }),
2829
- /* @__PURE__ */ jsx19(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
2978
+ /* @__PURE__ */ jsxs13(Card8, { children: [
2979
+ /* @__PURE__ */ jsxs13(CardHeader8, { children: [
2980
+ /* @__PURE__ */ jsx20(CardTitle8, { children: "Pending invites" }),
2981
+ /* @__PURE__ */ jsx20(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
2830
2982
  ] }),
2831
- /* @__PURE__ */ jsxs12(CardContent8, { children: [
2832
- revokeError && /* @__PURE__ */ jsx19(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
2833
- invitesQuery.isLoading && /* @__PURE__ */ jsx19(LoadingState2, {}),
2834
- invitesQuery.isError && /* @__PURE__ */ jsx19(Notice3, { tone: "error", description: "Failed to load invites." }),
2835
- invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx19("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
2983
+ /* @__PURE__ */ jsxs13(CardContent8, { children: [
2984
+ revokeError && /* @__PURE__ */ jsx20(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
2985
+ invitesQuery.isLoading && /* @__PURE__ */ jsx20(LoadingState2, {}),
2986
+ invitesQuery.isError && /* @__PURE__ */ jsx20(Notice3, { tone: "error", description: "Failed to load invites." }),
2987
+ invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx20("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
2836
2988
  const status = getInviteStatus(invite);
2837
- return /* @__PURE__ */ jsxs12(
2989
+ return /* @__PURE__ */ jsxs13(
2838
2990
  "div",
2839
2991
  {
2840
2992
  className: "flex items-center justify-between py-3",
2841
2993
  "data-testid": `invite-row-${invite.id}`,
2842
2994
  children: [
2843
- /* @__PURE__ */ jsxs12("div", { className: "space-y-1", children: [
2844
- /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium", children: invite.email }),
2845
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2846
- /* @__PURE__ */ jsx19("span", { children: invite.role }),
2847
- /* @__PURE__ */ jsx19(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
2848
- /* @__PURE__ */ jsxs12("span", { children: [
2995
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-1", children: [
2996
+ /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium", children: invite.email }),
2997
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2998
+ /* @__PURE__ */ jsx20("span", { children: invite.role }),
2999
+ /* @__PURE__ */ jsx20(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
3000
+ /* @__PURE__ */ jsxs13("span", { children: [
2849
3001
  "expires",
2850
3002
  " ",
2851
3003
  new Date(invite.expiresAt).toLocaleDateString()
2852
3004
  ] })
2853
3005
  ] })
2854
3006
  ] }),
2855
- status === "pending" && /* @__PURE__ */ jsx19(
2856
- Button13,
3007
+ status === "pending" && /* @__PURE__ */ jsx20(
3008
+ Button14,
2857
3009
  {
2858
3010
  variant: "destructive",
2859
3011
  size: "sm",
@@ -2874,8 +3026,8 @@ function InvitesPage() {
2874
3026
  }
2875
3027
 
2876
3028
  // src/front/workspace/MembersPage.tsx
2877
- import { useCallback as useCallback7, useState as useState18 } from "react";
2878
- import { useMutation as useMutation3, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
3029
+ import { useCallback as useCallback7, useState as useState19 } from "react";
3030
+ import { useMutation as useMutation3, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
2879
3031
  import {
2880
3032
  AlertDialog as AlertDialog2,
2881
3033
  AlertDialogCancel as AlertDialogCancel2,
@@ -2884,7 +3036,7 @@ import {
2884
3036
  AlertDialogFooter as AlertDialogFooter2,
2885
3037
  AlertDialogHeader as AlertDialogHeader2,
2886
3038
  AlertDialogTitle as AlertDialogTitle2,
2887
- Button as Button14,
3039
+ Button as Button15,
2888
3040
  Card as Card9,
2889
3041
  CardContent as CardContent9,
2890
3042
  CardDescription as CardDescription9,
@@ -2899,19 +3051,19 @@ import {
2899
3051
  LoadingState as LoadingState3,
2900
3052
  Notice as Notice4
2901
3053
  } from "@hachej/boring-ui-kit";
2902
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
3054
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
2903
3055
  var ROLE_OPTIONS = ["owner", "editor", "viewer"];
2904
3056
  function MembersPage() {
2905
3057
  const workspace = useCurrentWorkspace();
2906
3058
  const myRole = useWorkspaceRole();
2907
3059
  const session = useSession();
2908
- const queryClient = useQueryClient5();
3060
+ const queryClient = useQueryClient6();
2909
3061
  const workspaceId = workspace?.id ?? "";
2910
3062
  const currentUserId = session.data?.user?.id ?? "";
2911
3063
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
2912
3064
  const membersQuery = useWorkspaceMembers(workspaceId);
2913
- const [toast, setToast] = useState18(null);
2914
- const [confirmTarget, setConfirmTarget] = useState18(null);
3065
+ const [toast, setToast] = useState19(null);
3066
+ const [confirmTarget, setConfirmTarget] = useState19(null);
2915
3067
  const showToast = useCallback7((msg) => {
2916
3068
  setToast(msg);
2917
3069
  setTimeout(() => setToast(null), 4e3);
@@ -2972,11 +3124,11 @@ function MembersPage() {
2972
3124
  removeMutation.mutate(confirmTarget.userId);
2973
3125
  }, [confirmTarget, removeMutation]);
2974
3126
  const isOwner = myRole === "owner";
2975
- 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: [
2976
- /* @__PURE__ */ jsxs13(Card9, { children: [
2977
- /* @__PURE__ */ jsxs13(CardHeader9, { children: [
2978
- /* @__PURE__ */ jsx20(CardTitle9, { children: "Members" }),
2979
- /* @__PURE__ */ jsxs13(CardDescription9, { children: [
3127
+ return /* @__PURE__ */ jsx21("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs14("div", { className: "w-full max-w-2xl space-y-6", children: [
3128
+ /* @__PURE__ */ jsxs14(Card9, { children: [
3129
+ /* @__PURE__ */ jsxs14(CardHeader9, { children: [
3130
+ /* @__PURE__ */ jsx21(CardTitle9, { children: "Members" }),
3131
+ /* @__PURE__ */ jsxs14(CardDescription9, { children: [
2980
3132
  workspace?.name ?? "Workspace",
2981
3133
  " \xB7",
2982
3134
  " ",
@@ -2985,45 +3137,45 @@ function MembersPage() {
2985
3137
  (membersQuery.data?.length ?? 0) !== 1 ? "s" : ""
2986
3138
  ] })
2987
3139
  ] }),
2988
- /* @__PURE__ */ jsxs13(CardContent9, { children: [
2989
- toast && /* @__PURE__ */ jsx20(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
2990
- membersQuery.isLoading && /* @__PURE__ */ jsx20(LoadingState3, {}),
2991
- membersQuery.isError && /* @__PURE__ */ jsx20(Notice4, { tone: "error", description: "Failed to load members." }),
2992
- membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx20("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
3140
+ /* @__PURE__ */ jsxs14(CardContent9, { children: [
3141
+ toast && /* @__PURE__ */ jsx21(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
3142
+ membersQuery.isLoading && /* @__PURE__ */ jsx21(LoadingState3, {}),
3143
+ membersQuery.isError && /* @__PURE__ */ jsx21(Notice4, { tone: "error", description: "Failed to load members." }),
3144
+ membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx21("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
2993
3145
  const isSelf = member.userId === currentUserId;
2994
3146
  const canChangeRole = isOwner && !isSelf;
2995
3147
  const canRemove = isOwner || isSelf;
2996
- return /* @__PURE__ */ jsxs13(
3148
+ return /* @__PURE__ */ jsxs14(
2997
3149
  "div",
2998
3150
  {
2999
3151
  className: "flex items-center justify-between py-3",
3000
3152
  "data-testid": `member-row-${member.userId}`,
3001
3153
  children: [
3002
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-3", children: [
3003
- /* @__PURE__ */ jsx20(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
3004
- /* @__PURE__ */ jsxs13("div", { children: [
3005
- /* @__PURE__ */ jsxs13("p", { className: "text-sm font-medium", children: [
3154
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3", children: [
3155
+ /* @__PURE__ */ jsx21(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
3156
+ /* @__PURE__ */ jsxs14("div", { children: [
3157
+ /* @__PURE__ */ jsxs14("p", { className: "text-sm font-medium", children: [
3006
3158
  member.user.name ?? member.user.email,
3007
- isSelf && /* @__PURE__ */ jsx20("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
3159
+ isSelf && /* @__PURE__ */ jsx21("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
3008
3160
  ] }),
3009
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: member.user.email })
3161
+ /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: member.user.email })
3010
3162
  ] })
3011
3163
  ] }),
3012
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
3013
- /* @__PURE__ */ jsxs13(
3164
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
3165
+ /* @__PURE__ */ jsxs14(
3014
3166
  Select2,
3015
3167
  {
3016
3168
  value: member.role,
3017
3169
  disabled: !canChangeRole,
3018
3170
  onValueChange: (value) => handleRoleChange(member.userId, value),
3019
3171
  children: [
3020
- /* @__PURE__ */ jsx20(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx20(SelectValue2, { placeholder: "Role" }) }),
3021
- /* @__PURE__ */ jsx20(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx20(SelectItem2, { value: r, children: r }, r)) })
3172
+ /* @__PURE__ */ jsx21(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx21(SelectValue2, { placeholder: "Role" }) }),
3173
+ /* @__PURE__ */ jsx21(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx21(SelectItem2, { value: r, children: r }, r)) })
3022
3174
  ]
3023
3175
  }
3024
3176
  ),
3025
- canRemove && /* @__PURE__ */ jsx20(
3026
- Button14,
3177
+ canRemove && /* @__PURE__ */ jsx21(
3178
+ Button15,
3027
3179
  {
3028
3180
  variant: "destructive",
3029
3181
  size: "sm",
@@ -3040,22 +3192,22 @@ function MembersPage() {
3040
3192
  }) })
3041
3193
  ] })
3042
3194
  ] }),
3043
- /* @__PURE__ */ jsx20(
3195
+ /* @__PURE__ */ jsx21(
3044
3196
  AlertDialog2,
3045
3197
  {
3046
3198
  open: confirmTarget !== null,
3047
3199
  onOpenChange: (open) => {
3048
3200
  if (!open) setConfirmTarget(null);
3049
3201
  },
3050
- children: /* @__PURE__ */ jsxs13(AlertDialogContent2, { children: [
3051
- /* @__PURE__ */ jsxs13(AlertDialogHeader2, { children: [
3052
- /* @__PURE__ */ jsx20(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
3053
- /* @__PURE__ */ jsx20(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
3202
+ children: /* @__PURE__ */ jsxs14(AlertDialogContent2, { children: [
3203
+ /* @__PURE__ */ jsxs14(AlertDialogHeader2, { children: [
3204
+ /* @__PURE__ */ jsx21(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
3205
+ /* @__PURE__ */ jsx21(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
3054
3206
  ] }),
3055
- /* @__PURE__ */ jsxs13(AlertDialogFooter2, { children: [
3056
- /* @__PURE__ */ jsx20(AlertDialogCancel2, { children: "Cancel" }),
3057
- /* @__PURE__ */ jsx20(
3058
- Button14,
3207
+ /* @__PURE__ */ jsxs14(AlertDialogFooter2, { children: [
3208
+ /* @__PURE__ */ jsx21(AlertDialogCancel2, { children: "Cancel" }),
3209
+ /* @__PURE__ */ jsx21(
3210
+ Button15,
3059
3211
  {
3060
3212
  variant: "destructive",
3061
3213
  disabled: removeMutation.isPending,
@@ -3072,8 +3224,8 @@ function MembersPage() {
3072
3224
  }
3073
3225
 
3074
3226
  // src/front/workspace/WorkspaceSettingsPage.tsx
3075
- import { useCallback as useCallback8, useEffect as useEffect10, useState as useState19 } from "react";
3076
- import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
3227
+ import { useCallback as useCallback8, useEffect as useEffect10, useState as useState20 } from "react";
3228
+ import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
3077
3229
  import { useNavigate as useNavigate5 } from "react-router-dom";
3078
3230
  import {
3079
3231
  AlertDialog as AlertDialog3,
@@ -3083,14 +3235,14 @@ import {
3083
3235
  AlertDialogFooter as AlertDialogFooter3,
3084
3236
  AlertDialogHeader as AlertDialogHeader3,
3085
3237
  AlertDialogTitle as AlertDialogTitle3,
3086
- Button as Button15,
3238
+ Button as Button16,
3087
3239
  IconButton,
3088
3240
  SettingsActionRow as UiSettingsActionRow2,
3089
3241
  SettingsNav as UiSettingsNav2,
3090
3242
  SettingsPanel as UiSettingsPanel2,
3091
3243
  StatusBadge as StatusBadge2,
3092
- Input as Input9,
3093
- Label as Label9,
3244
+ Input as Input10,
3245
+ Label as Label10,
3094
3246
  Notice as Notice5
3095
3247
  } from "@hachej/boring-ui-kit";
3096
3248
  import {
@@ -3102,7 +3254,7 @@ import {
3102
3254
  ShieldAlert as ShieldAlert2,
3103
3255
  Trash2 as Trash22
3104
3256
  } from "lucide-react";
3105
- import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
3257
+ import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
3106
3258
  var STATE_TONES = {
3107
3259
  pending: "info",
3108
3260
  ready: "success",
@@ -3114,13 +3266,13 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
3114
3266
  const appInitial = (appTitle.trim().charAt(0) || "B").toUpperCase();
3115
3267
  const navigate = useNavigate5();
3116
3268
  const workspaceHref = workspaceId ? `/workspace/${encodeURIComponent(workspaceId)}` : "/";
3117
- return /* @__PURE__ */ jsx21(
3269
+ return /* @__PURE__ */ jsx22(
3118
3270
  "header",
3119
3271
  {
3120
3272
  className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
3121
3273
  "aria-label": "App top bar",
3122
- children: /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
3123
- /* @__PURE__ */ jsx21(
3274
+ children: /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
3275
+ /* @__PURE__ */ jsx22(
3124
3276
  IconButton,
3125
3277
  {
3126
3278
  type: "button",
@@ -3133,11 +3285,11 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
3133
3285
  children: appInitial
3134
3286
  }
3135
3287
  ),
3136
- /* @__PURE__ */ jsx21("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
3137
- /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3138
- /* @__PURE__ */ jsx21("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
3139
- /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3140
- /* @__PURE__ */ jsx21("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
3288
+ /* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
3289
+ /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3290
+ /* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
3291
+ /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
3292
+ /* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
3141
3293
  ] })
3142
3294
  }
3143
3295
  );
@@ -3148,26 +3300,26 @@ function SettingsPageHeader2({
3148
3300
  role,
3149
3301
  isDefault
3150
3302
  }) {
3151
- return /* @__PURE__ */ jsxs14("header", { className: "boring-settings-page-header", children: [
3152
- /* @__PURE__ */ jsxs14("div", { className: "boring-settings-context", children: [
3153
- /* @__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 }),
3154
- /* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
3155
- /* @__PURE__ */ jsx21("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
3156
- /* @__PURE__ */ jsxs14("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
3157
- /* @__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) }),
3158
- 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
3303
+ return /* @__PURE__ */ jsxs15("header", { className: "boring-settings-page-header", children: [
3304
+ /* @__PURE__ */ jsxs15("div", { className: "boring-settings-context", children: [
3305
+ /* @__PURE__ */ jsx22("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: workspaceInitial2 }),
3306
+ /* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
3307
+ /* @__PURE__ */ jsx22("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
3308
+ /* @__PURE__ */ jsxs15("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
3309
+ /* @__PURE__ */ jsx22("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
3310
+ isDefault ? /* @__PURE__ */ jsx22("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
3159
3311
  ] })
3160
3312
  ] })
3161
3313
  ] }),
3162
- /* @__PURE__ */ jsxs14("div", { className: "max-w-2xl", children: [
3163
- /* @__PURE__ */ jsx21("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
3164
- /* @__PURE__ */ jsx21("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
3165
- /* @__PURE__ */ jsx21("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
3314
+ /* @__PURE__ */ jsxs15("div", { className: "max-w-2xl", children: [
3315
+ /* @__PURE__ */ jsx22("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
3316
+ /* @__PURE__ */ jsx22("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
3317
+ /* @__PURE__ */ jsx22("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
3166
3318
  ] })
3167
3319
  ] });
3168
3320
  }
3169
3321
  function FieldNote({ children }) {
3170
- return /* @__PURE__ */ jsx21("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
3322
+ return /* @__PURE__ */ jsx22("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
3171
3323
  }
3172
3324
  function roleLabel(role) {
3173
3325
  if (!role) return "Loading role";
@@ -3182,17 +3334,17 @@ var WORKSPACE_NAV_ITEMS = [
3182
3334
  function WorkspaceSettingsPage({ topBar } = {}) {
3183
3335
  const workspace = useCurrentWorkspace();
3184
3336
  const role = useWorkspaceRole();
3185
- const queryClient = useQueryClient6();
3337
+ const queryClient = useQueryClient7();
3186
3338
  const navigate = useNavigate5();
3187
3339
  const workspaceId = workspace?.id ?? "";
3188
- const [nameValue, setNameValue] = useState19(null);
3189
- const [nameError, setNameError] = useState19(null);
3190
- const [retryError, setRetryError] = useState19(null);
3191
- const [deleteConfirmName, setDeleteConfirmName] = useState19("");
3192
- const [deleteDialogOpen, setDeleteDialogOpen] = useState19(false);
3193
- const [deleteError, setDeleteError] = useState19(null);
3194
- const [imageUploadDirValue, setImageUploadDirValue] = useState19(null);
3195
- const [fileSettingsError, setFileSettingsError] = useState19(null);
3340
+ const [nameValue, setNameValue] = useState20(null);
3341
+ const [nameError, setNameError] = useState20(null);
3342
+ const [retryError, setRetryError] = useState20(null);
3343
+ const [deleteConfirmName, setDeleteConfirmName] = useState20("");
3344
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState20(false);
3345
+ const [deleteError, setDeleteError] = useState20(null);
3346
+ const [imageUploadDirValue, setImageUploadDirValue] = useState20(null);
3347
+ const [fileSettingsError, setFileSettingsError] = useState20(null);
3196
3348
  const displayName = nameValue ?? workspace?.name ?? "";
3197
3349
  const encodedWorkspaceId = encodeURIComponent(workspaceId);
3198
3350
  const requestHeaders = workspaceId ? { "x-boring-workspace-id": workspaceId } : void 0;
@@ -3338,18 +3490,18 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3338
3490
  const canDeleteWorkspace = role === "owner" || role === null;
3339
3491
  const workspaceName = workspace?.name ?? "Workspace";
3340
3492
  const workspaceInitial2 = (workspace?.name?.trim()?.[0] ?? "W").toUpperCase();
3341
- const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx21(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
3493
+ const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx22(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
3342
3494
  const navItems = WORKSPACE_NAV_ITEMS.filter((item) => {
3343
3495
  if (item.href === "#runtime") return hasRuntime;
3344
3496
  if (item.href === "#files") return hasFileSettings;
3345
3497
  return true;
3346
3498
  });
3347
- return /* @__PURE__ */ jsxs14("main", { className: "boring-settings-shell", children: [
3499
+ return /* @__PURE__ */ jsxs15("main", { className: "boring-settings-shell", children: [
3348
3500
  topBarNode,
3349
- /* @__PURE__ */ jsx21("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs14("div", { className: "boring-settings-layout", children: [
3350
- /* @__PURE__ */ jsx21("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx21(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
3351
- /* @__PURE__ */ jsxs14("div", { className: "boring-settings-content space-y-4", children: [
3352
- /* @__PURE__ */ jsx21(
3501
+ /* @__PURE__ */ jsx22("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs15("div", { className: "boring-settings-layout", children: [
3502
+ /* @__PURE__ */ jsx22("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx22(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
3503
+ /* @__PURE__ */ jsxs15("div", { className: "boring-settings-content space-y-4", children: [
3504
+ /* @__PURE__ */ jsx22(
3353
3505
  SettingsPageHeader2,
3354
3506
  {
3355
3507
  workspaceName,
@@ -3358,16 +3510,16 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3358
3510
  isDefault: Boolean(workspace?.isDefault)
3359
3511
  }
3360
3512
  ),
3361
- /* @__PURE__ */ jsx21(
3513
+ /* @__PURE__ */ jsx22(
3362
3514
  UiSettingsPanel2,
3363
3515
  {
3364
3516
  id: "general",
3365
- icon: /* @__PURE__ */ jsx21(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3517
+ icon: /* @__PURE__ */ jsx22(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3366
3518
  title: "General",
3367
3519
  description: "Keep the workspace name clear enough to scan in menus.",
3368
- footer: /* @__PURE__ */ jsxs14(Fragment5, { children: [
3369
- nameChanged ? /* @__PURE__ */ jsx21(
3370
- Button15,
3520
+ footer: /* @__PURE__ */ jsxs15(Fragment5, { children: [
3521
+ nameChanged ? /* @__PURE__ */ jsx22(
3522
+ Button16,
3371
3523
  {
3372
3524
  type: "button",
3373
3525
  variant: "ghost",
@@ -3380,8 +3532,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3380
3532
  children: "Reset"
3381
3533
  }
3382
3534
  ) : null,
3383
- /* @__PURE__ */ jsx21(
3384
- Button15,
3535
+ /* @__PURE__ */ jsx22(
3536
+ Button16,
3385
3537
  {
3386
3538
  "data-testid": "save-name",
3387
3539
  size: "sm",
@@ -3391,12 +3543,12 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3391
3543
  }
3392
3544
  )
3393
3545
  ] }),
3394
- children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3395
- nameError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
3396
- /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
3397
- /* @__PURE__ */ jsx21(Label9, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
3398
- /* @__PURE__ */ jsx21(
3399
- Input9,
3546
+ children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3547
+ nameError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
3548
+ /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
3549
+ /* @__PURE__ */ jsx22(Label10, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
3550
+ /* @__PURE__ */ jsx22(
3551
+ Input10,
3400
3552
  {
3401
3553
  id: "workspace-name",
3402
3554
  "data-testid": "workspace-name-input",
@@ -3407,50 +3559,50 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3407
3559
  "aria-invalid": nameError ? "true" : "false"
3408
3560
  }
3409
3561
  ),
3410
- /* @__PURE__ */ jsx21(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
3562
+ /* @__PURE__ */ jsx22(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
3411
3563
  ] })
3412
3564
  ] })
3413
3565
  }
3414
3566
  ),
3415
- hasRuntime && /* @__PURE__ */ jsx21(
3567
+ hasRuntime && /* @__PURE__ */ jsx22(
3416
3568
  UiSettingsPanel2,
3417
3569
  {
3418
3570
  id: "runtime",
3419
3571
  testId: "runtime-card",
3420
- icon: /* @__PURE__ */ jsx21(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3572
+ icon: /* @__PURE__ */ jsx22(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3421
3573
  title: "Runtime",
3422
3574
  description: "Provisioning status for this workspace.",
3423
- children: /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
3424
- /* @__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: [
3425
- /* @__PURE__ */ jsx21("span", { className: "text-[13px] font-medium", children: "State" }),
3426
- /* @__PURE__ */ jsx21(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
3575
+ children: /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
3576
+ /* @__PURE__ */ jsxs15("div", { className: "flex min-h-10 flex-wrap items-center justify-between gap-3 rounded-md border border-border/50 bg-muted/10 px-3 py-2", children: [
3577
+ /* @__PURE__ */ jsx22("span", { className: "text-[13px] font-medium", children: "State" }),
3578
+ /* @__PURE__ */ jsx22(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
3427
3579
  ] }),
3428
- runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs14(
3580
+ runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs15(
3429
3581
  "div",
3430
3582
  {
3431
3583
  "data-testid": "volume-path",
3432
3584
  className: "space-y-1 rounded-md border border-border/50 bg-muted/10 px-3 py-2",
3433
3585
  children: [
3434
- /* @__PURE__ */ jsx21("p", { className: "text-[13px] font-medium", children: "Volume" }),
3435
- /* @__PURE__ */ jsx21("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
3586
+ /* @__PURE__ */ jsx22("p", { className: "text-[13px] font-medium", children: "Volume" }),
3587
+ /* @__PURE__ */ jsx22("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
3436
3588
  ]
3437
3589
  }
3438
3590
  ),
3439
- runtime.state === "error" && runtime.lastError && /* @__PURE__ */ jsxs14(
3591
+ runtime.state === "error" && runtime.lastError && /* @__PURE__ */ jsxs15(
3440
3592
  "div",
3441
3593
  {
3442
3594
  "data-testid": "runtime-error",
3443
3595
  role: "alert",
3444
3596
  className: "flex gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[13px] leading-5 text-destructive",
3445
3597
  children: [
3446
- /* @__PURE__ */ jsx21(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
3598
+ /* @__PURE__ */ jsx22(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
3447
3599
  runtime.lastError
3448
3600
  ]
3449
3601
  }
3450
3602
  ),
3451
- runtime.state === "error" && runtime.lastErrorOp === "provision" && /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
3452
- /* @__PURE__ */ jsxs14(
3453
- Button15,
3603
+ runtime.state === "error" && runtime.lastErrorOp === "provision" && /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
3604
+ /* @__PURE__ */ jsxs15(
3605
+ Button16,
3454
3606
  {
3455
3607
  "data-testid": "retry-provision",
3456
3608
  variant: "outline",
@@ -3458,14 +3610,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3458
3610
  disabled: retryMutation.isPending,
3459
3611
  onClick: () => retryMutation.mutate(),
3460
3612
  children: [
3461
- /* @__PURE__ */ jsx21(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
3613
+ /* @__PURE__ */ jsx22(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
3462
3614
  retryMutation.isPending ? "Retrying..." : "Retry provisioning"
3463
3615
  ]
3464
3616
  }
3465
3617
  ),
3466
- retryError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
3618
+ retryError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
3467
3619
  ] }),
3468
- runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx21(
3620
+ runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx22(
3469
3621
  "p",
3470
3622
  {
3471
3623
  "data-testid": "destroy-guidance",
@@ -3476,16 +3628,16 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3476
3628
  ] })
3477
3629
  }
3478
3630
  ),
3479
- hasFileSettings && /* @__PURE__ */ jsx21(
3631
+ hasFileSettings && /* @__PURE__ */ jsx22(
3480
3632
  UiSettingsPanel2,
3481
3633
  {
3482
3634
  id: "files",
3483
3635
  testId: "file-settings-card",
3484
- icon: /* @__PURE__ */ jsx21(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3636
+ icon: /* @__PURE__ */ jsx22(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3485
3637
  title: "Files",
3486
3638
  description: "Configure where markdown editor image uploads are stored. Direct/local workspaces can also edit .boring/settings.",
3487
- footer: /* @__PURE__ */ jsx21(
3488
- Button15,
3639
+ footer: /* @__PURE__ */ jsx22(
3640
+ Button16,
3489
3641
  {
3490
3642
  "data-testid": "save-file-settings",
3491
3643
  size: "sm",
@@ -3494,12 +3646,12 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3494
3646
  children: fileSettingsMutation.isPending ? "Saving..." : "Save file settings"
3495
3647
  }
3496
3648
  ),
3497
- children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3498
- fileSettingsError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
3499
- /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
3500
- /* @__PURE__ */ jsx21(Label9, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
3501
- /* @__PURE__ */ jsx21(
3502
- Input9,
3649
+ children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3650
+ fileSettingsError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
3651
+ /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
3652
+ /* @__PURE__ */ jsx22(Label10, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
3653
+ /* @__PURE__ */ jsx22(
3654
+ Input10,
3503
3655
  {
3504
3656
  id: "markdown-image-upload-dir",
3505
3657
  "data-testid": "markdown-image-upload-dir-input",
@@ -3509,35 +3661,35 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3509
3661
  disabled: !canEditName
3510
3662
  }
3511
3663
  ),
3512
- /* @__PURE__ */ jsxs14(FieldNote, { children: [
3664
+ /* @__PURE__ */ jsxs15(FieldNote, { children: [
3513
3665
  "Relative workspace path used by markdown image uploads. Stored in ",
3514
- /* @__PURE__ */ jsx21("code", { children: ".boring/settings" }),
3666
+ /* @__PURE__ */ jsx22("code", { children: ".boring/settings" }),
3515
3667
  "."
3516
3668
  ] })
3517
3669
  ] })
3518
3670
  ] })
3519
3671
  }
3520
3672
  ),
3521
- /* @__PURE__ */ jsx21(
3673
+ /* @__PURE__ */ jsx22(
3522
3674
  UiSettingsPanel2,
3523
3675
  {
3524
3676
  id: "danger-zone",
3525
3677
  testId: "danger-zone",
3526
- icon: /* @__PURE__ */ jsx21(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3678
+ icon: /* @__PURE__ */ jsx22(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
3527
3679
  title: "Danger zone",
3528
3680
  description: "Permanently delete this workspace and all provisioned data.",
3529
3681
  danger: true,
3530
- children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3531
- deleteError && /* @__PURE__ */ jsx21(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
3532
- !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,
3533
- /* @__PURE__ */ jsx21(
3682
+ children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3683
+ deleteError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
3684
+ !canDeleteWorkspace ? /* @__PURE__ */ jsx22("div", { className: "rounded-md border border-border/50 bg-muted/10 px-3 py-2 text-[13px] leading-5 text-muted-foreground", children: "Only workspace owners can delete this workspace." }) : null,
3685
+ /* @__PURE__ */ jsx22(
3534
3686
  UiSettingsActionRow2,
3535
3687
  {
3536
3688
  title: "Delete workspace",
3537
3689
  description: "Delete the workspace record and re-issue cleanup for provisioned runtime data.",
3538
- action: /* @__PURE__ */ jsxs14(AlertDialog3, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
3539
- /* @__PURE__ */ jsxs14(
3540
- Button15,
3690
+ action: /* @__PURE__ */ jsxs15(AlertDialog3, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
3691
+ /* @__PURE__ */ jsxs15(
3692
+ Button16,
3541
3693
  {
3542
3694
  variant: "destructive",
3543
3695
  size: "sm",
@@ -3548,22 +3700,22 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3548
3700
  setDeleteConfirmName("");
3549
3701
  },
3550
3702
  children: [
3551
- /* @__PURE__ */ jsx21(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
3703
+ /* @__PURE__ */ jsx22(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
3552
3704
  "Delete workspace"
3553
3705
  ]
3554
3706
  }
3555
3707
  ),
3556
- /* @__PURE__ */ jsxs14(AlertDialogContent3, { children: [
3557
- /* @__PURE__ */ jsxs14(AlertDialogHeader3, { children: [
3558
- /* @__PURE__ */ jsx21(AlertDialogTitle3, { children: "Delete workspace?" }),
3559
- /* @__PURE__ */ jsxs14(AlertDialogDescription3, { children: [
3708
+ /* @__PURE__ */ jsxs15(AlertDialogContent3, { children: [
3709
+ /* @__PURE__ */ jsxs15(AlertDialogHeader3, { children: [
3710
+ /* @__PURE__ */ jsx22(AlertDialogTitle3, { children: "Delete workspace?" }),
3711
+ /* @__PURE__ */ jsxs15(AlertDialogDescription3, { children: [
3560
3712
  "This action cannot be undone. Type ",
3561
- /* @__PURE__ */ jsx21("strong", { children: workspace?.name }),
3713
+ /* @__PURE__ */ jsx22("strong", { children: workspace?.name }),
3562
3714
  " to confirm."
3563
3715
  ] })
3564
3716
  ] }),
3565
- /* @__PURE__ */ jsx21("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx21(
3566
- Input9,
3717
+ /* @__PURE__ */ jsx22("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx22(
3718
+ Input10,
3567
3719
  {
3568
3720
  "data-testid": "delete-confirm-input",
3569
3721
  className: "h-8 text-[13px]",
@@ -3573,10 +3725,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3573
3725
  autoComplete: "off"
3574
3726
  }
3575
3727
  ) }),
3576
- /* @__PURE__ */ jsxs14(AlertDialogFooter3, { children: [
3577
- /* @__PURE__ */ jsx21(AlertDialogCancel3, { children: "Cancel" }),
3578
- /* @__PURE__ */ jsx21(
3579
- Button15,
3728
+ /* @__PURE__ */ jsxs15(AlertDialogFooter3, { children: [
3729
+ /* @__PURE__ */ jsx22(AlertDialogCancel3, { children: "Cancel" }),
3730
+ /* @__PURE__ */ jsx22(
3731
+ Button16,
3580
3732
  {
3581
3733
  variant: "destructive",
3582
3734
  size: "sm",
@@ -3600,10 +3752,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
3600
3752
  }
3601
3753
 
3602
3754
  // src/front/CoreFront.tsx
3603
- import { Fragment as Fragment6, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
3755
+ import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
3604
3756
  var CSP_NONCE_META_NAME = "boring-csp-nonce";
3605
3757
  function PlaceholderPage({ name }) {
3606
- return /* @__PURE__ */ jsxs15("div", { "data-testid": `placeholder-${name}`, children: [
3758
+ return /* @__PURE__ */ jsxs16("div", { "data-testid": `placeholder-${name}`, children: [
3607
3759
  name,
3608
3760
  " (not yet implemented)"
3609
3761
  ] });
@@ -3628,7 +3780,7 @@ function RouterAuthGate({ children, publicPaths }) {
3628
3780
  const config = useConfig();
3629
3781
  const location = useLocation2();
3630
3782
  const navigate = useNavigate6();
3631
- const authLocation = useMemo6(
3783
+ const authLocation = useMemo7(
3632
3784
  () => ({ pathname: location.pathname, search: location.search, hash: location.hash }),
3633
3785
  [location.hash, location.pathname, location.search]
3634
3786
  );
@@ -3638,7 +3790,7 @@ function RouterAuthGate({ children, publicPaths }) {
3638
3790
  },
3639
3791
  [navigate]
3640
3792
  );
3641
- return /* @__PURE__ */ jsx22(
3793
+ return /* @__PURE__ */ jsx23(
3642
3794
  AuthGate,
3643
3795
  {
3644
3796
  location: authLocation,
@@ -3650,8 +3802,8 @@ function RouterAuthGate({ children, publicPaths }) {
3650
3802
  );
3651
3803
  }
3652
3804
  function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdParam, publicPaths }) {
3653
- const queryClient = useMemo6(createDefaultQueryClient, []);
3654
- const resolvedCspNonce = useMemo6(
3805
+ const queryClient = useMemo7(createDefaultQueryClient, []);
3806
+ const resolvedCspNonce = useMemo7(
3655
3807
  () => cspNonce ?? readCspNonceFromDom(),
3656
3808
  [cspNonce]
3657
3809
  );
@@ -3662,10 +3814,10 @@ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdP
3662
3814
  const VerifyEmailPage2 = authPages?.verifyEmail ?? VerifyEmailPage;
3663
3815
  const AuthErrorPage2 = authPages?.authError ?? AuthErrorPage;
3664
3816
  const UserSettingsPage2 = authPages?.userSettings ?? UserSettingsPage;
3665
- 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, { workspaceRoute, workspaceIdParam, children: /* @__PURE__ */ jsxs15(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx22(UserMenu, {}), children: [
3666
- /* @__PURE__ */ jsx22(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsxs15(Fragment6, { children: [
3667
- /* @__PURE__ */ jsx22("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }),
3668
- /* @__PURE__ */ jsx22(
3817
+ return /* @__PURE__ */ jsx23(HelmetProvider, { children: /* @__PURE__ */ jsx23(AppErrorBoundary, { children: /* @__PURE__ */ jsx23(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx23(ConfigProvider, { children: /* @__PURE__ */ jsx23(ThemeProvider, { children: /* @__PURE__ */ jsx23(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx23(UserIdentityProvider, { children: /* @__PURE__ */ jsx23(BrowserRouter, { children: /* @__PURE__ */ jsx23(WorkspaceAuthProvider, { workspaceRoute, workspaceIdParam, children: /* @__PURE__ */ jsxs16(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx23(UserMenu, {}), children: [
3818
+ /* @__PURE__ */ jsx23(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsxs16(Fragment6, { children: [
3819
+ /* @__PURE__ */ jsx23("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }),
3820
+ /* @__PURE__ */ jsx23(
3669
3821
  "script",
3670
3822
  {
3671
3823
  type: "application/json",
@@ -3675,30 +3827,30 @@ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdP
3675
3827
  }
3676
3828
  )
3677
3829
  ] }) : null }),
3678
- /* @__PURE__ */ jsx22(RouterAuthGate, { publicPaths: ["/invites", ...publicPaths ?? []], children: /* @__PURE__ */ jsx22(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs15(Routes, { children: [
3679
- /* @__PURE__ */ jsx22(Route, { path: routes.signin, element: /* @__PURE__ */ jsx22(SignInPage2, {}) }),
3680
- /* @__PURE__ */ jsx22(Route, { path: routes.signup, element: /* @__PURE__ */ jsx22(SignUpPage2, {}) }),
3681
- /* @__PURE__ */ jsx22(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx22(ForgotPasswordPage2, {}) }),
3682
- /* @__PURE__ */ jsx22(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx22(ResetPasswordPage2, {}) }),
3683
- /* @__PURE__ */ jsx22(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx22(VerifyEmailPage2, {}) }),
3684
- /* @__PURE__ */ jsx22(Route, { path: routes.authError, element: /* @__PURE__ */ jsx22(AuthErrorPage2, {}) }),
3685
- /* @__PURE__ */ jsx22(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx22(PlaceholderPage, { name: "github-callback" }) }),
3686
- /* @__PURE__ */ jsx22(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx22(PlaceholderPage, { name: "google-callback" }) }),
3687
- /* @__PURE__ */ jsx22(Route, { path: routes.me, element: /* @__PURE__ */ jsx22(UserSettingsPage2, {}) }),
3688
- /* @__PURE__ */ jsx22(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx22(MembersPage, {}) }),
3689
- /* @__PURE__ */ jsx22(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx22(MembersPage, {}) }),
3690
- /* @__PURE__ */ jsx22(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx22(InvitesPage, {}) }),
3691
- /* @__PURE__ */ jsx22(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx22(InvitesPage, {}) }),
3692
- /* @__PURE__ */ jsx22(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx22(WorkspaceSettingsPage, {}) }),
3693
- /* @__PURE__ */ jsx22(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx22(WorkspaceSettingsPage, {}) }),
3694
- /* @__PURE__ */ jsx22(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx22(InviteAcceptPage, {}) }),
3830
+ /* @__PURE__ */ jsx23(RouterAuthGate, { publicPaths: ["/invites", ...publicPaths ?? []], children: /* @__PURE__ */ jsx23(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs16(Routes, { children: [
3831
+ /* @__PURE__ */ jsx23(Route, { path: routes.signin, element: /* @__PURE__ */ jsx23(SignInPage2, {}) }),
3832
+ /* @__PURE__ */ jsx23(Route, { path: routes.signup, element: /* @__PURE__ */ jsx23(SignUpPage2, {}) }),
3833
+ /* @__PURE__ */ jsx23(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx23(ForgotPasswordPage2, {}) }),
3834
+ /* @__PURE__ */ jsx23(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx23(ResetPasswordPage2, {}) }),
3835
+ /* @__PURE__ */ jsx23(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx23(VerifyEmailPage2, {}) }),
3836
+ /* @__PURE__ */ jsx23(Route, { path: routes.authError, element: /* @__PURE__ */ jsx23(AuthErrorPage2, {}) }),
3837
+ /* @__PURE__ */ jsx23(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx23(PlaceholderPage, { name: "github-callback" }) }),
3838
+ /* @__PURE__ */ jsx23(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx23(PlaceholderPage, { name: "google-callback" }) }),
3839
+ /* @__PURE__ */ jsx23(Route, { path: routes.me, element: /* @__PURE__ */ jsx23(UserSettingsPage2, {}) }),
3840
+ /* @__PURE__ */ jsx23(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx23(MembersPage, {}) }),
3841
+ /* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx23(MembersPage, {}) }),
3842
+ /* @__PURE__ */ jsx23(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx23(InvitesPage, {}) }),
3843
+ /* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx23(InvitesPage, {}) }),
3844
+ /* @__PURE__ */ jsx23(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx23(WorkspaceSettingsPage, {}) }),
3845
+ /* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx23(WorkspaceSettingsPage, {}) }),
3846
+ /* @__PURE__ */ jsx23(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx23(InviteAcceptPage, {}) }),
3695
3847
  children
3696
3848
  ] }) }) })
3697
3849
  ] }) }) }) }) }) }) }) }) }) });
3698
3850
  }
3699
3851
 
3700
3852
  // src/front/commands/CoreCommandContributions.tsx
3701
- import { useMemo as useMemo7, useState as useState20 } from "react";
3853
+ import { useMemo as useMemo8, useState as useState21 } from "react";
3702
3854
  import { useNavigate as useNavigate7 } from "react-router-dom";
3703
3855
 
3704
3856
  // src/front/workspace/commands.ts
@@ -3740,8 +3892,8 @@ function useCoreCommands() {
3740
3892
  const navigate = useNavigate7();
3741
3893
  const signOut = useSignOut();
3742
3894
  const workspace = useCurrentWorkspace();
3743
- const [isSigningOut, setIsSigningOut] = useState20(false);
3744
- return useMemo7(() => {
3895
+ const [isSigningOut, setIsSigningOut] = useState21(false);
3896
+ return useMemo8(() => {
3745
3897
  const result = [
3746
3898
  {
3747
3899
  id: "user:settings",
@@ -3887,6 +4039,7 @@ export {
3887
4039
  AuthGate,
3888
4040
  UserMenu,
3889
4041
  WorkspaceSwitcher,
4042
+ CreateWorkspaceDialog,
3890
4043
  ThemeToggle,
3891
4044
  InvitesPage,
3892
4045
  MembersPage,