Skip to content

Commit 362c247

Browse files
authoredMar 13, 2025··
refactor(preview): clean up preview fallback logic (#8904)
1 parent 1a7aaa2 commit 362c247

File tree

8 files changed

+45
-24
lines changed

8 files changed

+45
-24
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {WarningOutlineIcon} from '@sanity/icons'
22
import {type PreviewValue, type SanityDocument} from '@sanity/types'
3-
import {assignWith} from 'lodash'
43

5-
export function getMissingDocumentFallback(document: Partial<SanityDocument> | PreviewValue) {
4+
function getMissingDocumentFallback(document: Partial<SanityDocument> | PreviewValue) {
65
return {
76
title: <em>{document.title ? String(document.title) : 'Missing document'}</em>,
87
subtitle: (
@@ -14,25 +13,34 @@ export function getMissingDocumentFallback(document: Partial<SanityDocument> | P
1413
}
1514
}
1615

16+
/**
17+
* @internal
18+
*/
19+
export type Sources = {
20+
/**
21+
* Preview snapshot with current perspective applied
22+
* This takes priority of original and fallback
23+
*/
24+
snapshot?: Partial<SanityDocument> | PreviewValue | null | undefined
25+
/**
26+
* Preview of the original document (e.g. without current perspective applied)
27+
*/
28+
original?: Partial<SanityDocument> | PreviewValue | null | undefined
29+
/**
30+
* last resort fallback in case we don't have anything to preview
31+
* this can be a hard-coded preview value, or a document stub
32+
*/
33+
fallback?: Partial<SanityDocument> | PreviewValue
34+
}
35+
36+
const EMPTY: {[key: string]: never} = {}
37+
1738
/**
1839
* Obtain document preview values used in <SanityPreview> and <SanityDefaultPreview> components.
1940
* Also displays fallback values if the document cannot be found.
2041
*
2142
* @internal
2243
*/
23-
export function getPreviewValueWithFallback({
24-
snapshot,
25-
original,
26-
document,
27-
}: {
28-
document?: Partial<SanityDocument> | PreviewValue | null | undefined
29-
snapshot?: Partial<SanityDocument> | PreviewValue | null | undefined
30-
original?: Partial<SanityDocument> | PreviewValue | null | undefined
31-
}) {
32-
if (document && !original && !snapshot) {
33-
return getMissingDocumentFallback(document)
34-
}
35-
return assignWith({}, snapshot, original, (objValue, srcValue) => {
36-
return typeof srcValue === 'undefined' ? objValue : srcValue
37-
}) as PreviewValue
44+
export function getPreviewValueWithFallback({snapshot, original, fallback}: Sources) {
45+
return snapshot || original || getMissingDocumentFallback(fallback || EMPTY)
3846
}

‎packages/sanity/src/core/releases/tool/detail/useBundleDocuments.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ const getPublishedArchivedReleaseDocumentsObservable = ({
229229
map(({snapshot}) => ({
230230
isLoading: false,
231231
values: prepareForPreview(
232-
getPreviewValueWithFallback({snapshot, original: document}),
232+
getPreviewValueWithFallback({snapshot, fallback: document}),
233233
schemaType,
234234
),
235235
})),

‎packages/sanity/src/core/studio/components/navbar/StudioNavbar.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function StudioNavbar(props: Omit<NavbarProps, 'renderDefault'>) {
8787
searchOpen,
8888
} = useContext(NavbarContext)
8989

90-
const {selectedPerspective} = usePerspective()
90+
const {selectedPerspective, perspectiveStack} = usePerspective()
9191

9292
const ToolMenu = useToolMenuComponent()
9393

@@ -265,6 +265,7 @@ export function StudioNavbar(props: Omit<NavbarProps, 'renderDefault'>) {
265265
onClose={handleCloseSearch}
266266
onOpen={handleOpenSearch}
267267
open={searchOpen}
268+
previewPerspective={perspectiveStack}
268269
/>
269270
)}
270271
</BoundaryElementProvider>

‎packages/sanity/src/core/studio/components/navbar/search/components/searchResults/item/SearchResultItem.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,14 @@ export function SearchResultItem({
6969
// should the search items be disasabled
7070
const disabledAction = (!hasCreatePermission && state.canDisableAction) || existsInRelease
7171

72+
const documentStub = useMemo(
73+
() => ({_id: documentId, _type: documentType}),
74+
[documentId, documentType],
75+
)
7276
const preview = useValuePreview({
7377
enabled: true,
7478
schemaType: type,
75-
value: {_id: documentId},
79+
value: documentStub,
7680
})
7781

7882
const handleClick = useCallback(
@@ -105,6 +109,7 @@ export function SearchResultItem({
105109
>
106110
<SearchResultItemPreview
107111
documentId={documentId}
112+
documentType={documentType}
108113
layout={layout}
109114
perspective={previewPerspective}
110115
presence={documentPresence}

‎packages/sanity/src/core/studio/components/navbar/search/components/searchResults/item/SearchResultItemPreview.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {type DocumentPresence, useDocumentPreviewStore} from '../../../../../../
1919

2020
interface SearchResultItemPreviewProps {
2121
documentId: string
22+
documentType: string
2223
layout?: GeneralPreviewLayoutKey
2324
presence?: DocumentPresence[]
2425
perspective?: PerspectiveStack
@@ -43,6 +44,7 @@ const SearchResultItemPreviewBox = styled(Box)`
4344
*/
4445
export function SearchResultItemPreview({
4546
documentId,
47+
documentType,
4648
layout,
4749
presence,
4850
schemaType,
@@ -55,6 +57,11 @@ export function SearchResultItemPreview({
5557
return getPreviewStateObservable(documentPreviewStore, schemaType, documentId, perspective)
5658
}, [documentPreviewStore, schemaType, documentId, perspective])
5759

60+
const documentStub = useMemo(
61+
() => ({_id: documentId, _type: documentType}),
62+
[documentId, documentType],
63+
)
64+
5865
const {isLoading, snapshot, original} = useObservable(observable, {
5966
snapshot: null,
6067
isLoading: true,
@@ -97,7 +104,7 @@ export function SearchResultItemPreview({
97104
return (
98105
<SearchResultItemPreviewBox>
99106
<SanityDefaultPreview
100-
{...getPreviewValueWithFallback({snapshot, original})}
107+
{...getPreviewValueWithFallback({snapshot, original, fallback: documentStub})}
101108
isPlaceholder={isLoading ?? true}
102109
layout={layout || 'default'}
103110
icon={schemaType.icon}

‎packages/sanity/src/core/tasks/components/form/fields/TargetField.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ function Preview(props: {value: TaskTarget; handleRemove: () => void}) {
122122
<Flex gap={1} align={'center'} justify={'space-between'}>
123123
<Card as={CardLink} radius={2} data-as="button">
124124
<SearchResultItemPreview
125+
documentType={documentType}
125126
documentId={value.document._ref}
126127
layout={'compact'}
127128
presence={documentPresence}

‎packages/sanity/src/presentation/editor/ContentEditor.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
type Path,
77
PreviewCard,
88
SanityDefaultPreview,
9-
type SanityDocument,
109
Translate,
1110
useSchema,
1211
useTranslation,
@@ -77,8 +76,8 @@ export function ContentEditor(props: {
7776
return (
7877
<SanityDefaultPreview
7978
{...getPreviewValueWithFallback({
80-
document: mainDocumentState!.document! as SanityDocument,
8179
snapshot: previewState.snapshot,
80+
fallback: mainDocumentState!.document,
8281
})}
8382
schemaType={schemaType}
8483
status={

‎packages/sanity/src/structure/components/paneItem/PaneItemPreview.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export function PaneItemPreview(props: PaneItemPreviewProps) {
8484

8585
return (
8686
<SanityDefaultPreview
87-
{...getPreviewValueWithFallback({document, snapshot, original})}
87+
{...getPreviewValueWithFallback({snapshot, original, fallback: value})}
8888
isPlaceholder={isLoading}
8989
icon={icon}
9090
layout={layout}

0 commit comments

Comments
 (0)
Please sign in to comment.