@agent-native/core-corpus 0.201.0-nightly-20261005153421 → 0.201.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/templates/analytics/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +14 -4
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/analytics/CHANGELOG.md +6 -0
- package/corpus/templates/analytics/README.md +2 -2
- package/corpus/templates/analytics/changelog/2026-10-02-events-with-a-very-long-name-app-or-page-path-no-longer-caus.md +6 -0
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +9 -19
- package/corpus/templates/analytics/server/handlers/session-replay.ts +34 -47
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +9 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -36
- package/corpus/templates/analytics/server/lib/indexed-text.ts +53 -0
- package/corpus/templates/analytics/server/lib/request-errors.ts +73 -0
- package/corpus/templates/analytics/server/lib/session-event-index.ts +6 -16
- package/corpus/templates/analytics/server/lib/session-replay.ts +12 -2
- package/corpus/templates/analytics/server/plugins/auth.ts +2 -1
- package/corpus/templates/analytics/server/plugins/otel.ts +6 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/assets/CHANGELOG.md +7 -0
- package/corpus/templates/assets/README.md +2 -2
- package/corpus/templates/assets/package.json +1 -0
- package/corpus/templates/assets/server/plugins/auth.ts +2 -1
- package/corpus/templates/assets/server/plugins/otel.ts +6 -0
- package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +2 -1
- package/corpus/templates/brain/.agents/skills/brain/SKILL.md +5 -4
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/brain/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/brain/CHANGELOG.md +6 -0
- package/corpus/templates/brain/README.md +12 -8
- package/corpus/templates/brain/changelog/2026-10-05-private-slack-channels-are-searchable-org-wide.md +6 -0
- package/corpus/templates/brain/package.json +1 -0
- package/corpus/templates/brain/server/lib/audiences.ts +1 -98
- package/corpus/templates/brain/server/lib/connectors.ts +2 -166
- package/corpus/templates/brain/server/plugins/otel.ts +6 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/calendar/CHANGELOG.md +7 -0
- package/corpus/templates/calendar/README.md +2 -2
- package/corpus/templates/calendar/package.json +1 -0
- package/corpus/templates/calendar/server/plugins/auth.ts +2 -1
- package/corpus/templates/calendar/server/plugins/otel.ts +6 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/chat/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/chat/README.md +2 -2
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +9 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/clips/CHANGELOG.md +24 -0
- package/corpus/templates/clips/README.md +2 -2
- package/corpus/templates/clips/actions/lib/audio-chunk-list.ts +23 -0
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +187 -292
- package/corpus/templates/clips/actions/lib/chunked-transcription.ts +151 -0
- package/corpus/templates/clips/actions/lib/recording-audio-source.ts +191 -0
- package/corpus/templates/clips/actions/request-transcript.ts +81 -135
- package/corpus/templates/clips/actions/search-recordings.ts +19 -5
- package/corpus/templates/clips/app/components/clips-command-menu.tsx +5 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -1
- package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -0
- package/corpus/templates/clips/app/hooks/use-library.ts +1 -0
- package/corpus/templates/clips/app/lib/local-recording-upload.ts +13 -6
- package/corpus/templates/clips/app/lib/recording-section.ts +1 -1
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +7 -5
- package/corpus/templates/clips/app/routes/record.tsx +16 -6
- package/corpus/templates/clips/changelog/2026-10-02-long-uploads-an-hour-or-more-now-transcribe-reliably-instead.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-confirming-discard-recording-now-returns-you-to-your-library.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recording-now-removes-its-failed-upload-card-fr.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recovered-recording-no-longer-warns-that-it-s-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-search-results-identify-recordings-in-trash-and-open-them-wi.md +6 -0
- package/corpus/templates/clips/package.json +1 -0
- package/corpus/templates/clips/server/lib/builder-cdn.ts +5 -0
- package/corpus/templates/clips/server/lib/builder-media-compression.ts +2 -2
- package/corpus/templates/clips/server/plugins/auth.ts +2 -1
- package/corpus/templates/clips/server/plugins/otel.ts +6 -0
- package/corpus/templates/clips/shared/transcript-failure.ts +5 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +8 -2
- package/corpus/templates/content/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/content/CHANGELOG.md +41 -0
- package/corpus/templates/content/README.md +2 -2
- package/corpus/templates/content/actions/_database-navigation.ts +523 -344
- package/corpus/templates/content/actions/_database-row-mutation.ts +44 -10
- package/corpus/templates/content/actions/_database-setup-discovery.ts +9 -3
- package/corpus/templates/content/actions/_database-utils.ts +299 -271
- package/corpus/templates/content/actions/_property-utils.ts +293 -190
- package/corpus/templates/content/actions/_relation-values.ts +3 -1
- package/corpus/templates/content/actions/get-content-database.ts +1 -0
- package/corpus/templates/content/actions/query-content-database-items.ts +32 -5
- package/corpus/templates/content/actions/set-document-property.ts +17 -11
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +21 -6
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -43
- package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +159 -50
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +12 -28
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +6 -1
- package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +139 -70
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +16 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +180 -75
- package/corpus/templates/content/app/components/editor/database/DatabaseViewSkeleton.tsx +76 -0
- package/corpus/templates/content/app/components/editor/database/navigation-state.ts +60 -2
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +41 -42
- package/corpus/templates/content/app/components/editor/document-editor-layout.ts +18 -0
- package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +11 -3
- package/corpus/templates/content/app/components/editor/suggestions/draft-session.ts +15 -7
- package/corpus/templates/content/app/components/editor/suggestions/model.ts +13 -0
- package/corpus/templates/content/app/components/editor/suggestions/read-only-blocks.ts +136 -0
- package/corpus/templates/content/app/components/editor/table-view.ts +73 -0
- package/corpus/templates/content/app/components/layout/ContentStartupShell.tsx +1 -1
- package/corpus/templates/content/app/components/layout/Layout.tsx +5 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +57 -16
- package/corpus/templates/content/app/components/sidebar/MovePageDialog.tsx +4 -4
- package/corpus/templates/content/app/components/sidebar/SidebarNavigationRow.tsx +34 -10
- package/corpus/templates/content/app/global.css +16 -8
- package/corpus/templates/content/app/hooks/content-action-refresh.ts +14 -13
- package/corpus/templates/content/app/hooks/use-content-database.ts +72 -9
- package/corpus/templates/content/app/hooks/use-content-personal-navigation.ts +7 -3
- package/corpus/templates/content/app/hooks/use-documents.ts +27 -0
- package/corpus/templates/content/app/i18n-data.ts +3 -2
- package/corpus/templates/content/app/lib/content-landing.ts +3 -31
- package/corpus/templates/content/app/lib/files-navigation.ts +182 -10
- package/corpus/templates/content/app/lib/files-root-hint.ts +20 -32
- package/corpus/templates/content/app/lib/page-startup-hints.ts +108 -0
- package/corpus/templates/content/app/lib/private-link-redirect.ts +25 -0
- package/corpus/templates/content/app/lib/sidebar-layout-hint.ts +34 -1
- package/corpus/templates/content/app/lib/startup-timing.ts +2 -0
- package/corpus/templates/content/app/root.tsx +3 -1
- package/corpus/templates/content/app/routes/_app.home.tsx +10 -19
- package/corpus/templates/content/app/routes/p.$id.tsx +23 -5
- package/corpus/templates/content/changelog/2026-10-02-a-page-link-you-cant-open-now-says-so-instead-of-opening-an.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-after-a-refresh-the-files-sidebar-shows-the-open-page-s-fold.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-large-collections-open-faster.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-pages-stay-inside-the-window-at-every-width-long-inline-code.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-pages-with-open-comments-and-collections-with-sorted-or-filt.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-suggest-edits-works-on-pages-written-by-agents-including-pag.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-while-you-suggest-edits-tables-and-other-blocks-that-suggest.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-collection-view-context-now-survives-quick-page-changes-when.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-collection-views-keep-their-saved-rows-accurate-during-refre.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-exact-saved-view-links-keep-collection-retry-available.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-expanding-a-files-folder-now-shares-one-navigation-read-acro.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-files-navigation-retries-temporary-failures-consistently.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-shared-page-owners-keep-edit-and-manage-controls-in-files-an.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-tagging-an-ai-in-a-comment-works-again-instead-of-failing-ri.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-the-home-loading-shell-keeps-the-layout-of-your-last-opened-.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-typing-and-a-space-or-inserting-a-toggle-or-callout-no-longe.md +6 -0
- package/corpus/templates/content/docs/product/capabilities/content.workspace.session-restore.md +4 -1
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/corpus/templates/content/package.json +2 -1
- package/corpus/templates/content/scripts/seed-perf-database.mjs +600 -0
- package/corpus/templates/content/scripts/trace-startup.mjs +25 -3
- package/corpus/templates/content/server/db/index.ts +1 -1
- package/corpus/templates/content/server/lib/suggested-edits.ts +23 -26
- package/corpus/templates/content/server/plugins/auth.ts +2 -1
- package/corpus/templates/content/server/plugins/otel.ts +6 -0
- package/corpus/templates/content/shared/api.ts +17 -0
- package/corpus/templates/content/shared/suggestion-diff.ts +124 -38
- package/corpus/templates/content/shared/suggestion-formatting.ts +134 -3
- package/corpus/templates/crm/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/crm/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/crm/package.json +1 -0
- package/corpus/templates/crm/server/plugins/otel.ts +6 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/design/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/design/CHANGELOG.md +41 -0
- package/corpus/templates/design/README.md +2 -2
- package/corpus/templates/design/actions/list-designs.ts +11 -4
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +110 -32
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +28 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -0
- package/corpus/templates/design/app/components/home/DesignHomeLibrary.tsx +79 -0
- package/corpus/templates/design/app/components/layout/Header.tsx +2 -4
- package/corpus/templates/design/app/components/ui/tabs.tsx +59 -1
- package/corpus/templates/design/app/global.css +1 -34
- package/corpus/templates/design/app/i18n/en-US.ts +4 -0
- package/corpus/templates/design/app/lib/design-filter.ts +4 -2
- package/corpus/templates/design/app/pages/Index.tsx +91 -59
- package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +58 -17
- package/corpus/templates/design/changelog/2026-10-01-filter-designs-by-owner.md +6 -0
- package/corpus/templates/design/changelog/2026-10-03-layers-dropped-into-visible-canvas-space-beyond-a-screen-now.md +6 -0
- package/corpus/templates/design/changelog/2026-10-03-visible-screen-overflow-no-longer-routes-drops-to-the-canvas.md +6 -0
- package/corpus/templates/design/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-designs.md +6 -0
- package/corpus/templates/design/package.json +1 -0
- package/corpus/templates/design/server/plugins/auth.ts +2 -1
- package/corpus/templates/design/server/plugins/otel.ts +6 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/dispatch/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/dispatch/README.md +2 -2
- package/corpus/templates/dispatch/package.json +1 -0
- package/corpus/templates/dispatch/server/plugins/otel.ts +6 -0
- package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +2 -1
- package/corpus/templates/factory/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/plugins/otel.ts +6 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/forms/README.md +2 -2
- package/corpus/templates/forms/package.json +1 -0
- package/corpus/templates/forms/server/plugins/auth.ts +2 -1
- package/corpus/templates/forms/server/plugins/otel.ts +6 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/mail/CHANGELOG.md +6 -0
- package/corpus/templates/mail/README.md +2 -2
- package/corpus/templates/mail/package.json +1 -0
- package/corpus/templates/mail/server/plugins/auth.ts +2 -1
- package/corpus/templates/mail/server/plugins/otel.ts +6 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/plan/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/plan/CHANGELOG.md +1 -0
- package/corpus/templates/plan/README.md +2 -2
- package/corpus/templates/plan/package.json +1 -0
- package/corpus/templates/plan/server/plugins/auth.ts +2 -1
- package/corpus/templates/plan/server/plugins/otel.ts +6 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/slides/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/slides/CHANGELOG.md +23 -0
- package/corpus/templates/slides/README.md +2 -2
- package/corpus/templates/slides/actions/list-decks.ts +11 -4
- package/corpus/templates/slides/app/components/deck/DeckFilterMenu.tsx +44 -36
- package/corpus/templates/slides/app/components/home/SlidesHomeLibrary.tsx +79 -0
- package/corpus/templates/slides/app/components/layout/Header.tsx +2 -15
- package/corpus/templates/slides/app/components/ui/tabs.tsx +59 -0
- package/corpus/templates/slides/app/global.css +3 -54
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/deck-filter.ts +5 -2
- package/corpus/templates/slides/app/pages/Index.tsx +102 -88
- package/corpus/templates/slides/changelog/2026-10-01-filter-decks-by-owner.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-02-hide-recent-until-decks-available.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-decks-a.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/handlers/request-auth-context.ts +8 -0
- package/corpus/templates/slides/server/plugins/auth.ts +2 -1
- package/corpus/templates/slides/server/plugins/otel.ts +6 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/tasks/.agents/skills/storing-data/SKILL.md +12 -7
- package/package.json +1 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
2
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
3
2
|
import { parseIconValue, serializeIconValue } from "@agent-native/core/icons";
|
|
4
3
|
import type { IconValue } from "@agent-native/core/icons";
|
|
@@ -6,7 +5,6 @@ import type {
|
|
|
6
5
|
ContentDatabaseItem,
|
|
7
6
|
ContentDatabaseNavigationItem,
|
|
8
7
|
ContentDatabaseNavigationPageResponse,
|
|
9
|
-
ContentDatabaseNavigationSort,
|
|
10
8
|
ContentDatabaseOpenPagesIn,
|
|
11
9
|
ContentDatabasePersonalViewOverrides,
|
|
12
10
|
ContentDatabaseResponse,
|
|
@@ -63,13 +61,15 @@ import {
|
|
|
63
61
|
DropdownMenuTrigger,
|
|
64
62
|
} from "@/components/ui/dropdown-menu";
|
|
65
63
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
66
|
-
import { Skeleton } from "@/components/ui/skeleton";
|
|
67
64
|
import {
|
|
68
65
|
Tooltip,
|
|
69
66
|
TooltipContent,
|
|
70
67
|
TooltipTrigger,
|
|
71
68
|
} from "@/components/ui/tooltip";
|
|
72
|
-
import {
|
|
69
|
+
import {
|
|
70
|
+
filesNavigationPageParams,
|
|
71
|
+
useFilesNavigationPage,
|
|
72
|
+
} from "@/lib/files-navigation";
|
|
73
73
|
import type { SidebarRowsHint } from "@/lib/sidebar-layout-hint";
|
|
74
74
|
import {
|
|
75
75
|
SIDEBAR_FILES_ROW_ELEMENT_TIMING,
|
|
@@ -143,8 +143,6 @@ export function navigationItemAsDatabaseItem(
|
|
|
143
143
|
|
|
144
144
|
export function PagedContentFilesSidebarView({
|
|
145
145
|
databaseId,
|
|
146
|
-
sort,
|
|
147
|
-
viewId,
|
|
148
146
|
activeDocumentId,
|
|
149
147
|
expandedDocumentIds,
|
|
150
148
|
onDocumentExpandedChange,
|
|
@@ -159,10 +157,10 @@ export function PagedContentFilesSidebarView({
|
|
|
159
157
|
untitledLabel,
|
|
160
158
|
rootPlaceholder,
|
|
161
159
|
onRootPageShown,
|
|
160
|
+
branchPlaceholders,
|
|
161
|
+
onBranchShown,
|
|
162
162
|
}: {
|
|
163
163
|
databaseId: string;
|
|
164
|
-
sort: ContentDatabaseNavigationSort;
|
|
165
|
-
viewId?: string;
|
|
166
164
|
activeDocumentId?: string | null;
|
|
167
165
|
expandedDocumentIds: ReadonlySet<string>;
|
|
168
166
|
onDocumentExpandedChange: (documentId: string, expanded: boolean) => void;
|
|
@@ -180,6 +178,10 @@ export function PagedContentFilesSidebarView({
|
|
|
180
178
|
rootPlaceholder?: SidebarRowsHint;
|
|
181
179
|
/** Reports what the root page drew, for the next load's placeholder. */
|
|
182
180
|
onRootPageShown?: (shown: SidebarRowsHint) => void;
|
|
181
|
+
/** Rows to hold while an open folder's first page loads, by folder ID. */
|
|
182
|
+
branchPlaceholders?: Readonly<Record<string, SidebarRowsHint>>;
|
|
183
|
+
/** Reports what an open folder's first page drew. */
|
|
184
|
+
onBranchShown?: (documentId: string, shown: SidebarRowsHint) => void;
|
|
183
185
|
}) {
|
|
184
186
|
return (
|
|
185
187
|
<nav
|
|
@@ -188,13 +190,13 @@ export function PagedContentFilesSidebarView({
|
|
|
188
190
|
data-paged-files-navigation
|
|
189
191
|
>
|
|
190
192
|
<PagedContentFilesBranch
|
|
191
|
-
key={`${databaseId}:root
|
|
193
|
+
key={`${databaseId}:root`}
|
|
192
194
|
databaseId={databaseId}
|
|
193
195
|
parentId={null}
|
|
194
|
-
sort={sort}
|
|
195
|
-
viewId={viewId}
|
|
196
196
|
rootPlaceholder={rootPlaceholder}
|
|
197
197
|
onRootPageShown={onRootPageShown}
|
|
198
|
+
branchPlaceholders={branchPlaceholders}
|
|
199
|
+
onBranchShown={onBranchShown}
|
|
198
200
|
depth={0}
|
|
199
201
|
activeDocumentId={activeDocumentId}
|
|
200
202
|
expandedDocumentIds={expandedDocumentIds}
|
|
@@ -229,14 +231,14 @@ function PagedContentFilesBranch({
|
|
|
229
231
|
cursor?: string;
|
|
230
232
|
rootPlaceholder?: SidebarRowsHint;
|
|
231
233
|
onRootPageShown?: (shown: SidebarRowsHint) => void;
|
|
234
|
+
branchPlaceholders?: Readonly<Record<string, SidebarRowsHint>>;
|
|
235
|
+
onBranchShown?: (documentId: string, shown: SidebarRowsHint) => void;
|
|
232
236
|
precedingDocumentIds?: ReadonlySet<string>;
|
|
233
237
|
/**
|
|
234
238
|
* Reloads the branch from its first page. Returns false when an automatic
|
|
235
239
|
* reload is refused because the branch reloaded itself moments ago.
|
|
236
240
|
*/
|
|
237
241
|
reloadBranch?: (automatic: boolean) => boolean;
|
|
238
|
-
sort: ContentDatabaseNavigationSort;
|
|
239
|
-
viewId?: string;
|
|
240
242
|
depth: number;
|
|
241
243
|
activeDocumentId?: string | null;
|
|
242
244
|
expandedDocumentIds: ReadonlySet<string>;
|
|
@@ -256,15 +258,13 @@ function PagedContentFilesBranch({
|
|
|
256
258
|
const [continuationGeneration, setContinuationGeneration] = useState(0);
|
|
257
259
|
const lastAutomaticReload = useRef(Number.NEGATIVE_INFINITY);
|
|
258
260
|
const [reloadRefused, setReloadRefused] = useState(false);
|
|
259
|
-
const query =
|
|
260
|
-
"query-content-database-items",
|
|
261
|
+
const query = useFilesNavigationPage(
|
|
261
262
|
filesNavigationPageParams({
|
|
262
263
|
databaseId: props.databaseId,
|
|
263
264
|
parentId: props.parentId,
|
|
264
|
-
sort: props.sort,
|
|
265
|
-
viewId: props.viewId,
|
|
266
265
|
cursor,
|
|
267
266
|
}),
|
|
267
|
+
props.expandedDocumentIds,
|
|
268
268
|
);
|
|
269
269
|
const data =
|
|
270
270
|
query.data && !("available" in query.data)
|
|
@@ -328,47 +328,46 @@ function PagedContentFilesBranch({
|
|
|
328
328
|
}, [rootRowsShown]);
|
|
329
329
|
|
|
330
330
|
const firstRoot = props.depth === 0 && !cursor;
|
|
331
|
-
const
|
|
332
|
-
|
|
331
|
+
const firstPageRowCount =
|
|
332
|
+
!cursor && data
|
|
333
333
|
? data.items.length +
|
|
334
334
|
props.activePathDocuments.filter(
|
|
335
335
|
(document) =>
|
|
336
|
-
document.parentId ===
|
|
336
|
+
document.parentId === props.parentId &&
|
|
337
337
|
!data.items.some((item) => item.documentId === document.id),
|
|
338
338
|
).length
|
|
339
339
|
: null;
|
|
340
|
-
const
|
|
340
|
+
const firstPageHasMore = Boolean(
|
|
341
341
|
data?.pagination.hasMore && data.pagination.nextCursor,
|
|
342
342
|
);
|
|
343
343
|
useEffect(() => {
|
|
344
|
-
if (
|
|
345
|
-
|
|
344
|
+
if (firstPageRowCount === null) return;
|
|
345
|
+
const shown = { rows: firstPageRowCount, more: firstPageHasMore };
|
|
346
|
+
if (props.parentId === null) onRootPageShown?.(shown);
|
|
347
|
+
else props.onBranchShown?.(props.parentId, shown);
|
|
346
348
|
// The callback identity changes per render; only what was drawn matters.
|
|
347
349
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
348
|
-
}, [
|
|
350
|
+
}, [firstPageRowCount, firstPageHasMore]);
|
|
349
351
|
|
|
350
|
-
if (
|
|
352
|
+
if (query.isLoading || (cursorExpired && !reloadRefused)) {
|
|
353
|
+
// A first page holds the rows it drew last time, in the rows' own
|
|
354
|
+
// geometry, so the rows below it do not move when the page arrives.
|
|
355
|
+
const placeholder = cursor
|
|
356
|
+
? undefined
|
|
357
|
+
: props.parentId === null
|
|
358
|
+
? rootPlaceholder
|
|
359
|
+
: props.branchPlaceholders?.[props.parentId];
|
|
351
360
|
return (
|
|
352
361
|
<SidebarRowsSkeleton
|
|
353
362
|
framed={false}
|
|
354
|
-
rows={
|
|
355
|
-
more={
|
|
356
|
-
firstRowProps={
|
|
363
|
+
rows={placeholder?.rows ?? 3}
|
|
364
|
+
more={placeholder?.more}
|
|
365
|
+
firstRowProps={
|
|
366
|
+
firstRoot ? startupAnchor("sidebar-files-first-row") : undefined
|
|
367
|
+
}
|
|
357
368
|
/>
|
|
358
369
|
);
|
|
359
370
|
}
|
|
360
|
-
if (query.isLoading || (cursorExpired && !reloadRefused)) {
|
|
361
|
-
return (
|
|
362
|
-
<div aria-hidden="true" className="grid gap-1 p-1">
|
|
363
|
-
{[70, 55, 85].map((width) => (
|
|
364
|
-
<div key={width} className="flex h-7 items-center gap-1.5 px-1.5">
|
|
365
|
-
<Skeleton className="size-3.5 shrink-0 rounded-sm" />
|
|
366
|
-
<Skeleton className="h-3 rounded" style={{ width: `${width}%` }} />
|
|
367
|
-
</div>
|
|
368
|
-
))}
|
|
369
|
-
</div>
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
371
|
if (query.isError || !data) {
|
|
373
372
|
return (
|
|
374
373
|
<div className="px-1 py-1">
|
|
@@ -468,7 +467,7 @@ function PagedContentFilesBranch({
|
|
|
468
467
|
{expanded && navigationItem.hasChildren ? (
|
|
469
468
|
<PagedContentFilesBranch
|
|
470
469
|
{...props}
|
|
471
|
-
key={`${props.databaseId}:${navigationItem.documentId}
|
|
470
|
+
key={`${props.databaseId}:${navigationItem.documentId}`}
|
|
472
471
|
parentId={navigationItem.documentId}
|
|
473
472
|
depth={props.depth + 1}
|
|
474
473
|
/>
|
|
@@ -1193,7 +1192,7 @@ function DatabaseSidebarRow({
|
|
|
1193
1192
|
: t("sidebar.expandItem", { title });
|
|
1194
1193
|
const rowRef = useRef<HTMLDivElement>(null);
|
|
1195
1194
|
useEffect(() => {
|
|
1196
|
-
if (active) revealActiveSidebarRow(rowRef.current);
|
|
1195
|
+
if (active) return revealActiveSidebarRow(rowRef.current);
|
|
1197
1196
|
}, [active]);
|
|
1198
1197
|
const isLocalFile = item.document.source?.mode === "local-files";
|
|
1199
1198
|
const canChangePage = canEdit && !isLocalFile && pageActions !== null;
|
|
@@ -34,6 +34,12 @@ export const DOCUMENT_EDITOR_TITLE_CLASS_NAME =
|
|
|
34
34
|
export const DOCUMENT_EDITOR_PAGE_TITLE_SIZE_CLASS_NAME =
|
|
35
35
|
"text-3xl md:text-4xl md:pb-0.5";
|
|
36
36
|
|
|
37
|
+
export const DOCUMENT_EDITOR_DATABASE_TITLE_SIZE_CLASS_NAME = "text-3xl";
|
|
38
|
+
|
|
39
|
+
export function documentEditorDatabaseRegionClassName() {
|
|
40
|
+
return "shrink-0 min-w-0 w-full max-w-none px-4 pb-8 sm:px-8 lg:px-10";
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
export function documentEditorBodyClassName(host: "page" | "preview") {
|
|
38
44
|
return cn(
|
|
39
45
|
"mx-auto w-full max-w-3xl flex-1 cursor-text px-4",
|
|
@@ -44,3 +50,15 @@ export function documentEditorBodyClassName(host: "page" | "preview") {
|
|
|
44
50
|
// What sits above the title: the page icon (56px), the "Add icon" button an
|
|
45
51
|
// editor sees on a page without one (28px), or nothing for a reader.
|
|
46
52
|
export type DocumentEditorIconRow = "icon" | "add" | "none";
|
|
53
|
+
|
|
54
|
+
// What sits below the title: a page body; a page body beside the review margin
|
|
55
|
+
// its open comments and suggestions hold open; or a collection, whose tabs row
|
|
56
|
+
// may sit above a row of the view's sorts and filters.
|
|
57
|
+
export type DocumentEditorShape =
|
|
58
|
+
| "page"
|
|
59
|
+
| "review"
|
|
60
|
+
| "database"
|
|
61
|
+
| "database-constrained";
|
|
62
|
+
|
|
63
|
+
// The review margin opens only when the page column is at least this wide.
|
|
64
|
+
export const DOCUMENT_EDITOR_INLINE_REVIEW_MIN_WIDTH = 1088;
|
|
@@ -32,11 +32,13 @@ import {
|
|
|
32
32
|
mergeAttributes,
|
|
33
33
|
type NodeViewProps,
|
|
34
34
|
} from "@tiptap/react";
|
|
35
|
+
import { useState } from "react";
|
|
35
36
|
|
|
36
37
|
import { usePageLinkTarget } from "../../../hooks/use-content-links";
|
|
37
38
|
import { ContentIcon } from "../../icons/ContentIcon";
|
|
38
39
|
import { EmojiPicker } from "../EmojiPicker";
|
|
39
40
|
import { MathRenderer } from "../MathRenderer";
|
|
41
|
+
import { isSuggestingEdits } from "../suggestions/read-only-blocks";
|
|
40
42
|
|
|
41
43
|
const BLOCK_ATOM_TAGS = [
|
|
42
44
|
"page",
|
|
@@ -351,9 +353,13 @@ export function focusToggleSummaryAtPosition(
|
|
|
351
353
|
}
|
|
352
354
|
|
|
353
355
|
function ToggleView({ node, editor, getPos }: NodeViewProps) {
|
|
354
|
-
|
|
356
|
+
// The page stores whether a Toggle is open, and a suggestion cannot change
|
|
357
|
+
// a Toggle, so while suggesting it opens and closes only in this view.
|
|
358
|
+
const suggesting = isSuggestingEdits(editor.state);
|
|
359
|
+
const [suggestingOpen, setSuggestingOpen] = useState<boolean | null>(null);
|
|
360
|
+
const open = suggestingOpen ?? !!node.attrs.open;
|
|
355
361
|
const summary = (node.attrs.summary || "") as string;
|
|
356
|
-
const isEditable = editor.isEditable;
|
|
362
|
+
const isEditable = editor.isEditable && !suggesting;
|
|
357
363
|
const bodyHasNoBlocks = node.childCount === 0;
|
|
358
364
|
|
|
359
365
|
const updateToggleAttributes = (
|
|
@@ -374,7 +380,9 @@ function ToggleView({ node, editor, getPos }: NodeViewProps) {
|
|
|
374
380
|
};
|
|
375
381
|
|
|
376
382
|
const setOpen = (value: boolean) =>
|
|
377
|
-
|
|
383
|
+
suggesting
|
|
384
|
+
? setSuggestingOpen(value)
|
|
385
|
+
: updateToggleAttributes({ open: value }, "pointer");
|
|
378
386
|
|
|
379
387
|
const focusEmptyBody = (event: React.MouseEvent<HTMLElement>) => {
|
|
380
388
|
if (!isEditable) return;
|
|
@@ -2,7 +2,10 @@ import type {
|
|
|
2
2
|
ResourceSuggestion,
|
|
3
3
|
SuggestionOperation,
|
|
4
4
|
} from "@agent-native/core/review";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
SuggestionFormattingMappingError,
|
|
7
|
+
suggestionSourceAlignment,
|
|
8
|
+
} from "@shared/suggestion-formatting";
|
|
6
9
|
|
|
7
10
|
import {
|
|
8
11
|
draftSuggestionAnchors,
|
|
@@ -233,23 +236,28 @@ export function recordSuggestionReplacementIntent(
|
|
|
233
236
|
return false;
|
|
234
237
|
}
|
|
235
238
|
const operations = suggestionDraftOperations(session, currentContent);
|
|
239
|
+
// Intents are stored-base offsets; the draft is the base's canonical form.
|
|
240
|
+
const alignment = suggestionSourceAlignment(session.baseContent);
|
|
241
|
+
if (!alignment) return false;
|
|
236
242
|
const baseOffset = (position: number, side: "start" | "end") => {
|
|
237
243
|
let delta = 0;
|
|
238
244
|
for (const operation of operations) {
|
|
239
|
-
const
|
|
245
|
+
const from = alignment.map(operation.anchor.from, "stored");
|
|
246
|
+
const to = alignment.map(operation.anchor.to, "stored");
|
|
247
|
+
if (from === null || to === null) return null;
|
|
248
|
+
const start = from + delta;
|
|
240
249
|
const end = start + operation.after.changedText.length;
|
|
241
|
-
if (position < start) return position - delta;
|
|
250
|
+
if (position < start) return alignment.map(position - delta, "canonical");
|
|
242
251
|
if (position === start) return operation.anchor.from;
|
|
243
252
|
if (position < end)
|
|
244
253
|
return side === "start" ? operation.anchor.from : operation.anchor.to;
|
|
245
|
-
delta +=
|
|
246
|
-
operation.after.changedText.length -
|
|
247
|
-
(operation.anchor.to - operation.anchor.from);
|
|
254
|
+
delta += operation.after.changedText.length - (to - from);
|
|
248
255
|
}
|
|
249
|
-
return position - delta;
|
|
256
|
+
return alignment.map(position - delta, "canonical");
|
|
250
257
|
};
|
|
251
258
|
const start = baseOffset(candidates[0]!, "start");
|
|
252
259
|
const end = baseOffset(candidates[0]! + input.beforeText.length, "end");
|
|
260
|
+
if (start === null || end === null) return false;
|
|
253
261
|
if (start === end) return true;
|
|
254
262
|
const intents = session.replacementIntents ?? [];
|
|
255
263
|
if (!intents.some((intent) => intent.from <= start && intent.to >= end)) {
|
|
@@ -84,6 +84,19 @@ export const SUPPORTED_SUGGESTION_BLOCKS = new Set([
|
|
|
84
84
|
"horizontalRule",
|
|
85
85
|
]);
|
|
86
86
|
|
|
87
|
+
const SUPPORTED_SUGGESTION_INLINE_NODES = new Set(["hardBreak"]);
|
|
88
|
+
|
|
89
|
+
// A suggestion must leave every other node unchanged: the server refuses a
|
|
90
|
+
// proposal that edits one, so the suggesting editor keeps them read-only.
|
|
91
|
+
export function supportsSuggestionNode(type: string): boolean {
|
|
92
|
+
return (
|
|
93
|
+
type === "doc" ||
|
|
94
|
+
type === "text" ||
|
|
95
|
+
SUPPORTED_SUGGESTION_BLOCKS.has(type) ||
|
|
96
|
+
SUPPORTED_SUGGESTION_INLINE_NODES.has(type)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
87
100
|
export const SUPPORTED_SUGGESTION_MARKS = new Set<SuggestionMark>([
|
|
88
101
|
"bold",
|
|
89
102
|
"italic",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION } from "@agent-native/toolkit/editor";
|
|
2
|
+
import { Extension } from "@tiptap/core";
|
|
3
|
+
import type {
|
|
4
|
+
Fragment,
|
|
5
|
+
Node as ProseMirrorNode,
|
|
6
|
+
Slice,
|
|
7
|
+
} from "@tiptap/pm/model";
|
|
8
|
+
import {
|
|
9
|
+
Plugin,
|
|
10
|
+
PluginKey,
|
|
11
|
+
type EditorState,
|
|
12
|
+
type Transaction,
|
|
13
|
+
} from "@tiptap/pm/state";
|
|
14
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
15
|
+
|
|
16
|
+
import { supportsSuggestionNode } from "./model";
|
|
17
|
+
|
|
18
|
+
type NodeRange = { from: number; to: number };
|
|
19
|
+
|
|
20
|
+
export function unsupportedSuggestionRanges(doc: ProseMirrorNode): NodeRange[] {
|
|
21
|
+
const ranges: NodeRange[] = [];
|
|
22
|
+
doc.descendants((node, pos) => {
|
|
23
|
+
if (supportsSuggestionNode(node.type.name)) return true;
|
|
24
|
+
ranges.push({ from: pos, to: pos + node.nodeSize });
|
|
25
|
+
return false;
|
|
26
|
+
});
|
|
27
|
+
return ranges;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Mark and attribute steps have empty step maps, so read the range each step
|
|
31
|
+
// touches from its own fields rather than from its map.
|
|
32
|
+
function stepRange(
|
|
33
|
+
step: Transaction["steps"][number],
|
|
34
|
+
doc: ProseMirrorNode,
|
|
35
|
+
): NodeRange | null {
|
|
36
|
+
const { from, to, pos } = step as unknown as {
|
|
37
|
+
from?: number;
|
|
38
|
+
to?: number;
|
|
39
|
+
pos?: number;
|
|
40
|
+
};
|
|
41
|
+
if (typeof from === "number" && typeof to === "number") return { from, to };
|
|
42
|
+
if (typeof pos === "number") {
|
|
43
|
+
return { from: pos, to: pos + (doc.nodeAt(pos)?.nodeSize ?? 0) };
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function holdsUnsupportedNode(
|
|
49
|
+
content: Fragment,
|
|
50
|
+
from = 0,
|
|
51
|
+
to = content.size,
|
|
52
|
+
): boolean {
|
|
53
|
+
let found = false;
|
|
54
|
+
content.nodesBetween(from, to, (node) => {
|
|
55
|
+
if (found) return false;
|
|
56
|
+
if (supportsSuggestionNode(node.type.name)) return true;
|
|
57
|
+
found = true;
|
|
58
|
+
return false;
|
|
59
|
+
});
|
|
60
|
+
return found;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Loading a draft or the canonical body replaces the whole document outside
|
|
64
|
+
// undo history. Select-all followed by typing also replaces the whole
|
|
65
|
+
// document, so the history flag is what tells a load from an edit. A step
|
|
66
|
+
// that inserts an unsupported node is refused too: once in the draft, the
|
|
67
|
+
// node would be read-only and could not be removed again.
|
|
68
|
+
export function editsUnsupportedSuggestionNode(
|
|
69
|
+
transaction: Transaction,
|
|
70
|
+
): boolean {
|
|
71
|
+
if (transaction.getMeta(RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION)) return false;
|
|
72
|
+
const loadsBody = transaction.getMeta("addToHistory") === false;
|
|
73
|
+
return transaction.steps.some((step, index) => {
|
|
74
|
+
const doc = transaction.docs[index]!;
|
|
75
|
+
const range = stepRange(step, doc);
|
|
76
|
+
if (!range) return true;
|
|
77
|
+
if (loadsBody && range.from === 0 && range.to === doc.content.size) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const { slice } = step as { slice?: Slice };
|
|
81
|
+
return (
|
|
82
|
+
(slice !== undefined && holdsUnsupportedNode(slice.content)) ||
|
|
83
|
+
holdsUnsupportedNode(doc.content, range.from, range.to)
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const readOnlyBlocksKey = new PluginKey("suggestingReadOnlyBlocks");
|
|
89
|
+
|
|
90
|
+
export function isSuggestingEdits(state: EditorState): boolean {
|
|
91
|
+
return readOnlyBlocksKey.get(state)?.spec.isSuggesting?.() === true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function suggestingReadOnlyBlocksPlugin(isSuggesting: () => boolean) {
|
|
95
|
+
let cached: { doc: ProseMirrorNode; decorations: DecorationSet } | null =
|
|
96
|
+
null;
|
|
97
|
+
return new Plugin({
|
|
98
|
+
key: readOnlyBlocksKey,
|
|
99
|
+
isSuggesting,
|
|
100
|
+
filterTransaction: (transaction) =>
|
|
101
|
+
!isSuggesting() ||
|
|
102
|
+
!transaction.docChanged ||
|
|
103
|
+
!editsUnsupportedSuggestionNode(transaction),
|
|
104
|
+
props: {
|
|
105
|
+
decorations(state) {
|
|
106
|
+
if (!isSuggesting()) return null;
|
|
107
|
+
if (cached?.doc !== state.doc) {
|
|
108
|
+
cached = {
|
|
109
|
+
doc: state.doc,
|
|
110
|
+
decorations: DecorationSet.create(
|
|
111
|
+
state.doc,
|
|
112
|
+
unsupportedSuggestionRanges(state.doc).map(({ from, to }) =>
|
|
113
|
+
Decoration.node(from, to, { contenteditable: "false" }),
|
|
114
|
+
),
|
|
115
|
+
),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return cached.decorations;
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const SuggestingReadOnlyBlocks = Extension.create<{
|
|
125
|
+
isSuggesting: () => boolean;
|
|
126
|
+
}>({
|
|
127
|
+
name: "suggestingReadOnlyBlocks",
|
|
128
|
+
|
|
129
|
+
addOptions() {
|
|
130
|
+
return { isSuggesting: () => false };
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
addProseMirrorPlugins() {
|
|
134
|
+
return [suggestingReadOnlyBlocksPlugin(this.options.isSuggesting)];
|
|
135
|
+
},
|
|
136
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { TableView } from "@tiptap/extension-table";
|
|
2
|
+
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|
3
|
+
import type { EditorView } from "@tiptap/pm/view";
|
|
4
|
+
|
|
5
|
+
// The table's CSS keeps it at least as wide as the page, so this floor only
|
|
6
|
+
// matters once unresized columns stop fitting: the table then scrolls inside
|
|
7
|
+
// `.tableWrapper` instead of squeezing each column to a letter per line.
|
|
8
|
+
// Tiptap's `cellMinWidth` stays small because it is also the drag minimum.
|
|
9
|
+
export const READABLE_TABLE_COLUMN_MIN_WIDTH = 96;
|
|
10
|
+
|
|
11
|
+
// Column drags rewrite the table's inline `min-width` on every frame, so the
|
|
12
|
+
// floor lives in a custom property that the stylesheet enforces instead.
|
|
13
|
+
export const READABLE_TABLE_MIN_WIDTH_PROPERTY = "--content-table-min-width";
|
|
14
|
+
|
|
15
|
+
export function readableTableMinWidth(colgroup: HTMLElement): number | null {
|
|
16
|
+
let total = 0;
|
|
17
|
+
let hasUnsizedColumn = false;
|
|
18
|
+
for (const col of Array.from(colgroup.children)) {
|
|
19
|
+
const width = Number.parseFloat((col as HTMLElement).style.width);
|
|
20
|
+
if (width > 0) {
|
|
21
|
+
total += width;
|
|
22
|
+
} else {
|
|
23
|
+
total += READABLE_TABLE_COLUMN_MIN_WIDTH;
|
|
24
|
+
hasUnsizedColumn = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return hasUnsizedColumn ? total : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class ContentTableView extends TableView {
|
|
31
|
+
// A column drag restyles the <col>s on every frame but writes the new width
|
|
32
|
+
// to the document only on release, so the floor follows the <col>s.
|
|
33
|
+
private readonly columnObserver = new MutationObserver(() =>
|
|
34
|
+
this.applyReadableMinWidth(),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
constructor(
|
|
38
|
+
node: ProseMirrorNode,
|
|
39
|
+
cellMinWidth: number,
|
|
40
|
+
view?: EditorView,
|
|
41
|
+
HTMLAttributes: Record<string, unknown> = {},
|
|
42
|
+
) {
|
|
43
|
+
super(node, cellMinWidth, view, HTMLAttributes);
|
|
44
|
+
this.applyReadableMinWidth();
|
|
45
|
+
this.columnObserver.observe(this.colgroup, {
|
|
46
|
+
attributeFilter: ["style"],
|
|
47
|
+
childList: true,
|
|
48
|
+
subtree: true,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override update(node: ProseMirrorNode) {
|
|
53
|
+
if (!super.update(node)) return false;
|
|
54
|
+
this.applyReadableMinWidth();
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
destroy() {
|
|
59
|
+
this.columnObserver.disconnect();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private applyReadableMinWidth() {
|
|
63
|
+
const minWidth = readableTableMinWidth(this.colgroup);
|
|
64
|
+
if (minWidth === null) {
|
|
65
|
+
this.table.style.removeProperty(READABLE_TABLE_MIN_WIDTH_PROPERTY);
|
|
66
|
+
} else {
|
|
67
|
+
this.table.style.setProperty(
|
|
68
|
+
READABLE_TABLE_MIN_WIDTH_PROPERTY,
|
|
69
|
+
`${minWidth}px`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -114,7 +114,7 @@ export function ContentStartupShell({
|
|
|
114
114
|
<main className="agent-native-app-main relative flex min-w-0 min-h-0 flex-1 flex-col overflow-x-hidden">
|
|
115
115
|
{contentStartupShowsPage(pathname) ? (
|
|
116
116
|
<SidebarTriggerContext.Provider value={compactSidebarTrigger}>
|
|
117
|
-
<DocumentEditorSkeleton iconRow="startup" />
|
|
117
|
+
<DocumentEditorSkeleton iconRow="startup" shape="startup" />
|
|
118
118
|
</SidebarTriggerContext.Provider>
|
|
119
119
|
) : null}
|
|
120
120
|
</main>
|
|
@@ -38,8 +38,11 @@ import {
|
|
|
38
38
|
applyRegisteredDocumentHistoryRestore,
|
|
39
39
|
prepareRegisteredDocumentHistoryRestore,
|
|
40
40
|
} from "@/lib/document-history-restore-controller";
|
|
41
|
-
import { readPageIconRowHint } from "@/lib/page-icon-row-hint";
|
|
42
41
|
import { retirePageOpenReads } from "@/lib/page-open-reads";
|
|
42
|
+
import {
|
|
43
|
+
readPageIconRowHint,
|
|
44
|
+
readPageShapeHint,
|
|
45
|
+
} from "@/lib/page-startup-hints";
|
|
43
46
|
|
|
44
47
|
import { Header } from "./Header";
|
|
45
48
|
import { isContentSettingsRoute } from "./settings-route-policy";
|
|
@@ -367,6 +370,7 @@ export function Layout({ children }: LayoutProps) {
|
|
|
367
370
|
<DocumentEditorSkeleton
|
|
368
371
|
title={pendingDocumentTitle}
|
|
369
372
|
iconRow={readPageIconRowHint(pendingDocumentId)}
|
|
373
|
+
shape={readPageShapeHint(pendingDocumentId)}
|
|
370
374
|
/>
|
|
371
375
|
) : (
|
|
372
376
|
children
|