@agent-native/core 0.114.0 → 0.114.1

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 (162) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +9 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/client/build-compatibility.ts +77 -0
  5. package/corpus/core/src/client/route-chunk-recovery/index.ts +1 -0
  6. package/corpus/core/src/client/use-action.ts +32 -1
  7. package/corpus/core/src/deploy/build.ts +4 -1
  8. package/corpus/core/src/org/context.ts +56 -30
  9. package/corpus/core/src/server/action-routes.ts +52 -2
  10. package/corpus/core/src/server/auth-plugin.ts +9 -4
  11. package/corpus/core/src/server/better-auth-instance.ts +5 -1
  12. package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
  13. package/corpus/core/src/vite/client.ts +17 -0
  14. package/corpus/templates/content/AGENTS.md +2 -0
  15. package/corpus/templates/content/actions/_content-database-personal-view.ts +49 -5
  16. package/corpus/templates/content/actions/_content-document-access.ts +21 -0
  17. package/corpus/templates/content/actions/_content-favorites.ts +91 -0
  18. package/corpus/templates/content/actions/_content-files.ts +79 -23
  19. package/corpus/templates/content/actions/_content-sidebar-state.ts +24 -0
  20. package/corpus/templates/content/actions/_content-space-access.ts +15 -17
  21. package/corpus/templates/content/actions/_content-space-catalog-guards.ts +20 -0
  22. package/corpus/templates/content/actions/_content-spaces.ts +364 -167
  23. package/corpus/templates/content/actions/_database-source-utils.ts +8 -0
  24. package/corpus/templates/content/actions/_database-utils.ts +249 -15
  25. package/corpus/templates/content/actions/_delete-content-space.ts +84 -0
  26. package/corpus/templates/content/actions/_files-system-properties.ts +499 -0
  27. package/corpus/templates/content/actions/_local-file-documents.ts +0 -1
  28. package/corpus/templates/content/actions/_property-utils.ts +18 -9
  29. package/corpus/templates/content/actions/bind-content-database-source-field.ts +3 -0
  30. package/corpus/templates/content/actions/configure-document-property.ts +3 -0
  31. package/corpus/templates/content/actions/create-content-database.ts +2 -2
  32. package/corpus/templates/content/actions/create-content-space.ts +34 -0
  33. package/corpus/templates/content/actions/create-document.ts +4 -1
  34. package/corpus/templates/content/actions/delete-content-space.ts +19 -0
  35. package/corpus/templates/content/actions/delete-database-items.ts +28 -1
  36. package/corpus/templates/content/actions/delete-document-property.ts +3 -0
  37. package/corpus/templates/content/actions/delete-document.ts +39 -2
  38. package/corpus/templates/content/actions/duplicate-database-item.ts +6 -0
  39. package/corpus/templates/content/actions/duplicate-database-items.ts +6 -0
  40. package/corpus/templates/content/actions/duplicate-document-property.ts +3 -0
  41. package/corpus/templates/content/actions/get-content-database.ts +11 -2
  42. package/corpus/templates/content/actions/get-content-sidebar-state.ts +23 -0
  43. package/corpus/templates/content/actions/get-document.ts +32 -7
  44. package/corpus/templates/content/actions/import-content-source.ts +33 -1
  45. package/corpus/templates/content/actions/list-content-spaces.ts +34 -2
  46. package/corpus/templates/content/actions/list-documents.ts +39 -7
  47. package/corpus/templates/content/actions/reorder-document-property.ts +9 -0
  48. package/corpus/templates/content/actions/set-document-property.ts +41 -23
  49. package/corpus/templates/content/actions/share-local-file-document.ts +15 -0
  50. package/corpus/templates/content/actions/submit-content-database-form.ts +7 -0
  51. package/corpus/templates/content/actions/sync-local-folder-source.ts +14 -0
  52. package/corpus/templates/content/actions/update-content-database-view.ts +1 -0
  53. package/corpus/templates/content/actions/update-content-sidebar-state.ts +27 -0
  54. package/corpus/templates/content/actions/update-document.ts +158 -66
  55. package/corpus/templates/content/app/components/EmptyState.tsx +4 -57
  56. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +8 -1
  57. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +519 -178
  58. package/corpus/templates/content/app/components/editor/DocumentInfoPanel.tsx +39 -0
  59. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
  60. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +266 -7
  61. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +430 -152
  62. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +467 -66
  63. package/corpus/templates/content/app/components/editor/database/view-config.ts +9 -3
  64. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +720 -196
  65. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +173 -1
  66. package/corpus/templates/content/app/components/sidebar/document-sidebar-sections.ts +1 -1
  67. package/corpus/templates/content/app/components/sidebar/select-content-space.ts +91 -16
  68. package/corpus/templates/content/app/entry.client.tsx +5 -1
  69. package/corpus/templates/content/app/hooks/use-content-database.ts +84 -3
  70. package/corpus/templates/content/app/hooks/use-content-spaces.ts +60 -2
  71. package/corpus/templates/content/app/hooks/use-create-page.ts +30 -0
  72. package/corpus/templates/content/app/hooks/use-documents.ts +270 -19
  73. package/corpus/templates/content/app/i18n-data.ts +243 -20
  74. package/corpus/templates/content/app/lib/local-folder-picker-safety.ts +54 -0
  75. package/corpus/templates/content/app/lib/local-folder-picker-support.ts +18 -0
  76. package/corpus/templates/content/app/routes/_app.favorites.tsx +30 -0
  77. package/corpus/templates/content/app/routes/_app.local-files.tsx +18 -6
  78. package/corpus/templates/content/changelog/2026-07-17-workspace-files-now-stay-in-a-loading-state-until-automatic-.md +6 -0
  79. package/corpus/templates/content/changelog/2026-07-17-workspace-switching-now-opens-the-selected-files-database-pr.md +6 -0
  80. package/corpus/templates/content/changelog/2026-07-17-workspaces-now-expand-above-their-own-files-list-without-dup.md +6 -0
  81. package/corpus/templates/content/changelog/2026-07-18-create-named-workspaces-each-with-its-own-private-files-data.md +6 -0
  82. package/corpus/templates/content/changelog/2026-07-18-favorites-align-with-workspace-and-file-rows-in-the-sidebar.md +6 -0
  83. package/corpus/templates/content/changelog/2026-07-18-local-folder-selection-no-longer-invokes-the-unsafe-native-p.md +6 -0
  84. package/corpus/templates/content/changelog/2026-07-18-made-content-workspaces-independently-expandable-restored-or.md +6 -0
  85. package/corpus/templates/content/changelog/2026-07-18-page-details-now-live-in-a-shared-info-and-comments-rail-dat.md +6 -0
  86. package/corpus/templates/content/changelog/2026-07-18-workspace-database-views-now-control-sidebar-workspace-navig.md +6 -0
  87. package/corpus/templates/content/changelog/2026-07-18-workspace-navigation-now-aligns-favorites-with-workspace-pag.md +6 -0
  88. package/corpus/templates/content/changelog/2026-07-19-favorites-now-open-as-a-table-and-compact-breadcrumbs-make-w.md +6 -0
  89. package/corpus/templates/content/changelog/2026-07-19-files-databases-now-start-unfiltered-sidebar-rows-exactly-fo.md +6 -0
  90. package/corpus/templates/content/changelog/2026-07-19-sidebar-page-trees-now-open-only-when-expanded-remember-thei.md +6 -0
  91. package/corpus/templates/content/changelog/2026-07-19-workspace-file-databases-now-use-the-workspace-name-open-as-.md +6 -0
  92. package/corpus/templates/content/changelog/2026-07-19-workspace-navigation-now-stays-stable-on-hover-uses-folder-i.md +6 -0
  93. package/corpus/templates/content/changelog/2026-07-19-workspace-rows-now-use-folder-icons-and-deleting-a-user-crea.md +6 -0
  94. package/corpus/templates/content/changelog/2026-07-19-workspaces-can-be-created-without-leaving-the-workspaces-dat.md +6 -0
  95. package/corpus/templates/content/e2e/global-setup.ts +3 -2
  96. package/corpus/templates/content/parity/matrix.md +28 -28
  97. package/corpus/templates/content/parity/matrix.ts +8 -2
  98. package/corpus/templates/content/server/db/index.ts +1 -0
  99. package/corpus/templates/content/server/db/schema.ts +10 -0
  100. package/corpus/templates/content/server/lib/documents.ts +12 -7
  101. package/corpus/templates/content/server/plugins/db.ts +17 -0
  102. package/corpus/templates/content/shared/api.ts +9 -0
  103. package/corpus/templates/content/shared/database-form.ts +11 -2
  104. package/corpus/templates/content/vite.config.ts +1 -0
  105. package/dist/client/build-compatibility.d.ts +11 -0
  106. package/dist/client/build-compatibility.d.ts.map +1 -0
  107. package/dist/client/build-compatibility.js +56 -0
  108. package/dist/client/build-compatibility.js.map +1 -0
  109. package/dist/client/route-chunk-recovery/index.d.ts +1 -0
  110. package/dist/client/route-chunk-recovery/index.d.ts.map +1 -1
  111. package/dist/client/route-chunk-recovery/index.js +1 -0
  112. package/dist/client/route-chunk-recovery/index.js.map +1 -1
  113. package/dist/client/use-action.d.ts.map +1 -1
  114. package/dist/client/use-action.js +19 -1
  115. package/dist/client/use-action.js.map +1 -1
  116. package/dist/collab/routes.d.ts +1 -1
  117. package/dist/collab/struct-routes.d.ts +1 -1
  118. package/dist/deploy/build.js +2 -1
  119. package/dist/deploy/build.js.map +1 -1
  120. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  121. package/dist/notifications/routes.d.ts +1 -1
  122. package/dist/observability/routes.d.ts +5 -5
  123. package/dist/org/context.d.ts +4 -2
  124. package/dist/org/context.d.ts.map +1 -1
  125. package/dist/org/context.js +44 -22
  126. package/dist/org/context.js.map +1 -1
  127. package/dist/progress/routes.d.ts +1 -1
  128. package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
  129. package/dist/provider-api/actions/provider-api.d.ts +12 -12
  130. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  131. package/dist/resources/handlers.d.ts +1 -1
  132. package/dist/secrets/routes.d.ts +9 -9
  133. package/dist/server/action-routes.d.ts.map +1 -1
  134. package/dist/server/action-routes.js +32 -2
  135. package/dist/server/action-routes.js.map +1 -1
  136. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  137. package/dist/server/auth-plugin.d.ts.map +1 -1
  138. package/dist/server/auth-plugin.js +9 -5
  139. package/dist/server/auth-plugin.js.map +1 -1
  140. package/dist/server/better-auth-instance.d.ts.map +1 -1
  141. package/dist/server/better-auth-instance.js +4 -1
  142. package/dist/server/better-auth-instance.js.map +1 -1
  143. package/dist/server/transcribe-voice.d.ts +1 -1
  144. package/dist/shared/mcp-embed-headers.d.ts +1 -1
  145. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  146. package/dist/shared/mcp-embed-headers.js +1 -1
  147. package/dist/shared/mcp-embed-headers.js.map +1 -1
  148. package/dist/vite/client.d.ts +6 -0
  149. package/dist/vite/client.d.ts.map +1 -1
  150. package/dist/vite/client.js +8 -0
  151. package/dist/vite/client.js.map +1 -1
  152. package/package.json +1 -1
  153. package/src/client/build-compatibility.ts +77 -0
  154. package/src/client/route-chunk-recovery/index.ts +1 -0
  155. package/src/client/use-action.ts +32 -1
  156. package/src/deploy/build.ts +4 -1
  157. package/src/org/context.ts +56 -30
  158. package/src/server/action-routes.ts +52 -2
  159. package/src/server/auth-plugin.ts +9 -4
  160. package/src/server/better-auth-instance.ts +5 -1
  161. package/src/shared/mcp-embed-headers.ts +1 -1
  162. package/src/vite/client.ts +17 -0
