@agent-native/core 0.137.5 → 0.137.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/app/components/library/library-layout.tsx +95 -17
  3. package/corpus/templates/clips/app/components/library/space-card.tsx +136 -66
  4. package/corpus/templates/clips/app/components/library/space-dialogs.tsx +144 -0
  5. package/corpus/templates/clips/app/hooks/use-library.ts +2 -2
  6. package/corpus/templates/clips/app/i18n/en-US.ts +13 -0
  7. package/corpus/templates/clips/app/routes/_app.spaces._index.tsx +6 -2
  8. package/corpus/templates/clips/desktop/src/components/MediaDeviceRow.tsx +106 -87
  9. package/corpus/templates/clips/desktop/src/styles.css +19 -1
  10. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +7 -0
  11. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +103 -49
  12. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +4 -0
  13. package/corpus/templates/design/app/components/design/multi-screen/paint-suppression.ts +85 -0
  14. package/corpus/templates/design/changelog/2026-08-03-zoom-screen-blink.md +6 -0
  15. package/dist/agent/run-store.js +18 -0
  16. package/dist/client/AssistantChat.js +1 -0
  17. package/dist/client/chat/message-components.d.ts +10 -1
  18. package/dist/client/chat/message-components.js +13 -4
  19. package/dist/client/chat/runtime.js +20 -9
  20. package/dist/client/chat/tool-call-display.d.ts +7 -0
  21. package/dist/client/chat/tool-call-display.js +9 -1
  22. package/dist/client/sse-event-processor.d.ts +2 -0
  23. package/dist/client/sse-event-processor.js +39 -1
  24. package/dist/collab/awareness.d.ts +2 -2
  25. package/dist/collab/routes.d.ts +1 -1
  26. package/dist/collab/struct-routes.d.ts +1 -1
  27. package/dist/notifications/routes.d.ts +1 -1
  28. package/dist/progress/routes.d.ts +1 -1
  29. package/dist/resources/handlers.d.ts +1 -1
  30. package/dist/secrets/routes.d.ts +3 -3
  31. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  32. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -31,4 +31,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
31
31
 
32
32
  ## Generated Counts
33
33
 
34
- - template files: 7578
34
+ - template files: 7581
@@ -32,9 +32,11 @@ import {
32
32
  IconShare,
33
33
  IconSettings,
34
34
  IconSearch,
35
+ IconDots,
36
+ IconEdit,
35
37
  } from "@tabler/icons-react";
36
38
  import { ReactNode, useEffect, useMemo, useState } from "react";
37
- import { NavLink, useLocation, useParams } from "react-router";
39
+ import { NavLink, useLocation, useNavigate, useParams } from "react-router";
38
40
  import { toast } from "sonner";
39
41
 
