@agent-native/core-corpus 0.203.1 → 0.204.0-nightly-20261008011018
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/app/pages/sessions/session-replay-screenshot.ts +107 -12
- package/corpus/templates/analytics/changelog/2026-10-07-session-replay-screenshot-export-captures-readable-video-fra.md +6 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -1
- package/corpus/templates/clips/changelog/2026-10-07-builder-io-setup-choices-now-say-use-builder-io.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-07-clips-keeps-settings-at-its-full-size-while-a-recording-is-a.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +17 -10
- package/corpus/templates/clips/desktop/src/lib/popover-sizing.ts +17 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +0 -3
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +13 -6
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +281 -178
- package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +15 -2
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +16 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +16 -1
- package/corpus/templates/content/app/components/editor/WidgetLoadDiagnostic.tsx +103 -0
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +4 -3
- package/corpus/templates/content/app/hooks/use-document-properties.ts +5 -2
- package/corpus/templates/content/app/hooks/use-documents.ts +3 -0
- package/corpus/templates/content/app/i18n-data.ts +8 -0
- package/corpus/templates/content/changelog/2026-10-07-chatgpt-widgets-identify-a-stalled-content-editor-instead-of.md +6 -0
- package/corpus/templates/content/changelog/2026-10-07-chatgpt-widgets-open-document-content-without-a-cookie-sessi.md +6 -0
- package/corpus/templates/content/changelog/2026-10-07-content-documents-now-open-in-chatgpt-widgets-with-their-ful.md +6 -0
- package/corpus/templates/content/changelog/2026-10-07-text-two-people-type-at-the-same-spot-now-reaches-the-saved-.md +6 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +24 -6
- package/corpus/templates/design/CHANGELOG.md +1 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +26 -3
- package/corpus/templates/design/app/pages/design-editor/editor-helpers.ts +40 -11
- package/corpus/templates/design/app/pages/design-editor/position-coordinate-context.ts +21 -8
- package/corpus/templates/design/changelog/2026-10-07-canvas-layers-now-stay-positioned-and-selected-correctly-whe.md +6 -0
- package/corpus/templates/design/changelog/2026-10-07-design-waitlist-signups-work-from-make-real-and-design-systems.md +6 -0
- package/corpus/templates/design/changelog/2026-10-07-fixed-position-readouts-inside-transformed-containers-and-ke.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +5 -3
- package/corpus/templates/design/vite.config.ts +50 -0
- package/corpus/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +59 -70
- package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/reproduction-and-verification.md +46 -0
- package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +33 -0
- package/corpus/templates/factory/.agents/skills/review-prs/SKILL.md +5 -3
- package/corpus/templates/plan/actions/seed-plan-collab.ts +4 -3
- package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +8 -14
- package/corpus/templates/plan/app/components/plan/PlanMarkdownEditor.tsx +56 -0
- package/corpus/templates/plan/shared/plan-autosave-retry.ts +20 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +24 -0
- package/corpus/templates/slides/AGENTS.md +1 -1
- package/corpus/templates/slides/actions/add-slide.ts +10 -0
- package/corpus/templates/slides/actions/create-deck.ts +16 -4
- package/corpus/templates/slides/actions/export-html.ts +29 -16
- package/corpus/templates/slides/actions/update-slide.ts +4 -0
- package/corpus/templates/slides/actions/view-screen.ts +8 -0
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +18 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +20 -2
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +56 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +69 -14
- package/corpus/templates/slides/app/components/editor/SlidesLayersPanel.tsx +4 -0
- package/corpus/templates/slides/app/components/editor/bullet-editing.ts +1 -1
- package/corpus/templates/slides/app/components/editor/in-place-text-session.ts +226 -11
- package/corpus/templates/slides/app/components/editor/rich-text-selection.ts +32 -21
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +10 -1
- package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +2 -0
- package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +20 -7
- package/corpus/templates/slides/app/context/DeckContext.tsx +84 -2
- package/corpus/templates/slides/app/hooks/use-deck-access-reload.ts +70 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +13 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -0
- package/corpus/templates/slides/app/lib/deck-access-lost.ts +4 -0
- package/corpus/templates/slides/app/lib/generation-lifecycle.ts +24 -0
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +229 -62
- package/corpus/templates/slides/app/lib/slide-image-replacement.ts +30 -0
- package/corpus/templates/slides/app/lib/slide-source-map.ts +13 -1
- package/corpus/templates/slides/app/lib/slide-video.ts +163 -0
- package/corpus/templates/slides/app/lib/video-upload.ts +40 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +124 -70
- package/corpus/templates/slides/app/pages/Index.tsx +9 -0
- package/corpus/templates/slides/changelog/2026-10-02-opening-a-deck-you-no-longer-have-access-to-no-longer-floods.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-06-deleting-between-slide-paragraphs-now-preserves-inline-forma.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-a-deck-whose-access-is-revoked-while-it-is-open-now-says-acc.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-forward-delete-keeps-the-caret-on-the-correct-line-when-join.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-long-slide-text-editing-sessions-can-be-undone-without-losin.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-markdown-divider-shortcuts-and-autocorrect-replacements-rema.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-pasted-images-stay-inside-their-crop-frame-while-uploads-fin.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-right-click-slide-images-to-open-the-custom-menu-with-arrang.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-svgs-exported-with-a-standard-svg-1-1-declaration-now-upload.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-underline-styling-stays-consistent-when-formatting-nested-sl.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-07-videos-can-be-added-to-slides-and-played-on-click-or-automat.md +6 -0
- package/corpus/templates/slides/scripts/edit-fidelity/README.md +8 -0
- package/corpus/templates/slides/scripts/edit-fidelity/authoring-fuzz.ts +556 -54
- package/corpus/templates/slides/scripts/edit-fidelity/run.ts +281 -14
- package/corpus/templates/slides/server/handlers/assets.ts +1356 -8
- package/corpus/templates/slides/server/handlers/uploads.ts +13 -7
- package/corpus/templates/slides/server/lib/generation-completion.ts +13 -1
- package/corpus/templates/slides/server/routes/api/assets/upload-video.post.ts +1 -0
- package/corpus/templates/slides/shared/generation-timing.ts +19 -0
- package/package.json +1 -1
package/corpus/README.md
CHANGED
|
@@ -16,6 +16,7 @@ const MAX_IMAGE_RESPONSE_BYTES = 12_000_000;
|
|
|
16
16
|
const MAX_SCREENSHOT_DIMENSION = 8_192;
|
|
17
17
|
const MAX_SCREENSHOT_PIXELS = 16_000_000;
|
|
18
18
|
const MAX_REPLAY_IFRAME_DEPTH = 8;
|
|
19
|
+
const VIDEO_READY_STATE_HAVE_CURRENT_DATA = 2;
|
|
19
20
|
const REPLAY_SCREENSHOT_MARKER = "data-replay-screenshot-map";
|
|
20
21
|
|
|
21
22
|
type ReplayImageResource = { document: Document; url: string };
|
|
@@ -567,8 +568,12 @@ function imageResourcesInDocuments(
|
|
|
567
568
|
(element): element is HTMLVideoElement => element.tagName === "VIDEO",
|
|
568
569
|
)) {
|
|
569
570
|
if (!isElementRendered(video, current)) continue;
|
|
570
|
-
if (
|
|
571
|
-
|
|
571
|
+
if (video.controls) throw new ReplayScreenshotAssetError();
|
|
572
|
+
if (hasCurrentVideoFrame(video)) {
|
|
573
|
+
assertVideoFrameReadable(video);
|
|
574
|
+
} else if (video.poster) {
|
|
575
|
+
addUrl(video.poster, current.baseURI, current);
|
|
576
|
+
} else if (
|
|
572
577
|
video.currentSrc ||
|
|
573
578
|
video.hasAttribute("src") ||
|
|
574
579
|
video.srcObject ||
|
|
@@ -631,6 +636,68 @@ function imageResourcesInDocuments(
|
|
|
631
636
|
);
|
|
632
637
|
}
|
|
633
638
|
|
|
639
|
+
function hasCurrentVideoFrame(video: HTMLVideoElement): boolean {
|
|
640
|
+
return (
|
|
641
|
+
video.readyState >= VIDEO_READY_STATE_HAVE_CURRENT_DATA &&
|
|
642
|
+
video.videoWidth > 0 &&
|
|
643
|
+
video.videoHeight > 0
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function assertVideoFrameReadable(video: HTMLVideoElement): void {
|
|
648
|
+
const probe = video.ownerDocument.createElement("canvas");
|
|
649
|
+
probe.width = 1;
|
|
650
|
+
probe.height = 1;
|
|
651
|
+
const context = probe.getContext("2d");
|
|
652
|
+
if (!context) throw new ReplayScreenshotAssetError();
|
|
653
|
+
try {
|
|
654
|
+
context.drawImage(video, 0, 0, 1, 1);
|
|
655
|
+
context.getImageData(0, 0, 1, 1);
|
|
656
|
+
} catch {
|
|
657
|
+
throw new ReplayScreenshotAssetError();
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function copyComputedStyles(
|
|
662
|
+
source: Element,
|
|
663
|
+
target: HTMLElement,
|
|
664
|
+
view: Window,
|
|
665
|
+
): void {
|
|
666
|
+
const styles = view.getComputedStyle(source);
|
|
667
|
+
for (let index = 0; index < styles.length; index += 1) {
|
|
668
|
+
const property = styles.item(index);
|
|
669
|
+
target.style.setProperty(
|
|
670
|
+
property,
|
|
671
|
+
styles.getPropertyValue(property),
|
|
672
|
+
styles.getPropertyPriority(property),
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function html2CanvasVideoClone(
|
|
678
|
+
video: HTMLVideoElement,
|
|
679
|
+
clonesByMarker: Map<string, Element>,
|
|
680
|
+
): Element | undefined {
|
|
681
|
+
const parent = video.parentElement;
|
|
682
|
+
const parentMarker = parent?.getAttribute(REPLAY_SCREENSHOT_MARKER);
|
|
683
|
+
const clonedParent = parentMarker ? clonesByMarker.get(parentMarker) : null;
|
|
684
|
+
if (!parent || !clonedParent) return undefined;
|
|
685
|
+
|
|
686
|
+
const originalChildren = Array.from(parent.children).filter(
|
|
687
|
+
(element) => element.tagName !== "SCRIPT",
|
|
688
|
+
);
|
|
689
|
+
const videoIndex = originalChildren.indexOf(video);
|
|
690
|
+
if (videoIndex === -1) return undefined;
|
|
691
|
+
|
|
692
|
+
const clonedChildren = Array.from(clonedParent.children).filter(
|
|
693
|
+
(element) =>
|
|
694
|
+
element.tagName !== "SCRIPT" &&
|
|
695
|
+
element.localName !== "html2canvaspseudoelement",
|
|
696
|
+
);
|
|
697
|
+
const clone = clonedChildren[videoIndex];
|
|
698
|
+
return clone?.tagName === "CANVAS" ? clone : undefined;
|
|
699
|
+
}
|
|
700
|
+
|
|
634
701
|
function imageUrlsInDocuments(documents: Document[]): string[] {
|
|
635
702
|
return [
|
|
636
703
|
...new Set(imageResourcesInDocuments(documents).map(({ url }) => url)),
|
|
@@ -859,6 +926,17 @@ export function inlineReplayAssets(
|
|
|
859
926
|
}
|
|
860
927
|
}
|
|
861
928
|
|
|
929
|
+
for (const originalElement of originalElements) {
|
|
930
|
+
if (originalElement.tagName !== "VIDEO") continue;
|
|
931
|
+
const marker = originalElement.getAttribute(REPLAY_SCREENSHOT_MARKER);
|
|
932
|
+
if (!marker || clonesByMarker.has(marker)) continue;
|
|
933
|
+
const clone = html2CanvasVideoClone(
|
|
934
|
+
originalElement as HTMLVideoElement,
|
|
935
|
+
clonesByMarker,
|
|
936
|
+
);
|
|
937
|
+
if (clone) clonesByMarker.set(marker, clone);
|
|
938
|
+
}
|
|
939
|
+
|
|
862
940
|
for (const [documentIndex, original] of originalDocuments.entries()) {
|
|
863
941
|
const rootMarker = original.documentElement.getAttribute(
|
|
864
942
|
REPLAY_SCREENSHOT_MARKER,
|
|
@@ -878,9 +956,13 @@ export function inlineReplayAssets(
|
|
|
878
956
|
if (originalElement.tagName === "SCRIPT") continue;
|
|
879
957
|
const marker = originalElement.getAttribute(REPLAY_SCREENSHOT_MARKER);
|
|
880
958
|
let clonedElement = marker ? clonesByMarker.get(marker) : undefined;
|
|
959
|
+
const isHtml2CanvasVideoClone =
|
|
960
|
+
originalElement.tagName === "VIDEO" &&
|
|
961
|
+
clonedElement?.tagName === "CANVAS";
|
|
881
962
|
if (
|
|
882
963
|
!clonedElement ||
|
|
883
|
-
(
|
|
964
|
+
(!isHtml2CanvasVideoClone &&
|
|
965
|
+
originalElement.tagName !== clonedElement.tagName &&
|
|
884
966
|
!originalElement.localName.includes("-"))
|
|
885
967
|
) {
|
|
886
968
|
throw new ReplayScreenshotAssetError();
|
|
@@ -894,21 +976,34 @@ export function inlineReplayAssets(
|
|
|
894
976
|
const image = cloned.createElement("img");
|
|
895
977
|
image.alt = "";
|
|
896
978
|
image.src = screenshot;
|
|
897
|
-
|
|
898
|
-
for (let index = 0; index < frameStyles.length; index += 1) {
|
|
899
|
-
const property = frameStyles.item(index);
|
|
900
|
-
image.style.setProperty(
|
|
901
|
-
property,
|
|
902
|
-
frameStyles.getPropertyValue(property),
|
|
903
|
-
frameStyles.getPropertyPriority(property),
|
|
904
|
-
);
|
|
905
|
-
}
|
|
979
|
+
copyComputedStyles(originalElement, image, view);
|
|
906
980
|
image.style.setProperty("object-fit", "fill", "important");
|
|
907
981
|
clonedElement.replaceWith(image);
|
|
908
982
|
clonedElement = image;
|
|
909
983
|
if (marker) clonesByMarker.set(marker, image);
|
|
910
984
|
}
|
|
911
985
|
}
|
|
986
|
+
if (originalElement.tagName === "VIDEO") {
|
|
987
|
+
const video = originalElement as HTMLVideoElement;
|
|
988
|
+
if (!hasCurrentVideoFrame(video) && video.poster) {
|
|
989
|
+
const posterUrl = new URL(video.poster, original.baseURI).href;
|
|
990
|
+
const poster = documentAssets.get(posterUrl);
|
|
991
|
+
if (!poster) throw new ReplayScreenshotAssetError();
|
|
992
|
+
const image = cloned.createElement("img");
|
|
993
|
+
image.alt = "";
|
|
994
|
+
image.src = poster;
|
|
995
|
+
const videoStyles = view.getComputedStyle(video);
|
|
996
|
+
copyComputedStyles(video, image, view);
|
|
997
|
+
image.style.setProperty(
|
|
998
|
+
"object-fit",
|
|
999
|
+
videoStyles.objectFit || "contain",
|
|
1000
|
+
"important",
|
|
1001
|
+
);
|
|
1002
|
+
clonedElement.replaceWith(image);
|
|
1003
|
+
clonedElement = image;
|
|
1004
|
+
if (marker) clonesByMarker.set(marker, image);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
912
1007
|
if (originalElement instanceof view.HTMLImageElement) {
|
|
913
1008
|
const source = originalElement.currentSrc || originalElement.src;
|
|
914
1009
|
const dataUrl = documentAssets.get(source);
|
|
@@ -1395,7 +1395,7 @@ const messages = {
|
|
|
1395
1395
|
waitingForBuilder: "Waiting for Builder...",
|
|
1396
1396
|
description:
|
|
1397
1397
|
"Store recorded videos with Builder.io or S3-compatible storage. Builder.io includes free hosting and AI credits.",
|
|
1398
|
-
createBuilderAccount: "
|
|
1398
|
+
createBuilderAccount: "Use Builder.io",
|
|
1399
1399
|
signInWithBuilderAccount: "Sign in with Builder.io account",
|
|
1400
1400
|
free: "Free",
|
|
1401
1401
|
whyPrompt: "Why am I seeing this?",
|
|
@@ -137,6 +137,7 @@ import {
|
|
|
137
137
|
MACOS_UPDATE_RESTART_MESSAGE,
|
|
138
138
|
} from "./lib/permissions";
|
|
139
139
|
import { isMacPlatform, isWindowsPlatform } from "./lib/platform";
|
|
140
|
+
import { getPopoverAutoSizeOptions } from "./lib/popover-sizing";
|
|
140
141
|
import {
|
|
141
142
|
changeRecordFirstFiles,
|
|
142
143
|
effectiveLocalRecordingMode,
|
|
@@ -939,7 +940,10 @@ function measurePopoverHeight(el: HTMLElement): number {
|
|
|
939
940
|
|
|
940
941
|
function usePopoverAutoSize(
|
|
941
942
|
ref: RefObject<HTMLElement | null>,
|
|
942
|
-
options: {
|
|
943
|
+
options: {
|
|
944
|
+
disabled: boolean;
|
|
945
|
+
width: number;
|
|
946
|
+
},
|
|
943
947
|
): void {
|
|
944
948
|
const { disabled, width } = options;
|
|
945
949
|
|
|
@@ -2928,15 +2932,18 @@ export function App({
|
|
|
2928
2932
|
setPopoverView,
|
|
2929
2933
|
appRef,
|
|
2930
2934
|
);
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2935
|
+
const popoverLayoutView =
|
|
2936
|
+
popoverView === "settings"
|
|
2937
|
+
? "settings"
|
|
2938
|
+
: popoverView === "memory"
|
|
2939
|
+
? "memory"
|
|
2940
|
+
: "recorder";
|
|
2941
|
+
const popoverAutoSizeOptions = getPopoverAutoSizeOptions(
|
|
2942
|
+
popoverLayoutView,
|
|
2943
|
+
popoverVisible,
|
|
2944
|
+
recordingStartPending,
|
|
2945
|
+
);
|
|
2946
|
+
usePopoverAutoSize(appRef, popoverAutoSizeOptions);
|
|
2940
2947
|
|
|
2941
2948
|
const loadPendingUploads = useCallback(async () => {
|
|
2942
2949
|
const sequence = ++recoveryLookupSequence.current;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type PopoverAutoSizeView = "recorder" | "memory" | "settings";
|
|
2
|
+
|
|
3
|
+
export function getPopoverAutoSizeOptions(
|
|
4
|
+
view: PopoverAutoSizeView,
|
|
5
|
+
popoverVisible: boolean,
|
|
6
|
+
recordingStartPending: boolean,
|
|
7
|
+
): {
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
width: number;
|
|
10
|
+
} {
|
|
11
|
+
const isSettings = view === "settings";
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
disabled: !isSettings && (!popoverVisible || recordingStartPending),
|
|
15
|
+
width: isSettings ? 720 : view === "memory" ? 440 : 320,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -1458,9 +1458,6 @@ pub async fn resize_popover(app: AppHandle, height: f64, width: Option<f64>) ->
|
|
|
1458
1458
|
if voice_woken {
|
|
1459
1459
|
return Ok(());
|
|
1460
1460
|
}
|
|
1461
|
-
if is_recording_active(&app) {
|
|
1462
|
-
return Ok(());
|
|
1463
|
-
}
|
|
1464
1461
|
if let Some(w) = app.get_webview_window("popover") {
|
|
1465
1462
|
let tray_center = app
|
|
1466
1463
|
.try_state::<TrayAnchor>()
|
|
@@ -51,6 +51,7 @@ interface DocumentBlockFieldsProps {
|
|
|
51
51
|
databaseId: string | null;
|
|
52
52
|
databaseDocumentId: string | null;
|
|
53
53
|
canEdit: boolean;
|
|
54
|
+
usePagePropertiesOnly?: boolean;
|
|
54
55
|
suggesting?: boolean;
|
|
55
56
|
enteringSuggestion?: boolean;
|
|
56
57
|
onPrimaryFieldAvailabilityChange?: (
|
|
@@ -276,6 +277,7 @@ export function DocumentBlockFields({
|
|
|
276
277
|
databaseId,
|
|
277
278
|
databaseDocumentId,
|
|
278
279
|
canEdit,
|
|
280
|
+
usePagePropertiesOnly = false,
|
|
279
281
|
suggesting = false,
|
|
280
282
|
enteringSuggestion = false,
|
|
281
283
|
onPrimaryFieldAvailabilityChange,
|
|
@@ -288,21 +290,26 @@ export function DocumentBlockFields({
|
|
|
288
290
|
() => documentPropertiesPlaceholder(documentId, databaseId, pageProperties),
|
|
289
291
|
[databaseId, documentId, pageProperties],
|
|
290
292
|
);
|
|
291
|
-
const query = useDocumentProperties(documentId, databaseId, {
|
|
293
|
+
const query = useDocumentProperties(documentId, databaseId, {
|
|
294
|
+
enabled: !usePagePropertiesOnly,
|
|
295
|
+
placeholder,
|
|
296
|
+
});
|
|
297
|
+
const propertiesData = usePagePropertiesOnly ? placeholder : query.data;
|
|
298
|
+
const hasQueryError = !usePagePropertiesOnly && query.isError;
|
|
292
299
|
const canEditFields =
|
|
293
300
|
canEdit &&
|
|
294
|
-
|
|
301
|
+
propertiesData?.canEditValues === true &&
|
|
295
302
|
databaseId !== null &&
|
|
296
303
|
databaseDocumentId !== null;
|
|
297
|
-
const properties =
|
|
304
|
+
const properties = propertiesData?.properties ?? [];
|
|
298
305
|
const blockFields = useMemo(
|
|
299
306
|
() => blockFieldsFromProperties(properties),
|
|
300
307
|
[properties],
|
|
301
308
|
);
|
|
302
309
|
|
|
303
|
-
const loaded = isLoadedForDocument(documentId, databaseId,
|
|
310
|
+
const loaded = isLoadedForDocument(documentId, databaseId, propertiesData);
|
|
304
311
|
const state = blockFieldsRenderState({ loaded, blockFields });
|
|
305
|
-
const primaryAvailable = !
|
|
312
|
+
const primaryAvailable = !hasQueryError && primaryBlocksFieldAvailable(state);
|
|
306
313
|
const scope = `${documentId}:${databaseId ?? ""}:${databaseDocumentId ?? ""}`;
|
|
307
314
|
useLayoutEffect(() => {
|
|
308
315
|
onPrimaryFieldAvailabilityChange?.(scope, primaryAvailable);
|
|
@@ -310,7 +317,7 @@ export function DocumentBlockFields({
|
|
|
310
317
|
|
|
311
318
|
// A failed property read is not an empty field list. Rendering the editor in
|
|
312
319
|
// that state could bind the body before we know which storage target owns it.
|
|
313
|
-
if (
|
|
320
|
+
if (hasQueryError) {
|
|
314
321
|
return (
|
|
315
322
|
<div
|
|
316
323
|
className={cn(BLOCK_FIELDS_GRID, "gap-1")}
|