@@ -0,0 +1,39 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
2
+ import type { Document } from "@shared/api";
3
+
4
+ import { DescriptionField } from "./DescriptionField";
5
+ import { DocumentProperties } from "./DocumentProperties";
6
+
7
+ interface DocumentInfoPanelProps {
8
+ document: Document;
9
+ canEdit: boolean;
10
+ onSaveDescription: (description: string) => Promise<unknown> | unknown;
11
+ }
12
+
13
+ export function DocumentInfoPanel({
14
+ document,
15
+ canEdit,
16
+ onSaveDescription,
17
+ }: DocumentInfoPanelProps) {
18
+ const t = useT();
19
+ const isLocalFileDocument = document.source?.mode === "local-files";
20
+
21
+ return (
22
+ <div className="px-4 pb-8 pt-3" data-document-info-panel>
23
+ <DescriptionField
24
+ description={document.description}
25
+ canEdit={canEdit}
26
+ label={t("editor.properties.description")}
27
+ placeholder={
28
+ document.database
29
+ ? t("editor.properties.addDatabaseDescription")
30
+ : t("editor.properties.addPageDescription")
31
+ }
32
+ onSave={onSaveDescription}
33
+ />
34
+ {document.databaseMembership && !isLocalFileDocument ? (
35
+ <DocumentProperties documentId={document.id} canEdit={canEdit} />
36
+ ) : null}
37
+ </div>
38
+ );
39
+ }
@@ -916,7 +916,7 @@ function PropertyRow({
916
916
 
917
917
  return (
918
918
  <div className="grid min-h-8 grid-cols-[160px_minmax(0,1fr)] items-start gap-3 rounded px-1 py-1 text-sm hover:bg-muted/40">
919
- {canEdit ? (
919
+ {canEdit && !property.definition.systemRole ? (
920
920
  <PropertyManagementPopover
921
921
  property={property}
922
922
  documentId={documentId}
@@ -11,12 +11,14 @@ import {
11
11
  IconArrowBarDown,
12
12
  IconArrowBarUp,
13
13
  IconAlertTriangle,
14
+ IconCheck,
14
15
  IconCopy,
15
16
  IconDownload,
16
17
  IconDotsVertical,
17
18
  IconExternalLink,
18
19
  IconFileTypeHtml,
19
20
  IconFileTypePdf,
21
+ IconFolder,
20
22
  IconLinkOff,
21
23
  IconLoader2,
22
24
  IconMarkdown,
@@ -25,15 +27,34 @@ import {
25
27
  IconFolderOpen,
26
28
  IconPlus,
27
29
  IconHistory,
30
+ IconInfoCircle,
28
31
  IconLink,
32
+ IconMessageCircle,
29
33
  IconRefresh,
30
34
  IconShare3,
35
+ IconTrash,
31
36
  } from "@tabler/icons-react";
32
37
  import { useQueryClient } from "@tanstack/react-query";
33
- import { useCallback, useEffect, useRef, useState } from "react";
38
+ import {
39
+ useCallback,
40
+ useEffect,
41
+ useRef,
42
+ useState,
43
+ type ReactNode,
44
+ } from "react";
34
45
  import { useLocation, useNavigate } from "react-router";
35
46
  import { toast } from "sonner";
36
47
 
48
+ import {
49
+ AlertDialog,
50
+ AlertDialogAction,
51
+ AlertDialogCancel,
52
+ AlertDialogContent,
53
+ AlertDialogDescription,
54
+ AlertDialogFooter,
55
+ AlertDialogHeader,
56
+ AlertDialogTitle,
57
+ } from "@/components/ui/alert-dialog";
37
58
  import { Button } from "@/components/ui/button";
38
59
  import {
39
60
  DropdownMenu,
@@ -188,24 +209,27 @@ function ToolbarBreadcrumb({
188
209
  untitledLabel,
189
210
  onOpen,
190
211
  }: {
191
- items: { id?: string; title: string; icon?: string | null }[];
212
+ items: ToolbarBreadcrumbItem[];
192
213
  currentDocumentId: string;
193
214
  ariaLabel: string;
194
215
  untitledLabel: string;
195
216
  onOpen: (id: string) => void;
196
217
  }) {
218
+ const visibleItems = compactToolbarBreadcrumbItems(items);
197
219
  return (
198
220
  <nav
199
221
  aria-label={ariaLabel}
200
222
  className="flex min-w-0 flex-1 items-center gap-1 text-sm text-foreground"
201
223
  >
202
- {items.map((item, index) => {
203
- const isLast = index === items.length - 1;
224
+ {visibleItems.map((item, index) => {
225
+ const isLast = index === visibleItems.length - 1;
204
226
  const label = item.title.trim() || untitledLabel;
205
227
  const content = (
206
228
  <>
207
229
  {item.icon ? (
208
230
  <span className="shrink-0 text-sm leading-none">{item.icon}</span>
231
+ ) : item.iconKind === "folder" ? (
232
+ <IconFolder className="size-3.5 shrink-0 text-muted-foreground" />
209
233
  ) : null}
210
234
  <span className="truncate">{label}</span>
211
235
  </>
@@ -216,7 +240,18 @@ function ToolbarBreadcrumb({
216
240
  key={`${item.id ?? label}-${index}`}
217
241
  className="flex min-w-0 items-center gap-1"
218
242
  >
219
- {item.id && item.id !== currentDocumentId ? (
243
+ {item.menuItems?.length ? (
244
+ <ToolbarBreadcrumbMenu
245
+ item={item}
246
+ label={label}
247
+ currentDocumentId={currentDocumentId}
248
+ current={isLast}
249
+ untitledLabel={untitledLabel}
250
+ onOpen={onOpen}
251
+ >
252
+ {content}
253
+ </ToolbarBreadcrumbMenu>
254
+ ) : item.id && item.id !== currentDocumentId ? (
220
255
  <button
221
256
  type="button"
222
257
  className="flex min-w-0 max-w-48 items-center gap-1 rounded px-1.5 py-1 text-left text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
@@ -244,11 +279,134 @@ function ToolbarBreadcrumb({
244
279
  );
245
280
  }
246
281
 
282
+ export interface ToolbarBreadcrumbItem {
283
+ id?: string;
284
+ title: string;
285
+ icon?: string | null;
286
+ iconKind?: "folder";
287
+ menuItems?: Array<{
288
+ id: string;
289
+ title: string;
290
+ icon?: string | null;
291
+ iconKind?: "folder";
292
+ }>;
293
+ }
294
+
295
+ export function compactToolbarBreadcrumbItems(
296
+ items: ToolbarBreadcrumbItem[],
297
+ ): ToolbarBreadcrumbItem[] {
298
+ if (items.length <= 3) return items;
299
+ const hidden = items.slice(1, -2);
300
+ return [
301
+ items[0],
302
+ {
303
+ title: "…",
304
+ menuItems: hidden.flatMap((item) =>
305
+ item.id
306
+ ? [
307
+ {
308
+ id: item.id,
309
+ title: item.title,
310
+ icon: item.icon,
311
+ iconKind: item.iconKind,
312
+ },
313
+ ]
314
+ : [],
315
+ ),
316
+ },
317
+ ...items.slice(-2),
318
+ ];
319
+ }
320
+
321
+ function ToolbarBreadcrumbMenu({
322
+ item,
323
+ label,
324
+ currentDocumentId,
325
+ current,
326
+ untitledLabel,
327
+ onOpen,
328
+ children,
329
+ }: {
330
+ item: ToolbarBreadcrumbItem;
331
+ label: string;
332
+ currentDocumentId: string;
333
+ current: boolean;
334
+ untitledLabel: string;
335
+ onOpen: (id: string) => void;
336
+ children: ReactNode;
337
+ }) {
338
+ const [open, setOpen] = useState(false);
339
+ const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
340
+
341
+ function cancelClose() {
342
+ if (!closeTimerRef.current) return;
343
+ clearTimeout(closeTimerRef.current);
344
+ closeTimerRef.current = null;
345
+ }
346
+
347
+ function scheduleClose() {
348
+ cancelClose();
349
+ closeTimerRef.current = setTimeout(() => setOpen(false), 140);
350
+ }
351
+
352
+ return (
353
+ <DropdownMenu modal={false} open={open} onOpenChange={setOpen}>
354
+ <DropdownMenuTrigger asChild>
355
+ <button
356
+ type="button"
357
+ aria-label={label}
358
+ className={cn(
359
+ "flex min-w-0 max-w-48 items-center gap-1 rounded px-1.5 py-1 text-left hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
360
+ current ? "text-foreground" : "text-muted-foreground",
361
+ )}
362
+ onPointerEnter={() => {
363
+ cancelClose();
364
+ setOpen(true);
365
+ }}
366
+ onPointerLeave={scheduleClose}
367
+ >
368
+ {children}
369
+ </button>
370
+ </DropdownMenuTrigger>
371
+ <DropdownMenuContent
372
+ align="start"
373
+ className="w-64"
374
+ onPointerEnter={cancelClose}
375
+ onPointerLeave={scheduleClose}
376
+ >
377
+ {item.menuItems?.map((menuItem) => {
378
+ const menuLabel = menuItem.title.trim() || untitledLabel;
379
+ return (
380
+ <DropdownMenuItem
381
+ key={menuItem.id}
382
+ className="gap-2"
383
+ onSelect={() => onOpen(menuItem.id)}
384
+ >
385
+ <span className="flex size-4 shrink-0 items-center justify-center">
386
+ {menuItem.id === currentDocumentId ? (
387
+ <IconCheck className="size-3.5" />
388
+ ) : menuItem.icon ? (
389
+ <span className="text-sm leading-none">{menuItem.icon}</span>
390
+ ) : menuItem.iconKind === "folder" ? (
391
+ <IconFolder className="size-3.5 text-muted-foreground" />
392
+ ) : (
393
+ <IconFileText className="size-3.5 text-muted-foreground" />
394
+ )}
395
+ </span>
396
+ <span className="min-w-0 flex-1 truncate">{menuLabel}</span>
397
+ </DropdownMenuItem>
398
+ );
399
+ })}
400
+ </DropdownMenuContent>
401
+ </DropdownMenu>
402
+ );
403
+ }
404
+
247
405
  interface DocumentToolbarProps {
248
406
  documentId: string;
249
407
  documentTitle?: string;
250
408
  documentContent?: string;
251
- breadcrumbItems?: { id?: string; title: string; icon?: string | null }[];
409
+ breadcrumbItems?: ToolbarBreadcrumbItem[];
252
410
  documentUpdatedAt?: string | null;
253
411
  activeUsers?: CollabUser[];
254
412
  agentPresent?: boolean;
@@ -257,6 +415,13 @@ interface DocumentToolbarProps {
257
415
  canEdit?: boolean;
258
416
  hideFromSearch?: boolean;
259
417
  source?: DocumentSourceInfo;
418
+ canDelete?: boolean;
419
+ deletePending?: boolean;
420
+ onDelete?: () => Promise<void>;
421
+ utilityPanel: "info" | "comments" | null;
422
+ onUtilityPanelChange: (panel: "info" | "comments" | null) => void;
423
+ showCommentsControl?: boolean;
424
+ onOpenBreadcrumbItem?: (id: string) => void;
260
425
  }
261
426
 
262
427
  export function DocumentToolbar({
@@ -272,6 +437,13 @@ export function DocumentToolbar({
272
437
  canEdit = true,
273
438
  hideFromSearch = false,
274
439
  source,
440
+ canDelete = false,
441
+ deletePending = false,
442
+ onDelete,
443
+ utilityPanel,
444
+ onUtilityPanelChange,
445
+ showCommentsControl = true,
446
+ onOpenBreadcrumbItem,
275
447
  }: DocumentToolbarProps) {
276
448
  const t = useT();
277
449
  const navigate = useNavigate();
@@ -311,6 +483,7 @@ export function DocumentToolbar({
311
483
  boolean | null
312
484
  >(null);
313
485
  const [historyOpen, setHistoryOpen] = useState(false);
486
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
314
487
  const [searchQuery, setSearchQuery] = useState("");
315
488
  const [debouncedQuery, setDebouncedQuery] = useState("");
316
489
  const [linkingPageId, setLinkingPageId] = useState<string | null>(null);
@@ -651,7 +824,13 @@ export function DocumentToolbar({
651
824
  currentDocumentId={documentId}
652
825
  ariaLabel={t("editor.toolbar.pageBreadcrumb")}
653
826
  untitledLabel={t("sidebar.untitled")}
654
- onOpen={(id) => navigate(`/page/${id}`, { flushSync: true })}
827
+ onOpen={(id) => {
828
+ if (onOpenBreadcrumbItem) {
829
+ onOpenBreadcrumbItem(id);
830
+ return;
831
+ }
832
+ navigate(`/page/${id}`, { flushSync: true });
833
+ }}
655
834
  />
656
835
 
657
836
  <div className="ml-auto flex min-w-0 items-center gap-0.5 sm:gap-1">
@@ -756,6 +935,50 @@ export function DocumentToolbar({
756
935
  <TooltipContent>{t("editor.toolbar.copyPageLink")}</TooltipContent>
757
936
  </Tooltip>
758
937
 
938
+ <Tooltip>
939
+ <TooltipTrigger asChild>
940
+ <button
941
+ type="button"
942
+ className={cn(
943
+ "flex size-9 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
944
+ utilityPanel === "info" && "bg-accent text-foreground",
945
+ )}
946
+ aria-label={t("editor.toolbar.info")}
947
+ aria-pressed={utilityPanel === "info"}
948
+ onClick={() =>
949
+ onUtilityPanelChange(utilityPanel === "info" ? null : "info")
950
+ }
951
+ >
952
+ <IconInfoCircle size={16} />
953
+ </button>
954
+ </TooltipTrigger>
955
+ <TooltipContent>{t("editor.toolbar.info")}</TooltipContent>
956
+ </Tooltip>
957
+
958
+ {showCommentsControl ? (
959
+ <Tooltip>
960
+ <TooltipTrigger asChild>
961
+ <button
962
+ type="button"
963
+ className={cn(
964
+ "flex size-9 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
965
+ utilityPanel === "comments" && "bg-accent text-foreground",
966
+ )}
967
+ aria-label={t("comments.title")}
968
+ aria-pressed={utilityPanel === "comments"}
969
+ onClick={() =>
970
+ onUtilityPanelChange(
971
+ utilityPanel === "comments" ? null : "comments",
972
+ )
973
+ }
974
+ >
975
+ <IconMessageCircle size={16} />
976
+ </button>
977
+ </TooltipTrigger>
978
+ <TooltipContent>{t("comments.title")}</TooltipContent>
979
+ </Tooltip>
980
+ ) : null}
981
+
759
982
  <DropdownMenu modal={false}>
760
983
  <Tooltip>
761
984
  <TooltipTrigger asChild>
@@ -1202,11 +1425,47 @@ export function DocumentToolbar({
1202
1425
  </Popover>
1203
1426
  ) : null}
1204
1427
  </DropdownMenuGroup>
1428
+ {canDelete && onDelete ? (
1429
+ <>
1430
+ <DropdownMenuSeparator />
1431
+ <DropdownMenuItem
1432
+ className="text-destructive focus:text-destructive"
1433
+ onSelect={() => setDeleteDialogOpen(true)}
1434
+ >
1435
+ <IconTrash className="me-2 h-4 w-4" />
1436
+ {t("database.delete")}
1437
+ </DropdownMenuItem>
1438
+ </>
1439
+ ) : null}
1205
1440
  </DropdownMenuContent>
1206
1441
  </DropdownMenu>
1207
1442
  <AgentToggleButton />
1208
1443
  </div>
1209
1444
  </div>
1445
+ <AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
1446
+ <AlertDialogContent>
1447
+ <AlertDialogHeader>
1448
+ <AlertDialogTitle>
1449
+ {t("sidebar.deletePageQuestion")}
1450
+ </AlertDialogTitle>
1451
+ <AlertDialogDescription>
1452
+ {t("sidebar.deletePageDescription", {
1453
+ title: documentTitle || t("sidebar.untitled"),
1454
+ })}
1455
+ </AlertDialogDescription>
1456
+ </AlertDialogHeader>
1457
+ <AlertDialogFooter>
1458
+ <AlertDialogCancel>{t("comments.cancel")}</AlertDialogCancel>
1459
+ <AlertDialogAction
1460
+ className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
1461
+ disabled={deletePending}
1462
+ onClick={() => void onDelete?.()}
1463
+ >
1464
+ {t("database.delete")}
1465
+ </AlertDialogAction>
1466
+ </AlertDialogFooter>
1467
+ </AlertDialogContent>
1468
+ </AlertDialog>
1210
1469
  </>
1211
1470
  );
1212
1471
  }