@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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +9 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/build-compatibility.ts +77 -0
- package/corpus/core/src/client/route-chunk-recovery/index.ts +1 -0
- package/corpus/core/src/client/use-action.ts +32 -1
- package/corpus/core/src/deploy/build.ts +4 -1
- package/corpus/core/src/org/context.ts +56 -30
- package/corpus/core/src/server/action-routes.ts +52 -2
- package/corpus/core/src/server/auth-plugin.ts +9 -4
- package/corpus/core/src/server/better-auth-instance.ts +5 -1
- package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
- package/corpus/core/src/vite/client.ts +17 -0
- package/corpus/templates/content/AGENTS.md +2 -0
- package/corpus/templates/content/actions/_content-database-personal-view.ts +49 -5
- package/corpus/templates/content/actions/_content-document-access.ts +21 -0
- package/corpus/templates/content/actions/_content-favorites.ts +91 -0
- package/corpus/templates/content/actions/_content-files.ts +79 -23
- package/corpus/templates/content/actions/_content-sidebar-state.ts +24 -0
- package/corpus/templates/content/actions/_content-space-access.ts +15 -17
- package/corpus/templates/content/actions/_content-space-catalog-guards.ts +20 -0
- package/corpus/templates/content/actions/_content-spaces.ts +364 -167
- package/corpus/templates/content/actions/_database-source-utils.ts +8 -0
- package/corpus/templates/content/actions/_database-utils.ts +249 -15
- package/corpus/templates/content/actions/_delete-content-space.ts +84 -0
- package/corpus/templates/content/actions/_files-system-properties.ts +499 -0
- package/corpus/templates/content/actions/_local-file-documents.ts +0 -1
- package/corpus/templates/content/actions/_property-utils.ts +18 -9
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +3 -0
- package/corpus/templates/content/actions/configure-document-property.ts +3 -0
- package/corpus/templates/content/actions/create-content-database.ts +2 -2
- package/corpus/templates/content/actions/create-content-space.ts +34 -0
- package/corpus/templates/content/actions/create-document.ts +4 -1
- package/corpus/templates/content/actions/delete-content-space.ts +19 -0
- package/corpus/templates/content/actions/delete-database-items.ts +28 -1
- package/corpus/templates/content/actions/delete-document-property.ts +3 -0
- package/corpus/templates/content/actions/delete-document.ts +39 -2
- package/corpus/templates/content/actions/duplicate-database-item.ts +6 -0
- package/corpus/templates/content/actions/duplicate-database-items.ts +6 -0
- package/corpus/templates/content/actions/duplicate-document-property.ts +3 -0
- package/corpus/templates/content/actions/get-content-database.ts +11 -2
- package/corpus/templates/content/actions/get-content-sidebar-state.ts +23 -0
- package/corpus/templates/content/actions/get-document.ts +32 -7
- package/corpus/templates/content/actions/import-content-source.ts +33 -1
- package/corpus/templates/content/actions/list-content-spaces.ts +34 -2
- package/corpus/templates/content/actions/list-documents.ts +39 -7
- package/corpus/templates/content/actions/reorder-document-property.ts +9 -0
- package/corpus/templates/content/actions/set-document-property.ts +41 -23
- package/corpus/templates/content/actions/share-local-file-document.ts +15 -0
- package/corpus/templates/content/actions/submit-content-database-form.ts +7 -0
- package/corpus/templates/content/actions/sync-local-folder-source.ts +14 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +1 -0
- package/corpus/templates/content/actions/update-content-sidebar-state.ts +27 -0
- package/corpus/templates/content/actions/update-document.ts +158 -66
- package/corpus/templates/content/app/components/EmptyState.tsx +4 -57
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +8 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +519 -178
- package/corpus/templates/content/app/components/editor/DocumentInfoPanel.tsx +39 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +266 -7
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +430 -152
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +467 -66
- package/corpus/templates/content/app/components/editor/database/view-config.ts +9 -3
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +720 -196
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +173 -1
- package/corpus/templates/content/app/components/sidebar/document-sidebar-sections.ts +1 -1
- package/corpus/templates/content/app/components/sidebar/select-content-space.ts +91 -16
- package/corpus/templates/content/app/entry.client.tsx +5 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +84 -3
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +60 -2
- package/corpus/templates/content/app/hooks/use-create-page.ts +30 -0
- package/corpus/templates/content/app/hooks/use-documents.ts +270 -19
- package/corpus/templates/content/app/i18n-data.ts +243 -20
- package/corpus/templates/content/app/lib/local-folder-picker-safety.ts +54 -0
- package/corpus/templates/content/app/lib/local-folder-picker-support.ts +18 -0
- package/corpus/templates/content/app/routes/_app.favorites.tsx +30 -0
- package/corpus/templates/content/app/routes/_app.local-files.tsx +18 -6
- package/corpus/templates/content/changelog/2026-07-17-workspace-files-now-stay-in-a-loading-state-until-automatic-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-workspace-switching-now-opens-the-selected-files-database-pr.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-workspaces-now-expand-above-their-own-files-list-without-dup.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-create-named-workspaces-each-with-its-own-private-files-data.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-favorites-align-with-workspace-and-file-rows-in-the-sidebar.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-local-folder-selection-no-longer-invokes-the-unsafe-native-p.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-made-content-workspaces-independently-expandable-restored-or.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-page-details-now-live-in-a-shared-info-and-comments-rail-dat.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-workspace-database-views-now-control-sidebar-workspace-navig.md +6 -0
- package/corpus/templates/content/changelog/2026-07-18-workspace-navigation-now-aligns-favorites-with-workspace-pag.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-favorites-now-open-as-a-table-and-compact-breadcrumbs-make-w.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-files-databases-now-start-unfiltered-sidebar-rows-exactly-fo.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-sidebar-page-trees-now-open-only-when-expanded-remember-thei.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspace-file-databases-now-use-the-workspace-name-open-as-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspace-navigation-now-stays-stable-on-hover-uses-folder-i.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspace-rows-now-use-folder-icons-and-deleting-a-user-crea.md +6 -0
- package/corpus/templates/content/changelog/2026-07-19-workspaces-can-be-created-without-leaving-the-workspaces-dat.md +6 -0
- package/corpus/templates/content/e2e/global-setup.ts +3 -2
- package/corpus/templates/content/parity/matrix.md +28 -28
- package/corpus/templates/content/parity/matrix.ts +8 -2
- package/corpus/templates/content/server/db/index.ts +1 -0
- package/corpus/templates/content/server/db/schema.ts +10 -0
- package/corpus/templates/content/server/lib/documents.ts +12 -7
- package/corpus/templates/content/server/plugins/db.ts +17 -0
- package/corpus/templates/content/shared/api.ts +9 -0
- package/corpus/templates/content/shared/database-form.ts +11 -2
- package/corpus/templates/content/vite.config.ts +1 -0
- package/dist/client/build-compatibility.d.ts +11 -0
- package/dist/client/build-compatibility.d.ts.map +1 -0
- package/dist/client/build-compatibility.js +56 -0
- package/dist/client/build-compatibility.js.map +1 -0
- package/dist/client/route-chunk-recovery/index.d.ts +1 -0
- package/dist/client/route-chunk-recovery/index.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery/index.js +1 -0
- package/dist/client/route-chunk-recovery/index.js.map +1 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +19 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +2 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/org/context.d.ts +4 -2
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +44 -22
- package/dist/org/context.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +32 -2
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth-plugin.d.ts.map +1 -1
- package/dist/server/auth-plugin.js +9 -5
- package/dist/server/auth-plugin.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +4 -1
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/vite/client.d.ts +6 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +8 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +1 -1
- package/src/client/build-compatibility.ts +77 -0
- package/src/client/route-chunk-recovery/index.ts +1 -0
- package/src/client/use-action.ts +32 -1
- package/src/deploy/build.ts +4 -1
- package/src/org/context.ts +56 -30
- package/src/server/action-routes.ts +52 -2
- package/src/server/auth-plugin.ts +9 -4
- package/src/server/better-auth-instance.ts +5 -1
- package/src/shared/mcp-embed-headers.ts +1 -1
- 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 {
|
|
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:
|
|
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
|
-
{
|
|
203
|
-
const isLast = index ===
|
|
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.
|
|
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?:
|
|
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) =>
|
|
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
|
}
|