@agent-native/core 0.102.2 → 0.103.0
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 +6 -0
- package/corpus/core/docs/content/local-file-mode.mdx +99 -489
- package/corpus/core/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
- package/corpus/core/docs/content/locales/ar-SA/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
- package/corpus/core/docs/content/locales/de-DE/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
- package/corpus/core/docs/content/locales/es-ES/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
- package/corpus/core/docs/content/locales/fr-FR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
- package/corpus/core/docs/content/locales/hi-IN/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
- package/corpus/core/docs/content/locales/ja-JP/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
- package/corpus/core/docs/content/locales/ko-KR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
- package/corpus/core/docs/content/locales/pt-BR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
- package/corpus/core/docs/content/locales/zh-CN/template-content.mdx +9 -24
- package/corpus/core/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
- package/corpus/core/docs/content/locales/zh-TW/template-content.mdx +9 -24
- package/corpus/core/docs/content/template-content.mdx +26 -42
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/content-local.ts +86 -18
- package/corpus/core/src/cli/index.ts +2 -2
- package/corpus/core/src/cli/skills-content/content-skill.ts +36 -25
- package/corpus/core/src/cli/skills.ts +47 -13
- package/corpus/core/src/local-artifacts/index.ts +65 -0
- package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +325 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +12 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/assets/app/i18n-data.ts +215 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +19 -479
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +446 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +12 -2
- package/corpus/templates/clips/app/components/player/settings-panel.tsx +30 -12
- package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
- package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +22 -3
- package/corpus/templates/clips/app/i18n/ar-SA.ts +3 -2
- package/corpus/templates/clips/app/i18n/de-DE.ts +4 -2
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -2
- package/corpus/templates/clips/app/i18n/es-ES.ts +4 -2
- package/corpus/templates/clips/app/i18n/fr-FR.ts +3 -2
- package/corpus/templates/clips/app/i18n/hi-IN.ts +3 -2
- package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +3 -2
- package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -2
- package/corpus/templates/clips/app/i18n/zh-CN.ts +3 -2
- package/corpus/templates/clips/app/i18n/zh-TW.ts +3 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +27 -1
- package/corpus/templates/clips/server/lib/share-password.ts +6 -3
- package/corpus/templates/content/.agents/skills/content/SKILL.md +26 -39
- package/corpus/templates/content/AGENTS.md +25 -30
- package/corpus/templates/content/actions/_builder-docs-client.ts +23 -0
- package/corpus/templates/content/actions/_content-database-source-adapters.ts +21 -3
- package/corpus/templates/content/actions/_content-files.ts +338 -0
- package/corpus/templates/content/actions/_content-space-access.ts +135 -0
- package/corpus/templates/content/actions/_content-spaces.ts +640 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +90 -7
- package/corpus/templates/content/actions/_database-utils.ts +7 -1
- package/corpus/templates/content/actions/_local-file-documents.ts +0 -9
- package/corpus/templates/content/actions/_local-folder-source.ts +53 -0
- package/corpus/templates/content/actions/_property-utils.ts +9 -4
- package/corpus/templates/content/actions/add-database-item.ts +108 -65
- package/corpus/templates/content/actions/backfill-content-files.ts +22 -0
- package/corpus/templates/content/actions/connect-local-folder-source.ts +221 -0
- package/corpus/templates/content/actions/create-content-database.ts +129 -3
- package/corpus/templates/content/actions/create-document.ts +65 -55
- package/corpus/templates/content/actions/create-inline-content-database.ts +6 -1
- package/corpus/templates/content/actions/delete-content-database.ts +3 -0
- package/corpus/templates/content/actions/delete-document.ts +7 -11
- package/corpus/templates/content/actions/disconnect-local-folder-source.ts +175 -0
- package/corpus/templates/content/actions/duplicate-database-item.ts +10 -0
- package/corpus/templates/content/actions/duplicate-database-items.ts +13 -0
- package/corpus/templates/content/actions/edit-document.ts +2 -28
- package/corpus/templates/content/actions/ensure-content-spaces.ts +26 -0
- package/corpus/templates/content/actions/export-content-source.ts +47 -9
- package/corpus/templates/content/actions/get-document.ts +0 -14
- package/corpus/templates/content/actions/import-content-source.ts +43 -3
- package/corpus/templates/content/actions/list-content-spaces.ts +103 -0
- package/corpus/templates/content/actions/list-documents.ts +12 -9
- package/corpus/templates/content/actions/move-document.ts +3 -14
- package/corpus/templates/content/actions/pull-document.ts +0 -23
- package/corpus/templates/content/actions/remove-local-file-source.ts +50 -29
- package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +442 -0
- package/corpus/templates/content/actions/reveal-local-source-file.ts +6 -17
- package/corpus/templates/content/actions/search-documents.ts +0 -34
- package/corpus/templates/content/actions/share-local-file-document.ts +25 -1
- package/corpus/templates/content/actions/submit-content-database-form.ts +12 -0
- package/corpus/templates/content/actions/sync-local-folder-source.ts +731 -0
- package/corpus/templates/content/actions/sync-manifest-local-folder-source.ts +123 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +10 -1
- package/corpus/templates/content/actions/update-document.ts +0 -15
- package/corpus/templates/content/actions/view-screen.ts +2 -50
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +76 -62
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +70 -22
- package/corpus/templates/content/app/components/editor/database/grouping.ts +2 -1
- package/corpus/templates/content/app/components/editor/database/settings.tsx +23 -20
- package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +330 -0
- package/corpus/templates/content/app/components/editor/database/types.ts +1 -0
- package/corpus/templates/content/app/components/editor/database/view-config.ts +3 -1
- package/corpus/templates/content/app/components/layout/Layout.tsx +25 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +209 -113
- package/corpus/templates/content/app/components/sidebar/select-content-space.ts +31 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +16 -0
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +39 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +11 -0
- package/corpus/templates/content/app/i18n-data.ts +75 -0
- package/corpus/templates/content/app/routes/_app.local-files.tsx +174 -65
- package/corpus/templates/content/changelog/2026-07-16-content-callouts-can-now-be-reviewed-and-published-to-builder.md +6 -0
- package/corpus/templates/content/changelog/2026-07-16-heading-5-and-heading-6-are-available-from-the-editor-slash-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-16-organize-every-workspace-through-a-customizable-files-databa.md +6 -0
- package/corpus/templates/content/parity/matrix.md +2 -1
- package/corpus/templates/content/parity/matrix.ts +37 -1
- package/corpus/templates/content/scripts/dev-database.mjs +7 -5
- package/corpus/templates/content/server/db/schema.ts +113 -40
- package/corpus/templates/content/server/lib/document-context.ts +15 -1
- package/corpus/templates/content/server/lib/notion-sync.ts +6 -0
- package/corpus/templates/content/server/plugins/db.ts +153 -0
- package/corpus/templates/content/shared/api.ts +17 -3
- package/corpus/templates/content/shared/builder-mdx.ts +163 -16
- package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +59 -0
- package/corpus/templates/design/AGENTS.md +6 -1
- package/corpus/templates/design/actions/create-design-from-template.ts +19 -7
- package/corpus/templates/design/actions/list-design-templates.ts +69 -21
- package/corpus/templates/design/actions/navigate.ts +2 -2
- package/corpus/templates/design/actions/view-screen.ts +15 -2
- package/corpus/templates/design/agent-native.app-skill.json +5 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +281 -56
- package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +14 -2
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -3
- package/corpus/templates/design/app/i18n-data.ts +21 -2
- package/corpus/templates/design/app/i18n-template-feature.ts +218 -10
- package/corpus/templates/design/app/pages/Index.tsx +195 -24
- package/corpus/templates/design/app/pages/Templates.tsx +144 -55
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +12 -1
- package/corpus/templates/design/changelog/2026-07-14-templates-now-appear-in-the-new-design-picker-with-previews-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-15-templates-now-open-immediately-after-copying-even-while-the-.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/mail/AGENTS.md +23 -18
- package/corpus/templates/mail/actions/bulk-archive.ts +32 -28
- package/corpus/templates/mail/actions/mark-read.ts +131 -20
- package/corpus/templates/mail/actions/mark-thread-read.ts +1 -1
- package/corpus/templates/mail/actions/move-email.ts +30 -24
- package/corpus/templates/mail/actions/send-email.ts +73 -68
- package/corpus/templates/mail/changelog/2026-07-15-unread-inbox-cleanup-now-completes-reliably.md +6 -0
- package/corpus/templates/mail/server/handlers/emails.ts +218 -209
- package/corpus/templates/mail/server/lib/bulk-mark-read.ts +30 -0
- package/corpus/templates/mail/server/lib/email-state.ts +198 -113
- package/corpus/templates/mail/server/lib/google-auth.ts +218 -25
- package/corpus/templates/mail/server/lib/jobs.ts +69 -74
- package/corpus/templates/mail/server/lib/local-email-store.ts +265 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
- package/dist/cli/content-local.d.ts +1 -0
- package/dist/cli/content-local.d.ts.map +1 -1
- package/dist/cli/content-local.js +75 -17
- package/dist/cli/content-local.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills-content/content-skill.d.ts +1 -1
- package/dist/cli/skills-content/content-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/content-skill.js +36 -25
- package/dist/cli/skills-content/content-skill.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +47 -14
- package/dist/cli/skills.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/local-artifacts/index.d.ts +10 -0
- package/dist/local-artifacts/index.d.ts.map +1 -1
- package/dist/local-artifacts/index.js +39 -0
- package/dist/local-artifacts/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/docs/content/local-file-mode.mdx +99 -489
- package/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
- package/docs/content/locales/ar-SA/template-content.mdx +10 -24
- package/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
- package/docs/content/locales/de-DE/template-content.mdx +10 -24
- package/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
- package/docs/content/locales/es-ES/template-content.mdx +10 -24
- package/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
- package/docs/content/locales/fr-FR/template-content.mdx +10 -24
- package/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
- package/docs/content/locales/hi-IN/template-content.mdx +10 -24
- package/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
- package/docs/content/locales/ja-JP/template-content.mdx +10 -24
- package/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
- package/docs/content/locales/ko-KR/template-content.mdx +10 -24
- package/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
- package/docs/content/locales/pt-BR/template-content.mdx +10 -24
- package/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
- package/docs/content/locales/zh-CN/template-content.mdx +9 -24
- package/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
- package/docs/content/locales/zh-TW/template-content.mdx +9 -24
- package/docs/content/template-content.mdx +26 -42
- package/package.json +1 -1
- package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +0 -126
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
2
|
+
import {
|
|
3
|
+
Collapsible,
|
|
4
|
+
CollapsibleContent,
|
|
5
|
+
CollapsibleTrigger,
|
|
6
|
+
} from "@agent-native/toolkit/ui/collapsible";
|
|
7
|
+
import { ScrollArea } from "@agent-native/toolkit/ui/scroll-area";
|
|
8
|
+
import type {
|
|
9
|
+
ContentDatabaseItem,
|
|
10
|
+
ContentDatabaseOpenPagesIn,
|
|
11
|
+
ContentDatabasePersonalViewOverrides,
|
|
12
|
+
ContentDatabaseResponse,
|
|
13
|
+
ContentDatabaseViewConfig,
|
|
14
|
+
} from "@shared/api";
|
|
15
|
+
import {
|
|
16
|
+
IconChevronDown,
|
|
17
|
+
IconChevronRight,
|
|
18
|
+
IconFileText,
|
|
19
|
+
IconLoader2,
|
|
20
|
+
} from "@tabler/icons-react";
|
|
21
|
+
import { useEffect, useState, type MouseEvent } from "react";
|
|
22
|
+
import { Link } from "react-router";
|
|
23
|
+
|
|
24
|
+
import { cn } from "@/lib/utils";
|
|
25
|
+
|
|
26
|
+
import { applyDatabaseView } from "./filter-sort";
|
|
27
|
+
import {
|
|
28
|
+
databaseViewGroupingProperty,
|
|
29
|
+
databaseViewItemGroups,
|
|
30
|
+
databaseVisibleGroups,
|
|
31
|
+
} from "./grouping";
|
|
32
|
+
import type { DatabaseBoardGroup } from "./types";
|
|
33
|
+
import {
|
|
34
|
+
activeDatabaseView,
|
|
35
|
+
defaultDatabaseViewConfig,
|
|
36
|
+
normalizeClientDatabaseViewConfig,
|
|
37
|
+
} from "./view-config";
|
|
38
|
+
|
|
39
|
+
function applyPersonalSidebarViewOverrides(
|
|
40
|
+
savedViewConfig: ContentDatabaseViewConfig,
|
|
41
|
+
overrides: ContentDatabasePersonalViewOverrides | null | undefined,
|
|
42
|
+
) {
|
|
43
|
+
const saved = normalizeClientDatabaseViewConfig(savedViewConfig);
|
|
44
|
+
if (!overrides) return saved;
|
|
45
|
+
const overridesByViewId = new Map(
|
|
46
|
+
overrides.views.map((view) => [view.id, view]),
|
|
47
|
+
);
|
|
48
|
+
return normalizeClientDatabaseViewConfig({
|
|
49
|
+
...saved,
|
|
50
|
+
activeViewId: saved.views.some((view) => view.id === overrides.activeViewId)
|
|
51
|
+
? overrides.activeViewId
|
|
52
|
+
: saved.activeViewId,
|
|
53
|
+
views: saved.views.map((view) => {
|
|
54
|
+
const override = overridesByViewId.get(view.id);
|
|
55
|
+
return override
|
|
56
|
+
? {
|
|
57
|
+
...view,
|
|
58
|
+
sorts: override.sorts,
|
|
59
|
+
filters: override.filters,
|
|
60
|
+
filterMode: override.filterMode,
|
|
61
|
+
}
|
|
62
|
+
: view;
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function ContentFilesSidebarView({
|
|
68
|
+
data,
|
|
69
|
+
overrides,
|
|
70
|
+
isLoading,
|
|
71
|
+
labels,
|
|
72
|
+
onSelectView,
|
|
73
|
+
}: {
|
|
74
|
+
data: ContentDatabaseResponse | undefined;
|
|
75
|
+
overrides: ContentDatabasePersonalViewOverrides | null | undefined;
|
|
76
|
+
isLoading: boolean;
|
|
77
|
+
onSelectView?: (viewId: string) => void;
|
|
78
|
+
labels: Omit<
|
|
79
|
+
Parameters<typeof DatabaseSidebarView>[0],
|
|
80
|
+
| "groups"
|
|
81
|
+
| "grouped"
|
|
82
|
+
| "isLoading"
|
|
83
|
+
| "hasActiveConstraints"
|
|
84
|
+
| "openPagesIn"
|
|
85
|
+
| "onClearResultConstraints"
|
|
86
|
+
| "onPreview"
|
|
87
|
+
>;
|
|
88
|
+
}) {
|
|
89
|
+
const viewConfig = applyPersonalSidebarViewOverrides(
|
|
90
|
+
data?.database.viewConfig ?? defaultDatabaseViewConfig(),
|
|
91
|
+
overrides,
|
|
92
|
+
);
|
|
93
|
+
const [selectedViewId, setSelectedViewId] = useState(
|
|
94
|
+
() => viewConfig.activeViewId,
|
|
95
|
+
);
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
setSelectedViewId(viewConfig.activeViewId);
|
|
98
|
+
}, [viewConfig.activeViewId]);
|
|
99
|
+
const activeView =
|
|
100
|
+
viewConfig.views.find((view) => view.id === selectedViewId) ??
|
|
101
|
+
activeDatabaseView(viewConfig);
|
|
102
|
+
const items = data
|
|
103
|
+
? applyDatabaseView(
|
|
104
|
+
data.items,
|
|
105
|
+
data.properties,
|
|
106
|
+
"",
|
|
107
|
+
activeView.filters,
|
|
108
|
+
activeView.sorts,
|
|
109
|
+
activeView.filterMode ?? "and",
|
|
110
|
+
)
|
|
111
|
+
: [];
|
|
112
|
+
const groups = databaseVisibleGroups(
|
|
113
|
+
databaseViewItemGroups(
|
|
114
|
+
items,
|
|
115
|
+
data?.properties ?? [],
|
|
116
|
+
activeView.groupByPropertyId,
|
|
117
|
+
),
|
|
118
|
+
activeView.hideEmptyGroups === true,
|
|
119
|
+
);
|
|
120
|
+
return (
|
|
121
|
+
<div className="min-w-0">
|
|
122
|
+
{viewConfig.views.length > 1 && (
|
|
123
|
+
<div className="flex min-w-0 gap-1 overflow-x-auto px-1 pb-1">
|
|
124
|
+
{viewConfig.views.map((view) => (
|
|
125
|
+
<button
|
|
126
|
+
key={view.id}
|
|
127
|
+
type="button"
|
|
128
|
+
className={cn(
|
|
129
|
+
"shrink-0 rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
130
|
+
activeView.id === view.id &&
|
|
131
|
+
"bg-muted font-medium text-foreground",
|
|
132
|
+
)}
|
|
133
|
+
onClick={() => {
|
|
134
|
+
setSelectedViewId(view.id);
|
|
135
|
+
onSelectView?.(view.id);
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
{view.name}
|
|
139
|
+
</button>
|
|
140
|
+
))}
|
|
141
|
+
</div>
|
|
142
|
+
)}
|
|
143
|
+
<DatabaseSidebarView
|
|
144
|
+
{...labels}
|
|
145
|
+
groups={groups}
|
|
146
|
+
grouped={
|
|
147
|
+
!!databaseViewGroupingProperty(activeView, data?.properties ?? [])
|
|
148
|
+
}
|
|
149
|
+
isLoading={isLoading}
|
|
150
|
+
hasActiveConstraints={false}
|
|
151
|
+
openPagesIn="full_page"
|
|
152
|
+
onClearResultConstraints={() => {}}
|
|
153
|
+
onPreview={() => {}}
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function DatabaseSidebarView({
|
|
160
|
+
groups,
|
|
161
|
+
grouped,
|
|
162
|
+
isLoading,
|
|
163
|
+
hasActiveConstraints,
|
|
164
|
+
openPagesIn,
|
|
165
|
+
onClearResultConstraints,
|
|
166
|
+
onPreview,
|
|
167
|
+
loadingLabel,
|
|
168
|
+
noMatchesLabel,
|
|
169
|
+
clearLabel,
|
|
170
|
+
navigationLabel,
|
|
171
|
+
untitledLabel,
|
|
172
|
+
}: {
|
|
173
|
+
groups: DatabaseBoardGroup[];
|
|
174
|
+
grouped: boolean;
|
|
175
|
+
isLoading: boolean;
|
|
176
|
+
hasActiveConstraints: boolean;
|
|
177
|
+
openPagesIn: ContentDatabaseOpenPagesIn;
|
|
178
|
+
onClearResultConstraints: () => void;
|
|
179
|
+
onPreview: (item: ContentDatabaseItem) => void;
|
|
180
|
+
loadingLabel: string;
|
|
181
|
+
noMatchesLabel: string;
|
|
182
|
+
clearLabel: string;
|
|
183
|
+
navigationLabel: string;
|
|
184
|
+
untitledLabel: string;
|
|
185
|
+
}) {
|
|
186
|
+
const [collapsedGroupIds, setCollapsedGroupIds] = useState<Set<string>>(
|
|
187
|
+
() => new Set(),
|
|
188
|
+
);
|
|
189
|
+
const items = groups.flatMap((group) => group.items);
|
|
190
|
+
|
|
191
|
+
function setGroupOpen(groupId: string, open: boolean) {
|
|
192
|
+
setCollapsedGroupIds((current) => {
|
|
193
|
+
const next = new Set(current);
|
|
194
|
+
if (open) next.delete(groupId);
|
|
195
|
+
else next.add(groupId);
|
|
196
|
+
return next;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (isLoading) {
|
|
201
|
+
return (
|
|
202
|
+
<div className="flex h-16 items-center gap-2 px-2 text-sm text-muted-foreground">
|
|
203
|
+
<IconLoader2 className="size-4 animate-spin" />
|
|
204
|
+
{loadingLabel}
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (items.length === 0 && hasActiveConstraints) {
|
|
210
|
+
return (
|
|
211
|
+
<div className="flex min-h-16 flex-wrap items-center justify-between gap-2 px-2 py-3 text-sm text-muted-foreground">
|
|
212
|
+
<span>{noMatchesLabel}</span>
|
|
213
|
+
<Button
|
|
214
|
+
type="button"
|
|
215
|
+
size="sm"
|
|
216
|
+
variant="ghost"
|
|
217
|
+
onClick={onClearResultConstraints}
|
|
218
|
+
>
|
|
219
|
+
{clearLabel}
|
|
220
|
+
</Button>
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<ScrollArea className="max-h-[32rem] w-full">
|
|
227
|
+
<nav aria-label={navigationLabel} className="grid gap-1 p-1">
|
|
228
|
+
{grouped
|
|
229
|
+
? groups.map((group) => {
|
|
230
|
+
const open = !collapsedGroupIds.has(group.id);
|
|
231
|
+
return (
|
|
232
|
+
<Collapsible
|
|
233
|
+
key={group.id}
|
|
234
|
+
open={open}
|
|
235
|
+
onOpenChange={(nextOpen) => setGroupOpen(group.id, nextOpen)}
|
|
236
|
+
>
|
|
237
|
+
<CollapsibleTrigger className="group flex h-7 w-full items-center gap-1 rounded px-1.5 text-left text-xs font-medium text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
|
|
238
|
+
{open ? (
|
|
239
|
+
<IconChevronDown className="size-3.5 shrink-0" />
|
|
240
|
+
) : (
|
|
241
|
+
<IconChevronRight className="size-3.5 shrink-0" />
|
|
242
|
+
)}
|
|
243
|
+
<span className="min-w-0 flex-1 truncate">
|
|
244
|
+
{group.label}
|
|
245
|
+
</span>
|
|
246
|
+
<span className="text-[11px] font-normal text-muted-foreground/75">
|
|
247
|
+
{group.items.length}
|
|
248
|
+
</span>
|
|
249
|
+
</CollapsibleTrigger>
|
|
250
|
+
<CollapsibleContent className="grid gap-0.5 pl-2">
|
|
251
|
+
{group.items.map((item) => (
|
|
252
|
+
<DatabaseSidebarRow
|
|
253
|
+
key={item.id}
|
|
254
|
+
item={item}
|
|
255
|
+
openPagesIn={openPagesIn}
|
|
256
|
+
onPreview={onPreview}
|
|
257
|
+
untitledLabel={untitledLabel}
|
|
258
|
+
/>
|
|
259
|
+
))}
|
|
260
|
+
</CollapsibleContent>
|
|
261
|
+
</Collapsible>
|
|
262
|
+
);
|
|
263
|
+
})
|
|
264
|
+
: items.map((item) => (
|
|
265
|
+
<DatabaseSidebarRow
|
|
266
|
+
key={item.id}
|
|
267
|
+
item={item}
|
|
268
|
+
openPagesIn={openPagesIn}
|
|
269
|
+
onPreview={onPreview}
|
|
270
|
+
untitledLabel={untitledLabel}
|
|
271
|
+
/>
|
|
272
|
+
))}
|
|
273
|
+
</nav>
|
|
274
|
+
</ScrollArea>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function DatabaseSidebarRow({
|
|
279
|
+
item,
|
|
280
|
+
openPagesIn,
|
|
281
|
+
onPreview,
|
|
282
|
+
untitledLabel,
|
|
283
|
+
}: {
|
|
284
|
+
item: ContentDatabaseItem;
|
|
285
|
+
openPagesIn: ContentDatabaseOpenPagesIn;
|
|
286
|
+
onPreview: (item: ContentDatabaseItem) => void;
|
|
287
|
+
untitledLabel: string;
|
|
288
|
+
}) {
|
|
289
|
+
function handleClick(event: MouseEvent<HTMLAnchorElement>) {
|
|
290
|
+
if (
|
|
291
|
+
openPagesIn !== "preview" ||
|
|
292
|
+
event.defaultPrevented ||
|
|
293
|
+
event.button !== 0 ||
|
|
294
|
+
event.metaKey ||
|
|
295
|
+
event.altKey ||
|
|
296
|
+
event.ctrlKey ||
|
|
297
|
+
event.shiftKey
|
|
298
|
+
) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
event.preventDefault();
|
|
302
|
+
onPreview(item);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<Link
|
|
307
|
+
to={`/page/${item.document.id}`}
|
|
308
|
+
className={cn(
|
|
309
|
+
"flex h-7 min-w-0 items-center gap-1.5 rounded px-1.5 text-sm text-foreground/85 hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
310
|
+
item.document.icon ? "pl-1" : "pl-1.5",
|
|
311
|
+
)}
|
|
312
|
+
onClick={handleClick}
|
|
313
|
+
>
|
|
314
|
+
{item.document.icon ? (
|
|
315
|
+
<span aria-hidden="true" className="shrink-0 text-sm leading-none">
|
|
316
|
+
{item.document.icon}
|
|
317
|
+
</span>
|
|
318
|
+
) : (
|
|
319
|
+
<IconFileText className="size-3.5 shrink-0 text-muted-foreground" />
|
|
320
|
+
)}
|
|
321
|
+
<span className="min-w-0 flex-1 truncate">
|
|
322
|
+
{item.document.title || untitledLabel}
|
|
323
|
+
</span>
|
|
324
|
+
</Link>
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function databaseSidebarRows(groups: DatabaseBoardGroup[]) {
|
|
329
|
+
return groups.flatMap((group) => group.items);
|
|
330
|
+
}
|
|
@@ -299,7 +299,8 @@ function normalizeClientDatabaseView(
|
|
|
299
299
|
value.type === "gallery" ||
|
|
300
300
|
value.type === "calendar" ||
|
|
301
301
|
value.type === "timeline" ||
|
|
302
|
-
value.type === "form"
|
|
302
|
+
value.type === "form" ||
|
|
303
|
+
value.type === "sidebar"
|
|
303
304
|
? value.type
|
|
304
305
|
: "table";
|
|
305
306
|
return createDatabaseView(
|
|
@@ -460,6 +461,7 @@ export function databaseViewDefaultName(type: ContentDatabaseViewType) {
|
|
|
460
461
|
if (type === "calendar") return "Calendar";
|
|
461
462
|
if (type === "timeline") return "Timeline";
|
|
462
463
|
if (type === "form") return "Form";
|
|
464
|
+
if (type === "sidebar") return "Sidebar";
|
|
463
465
|
return "Table";
|
|
464
466
|
}
|
|
465
467
|
|
|
@@ -24,6 +24,7 @@ const SIDEBAR_WIDTH_KEY = "sidebar-width";
|
|
|
24
24
|
const DEFAULT_SIDEBAR_WIDTH = 240;
|
|
25
25
|
const MIN_SIDEBAR_WIDTH = 240;
|
|
26
26
|
const MAX_SIDEBAR_WIDTH = 480;
|
|
27
|
+
const NARROW_DESKTOP_QUERY = "(max-width: 1099px)";
|
|
27
28
|
|
|
28
29
|
// Routes whose page renders its own custom toolbar (with AgentToggleButton).
|
|
29
30
|
// Layout still mounts Sidebar + AgentSidebar, but skips its own Header so
|
|
@@ -41,6 +42,22 @@ function loadSidebarWidth(): number {
|
|
|
41
42
|
return DEFAULT_SIDEBAR_WIDTH;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
function useIsNarrowDesktop() {
|
|
46
|
+
const [isNarrow, setIsNarrow] = useState(
|
|
47
|
+
() =>
|
|
48
|
+
typeof window !== "undefined" &&
|
|
49
|
+
window.matchMedia(NARROW_DESKTOP_QUERY).matches,
|
|
50
|
+
);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
const media = window.matchMedia(NARROW_DESKTOP_QUERY);
|
|
53
|
+
const update = () => setIsNarrow(media.matches);
|
|
54
|
+
update();
|
|
55
|
+
media.addEventListener("change", update);
|
|
56
|
+
return () => media.removeEventListener("change", update);
|
|
57
|
+
}, []);
|
|
58
|
+
return isNarrow;
|
|
59
|
+
}
|
|
60
|
+
|
|
44
61
|
export function documentPageIdFromPathname(pathname: string) {
|
|
45
62
|
return pathname.match(/^\/page\/(.+)/)?.[1] ?? null;
|
|
46
63
|
}
|
|
@@ -72,6 +89,7 @@ export function Layout({ children }: LayoutProps) {
|
|
|
72
89
|
[activeDocumentId],
|
|
73
90
|
);
|
|
74
91
|
const isMobile = useIsMobile();
|
|
92
|
+
const isNarrowDesktop = useIsNarrowDesktop();
|
|
75
93
|
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
|
76
94
|
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
|
77
95
|
const [sidebarWidth, setSidebarWidth] = useState(loadSidebarWidth);
|
|
@@ -105,6 +123,12 @@ export function Layout({ children }: LayoutProps) {
|
|
|
105
123
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
106
124
|
}, [createPage]);
|
|
107
125
|
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (isNarrowDesktop) {
|
|
128
|
+
window.dispatchEvent(new Event("agent-panel:close"));
|
|
129
|
+
}
|
|
130
|
+
}, [isNarrowDesktop]);
|
|
131
|
+
|
|
108
132
|
const mobileSidebarTrigger = isMobile ? (
|
|
109
133
|
<button
|
|
110
134
|
type="button"
|
|
@@ -164,7 +188,7 @@ export function Layout({ children }: LayoutProps) {
|
|
|
164
188
|
)}
|
|
165
189
|
<AgentSidebar
|
|
166
190
|
position="right"
|
|
167
|
-
defaultOpen={!isMobile}
|
|
191
|
+
defaultOpen={!isMobile && !isNarrowDesktop}
|
|
168
192
|
agentPageHref="/agent"
|
|
169
193
|
emptyStateText={t("chat.emptyState")}
|
|
170
194
|
suggestions={[
|