40
42
  import {
@@ -52,6 +54,12 @@ import {
52
54
  AlertDialogTitle,
53
55
  } from "@/components/ui/alert-dialog";
54
56
  import { Button } from "@/components/ui/button";
57
+ import {
58
+ DropdownMenu,
59
+ DropdownMenuContent,
60
+ DropdownMenuItem,
61
+ DropdownMenuTrigger,
62
+ } from "@/components/ui/dropdown-menu";
55
63
  import {
56
64
  Tooltip,
57
65
  TooltipContent,
@@ -73,6 +81,7 @@ import { CreateSpaceDialog } from "./create-space-dialog";
73
81
  import { FolderTree, type FolderNode } from "./folder-tree";
74
82
  import { PageHeaderSlotProvider } from "./page-header";
75
83
  import { SearchBar } from "./search-bar";
84
+ import { SpaceDialogs } from "./space-dialogs";
76
85
 
77
86
  interface LibraryLayoutProps {
78
87
  children: ReactNode;
@@ -98,6 +107,7 @@ function ClipsAgentToggleButton() {
98
107
 
99
108
  export function LibraryLayout({ children }: LibraryLayoutProps) {
100
109
  const location = useLocation();
110
+ const navigate = useNavigate();
101
111
  const t = useT();
102
112
  // Bind chat to the currently-open recording (`/r/:id`). Library, spaces,
103
113
  // meetings, dictate, and settings stay unscoped — those are list-y views
@@ -123,9 +133,12 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
123
133
  const currentOrganizationId =
124
134
  organizations?.currentId ?? organizations?.organizations?.[0]?.id;
125
135
 
126
- const { data: spaces } = useSpaces(currentOrganizationId, {
127
- enabled: hasActiveOrg && Boolean(currentOrganizationId),
128
- });
136
+ const { data: spaces, refetch: refetchSpaces } = useSpaces(
137
+ currentOrganizationId,
138
+ {
139
+ enabled: hasActiveOrg && Boolean(currentOrganizationId),
140
+ },
141
+ );
129
142
  const { data: libFolders } = useFolders(
130
143
  {
131
144
  organizationId: currentOrganizationId,
@@ -240,6 +253,10 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
240
253
  const [newFolderOpen, setNewFolderOpen] = useState(false);
241
254
  const [newFolderName, setNewFolderName] = useState("");
242
255
  const [newSpaceOpen, setNewSpaceOpen] = useState(false);
256
+ const [deleteSpaceId, setDeleteSpaceId] = useState<string | null>(null);
257
+ const [deleteSpaceName, setDeleteSpaceName] = useState("");
258
+ const [renameSpaceId, setRenameSpaceId] = useState<string | null>(null);
259
+ const [renameSpaceValue, setRenameSpaceValue] = useState("");
243
260
  const createFolder = useCreateFolder();
244
261
 
245
262
  const navItems: {
@@ -540,26 +557,70 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
540
557
  const active = spaceId === s.id;
541
558
  return (
542
559
  <li key={s.id}>
543
- <NavLink
544
- to={`/spaces/${s.id}`}
560
+ <div
545
561
  className={cn(
546
- "flex items-center gap-2 rounded px-2 py-1 text-xs",
562
+ "group flex items-center gap-2 rounded px-2 py-1 text-xs",
547
563
  active
548
564
  ? "bg-primary/10 text-primary"
549
565
  : "text-foreground hover:bg-accent/60",
550
566
  )}
551
567
  >
552
- <div
553
- className="flex h-4 w-4 items-center justify-center rounded text-[10px]"
554
- style={{
555
- background: s.color ?? "hsl(var(--primary))",
556
- color: "white",
557
- }}
568
+ <NavLink
569
+ to={`/spaces/${s.id}`}
570
+ className="flex min-w-0 flex-1 items-center gap-2"
558
571
  >
559
- {s.iconEmoji ?? s.name.slice(0, 1).toUpperCase()}
560
- </div>
561
- <span className="truncate">{s.name}</span>
562
- </NavLink>
572
+ <div
573
+ className="flex h-4 w-4 items-center justify-center rounded text-[10px] shrink-0"
574
+ style={{
575
+ background: s.color ?? "hsl(var(--primary))",
576
+ color: "white",
577
+ }}
578
+ >
579
+ {s.iconEmoji ??
580
+ s.name.slice(0, 1).toUpperCase()}
581
+ </div>
582
+ <span className="truncate">{s.name}</span>
583
+ </NavLink>
584
+ {canManageOrg && (
585
+ <DropdownMenu>
586
+ <DropdownMenuTrigger asChild>
587
+ <button
588
+ type="button"
589
+ aria-label={`${s.name}: ${t("root.commandActions")}`}
590
+ title={`${s.name}: ${t("root.commandActions")}`}
591
+ className="rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100"
592
+ >
593
+ <IconDots className="h-3.5 w-3.5" />
594
+ </button>
595
+ </DropdownMenuTrigger>
596
+ <DropdownMenuContent align="start" side="right">
597
+ <DropdownMenuItem
598
+ onSelect={() => {
599
+ setTimeout(() => {
600
+ setRenameSpaceValue(s.name);
601
+ setRenameSpaceId(s.id);
602
+ }, 0);
603
+ }}
604
+ >
605
+ <IconEdit className="h-3.5 w-3.5 me-2" />
606
+ {t("spaceDialog.renameSpace")}
607
+ </DropdownMenuItem>
608
+ <DropdownMenuItem
609
+ onSelect={() => {
610
+ setTimeout(() => {
611
+ setDeleteSpaceId(s.id);
612
+ setDeleteSpaceName(s.name);
613
+ }, 0);
614
+ }}
615
+ className="text-destructive"
616
+ >
617
+ <IconTrash className="h-3.5 w-3.5 me-2" />
618
+ {t("spaceDialog.deleteSpace")}
619
+ </DropdownMenuItem>
620
+ </DropdownMenuContent>
621
+ </DropdownMenu>
622
+ )}
623
+ </div>
563
624
  </li>
564
625
  );
565
626
  })}
@@ -781,6 +842,23 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
781
842
  onOpenChange={setNewSpaceOpen}
782
843
  organizationId={currentOrganizationId}
783
844
  />
845
+
846
+ <SpaceDialogs
847
+ renameSpaceId={renameSpaceId}
848
+ renameSpaceName=""
849
+ setRenameSpaceId={setRenameSpaceId}
850
+ renameValue={renameSpaceValue}
851
+ setRenameValue={setRenameSpaceValue}
852
+ deleteSpaceId={deleteSpaceId}
853
+ deleteSpaceName={deleteSpaceName}
854
+ setDeleteSpaceId={setDeleteSpaceId}
855
+ onMutationSuccess={(deletedSpaceId) => {
856
+ if (deletedSpaceId && spaceId === deletedSpaceId) {
857
+ navigate("/spaces");
858
+ }
859
+ refetchSpaces?.();
860
+ }}
861
+ />
784
862
  </div>
785
863
  );
786
864
  }
@@ -1,8 +1,24 @@
1
- import { IconUsersGroup, IconVideo } from "@tabler/icons-react";
1
+ import { useT } from "@agent-native/core/client/i18n";
2
+ import { useOrgRole } from "@agent-native/core/client/org";
3
+ import {
4
+ IconUsersGroup,
5
+ IconVideo,
6
+ IconTrash,
7
+ IconEdit,
8
+ } from "@tabler/icons-react";
9
+ import { useState } from "react";
2
10
  import { Link } from "react-router";
3
11
 
12
+ import {
13
+ ContextMenu,
14
+ ContextMenuContent,
15
+ ContextMenuItem,
16
+ ContextMenuTrigger,
17
+ } from "@/components/ui/context-menu";
4
18
  import { cn } from "@/lib/utils";
5
19
 
20
+ import { SpaceDialogs } from "./space-dialogs";
21
+
6
22
  export interface SpaceCardData {
7
23
  id: string;
8
24
  name: string;
@@ -16,80 +32,134 @@ export interface SpaceCardData {
16
32
  interface SpaceCardProps {
17
33
  space: SpaceCardData;
18
34
  className?: string;
35
+ onMutationSuccess?: () => void;
19
36
  }
20
37
 
21
- export function SpaceCard({ space, className }: SpaceCardProps) {
38
+ export function SpaceCard({
39
+ space,
40
+ className,
41
+ onMutationSuccess,
42
+ }: SpaceCardProps) {
43
+ const t = useT();
44
+ const { canManageOrg } = useOrgRole();
22
45
  const color = space.color || "hsl(var(--primary))";
23
46
  const members = space.memberEmails ?? [];
24
47
  const initial = (space.name.trim().slice(0, 1) || "S").toUpperCase();
48
+ const [renameSpaceId, setRenameSpaceId] = useState<string | null>(null);
49
+ const [renameValue, setRenameValue] = useState("");
50
+ const [deleteSpaceId, setDeleteSpaceId] = useState<string | null>(null);
25
51
 
26
52
  return (
27
- <Link
28
- to={`/spaces/${space.id}`}
29
- className={cn(
30
- "group flex flex-col overflow-hidden rounded-lg border border-border bg-card text-start",
31
- "hover:border-primary/40",
32
- "shadow-[0_1px_2px_rgba(15,23,42,0.04)] hover:shadow-md",
33
- className,
34
- )}
35
- >
36
- <div
37
- className="relative flex h-24 items-center justify-center"
38
- style={{
39
- background: `linear-gradient(135deg, ${color} 0%, ${color}dd 100%)`,
40
- }}
41
- >
42
- {space.iconEmoji ? (
43
- <span className="text-3xl">{space.iconEmoji}</span>
44
- ) : (
45
- <span className="text-3xl font-semibold text-white">{initial}</span>
46
- )}
47
- </div>
48
- <div className="flex flex-1 flex-col p-3">
49
- <h3 className="text-sm font-semibold text-foreground truncate">
50
- {space.name}
51
- </h3>
52
- <div className="mt-2 flex items-center justify-between text-[11px] text-muted-foreground">
53
- <div className="flex items-center gap-1">
54
- <IconUsersGroup className="h-3.5 w-3.5" />
55
- <span>
56
- {space.memberCount ?? members.length} member
57
- {(space.memberCount ?? members.length) === 1 ? "" : "s"}
58
- </span>
59
- </div>
60
- <div className="flex items-center gap-1">
61
- <IconVideo className="h-3.5 w-3.5" />
62
- <span>
63
- {space.recordingCount ?? 0} recording
64
- {(space.recordingCount ?? 0) === 1 ? "" : "s"}
65
- </span>
66
- </div>
67
- </div>
68
-
69
- {members.length > 0 && (
70
- <div className="mt-2 flex -space-x-1">
71
- {members.slice(0, 5).map((email) => {
72
- const initials = (email.split("@")[0] || "?")
73
- .slice(0, 2)
74
- .toUpperCase();
75
- return (
76
- <div
77
- key={email}
78
- title={email}
79
- className="flex h-5 w-5 items-center justify-center rounded-full border border-background bg-primary/15 text-[9px] font-medium text-primary"
80
- >
81
- {initials}
53
+ <>
54
+ <ContextMenu>
55
+ <ContextMenuTrigger asChild>
56
+ <Link
57
+ to={`/spaces/${space.id}`}
58
+ className={cn(
59
+ "group flex flex-col overflow-hidden rounded-lg border border-border bg-card text-start",
60
+ "hover:border-primary/40",
61
+ "shadow-[0_1px_2px_rgba(15,23,42,0.04)] hover:shadow-md",
62
+ className,
63
+ )}
64
+ >
65
+ <div
66
+ className="relative flex h-24 items-center justify-center"
67
+ style={{
68
+ background: `linear-gradient(135deg, ${color} 0%, ${color}dd 100%)`,
69
+ }}
70
+ >
71
+ {space.iconEmoji ? (
72
+ <span className="text-3xl">{space.iconEmoji}</span>
73
+ ) : (
74
+ <span className="text-3xl font-semibold text-white">
75
+ {initial}
76
+ </span>
77
+ )}
78
+ </div>
79
+ <div className="flex flex-1 flex-col p-3">
80
+ <h3 className="text-sm font-semibold text-foreground truncate">
81
+ {space.name}
82
+ </h3>
83
+ <div className="mt-2 flex items-center justify-between text-[11px] text-muted-foreground">
84
+ <div className="flex items-center gap-1">
85
+ <IconUsersGroup className="h-3.5 w-3.5" />
86
+ <span>
87
+ {space.memberCount ?? members.length} member
88
+ {(space.memberCount ?? members.length) === 1 ? "" : "s"}
89
+ </span>
90
+ </div>
91
+ <div className="flex items-center gap-1">
92
+ <IconVideo className="h-3.5 w-3.5" />
93
+ <span>
94
+ {space.recordingCount ?? 0} recording
95
+ {(space.recordingCount ?? 0) === 1 ? "" : "s"}
96
+ </span>
82
97
  </div>
83
- );
84
- })}
85
- {members.length > 5 && (
86
- <div className="flex h-5 w-5 items-center justify-center rounded-full border border-background bg-muted text-[9px] text-muted-foreground">
87
- +{members.length - 5}
88
98
  </div>
89
- )}
90
- </div>
99
+
100
+ {members.length > 0 && (
101
+ <div className="mt-2 flex -space-x-1">
102
+ {members.slice(0, 5).map((email) => {
103
+ const initials = (email.split("@")[0] || "?")
104
+ .slice(0, 2)
105
+ .toUpperCase();
106
+ return (
107
+ <div
108
+ key={email}
109
+ title={email}
110
+ className="flex h-5 w-5 items-center justify-center rounded-full border border-background bg-primary/15 text-[9px] font-medium text-primary"
111
+ >
112
+ {initials}
113
+ </div>
114
+ );
115
+ })}
116
+ {members.length > 5 && (
117
+ <div className="flex h-5 w-5 items-center justify-center rounded-full border border-background bg-muted text-[9px] text-muted-foreground">
118
+ +{members.length - 5}
119
+ </div>
120
+ )}
121
+ </div>
122
+ )}
123
+ </div>
124
+ </Link>
125
+ </ContextMenuTrigger>
126
+ {canManageOrg && (
127
+ <ContextMenuContent>
128
+ <ContextMenuItem
129
+ onSelect={() => {
130
+ setTimeout(() => {
131
+ setRenameValue(space.name);
132
+ setRenameSpaceId(space.id);
133
+ }, 0);
134
+ }}
135
+ >
136
+ <IconEdit className="h-4 w-4 mr-2" />
137
+ {t("spaceDialog.renameSpace")}
138
+ </ContextMenuItem>
139
+ <ContextMenuItem
140
+ onSelect={() => {
141
+ setTimeout(() => setDeleteSpaceId(space.id), 0);
142
+ }}
143
+ className="text-destructive focus:text-destructive"
144
+ >
145
+ <IconTrash className="h-4 w-4 mr-2" />
146
+ {t("spaceDialog.deleteSpace")}
147
+ </ContextMenuItem>
148
+ </ContextMenuContent>
91
149
  )}
92
- </div>
93
- </Link>
150
+ </ContextMenu>
151
+
152
+ <SpaceDialogs
153
+ renameSpaceId={renameSpaceId}
154
+ renameSpaceName={space.name}
155
+ setRenameSpaceId={setRenameSpaceId}
156
+ renameValue={renameValue}
157
+ setRenameValue={setRenameValue}
158
+ deleteSpaceId={deleteSpaceId}
159
+ deleteSpaceName={space.name}
160
+ setDeleteSpaceId={setDeleteSpaceId}
161
+ onMutationSuccess={onMutationSuccess}
162
+ />
163
+ </>
94
164
  );
95
165
  }
@@ -0,0 +1,144 @@
1
+ import { useActionMutation } from "@agent-native/core/client/hooks";
2
+ import { useT } from "@agent-native/core/client/i18n";
3
+ import { useState } from "react";
4
+ import { toast } from "sonner";
5
+
6
+ import {
7
+ AlertDialog,
8
+ AlertDialogAction,
9
+ AlertDialogCancel,
10
+ AlertDialogContent,
11
+ AlertDialogDescription,
12
+ AlertDialogTitle,
13
+ } from "@/components/ui/alert-dialog";
14
+
15
+ interface SpaceDialogsProps {
16
+ renameSpaceId: string | null;
17
+ renameSpaceName: string;
18
+ setRenameSpaceId: (id: string | null) => void;
19
+ renameValue: string;
20
+ setRenameValue: (value: string) => void;
21
+ deleteSpaceId: string | null;
22
+ deleteSpaceName: string;
23
+ setDeleteSpaceId: (id: string | null) => void;
24
+ onMutationSuccess?: (deletedSpaceId?: string) => void;
25
+ }
26
+
27
+ export function SpaceDialogs({
28
+ renameSpaceId,
29
+ renameSpaceName,
30
+ setRenameSpaceId,
31
+ renameValue,
32
+ setRenameValue,
33
+ deleteSpaceId,
34
+ deleteSpaceName,
35
+ setDeleteSpaceId,
36
+ onMutationSuccess,
37
+ }: SpaceDialogsProps) {
38
+ const t = useT();
39
+ const renameSpace = useActionMutation("rename-space");
40
+ const deleteSpace = useActionMutation("delete-space");
41
+
42
+ const handleRename = async () => {
43
+ if (!renameSpaceId) return;
44
+ try {
45
+ await renameSpace.mutateAsync({
46
+ id: renameSpaceId,
47
+ name: renameValue.trim(),
48
+ });
49
+ toast.success(t("spaceDialog.renamed"));
50
+ setRenameSpaceId(null);
51
+ setRenameValue("");
52
+ onMutationSuccess?.();
53
+ } catch (err) {
54
+ toast.error(
55
+ err instanceof Error ? err.message : t("spaceDialog.renameFailed"),
56
+ );
57
+ }
58
+ };
59
+
60
+ const handleDelete = async () => {
61
+ if (!deleteSpaceId) return;
62
+ try {
63
+ await deleteSpace.mutateAsync({ id: deleteSpaceId });
64
+ toast.success(t("spaceDialog.deleted", { name: deleteSpaceName }));
65
+ setDeleteSpaceId(null);
66
+ onMutationSuccess?.(deleteSpaceId);
67
+ } catch (err) {
68
+ toast.error(
69
+ err instanceof Error ? err.message : t("spaceDialog.deleteFailed"),
70
+ );
71
+ }
72
+ };
73
+
74
+ return (
75
+ <>
76
+ {/* Rename space dialog */}
77
+ <AlertDialog
78
+ open={renameSpaceId !== null}
79
+ onOpenChange={(open) => {
80
+ if (!open) {
81
+ setRenameSpaceId(null);
82
+ setRenameValue("");
83
+ }
84
+ }}
85
+ >
86
+ <AlertDialogContent>
87
+ <AlertDialogTitle>{t("spaceDialog.renameSpace")}</AlertDialogTitle>
88
+ <input
89
+ autoFocus
90
+ value={renameValue}
91
+ onChange={(e) => setRenameValue(e.target.value)}
92
+ className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"
93
+ />
94
+ <div className="flex justify-end gap-2">
95
+ <AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
96
+ <AlertDialogAction
97
+ onClick={(event) => {
98
+ event.preventDefault();
99
+ void handleRename();
100
+ }}
101
+ disabled={renameSpace.isPending || !renameValue.trim()}
102
+ >
103
+ {renameSpace.isPending
104
+ ? t("spaceDialog.renaming")
105
+ : t("spaceDialog.renameSpace")}
106
+ </AlertDialogAction>
107
+ </div>
108
+ </AlertDialogContent>
109
+ </AlertDialog>
110
+
111
+ {/* Delete space dialog */}
112
+ <AlertDialog
113
+ open={deleteSpaceId !== null}
114
+ onOpenChange={(open) => {
115
+ if (!open) setDeleteSpaceId(null);
116
+ }}
117
+ >
118
+ <AlertDialogContent>
119
+ <AlertDialogTitle>
120
+ {t("spaceDialog.deleteTitle", { name: deleteSpaceName })}
121
+ </AlertDialogTitle>
122
+ <AlertDialogDescription>
123
+ {t("spaceDialog.deleteDescription")}
124
+ </AlertDialogDescription>
125
+ <div className="flex justify-end gap-2">
126
+ <AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
127
+ <AlertDialogAction
128
+ onClick={(event) => {
129
+ event.preventDefault();
130
+ void handleDelete();
131
+ }}
132
+ disabled={deleteSpace.isPending}
133
+ className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
134
+ >
135
+ {deleteSpace.isPending
136
+ ? t("spaceDialog.deleting")
137
+ : t("spaceDialog.deleteSpace")}
138
+ </AlertDialogAction>
139
+ </div>
140
+ </AlertDialogContent>
141
+ </AlertDialog>
142
+ </>
143
+ );
144
+ }
@@ -240,11 +240,11 @@ export function useSpaces(
240
240
  organizationId?: string,
241
241
  options: { enabled?: boolean } = {},
242
242
  ) {
243
- const { data, isLoading } = useOrganizationState(organizationId, {
243
+ const { data, isLoading, refetch } = useOrganizationState(organizationId, {
244
244
  enabled: options.enabled ?? Boolean(organizationId),
245
245
  });
246
246
  const spaces = Array.isArray(data?.spaces) ? (data.spaces as any[]) : [];
247
- return { data: { spaces }, isLoading };
247
+ return { data: { spaces }, isLoading, refetch };
248
248
  }
249
249
 
250
250
  export function useOrganizations(options: { enabled?: boolean } = {}) {
@@ -1101,6 +1101,19 @@ All notable user-facing changes to Clips are documented here. Open it any time f
1101
1101
  spaceCreated: "Space created",
1102
1102
  createFailed: "Could not create space",
1103
1103
  },
1104
+ spaceDialog: {
1105
+ deleteSpace: "Delete space",
1106
+ renameSpace: "Rename space",
1107
+ deleteTitle: 'Delete "{{name}}"?',
1108
+ deleteDescription:
1109
+ "This will delete the space and remove it from all recordings. This action cannot be undone.",
1110
+ renamed: "Space renamed",
1111
+ deleted: 'Deleted "{{name}}"',
1112
+ renameFailed: "Failed to rename space",
1113
+ deleteFailed: "Failed to delete space",
1114
+ renaming: "Renaming...",
1115
+ deleting: "Deleting...",
1116
+ },
1104
1117
  signInPrompt: {
1105
1118
  title: "Sign in to {{intent}}",
1106
1119
  description:
@@ -34,7 +34,7 @@ export default function SpacesIndexRoute() {
34
34
  const { data: organizations } = useOrganizations();
35
35
  const currentOrganizationId =
36
36
  organizations?.currentId ?? organizations?.organizations?.[0]?.id;
37
- const { data, isLoading } = useSpaces(currentOrganizationId);
37
+ const { data, isLoading, refetch } = useSpaces(currentOrganizationId);
38
38
 
39
39
  const spaces: SpaceCardData[] = (data?.spaces ?? []).map((s: any) => ({
40
40
  id: s.id,
@@ -80,7 +80,11 @@ export default function SpacesIndexRoute() {
80
80
  ) : (
81
81
  <div className="grid gap-4 [grid-template-columns:repeat(auto-fill,minmax(240px,1fr))]">
82
82
  {spaces.map((s) => (
83
- <SpaceCard key={s.id} space={s} />
83
+ <SpaceCard
84
+ key={s.id}
85
+ space={s}
86
+ onMutationSuccess={() => refetch?.()}
87
+ />
84
88
  ))}
85
89
  </div>
86
90
  )}