@agent-native/core 0.77.8 → 0.77.11
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 +1 -1
- package/corpus/core/CHANGELOG.md +35 -0
- package/corpus/core/package.json +3 -3
- package/corpus/core/src/a2a/task-store.ts +25 -3
- package/corpus/core/src/agent/harness/store.ts +89 -55
- package/corpus/core/src/agent/observational-memory/store.ts +40 -14
- package/corpus/core/src/agent/run-store.ts +116 -59
- package/corpus/core/src/application-state/store.ts +36 -2
- package/corpus/core/src/audit/store.ts +37 -6
- package/corpus/core/src/browser-sessions/store.ts +31 -12
- package/corpus/core/src/chat-threads/store.ts +67 -3
- package/corpus/core/src/checkpoints/store.ts +14 -3
- package/corpus/core/src/cli/create.ts +9 -0
- package/corpus/core/src/collab/awareness.ts +12 -9
- package/corpus/core/src/collab/client.ts +4 -2
- package/corpus/core/src/collab/storage.ts +20 -2
- package/corpus/core/src/db/ddl-guard.ts +112 -0
- package/corpus/core/src/extensions/store.ts +76 -3
- package/corpus/core/src/integrations/a2a-continuations-store.ts +69 -26
- package/corpus/core/src/integrations/config-store.ts +19 -18
- package/corpus/core/src/integrations/pending-tasks-store.ts +40 -16
- package/corpus/core/src/integrations/remote-commands-store.ts +37 -23
- package/corpus/core/src/integrations/remote-devices-store.ts +64 -20
- package/corpus/core/src/integrations/remote-push-store.ts +75 -35
- package/corpus/core/src/integrations/remote-run-events-store.ts +38 -12
- package/corpus/core/src/integrations/thread-mapping-store.ts +11 -2
- package/corpus/core/src/mcp/connect-store.ts +53 -16
- package/corpus/core/src/mcp/oauth-store.ts +32 -7
- package/corpus/core/src/notifications/store.ts +20 -4
- package/corpus/core/src/oauth-tokens/store.ts +45 -2
- package/corpus/core/src/observability/store.ts +154 -47
- package/corpus/core/src/progress/store.ts +36 -21
- package/corpus/core/src/provider-api/corpus-jobs-store.ts +25 -5
- package/corpus/core/src/provider-api/custom-registry.ts +15 -4
- package/corpus/core/src/provider-api/quota-governor.ts +15 -3
- package/corpus/core/src/provider-api/staged-datasets-store.ts +22 -5
- package/corpus/core/src/resources/store.ts +66 -31
- package/corpus/core/src/secrets/storage.ts +18 -22
- package/corpus/core/src/server/agent-teams-run-queue.ts +22 -10
- package/corpus/core/src/server/auth.ts +22 -4
- package/corpus/core/src/server/better-auth-instance.ts +49 -15
- package/corpus/core/src/server/embed-session.ts +19 -4
- package/corpus/core/src/server/identity-sso-store.ts +40 -11
- package/corpus/core/src/server/recap-image-store.ts +28 -9
- package/corpus/core/src/settings/store.ts +14 -19
- package/corpus/core/src/usage/store.ts +51 -16
- package/corpus/core/src/workspace-connections/store.ts +200 -22
- package/corpus/templates/calendar/changelog/2026-06-25-booking-link-previews-now-show-the-content-directly-on-the-g.md +6 -0
- package/corpus/templates/calendar/server/lib/booking-og-image.ts +0 -2
- package/corpus/templates/clips/chrome-extension/package.json +1 -1
- package/corpus/templates/content/actions/list-trashed-content-databases.ts +36 -2
- package/corpus/templates/content/actions/move-document.ts +79 -33
- package/corpus/templates/content/actions/restore-content-database.ts +40 -3
- package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +84 -2
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +177 -49
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +393 -219
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +632 -467
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +114 -14
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +56 -15
- package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +6 -5
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +12 -4
- package/corpus/templates/content/app/global.css +9 -0
- package/corpus/templates/content/app/hooks/use-create-page.ts +36 -7
- package/corpus/templates/content/app/i18n-data.ts +140 -10
- package/corpus/templates/content/changelog/2026-06-25-comment-cards-now-track-their-highlighted-text-while-scrolli.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-comments-now-scroll-with-the-document-and-stay-below-the-pag.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-creating-a-database-from-the-slash-menu-no-longer-leaves-sta.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-sidebar-hover-controls-no-longer-leave-a-lingering-fade-when.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-sidebar-page-actions-are-now-easier-to-see-when-hovering-ina.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-text-selections-in-the-editor-no-longer-show-white-gaps-when.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-the-editor-toolbar-now-has-a-one-click-page-link-copy-button.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-the-editor-toolbar-now-shows-page-breadcrumbs-and-the-latest.md +6 -0
- package/corpus/templates/content/changelog/2026-06-25-the-page-command-now-leaves-a-notion-style-page-reference-an.md +6 -0
- package/corpus/templates/content/shared/nfm.ts +16 -0
- package/corpus/templates/forms/changelog/2026-06-25-form-previews-now-show-the-content-directly-on-the-grid-back.md +6 -0
- package/corpus/templates/forms/server/lib/form-og-image.ts +0 -2
- package/corpus/templates/plan/app/global.css +6 -11
- package/corpus/templates/plan/app/pages/PlansPage.tsx +12 -10
- package/corpus/templates/plan/changelog/2026-06-25-plan-access-request-pages-stay-visible-during-background-ref.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-25-plan-documents-keep-their-full-reading-width-below-1200px-an.md +6 -0
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +19 -3
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/agent/harness/store.d.ts.map +1 -1
- package/dist/agent/harness/store.js +63 -34
- package/dist/agent/harness/store.js.map +1 -1
- package/dist/agent/observational-memory/store.d.ts.map +1 -1
- package/dist/agent/observational-memory/store.js +30 -8
- package/dist/agent/observational-memory/store.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +103 -46
- package/dist/agent/run-store.js.map +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +28 -2
- package/dist/application-state/store.js.map +1 -1
- package/dist/audit/store.d.ts.map +1 -1
- package/dist/audit/store.js +18 -3
- package/dist/audit/store.js.map +1 -1
- package/dist/browser-sessions/store.d.ts.map +1 -1
- package/dist/browser-sessions/store.js +22 -7
- package/dist/browser-sessions/store.js.map +1 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +51 -3
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/store.d.ts.map +1 -1
- package/dist/checkpoints/store.js +12 -3
- package/dist/checkpoints/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +9 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/collab/awareness.d.ts +1 -1
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/awareness.js +12 -8
- package/dist/collab/awareness.js.map +1 -1
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +4 -3
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/storage.d.ts.map +1 -1
- package/dist/collab/storage.js +14 -2
- package/dist/collab/storage.js.map +1 -1
- package/dist/db/ddl-guard.d.ts +63 -0
- package/dist/db/ddl-guard.d.ts.map +1 -1
- package/dist/db/ddl-guard.js +85 -0
- package/dist/db/ddl-guard.js.map +1 -1
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +32 -3
- package/dist/extensions/store.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +44 -24
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/config-store.d.ts.map +1 -1
- package/dist/integrations/config-store.js +17 -11
- package/dist/integrations/config-store.js.map +1 -1
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-store.js +24 -16
- package/dist/integrations/pending-tasks-store.js.map +1 -1
- package/dist/integrations/remote-commands-store.d.ts.map +1 -1
- package/dist/integrations/remote-commands-store.js +29 -21
- package/dist/integrations/remote-commands-store.js.map +1 -1
- package/dist/integrations/remote-devices-store.d.ts.map +1 -1
- package/dist/integrations/remote-devices-store.js +33 -18
- package/dist/integrations/remote-devices-store.js.map +1 -1
- package/dist/integrations/remote-push-store.d.ts.map +1 -1
- package/dist/integrations/remote-push-store.js +53 -31
- package/dist/integrations/remote-push-store.js.map +1 -1
- package/dist/integrations/remote-run-events-store.d.ts.map +1 -1
- package/dist/integrations/remote-run-events-store.js +26 -10
- package/dist/integrations/remote-run-events-store.js.map +1 -1
- package/dist/integrations/thread-mapping-store.d.ts.map +1 -1
- package/dist/integrations/thread-mapping-store.js +10 -2
- package/dist/integrations/thread-mapping-store.js.map +1 -1
- package/dist/mcp/connect-store.d.ts.map +1 -1
- package/dist/mcp/connect-store.js +34 -16
- package/dist/mcp/connect-store.js.map +1 -1
- package/dist/mcp/oauth-store.d.ts.map +1 -1
- package/dist/mcp/oauth-store.js +22 -7
- package/dist/mcp/oauth-store.js.map +1 -1
- package/dist/notifications/store.d.ts.map +1 -1
- package/dist/notifications/store.js +15 -3
- package/dist/notifications/store.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +33 -2
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +72 -29
- package/dist/observability/store.js.map +1 -1
- package/dist/progress/store.d.ts.map +1 -1
- package/dist/progress/store.js +31 -16
- package/dist/progress/store.js.map +1 -1
- package/dist/provider-api/corpus-jobs-store.d.ts.map +1 -1
- package/dist/provider-api/corpus-jobs-store.js +16 -5
- package/dist/provider-api/corpus-jobs-store.js.map +1 -1
- package/dist/provider-api/custom-registry.d.ts.map +1 -1
- package/dist/provider-api/custom-registry.js +14 -4
- package/dist/provider-api/custom-registry.js.map +1 -1
- package/dist/provider-api/quota-governor.d.ts.map +1 -1
- package/dist/provider-api/quota-governor.js +12 -3
- package/dist/provider-api/quota-governor.js.map +1 -1
- package/dist/provider-api/staged-datasets-store.d.ts.map +1 -1
- package/dist/provider-api/staged-datasets-store.js +16 -5
- package/dist/provider-api/staged-datasets-store.js.map +1 -1
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +56 -25
- package/dist/resources/store.js.map +1 -1
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +10 -14
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/agent-teams-run-queue.d.ts.map +1 -1
- package/dist/server/agent-teams-run-queue.js +15 -4
- package/dist/server/agent-teams-run-queue.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +16 -2
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +55 -21
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/embed-session.d.ts.map +1 -1
- package/dist/server/embed-session.js +15 -4
- package/dist/server/embed-session.js.map +1 -1
- package/dist/server/identity-sso-store.d.ts.map +1 -1
- package/dist/server/identity-sso-store.js +30 -11
- package/dist/server/identity-sso-store.js.map +1 -1
- package/dist/server/recap-image-store.d.ts.map +1 -1
- package/dist/server/recap-image-store.js +21 -7
- package/dist/server/recap-image-store.js.map +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +11 -13
- package/dist/settings/store.js.map +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +36 -11
- package/dist/usage/store.js.map +1 -1
- package/dist/workspace-connections/store.d.ts.map +1 -1
- package/dist/workspace-connections/store.js +57 -7
- package/dist/workspace-connections/store.js.map +1 -1
- package/package.json +3 -3
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
IconFolderOpen,
|
|
28
28
|
IconPlus,
|
|
29
29
|
IconHistory,
|
|
30
|
+
IconLink,
|
|
30
31
|
IconRefresh,
|
|
31
32
|
IconShare3,
|
|
32
33
|
} from "@tabler/icons-react";
|
|
@@ -152,10 +153,105 @@ function NotionIcon({ className }: { className?: string }) {
|
|
|
152
153
|
);
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
function formatEditedLabel(updatedAt?: string | null) {
|
|
157
|
+
if (!updatedAt) return null;
|
|
158
|
+
const timestamp = new Date(updatedAt).getTime();
|
|
159
|
+
if (!Number.isFinite(timestamp)) return null;
|
|
160
|
+
|
|
161
|
+
const diffMs = Math.max(0, Date.now() - timestamp);
|
|
162
|
+
const minute = 60_000;
|
|
163
|
+
const hour = 60 * minute;
|
|
164
|
+
const day = 24 * hour;
|
|
165
|
+
|
|
166
|
+
if (diffMs < minute) return "Edited just now";
|
|
167
|
+
if (diffMs < hour) {
|
|
168
|
+
const minutes = Math.max(1, Math.round(diffMs / minute));
|
|
169
|
+
return `Edited ${minutes}m ago`;
|
|
170
|
+
}
|
|
171
|
+
if (diffMs < day) {
|
|
172
|
+
const hours = Math.max(1, Math.round(diffMs / hour));
|
|
173
|
+
return `Edited ${hours}h ago`;
|
|
174
|
+
}
|
|
175
|
+
if (diffMs < 7 * day) {
|
|
176
|
+
const days = Math.max(1, Math.round(diffMs / day));
|
|
177
|
+
return `Edited ${days}d ago`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return `Edited ${new Date(updatedAt).toLocaleDateString("en-US", {
|
|
181
|
+
month: "short",
|
|
182
|
+
day: "numeric",
|
|
183
|
+
})}`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function ToolbarBreadcrumb({
|
|
187
|
+
items,
|
|
188
|
+
currentDocumentId,
|
|
189
|
+
ariaLabel,
|
|
190
|
+
untitledLabel,
|
|
191
|
+
onOpen,
|
|
192
|
+
}: {
|
|
193
|
+
items: { id?: string; title: string; icon?: string | null }[];
|
|
194
|
+
currentDocumentId: string;
|
|
195
|
+
ariaLabel: string;
|
|
196
|
+
untitledLabel: string;
|
|
197
|
+
onOpen: (id: string) => void;
|
|
198
|
+
}) {
|
|
199
|
+
return (
|
|
200
|
+
<nav
|
|
201
|
+
aria-label={ariaLabel}
|
|
202
|
+
className="flex min-w-0 flex-1 items-center gap-1 text-sm text-foreground"
|
|
203
|
+
>
|
|
204
|
+
{items.map((item, index) => {
|
|
205
|
+
const isLast = index === items.length - 1;
|
|
206
|
+
const label = item.title.trim() || untitledLabel;
|
|
207
|
+
const content = (
|
|
208
|
+
<>
|
|
209
|
+
{item.icon ? (
|
|
210
|
+
<span className="shrink-0 text-sm leading-none">{item.icon}</span>
|
|
211
|
+
) : null}
|
|
212
|
+
<span className="truncate">{label}</span>
|
|
213
|
+
</>
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<div
|
|
218
|
+
key={`${item.id ?? label}-${index}`}
|
|
219
|
+
className="flex min-w-0 items-center gap-1"
|
|
220
|
+
>
|
|
221
|
+
{item.id && item.id !== currentDocumentId ? (
|
|
222
|
+
<button
|
|
223
|
+
type="button"
|
|
224
|
+
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"
|
|
225
|
+
onClick={() => onOpen(item.id!)}
|
|
226
|
+
>
|
|
227
|
+
{content}
|
|
228
|
+
</button>
|
|
229
|
+
) : (
|
|
230
|
+
<span
|
|
231
|
+
className={cn(
|
|
232
|
+
"flex min-w-0 max-w-56 items-center gap-1 truncate px-1.5 py-1",
|
|
233
|
+
isLast ? "text-foreground" : "text-muted-foreground",
|
|
234
|
+
)}
|
|
235
|
+
>
|
|
236
|
+
{content}
|
|
237
|
+
</span>
|
|
238
|
+
)}
|
|
239
|
+
{!isLast ? (
|
|
240
|
+
<span className="shrink-0 text-muted-foreground/70">/</span>
|
|
241
|
+
) : null}
|
|
242
|
+
</div>
|
|
243
|
+
);
|
|
244
|
+
})}
|
|
245
|
+
</nav>
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
155
249
|
interface DocumentToolbarProps {
|
|
156
250
|
documentId: string;
|
|
157
251
|
documentTitle?: string;
|
|
158
252
|
documentContent?: string;
|
|
253
|
+
breadcrumbItems?: { id?: string; title: string; icon?: string | null }[];
|
|
254
|
+
documentUpdatedAt?: string | null;
|
|
159
255
|
activeUsers?: CollabUser[];
|
|
160
256
|
agentPresent?: boolean;
|
|
161
257
|
agentActive?: boolean;
|
|
@@ -169,6 +265,8 @@ export function DocumentToolbar({
|
|
|
169
265
|
documentId,
|
|
170
266
|
documentTitle,
|
|
171
267
|
documentContent,
|
|
268
|
+
breadcrumbItems = [],
|
|
269
|
+
documentUpdatedAt,
|
|
172
270
|
activeUsers,
|
|
173
271
|
agentPresent,
|
|
174
272
|
agentActive,
|
|
@@ -238,7 +336,13 @@ export function DocumentToolbar({
|
|
|
238
336
|
typeof window === "undefined"
|
|
239
337
|
? `/p/${documentId}`
|
|
240
338
|
: `${window.location.origin}${appPath(`/p/${documentId}`)}`;
|
|
339
|
+
const pageUrl =
|
|
340
|
+
typeof window === "undefined"
|
|
341
|
+
? `/page/${documentId}`
|
|
342
|
+
: `${window.location.origin}${appPath(`/page/${documentId}`)}`;
|
|
343
|
+
const copyPageUrl = isLocalFileDocument ? pageUrl : shareUrl;
|
|
241
344
|
const effectiveHideFromSearch = pendingHideFromSearch ?? hideFromSearch;
|
|
345
|
+
const editedLabel = formatEditedLabel(documentUpdatedAt);
|
|
242
346
|
|
|
243
347
|
const { data: searchResults, isLoading: searchLoading } =
|
|
244
348
|
useSearchNotionPages(debouncedQuery, open && isConnected && !isLinked);
|
|
@@ -320,6 +424,25 @@ export function DocumentToolbar({
|
|
|
320
424
|
toast.success(t("editor.toolbar.copiedAbsolutePath"));
|
|
321
425
|
}, [source, t]);
|
|
322
426
|
|
|
427
|
+
const handleCopyPageLink = useCallback(async () => {
|
|
428
|
+
if (!navigator.clipboard?.writeText) {
|
|
429
|
+
toast.error(t("editor.toolbar.couldNotCopyLink"), {
|
|
430
|
+
description: t("editor.toolbar.clipboardAccessUnavailable"),
|
|
431
|
+
});
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
try {
|
|
436
|
+
await navigator.clipboard.writeText(copyPageUrl);
|
|
437
|
+
toast.success(t("editor.toolbar.copiedPageLink"));
|
|
438
|
+
} catch (error) {
|
|
439
|
+
toast.error(t("editor.toolbar.couldNotCopyLink"), {
|
|
440
|
+
description:
|
|
441
|
+
error instanceof Error ? error.message : t("empty.genericError"),
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}, [copyPageUrl, t]);
|
|
445
|
+
|
|
323
446
|
const handleRevealLocalPath = useCallback(async () => {
|
|
324
447
|
try {
|
|
325
448
|
const result = await revealLinkedLocalSourceFile(source);
|
|
@@ -528,515 +651,557 @@ export function DocumentToolbar({
|
|
|
528
651
|
|
|
529
652
|
return (
|
|
530
653
|
<>
|
|
531
|
-
<div className="
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
654
|
+
<div className="relative z-10 flex h-12 shrink-0 items-center gap-3 bg-background px-4">
|
|
655
|
+
<ToolbarBreadcrumb
|
|
656
|
+
items={
|
|
657
|
+
breadcrumbItems.length
|
|
658
|
+
? breadcrumbItems
|
|
659
|
+
: [{ id: documentId, title: documentTitle || "Untitled" }]
|
|
660
|
+
}
|
|
661
|
+
currentDocumentId={documentId}
|
|
662
|
+
ariaLabel={t("editor.toolbar.pageBreadcrumb")}
|
|
663
|
+
untitledLabel={t("sidebar.untitled")}
|
|
664
|
+
onOpen={(id) => navigate(`/page/${id}`, { flushSync: true })}
|
|
539
665
|
/>
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
disabled={shareLocalFile.isPending}
|
|
546
|
-
onClick={() => void handleShareLocalFile()}
|
|
547
|
-
>
|
|
548
|
-
{shareLocalFile.isPending ? (
|
|
549
|
-
<IconLoader2 className="h-4 w-4 animate-spin" />
|
|
550
|
-
) : (
|
|
551
|
-
<IconShare3 className="h-4 w-4" />
|
|
552
|
-
)}
|
|
553
|
-
<span className="hidden sm:inline">
|
|
554
|
-
{t("editor.toolbar.share")}
|
|
666
|
+
|
|
667
|
+
<div className="ml-auto flex min-w-0 items-center gap-0.5 sm:gap-1">
|
|
668
|
+
{editedLabel ? (
|
|
669
|
+
<span className="hidden shrink-0 px-2 text-sm text-muted-foreground lg:inline">
|
|
670
|
+
{editedLabel}
|
|
555
671
|
</span>
|
|
556
|
-
|
|
557
|
-
) : (
|
|
558
|
-
<>
|
|
559
|
-
<ShareButton
|
|
560
|
-
resourceType="document"
|
|
561
|
-
resourceId={documentId}
|
|
562
|
-
resourceTitle={documentTitle}
|
|
563
|
-
shareUrl={shareUrl}
|
|
564
|
-
defaultOpen={openShareOnLoad}
|
|
565
|
-
onOpenChange={handleDbShareOpenChange}
|
|
566
|
-
visibilityCopy={{
|
|
567
|
-
org: {
|
|
568
|
-
description: effectiveHideFromSearch
|
|
569
|
-
? t("editor.toolbar.orgLinkCanView")
|
|
570
|
-
: t("editor.toolbar.orgCanFindAndView"),
|
|
571
|
-
},
|
|
572
|
-
}}
|
|
573
|
-
hideInSearchControl={{
|
|
574
|
-
checked: effectiveHideFromSearch,
|
|
575
|
-
pending: setDocumentDiscoverability.isPending,
|
|
576
|
-
label: t("editor.toolbar.hideInSearch"),
|
|
577
|
-
description: t("editor.toolbar.hideInSearchDescription"),
|
|
578
|
-
onCheckedChange: handleHideFromSearchChange,
|
|
579
|
-
}}
|
|
580
|
-
variant="compact"
|
|
581
|
-
/>
|
|
672
|
+
) : null}
|
|
582
673
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
674
|
+
{/* Presence — shared PresenceBar (agent + collaborator avatars) */}
|
|
675
|
+
<PresenceBar
|
|
676
|
+
activeUsers={activeUsers ?? []}
|
|
677
|
+
agentPresent={agentPresent}
|
|
678
|
+
agentActive={agentActive}
|
|
679
|
+
currentUserEmail={currentUserEmail}
|
|
680
|
+
className="mr-1"
|
|
681
|
+
/>
|
|
682
|
+
{isLocalFileDocument ? (
|
|
683
|
+
<Button
|
|
684
|
+
size="sm"
|
|
685
|
+
variant="outline"
|
|
686
|
+
className="h-9 gap-1.5 rounded-lg px-3"
|
|
687
|
+
disabled={shareLocalFile.isPending}
|
|
688
|
+
onClick={() => void handleShareLocalFile()}
|
|
689
|
+
>
|
|
690
|
+
{shareLocalFile.isPending ? (
|
|
691
|
+
<IconLoader2 className="h-4 w-4 animate-spin" />
|
|
692
|
+
) : (
|
|
693
|
+
<IconShare3 className="h-4 w-4" />
|
|
694
|
+
)}
|
|
695
|
+
<span className="hidden sm:inline">
|
|
696
|
+
{t("editor.toolbar.share")}
|
|
697
|
+
</span>
|
|
698
|
+
</Button>
|
|
699
|
+
) : (
|
|
700
|
+
<>
|
|
701
|
+
<ShareButton
|
|
702
|
+
resourceType="document"
|
|
703
|
+
resourceId={documentId}
|
|
704
|
+
resourceTitle={documentTitle}
|
|
705
|
+
shareUrl={shareUrl}
|
|
706
|
+
defaultOpen={openShareOnLoad}
|
|
707
|
+
onOpenChange={handleDbShareOpenChange}
|
|
708
|
+
visibilityCopy={{
|
|
709
|
+
org: {
|
|
710
|
+
description: effectiveHideFromSearch
|
|
711
|
+
? t("editor.toolbar.orgLinkCanView")
|
|
712
|
+
: t("editor.toolbar.orgCanFindAndView"),
|
|
713
|
+
},
|
|
714
|
+
}}
|
|
715
|
+
hideInSearchControl={{
|
|
716
|
+
checked: effectiveHideFromSearch,
|
|
717
|
+
pending: setDocumentDiscoverability.isPending,
|
|
718
|
+
label: t("editor.toolbar.hideInSearch"),
|
|
719
|
+
description: t("editor.toolbar.hideInSearchDescription"),
|
|
720
|
+
onCheckedChange: handleHideFromSearchChange,
|
|
721
|
+
}}
|
|
722
|
+
variant="compact"
|
|
723
|
+
/>
|
|
724
|
+
|
|
725
|
+
<VersionHistoryPanel
|
|
726
|
+
documentId={documentId}
|
|
727
|
+
open={historyOpen}
|
|
728
|
+
onOpenChange={setHistoryOpen}
|
|
729
|
+
canRestore={canEdit}
|
|
730
|
+
activeUsers={activeUsers}
|
|
731
|
+
/>
|
|
732
|
+
</>
|
|
733
|
+
)}
|
|
592
734
|
|
|
593
|
-
<DropdownMenu modal={false}>
|
|
594
735
|
<Tooltip>
|
|
595
736
|
<TooltipTrigger asChild>
|
|
596
|
-
<
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
</
|
|
737
|
+
<button
|
|
738
|
+
type="button"
|
|
739
|
+
className="flex h-9 w-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"
|
|
740
|
+
aria-label={t("editor.toolbar.copyPageLink")}
|
|
741
|
+
onClick={() => void handleCopyPageLink()}
|
|
742
|
+
>
|
|
743
|
+
<IconLink size={16} />
|
|
744
|
+
</button>
|
|
604
745
|
</TooltipTrigger>
|
|
605
|
-
<TooltipContent>
|
|
606
|
-
{t("editor.toolbar.morePageActions")}
|
|
607
|
-
</TooltipContent>
|
|
746
|
+
<TooltipContent>{t("editor.toolbar.copyPageLink")}</TooltipContent>
|
|
608
747
|
</Tooltip>
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
{t("editor.toolbar.copyRelativePath")}
|
|
629
|
-
</DropdownMenuItem>
|
|
630
|
-
<DropdownMenuItem
|
|
631
|
-
onSelect={() => void handleCopyLocalAbsolutePath()}
|
|
632
|
-
>
|
|
633
|
-
<IconCopy className="me-2 h-4 w-4" />
|
|
634
|
-
{t("editor.toolbar.copyAbsolutePath")}
|
|
635
|
-
</DropdownMenuItem>
|
|
636
|
-
</DropdownMenuGroup>
|
|
637
|
-
) : (
|
|
638
|
-
<>
|
|
748
|
+
|
|
749
|
+
<DropdownMenu modal={false}>
|
|
750
|
+
<Tooltip>
|
|
751
|
+
<TooltipTrigger asChild>
|
|
752
|
+
<DropdownMenuTrigger asChild>
|
|
753
|
+
<button
|
|
754
|
+
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
755
|
+
aria-label={t("editor.toolbar.morePageActions")}
|
|
756
|
+
>
|
|
757
|
+
<IconDotsVertical size={16} />
|
|
758
|
+
</button>
|
|
759
|
+
</DropdownMenuTrigger>
|
|
760
|
+
</TooltipTrigger>
|
|
761
|
+
<TooltipContent>
|
|
762
|
+
{t("editor.toolbar.morePageActions")}
|
|
763
|
+
</TooltipContent>
|
|
764
|
+
</Tooltip>
|
|
765
|
+
<DropdownMenuContent align="end" className="w-60">
|
|
766
|
+
{isLocalFileDocument ? (
|
|
639
767
|
<DropdownMenuGroup>
|
|
640
|
-
<
|
|
641
|
-
|
|
642
|
-
|
|
768
|
+
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
|
769
|
+
{t("editor.toolbar.localFile")}
|
|
770
|
+
</DropdownMenuLabel>
|
|
771
|
+
<DropdownMenuItem disabled className="min-w-0">
|
|
772
|
+
<IconFileText className="me-2 h-4 w-4 shrink-0" />
|
|
773
|
+
<span className="truncate">{source?.path}</span>
|
|
774
|
+
</DropdownMenuItem>
|
|
775
|
+
<DropdownMenuItem
|
|
776
|
+
disabled={revealLocalSource.isPending}
|
|
777
|
+
onSelect={() => void handleRevealLocalPath()}
|
|
778
|
+
>
|
|
779
|
+
<IconFolderOpen className="me-2 h-4 w-4" />
|
|
780
|
+
{t("editor.toolbar.revealInFinder")}
|
|
781
|
+
</DropdownMenuItem>
|
|
782
|
+
<DropdownMenuItem onSelect={handleCopyLocalRelativePath}>
|
|
783
|
+
<IconCopy className="me-2 h-4 w-4" />
|
|
784
|
+
{t("editor.toolbar.copyRelativePath")}
|
|
785
|
+
</DropdownMenuItem>
|
|
786
|
+
<DropdownMenuItem
|
|
787
|
+
onSelect={() => void handleCopyLocalAbsolutePath()}
|
|
788
|
+
>
|
|
789
|
+
<IconCopy className="me-2 h-4 w-4" />
|
|
790
|
+
{t("editor.toolbar.copyAbsolutePath")}
|
|
643
791
|
</DropdownMenuItem>
|
|
644
792
|
</DropdownMenuGroup>
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
<
|
|
648
|
-
{
|
|
649
|
-
<
|
|
650
|
-
|
|
651
|
-
<IconDownload className="me-2 h-4 w-4" />
|
|
652
|
-
)}
|
|
653
|
-
{t("editor.toolbar.export")}
|
|
654
|
-
</DropdownMenuSubTrigger>
|
|
655
|
-
<DropdownMenuSubContent className="w-44">
|
|
656
|
-
<DropdownMenuItem
|
|
657
|
-
disabled={exportDocument.isPending}
|
|
658
|
-
onSelect={() => void handleExport("pdf")}
|
|
659
|
-
>
|
|
660
|
-
<IconFileTypePdf className="me-2 h-4 w-4" />
|
|
661
|
-
PDF
|
|
793
|
+
) : (
|
|
794
|
+
<>
|
|
795
|
+
<DropdownMenuGroup>
|
|
796
|
+
<DropdownMenuItem onSelect={() => setHistoryOpen(true)}>
|
|
797
|
+
<IconHistory className="me-2 h-4 w-4" />
|
|
798
|
+
{t("editor.toolbar.versionHistory")}
|
|
662
799
|
</DropdownMenuItem>
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
>
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
disabled={exportDocument.isPending}
|
|
672
|
-
onSelect={() => void handleExport("html")}
|
|
673
|
-
>
|
|
674
|
-
<IconFileTypeHtml className="me-2 h-4 w-4" />
|
|
675
|
-
HTML
|
|
676
|
-
</DropdownMenuItem>
|
|
677
|
-
</DropdownMenuSubContent>
|
|
678
|
-
</DropdownMenuSub>
|
|
679
|
-
</>
|
|
680
|
-
)}
|
|
681
|
-
<DropdownMenuSeparator />
|
|
682
|
-
<DropdownMenuGroup>
|
|
683
|
-
{canEdit && !isLocalFileDocument ? (
|
|
684
|
-
<Popover open={open} onOpenChange={setOpen}>
|
|
685
|
-
<PopoverTrigger asChild>
|
|
686
|
-
<button
|
|
687
|
-
type="button"
|
|
688
|
-
className={cn(
|
|
689
|
-
"flex w-full items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground",
|
|
690
|
-
isLinked ? "text-foreground" : "text-muted-foreground",
|
|
800
|
+
</DropdownMenuGroup>
|
|
801
|
+
<DropdownMenuSeparator />
|
|
802
|
+
<DropdownMenuSub>
|
|
803
|
+
<DropdownMenuSubTrigger disabled={exportDocument.isPending}>
|
|
804
|
+
{exportDocument.isPending ? (
|
|
805
|
+
<IconLoader2 className="me-2 h-4 w-4 animate-spin" />
|
|
806
|
+
) : (
|
|
807
|
+
<IconDownload className="me-2 h-4 w-4" />
|
|
691
808
|
)}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
809
|
+
{t("editor.toolbar.export")}
|
|
810
|
+
</DropdownMenuSubTrigger>
|
|
811
|
+
<DropdownMenuSubContent className="w-44">
|
|
812
|
+
<DropdownMenuItem
|
|
813
|
+
disabled={exportDocument.isPending}
|
|
814
|
+
onSelect={() => void handleExport("pdf")}
|
|
815
|
+
>
|
|
816
|
+
<IconFileTypePdf className="me-2 h-4 w-4" />
|
|
817
|
+
PDF
|
|
818
|
+
</DropdownMenuItem>
|
|
819
|
+
<DropdownMenuItem
|
|
820
|
+
disabled={exportDocument.isPending}
|
|
821
|
+
onSelect={() => void handleExport("markdown")}
|
|
822
|
+
>
|
|
823
|
+
<IconMarkdown className="me-2 h-4 w-4" />
|
|
824
|
+
Markdown
|
|
825
|
+
</DropdownMenuItem>
|
|
826
|
+
<DropdownMenuItem
|
|
827
|
+
disabled={exportDocument.isPending}
|
|
828
|
+
onSelect={() => void handleExport("html")}
|
|
829
|
+
>
|
|
830
|
+
<IconFileTypeHtml className="me-2 h-4 w-4" />
|
|
831
|
+
HTML
|
|
832
|
+
</DropdownMenuItem>
|
|
833
|
+
</DropdownMenuSubContent>
|
|
834
|
+
</DropdownMenuSub>
|
|
835
|
+
</>
|
|
836
|
+
)}
|
|
837
|
+
<DropdownMenuSeparator />
|
|
838
|
+
<DropdownMenuGroup>
|
|
839
|
+
{canEdit && !isLocalFileDocument ? (
|
|
840
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
841
|
+
<PopoverTrigger asChild>
|
|
842
|
+
<button
|
|
843
|
+
type="button"
|
|
844
|
+
className={cn(
|
|
845
|
+
"flex w-full items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground",
|
|
846
|
+
isLinked
|
|
847
|
+
? "text-foreground"
|
|
848
|
+
: "text-muted-foreground",
|
|
709
849
|
)}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
850
|
+
>
|
|
851
|
+
<span className="me-2 flex h-4 w-4 shrink-0 items-center justify-center">
|
|
852
|
+
{hasConflict ? (
|
|
853
|
+
<span className="relative">
|
|
854
|
+
<NotionIcon className="h-4 w-4" />
|
|
855
|
+
<IconAlertTriangle
|
|
856
|
+
size={8}
|
|
857
|
+
className="absolute -end-1 -top-1 text-amber-500"
|
|
858
|
+
/>
|
|
859
|
+
</span>
|
|
860
|
+
) : isLinked && autoSync ? (
|
|
861
|
+
<span className="relative">
|
|
862
|
+
<NotionIcon className="h-4 w-4" />
|
|
863
|
+
<span className="absolute -end-0.5 -top-0.5 h-2 w-2 rounded-full bg-emerald-500" />
|
|
864
|
+
</span>
|
|
865
|
+
) : (
|
|
866
|
+
<NotionIcon className="h-4 w-4" />
|
|
867
|
+
)}
|
|
868
|
+
</span>
|
|
869
|
+
<span className="min-w-0 flex-1 truncate text-start">
|
|
870
|
+
{isLinked
|
|
871
|
+
? t("editor.toolbar.notionSync")
|
|
872
|
+
: isConnected
|
|
873
|
+
? t("editor.toolbar.linkToNotion")
|
|
874
|
+
: t("editor.toolbar.connectNotion")}
|
|
875
|
+
</span>
|
|
876
|
+
</button>
|
|
877
|
+
</PopoverTrigger>
|
|
720
878
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
879
|
+
<PopoverContent
|
|
880
|
+
side="left"
|
|
881
|
+
align="start"
|
|
882
|
+
sideOffset={8}
|
|
883
|
+
className="w-80 p-0"
|
|
884
|
+
onOpenAutoFocus={(e) => e.preventDefault()}
|
|
885
|
+
>
|
|
886
|
+
{!isConnected ? (
|
|
887
|
+
/* ─── Not connected ─── */
|
|
888
|
+
<div className="p-4">
|
|
889
|
+
<div className="flex items-center gap-2 mb-2">
|
|
890
|
+
<NotionIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
891
|
+
<p className="text-sm font-medium">
|
|
892
|
+
{t("editor.toolbar.connectNotion")}
|
|
893
|
+
</p>
|
|
894
|
+
</div>
|
|
895
|
+
<p className="text-xs text-muted-foreground mb-3">
|
|
896
|
+
{t("editor.toolbar.setUpNotionToSync")}
|
|
735
897
|
</p>
|
|
898
|
+
<Button
|
|
899
|
+
size="sm"
|
|
900
|
+
className="w-full"
|
|
901
|
+
onClick={handleSetup}
|
|
902
|
+
>
|
|
903
|
+
{t("editor.toolbar.setUpNotion")}
|
|
904
|
+
</Button>
|
|
736
905
|
</div>
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
{t("editor.toolbar.setUpNotion")}
|
|
746
|
-
</Button>
|
|
747
|
-
</div>
|
|
748
|
-
) : isLinked ? (
|
|
749
|
-
/* ─── Linked — show sync actions ─── */
|
|
750
|
-
<div>
|
|
751
|
-
<div className="px-4 py-3 border-b border-border">
|
|
752
|
-
<div className="flex items-center gap-2">
|
|
753
|
-
<NotionIcon className="h-3.5 w-3.5 shrink-0" />
|
|
754
|
-
<span className="text-xs font-medium truncate">
|
|
755
|
-
{t("editor.toolbar.linkedToNotion")}
|
|
756
|
-
</span>
|
|
757
|
-
{autoSync && (
|
|
758
|
-
<span className="inline-flex items-center gap-1 rounded-full bg-emerald-500/15 px-1.5 py-0.5 text-[10px] font-medium text-emerald-700 dark:text-emerald-300">
|
|
759
|
-
<IconRefresh size={9} />
|
|
760
|
-
{t("editor.toolbar.auto")}
|
|
906
|
+
) : isLinked ? (
|
|
907
|
+
/* ─── Linked — show sync actions ─── */
|
|
908
|
+
<div>
|
|
909
|
+
<div className="px-4 py-3 border-b border-border">
|
|
910
|
+
<div className="flex items-center gap-2">
|
|
911
|
+
<NotionIcon className="h-3.5 w-3.5 shrink-0" />
|
|
912
|
+
<span className="text-xs font-medium truncate">
|
|
913
|
+
{t("editor.toolbar.linkedToNotion")}
|
|
761
914
|
</span>
|
|
915
|
+
{autoSync && (
|
|
916
|
+
<span className="inline-flex items-center gap-1 rounded-full bg-emerald-500/15 px-1.5 py-0.5 text-[10px] font-medium text-emerald-700 dark:text-emerald-300">
|
|
917
|
+
<IconRefresh size={9} />
|
|
918
|
+
{t("editor.toolbar.auto")}
|
|
919
|
+
</span>
|
|
920
|
+
)}
|
|
921
|
+
</div>
|
|
922
|
+
{syncStatus?.lastSyncedAt && (
|
|
923
|
+
<p className="mt-1 text-[10px] text-muted-foreground">
|
|
924
|
+
{t("editor.toolbar.lastSynced")}{" "}
|
|
925
|
+
{new Date(
|
|
926
|
+
syncStatus.lastSyncedAt,
|
|
927
|
+
).toLocaleString()}
|
|
928
|
+
</p>
|
|
762
929
|
)}
|
|
930
|
+
{syncStatus?.lastError && (
|
|
931
|
+
<p className="mt-1 text-[10px] text-destructive">
|
|
932
|
+
{syncStatus.lastError}
|
|
933
|
+
</p>
|
|
934
|
+
)}
|
|
935
|
+
{syncStatus?.warnings?.length ? (
|
|
936
|
+
<div className="mt-1.5 space-y-1">
|
|
937
|
+
{syncStatus.warnings
|
|
938
|
+
.slice(0, 3)
|
|
939
|
+
.map((warning, index) => (
|
|
940
|
+
<p
|
|
941
|
+
key={`${warning}-${index}`}
|
|
942
|
+
className="text-[10px] text-muted-foreground"
|
|
943
|
+
>
|
|
944
|
+
{warning}
|
|
945
|
+
</p>
|
|
946
|
+
))}
|
|
947
|
+
</div>
|
|
948
|
+
) : null}
|
|
763
949
|
</div>
|
|
764
|
-
{syncStatus?.lastSyncedAt && (
|
|
765
|
-
<p className="mt-1 text-[10px] text-muted-foreground">
|
|
766
|
-
{t("editor.toolbar.lastSynced")}{" "}
|
|
767
|
-
{new Date(
|
|
768
|
-
syncStatus.lastSyncedAt,
|
|
769
|
-
).toLocaleString()}
|
|
770
|
-
</p>
|
|
771
|
-
)}
|
|
772
|
-
{syncStatus?.lastError && (
|
|
773
|
-
<p className="mt-1 text-[10px] text-destructive">
|
|
774
|
-
{syncStatus.lastError}
|
|
775
|
-
</p>
|
|
776
|
-
)}
|
|
777
|
-
{syncStatus?.warnings?.length ? (
|
|
778
|
-
<div className="mt-1.5 space-y-1">
|
|
779
|
-
{syncStatus.warnings
|
|
780
|
-
.slice(0, 3)
|
|
781
|
-
.map((warning, index) => (
|
|
782
|
-
<p
|
|
783
|
-
key={`${warning}-${index}`}
|
|
784
|
-
className="text-[10px] text-muted-foreground"
|
|
785
|
-
>
|
|
786
|
-
{warning}
|
|
787
|
-
</p>
|
|
788
|
-
))}
|
|
789
|
-
</div>
|
|
790
|
-
) : null}
|
|
791
|
-
</div>
|
|
792
950
|
|
|
793
|
-
|
|
951
|
+
{/* Conflict is shown via NotionConflictBanner above the title */}
|
|
794
952
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
>
|
|
800
|
-
<IconRefresh
|
|
801
|
-
size={12}
|
|
802
|
-
className={
|
|
803
|
-
autoSync
|
|
804
|
-
? "text-emerald-500"
|
|
805
|
-
: "text-muted-foreground"
|
|
806
|
-
}
|
|
807
|
-
/>
|
|
808
|
-
<span
|
|
809
|
-
className={
|
|
810
|
-
autoSync
|
|
811
|
-
? "text-foreground font-medium"
|
|
812
|
-
: "text-muted-foreground"
|
|
813
|
-
}
|
|
814
|
-
>
|
|
815
|
-
{t("editor.toolbar.autoSync")}
|
|
816
|
-
</span>
|
|
817
|
-
<span
|
|
818
|
-
className={cn(
|
|
819
|
-
"ml-auto h-4 w-7 rounded-full relative",
|
|
820
|
-
autoSync
|
|
821
|
-
? "bg-emerald-500"
|
|
822
|
-
: "bg-muted-foreground/30",
|
|
823
|
-
)}
|
|
953
|
+
<div className="p-1.5">
|
|
954
|
+
<button
|
|
955
|
+
onClick={() => setAutoSync(!autoSync)}
|
|
956
|
+
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs hover:bg-accent rounded-md"
|
|
824
957
|
>
|
|
958
|
+
<IconRefresh
|
|
959
|
+
size={12}
|
|
960
|
+
className={
|
|
961
|
+
autoSync
|
|
962
|
+
? "text-emerald-500"
|
|
963
|
+
: "text-muted-foreground"
|
|
964
|
+
}
|
|
965
|
+
/>
|
|
966
|
+
<span
|
|
967
|
+
className={
|
|
968
|
+
autoSync
|
|
969
|
+
? "text-foreground font-medium"
|
|
970
|
+
: "text-muted-foreground"
|
|
971
|
+
}
|
|
972
|
+
>
|
|
973
|
+
{t("editor.toolbar.autoSync")}
|
|
974
|
+
</span>
|
|
825
975
|
<span
|
|
826
976
|
className={cn(
|
|
827
|
-
"
|
|
828
|
-
autoSync
|
|
977
|
+
"ml-auto h-4 w-7 rounded-full relative",
|
|
978
|
+
autoSync
|
|
979
|
+
? "bg-emerald-500"
|
|
980
|
+
: "bg-muted-foreground/30",
|
|
829
981
|
)}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
{t("editor.toolbar.pullFromNotion")}
|
|
844
|
-
</button>
|
|
845
|
-
<button
|
|
846
|
-
onClick={handlePush}
|
|
847
|
-
disabled={isWorking}
|
|
848
|
-
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded-md disabled:opacity-40"
|
|
849
|
-
>
|
|
850
|
-
{pushDocument.isPending ? (
|
|
851
|
-
<IconLoader2 size={12} className="animate-spin" />
|
|
852
|
-
) : (
|
|
853
|
-
<IconArrowBarUp size={12} />
|
|
854
|
-
)}
|
|
855
|
-
{t("editor.toolbar.pushToNotion")}
|
|
856
|
-
</button>
|
|
857
|
-
{syncStatus?.pageUrl && (
|
|
858
|
-
<a
|
|
859
|
-
href={syncStatus.pageUrl}
|
|
860
|
-
target="_blank"
|
|
861
|
-
rel="noopener noreferrer"
|
|
862
|
-
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded-md"
|
|
982
|
+
>
|
|
983
|
+
<span
|
|
984
|
+
className={cn(
|
|
985
|
+
"absolute top-0.5 h-3 w-3 rounded-full bg-white",
|
|
986
|
+
autoSync ? "right-0.5" : "left-0.5",
|
|
987
|
+
)}
|
|
988
|
+
/>
|
|
989
|
+
</span>
|
|
990
|
+
</button>
|
|
991
|
+
<button
|
|
992
|
+
onClick={handlePull}
|
|
993
|
+
disabled={isWorking}
|
|
994
|
+
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded-md disabled:opacity-40"
|
|
863
995
|
>
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-destructive hover:bg-destructive/10 rounded-md disabled:opacity-40"
|
|
872
|
-
>
|
|
873
|
-
<IconLinkOff size={12} />
|
|
874
|
-
{t("editor.toolbar.unlink")}
|
|
875
|
-
</button>
|
|
876
|
-
</div>
|
|
877
|
-
</div>
|
|
878
|
-
) : (
|
|
879
|
-
/* ─── Not linked — show search ─── */
|
|
880
|
-
<div>
|
|
881
|
-
<div className="p-3 pb-2">
|
|
882
|
-
<div className="flex items-center gap-2 mb-2">
|
|
883
|
-
<NotionIcon className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
884
|
-
<span className="text-xs font-medium">
|
|
885
|
-
{t("editor.toolbar.linkToNotionPage")}
|
|
886
|
-
</span>
|
|
887
|
-
</div>
|
|
888
|
-
<div className="relative">
|
|
889
|
-
<IconSearch
|
|
890
|
-
size={13}
|
|
891
|
-
className="absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground"
|
|
892
|
-
/>
|
|
893
|
-
<input
|
|
894
|
-
ref={searchInputRef}
|
|
895
|
-
type="text"
|
|
896
|
-
value={searchQuery}
|
|
897
|
-
onChange={(e) => setSearchQuery(e.target.value)}
|
|
898
|
-
placeholder={t(
|
|
899
|
-
"editor.toolbar.searchNotionPages",
|
|
996
|
+
{pullDocument.isPending ? (
|
|
997
|
+
<IconLoader2
|
|
998
|
+
size={12}
|
|
999
|
+
className="animate-spin"
|
|
1000
|
+
/>
|
|
1001
|
+
) : (
|
|
1002
|
+
<IconArrowBarDown size={12} />
|
|
900
1003
|
)}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
</div>
|
|
904
|
-
</div>
|
|
905
|
-
|
|
906
|
-
<div className="max-h-64 overflow-y-auto border-t border-border">
|
|
907
|
-
{/* Create new page option */}
|
|
908
|
-
<div className="p-1.5 border-b border-border">
|
|
1004
|
+
{t("editor.toolbar.pullFromNotion")}
|
|
1005
|
+
</button>
|
|
909
1006
|
<button
|
|
910
|
-
onClick={
|
|
1007
|
+
onClick={handlePush}
|
|
911
1008
|
disabled={isWorking}
|
|
912
|
-
className="w-full flex items-center gap-2
|
|
1009
|
+
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded-md disabled:opacity-40"
|
|
913
1010
|
>
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1011
|
+
{pushDocument.isPending ? (
|
|
1012
|
+
<IconLoader2
|
|
1013
|
+
size={12}
|
|
1014
|
+
className="animate-spin"
|
|
1015
|
+
/>
|
|
1016
|
+
) : (
|
|
1017
|
+
<IconArrowBarUp size={12} />
|
|
1018
|
+
)}
|
|
1019
|
+
{t("editor.toolbar.pushToNotion")}
|
|
1020
|
+
</button>
|
|
1021
|
+
{syncStatus?.pageUrl && (
|
|
1022
|
+
<a
|
|
1023
|
+
href={syncStatus.pageUrl}
|
|
1024
|
+
target="_blank"
|
|
1025
|
+
rel="noopener noreferrer"
|
|
1026
|
+
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded-md"
|
|
1027
|
+
>
|
|
1028
|
+
<IconExternalLink size={12} />
|
|
1029
|
+
{t("editor.toolbar.openInNotion")}
|
|
1030
|
+
</a>
|
|
1031
|
+
)}
|
|
1032
|
+
<button
|
|
1033
|
+
onClick={handleUnlink}
|
|
1034
|
+
disabled={isWorking}
|
|
1035
|
+
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-destructive hover:bg-destructive/10 rounded-md disabled:opacity-40"
|
|
1036
|
+
>
|
|
1037
|
+
<IconLinkOff size={12} />
|
|
1038
|
+
{t("editor.toolbar.unlink")}
|
|
1039
|
+
</button>
|
|
1040
|
+
</div>
|
|
1041
|
+
</div>
|
|
1042
|
+
) : (
|
|
1043
|
+
/* ─── Not linked — show search ─── */
|
|
1044
|
+
<div>
|
|
1045
|
+
<div className="p-3 pb-2">
|
|
1046
|
+
<div className="flex items-center gap-2 mb-2">
|
|
1047
|
+
<NotionIcon className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
927
1048
|
<span className="text-xs font-medium">
|
|
928
|
-
{t("editor.toolbar.
|
|
1049
|
+
{t("editor.toolbar.linkToNotionPage")}
|
|
929
1050
|
</span>
|
|
930
|
-
</
|
|
1051
|
+
</div>
|
|
1052
|
+
<div className="relative">
|
|
1053
|
+
<IconSearch
|
|
1054
|
+
size={13}
|
|
1055
|
+
className="absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground"
|
|
1056
|
+
/>
|
|
1057
|
+
<input
|
|
1058
|
+
ref={searchInputRef}
|
|
1059
|
+
type="text"
|
|
1060
|
+
value={searchQuery}
|
|
1061
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
1062
|
+
placeholder={t(
|
|
1063
|
+
"editor.toolbar.searchNotionPages",
|
|
1064
|
+
)}
|
|
1065
|
+
className="w-full rounded-md border border-input bg-background pl-8 pr-3 py-1.5 text-xs outline-none focus:ring-1 focus:ring-ring placeholder:text-muted-foreground"
|
|
1066
|
+
/>
|
|
1067
|
+
</div>
|
|
931
1068
|
</div>
|
|
932
1069
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1070
|
+
<div className="max-h-64 overflow-y-auto border-t border-border">
|
|
1071
|
+
{/* Create new page option */}
|
|
1072
|
+
<div className="p-1.5 border-b border-border">
|
|
1073
|
+
<button
|
|
1074
|
+
onClick={() => handleCreateAndLink()}
|
|
1075
|
+
disabled={isWorking}
|
|
1076
|
+
className="w-full flex items-center gap-2.5 px-2.5 py-2 text-left rounded-md hover:bg-accent disabled:opacity-40"
|
|
1077
|
+
>
|
|
1078
|
+
<span className="flex h-5 w-5 shrink-0 items-center justify-center">
|
|
1079
|
+
{createAndLink.isPending ? (
|
|
1080
|
+
<IconLoader2
|
|
1081
|
+
size={14}
|
|
1082
|
+
className="animate-spin text-muted-foreground"
|
|
1083
|
+
/>
|
|
1084
|
+
) : (
|
|
1085
|
+
<IconPlus
|
|
1086
|
+
size={14}
|
|
1087
|
+
className="text-muted-foreground"
|
|
1088
|
+
/>
|
|
1089
|
+
)}
|
|
1090
|
+
</span>
|
|
1091
|
+
<span className="text-xs font-medium">
|
|
1092
|
+
{t("editor.toolbar.createNewPageInNotion")}
|
|
1093
|
+
</span>
|
|
1094
|
+
</button>
|
|
939
1095
|
</div>
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
<
|
|
944
|
-
|
|
945
|
-
className="
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1096
|
+
|
|
1097
|
+
{searchLoading ? (
|
|
1098
|
+
<div className="flex items-center justify-center py-6">
|
|
1099
|
+
<IconLoader2
|
|
1100
|
+
size={16}
|
|
1101
|
+
className="animate-spin text-muted-foreground"
|
|
1102
|
+
/>
|
|
1103
|
+
</div>
|
|
1104
|
+
) : searchResults?.results.length ? (
|
|
1105
|
+
<div className="p-1.5">
|
|
1106
|
+
{searchResults.results.map((page) => (
|
|
1107
|
+
<div
|
|
1108
|
+
key={page.id}
|
|
1109
|
+
className="flex items-center gap-1 rounded-md hover:bg-accent"
|
|
951
1110
|
>
|
|
952
|
-
<
|
|
953
|
-
{
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
page.icon || (
|
|
960
|
-
<IconFileText
|
|
961
|
-
size={14}
|
|
962
|
-
className="text-muted-foreground"
|
|
963
|
-
/>
|
|
964
|
-
)
|
|
965
|
-
)}
|
|
966
|
-
</span>
|
|
967
|
-
<div className="min-w-0 flex-1">
|
|
968
|
-
<p className="text-xs font-medium truncate">
|
|
969
|
-
{page.title}
|
|
970
|
-
</p>
|
|
971
|
-
{linkingPageId === page.id ? (
|
|
972
|
-
<p className="text-[10px] text-muted-foreground">
|
|
973
|
-
{t(
|
|
974
|
-
"editor.toolbar.importingFromNotion",
|
|
975
|
-
)}
|
|
976
|
-
</p>
|
|
977
|
-
) : page.lastEditedTime ? (
|
|
978
|
-
<p className="text-[10px] text-muted-foreground">
|
|
979
|
-
{t("editor.toolbar.edited")}{" "}
|
|
980
|
-
{new Date(
|
|
981
|
-
page.lastEditedTime,
|
|
982
|
-
).toLocaleDateString()}
|
|
983
|
-
</p>
|
|
984
|
-
) : null}
|
|
985
|
-
</div>
|
|
986
|
-
</button>
|
|
987
|
-
<Tooltip>
|
|
988
|
-
<TooltipTrigger asChild>
|
|
989
|
-
<button
|
|
990
|
-
onClick={() =>
|
|
991
|
-
handleCreateAndLink(page.id)
|
|
992
|
-
}
|
|
993
|
-
disabled={isWorking}
|
|
994
|
-
className="mr-1 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background hover:text-foreground disabled:opacity-40"
|
|
995
|
-
aria-label={t(
|
|
996
|
-
"editor.toolbar.createNewPageInside",
|
|
997
|
-
{ title: page.title },
|
|
998
|
-
)}
|
|
999
|
-
>
|
|
1000
|
-
{creatingParentPageId === page.id ? (
|
|
1111
|
+
<button
|
|
1112
|
+
onClick={() => handleLink(page.id)}
|
|
1113
|
+
disabled={isWorking}
|
|
1114
|
+
className="min-w-0 flex-1 flex items-center gap-2.5 px-2.5 py-2 text-left rounded-md disabled:opacity-40"
|
|
1115
|
+
>
|
|
1116
|
+
<span className="flex h-5 w-5 shrink-0 items-center justify-center text-sm">
|
|
1117
|
+
{linkingPageId === page.id ? (
|
|
1001
1118
|
<IconLoader2
|
|
1002
|
-
size={
|
|
1003
|
-
className="animate-spin"
|
|
1119
|
+
size={14}
|
|
1120
|
+
className="animate-spin text-muted-foreground"
|
|
1004
1121
|
/>
|
|
1005
1122
|
) : (
|
|
1006
|
-
|
|
1123
|
+
page.icon || (
|
|
1124
|
+
<IconFileText
|
|
1125
|
+
size={14}
|
|
1126
|
+
className="text-muted-foreground"
|
|
1127
|
+
/>
|
|
1128
|
+
)
|
|
1007
1129
|
)}
|
|
1008
|
-
</
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1130
|
+
</span>
|
|
1131
|
+
<div className="min-w-0 flex-1">
|
|
1132
|
+
<p className="text-xs font-medium truncate">
|
|
1133
|
+
{page.title}
|
|
1134
|
+
</p>
|
|
1135
|
+
{linkingPageId === page.id ? (
|
|
1136
|
+
<p className="text-[10px] text-muted-foreground">
|
|
1137
|
+
{t(
|
|
1138
|
+
"editor.toolbar.importingFromNotion",
|
|
1139
|
+
)}
|
|
1140
|
+
</p>
|
|
1141
|
+
) : page.lastEditedTime ? (
|
|
1142
|
+
<p className="text-[10px] text-muted-foreground">
|
|
1143
|
+
{t("editor.toolbar.edited")}{" "}
|
|
1144
|
+
{new Date(
|
|
1145
|
+
page.lastEditedTime,
|
|
1146
|
+
).toLocaleDateString()}
|
|
1147
|
+
</p>
|
|
1148
|
+
) : null}
|
|
1149
|
+
</div>
|
|
1150
|
+
</button>
|
|
1151
|
+
<Tooltip>
|
|
1152
|
+
<TooltipTrigger asChild>
|
|
1153
|
+
<button
|
|
1154
|
+
onClick={() =>
|
|
1155
|
+
handleCreateAndLink(page.id)
|
|
1156
|
+
}
|
|
1157
|
+
disabled={isWorking}
|
|
1158
|
+
className="mr-1 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background hover:text-foreground disabled:opacity-40"
|
|
1159
|
+
aria-label={t(
|
|
1160
|
+
"editor.toolbar.createNewPageInside",
|
|
1161
|
+
{ title: page.title },
|
|
1162
|
+
)}
|
|
1163
|
+
>
|
|
1164
|
+
{creatingParentPageId === page.id ? (
|
|
1165
|
+
<IconLoader2
|
|
1166
|
+
size={13}
|
|
1167
|
+
className="animate-spin"
|
|
1168
|
+
/>
|
|
1169
|
+
) : (
|
|
1170
|
+
<IconPlus size={13} />
|
|
1171
|
+
)}
|
|
1172
|
+
</button>
|
|
1173
|
+
</TooltipTrigger>
|
|
1174
|
+
<TooltipContent>
|
|
1175
|
+
{t(
|
|
1176
|
+
"editor.toolbar.createNewPageInsideThisPage",
|
|
1177
|
+
)}
|
|
1178
|
+
</TooltipContent>
|
|
1179
|
+
</Tooltip>
|
|
1180
|
+
</div>
|
|
1181
|
+
))}
|
|
1182
|
+
</div>
|
|
1183
|
+
) : debouncedQuery || searchResults ? (
|
|
1184
|
+
<div className="py-6 text-center text-xs text-muted-foreground">
|
|
1185
|
+
{t("editor.toolbar.noPagesFound")}
|
|
1186
|
+
</div>
|
|
1187
|
+
) : null}
|
|
1188
|
+
</div>
|
|
1024
1189
|
</div>
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
</
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
</
|
|
1035
|
-
</
|
|
1036
|
-
</
|
|
1037
|
-
</
|
|
1038
|
-
|
|
1039
|
-
|
|
1190
|
+
)}
|
|
1191
|
+
</PopoverContent>
|
|
1192
|
+
</Popover>
|
|
1193
|
+
) : null}
|
|
1194
|
+
<div className="group relative">
|
|
1195
|
+
<NotificationsBell className="!h-8 !w-full !justify-start !rounded-sm !px-2 !py-1.5 !text-sm hover:!bg-accent hover:!text-accent-foreground focus-visible:!ring-0" />
|
|
1196
|
+
<span className="pointer-events-none absolute start-8 top-1/2 -translate-y-1/2 text-sm text-muted-foreground group-hover:text-accent-foreground">
|
|
1197
|
+
{t("editor.toolbar.notifications")}
|
|
1198
|
+
</span>
|
|
1199
|
+
</div>
|
|
1200
|
+
</DropdownMenuGroup>
|
|
1201
|
+
</DropdownMenuContent>
|
|
1202
|
+
</DropdownMenu>
|
|
1203
|
+
<AgentToggleButton />
|
|
1204
|
+
</div>
|
|
1040
1205
|
</div>
|
|
1041
1206
|
</>
|
|
1042
1207
|
);
|