From 04a0fc4e4d1b34c8c3f93641b6de9a5edf80f365 Mon Sep 17 00:00:00 2001 From: Magnus Holm Date: Wed, 24 Sep 2025 12:04:19 +0200 Subject: [PATCH] feat: add support for `source` in useDocumentPreview --- .../core/src/preview/getPreviewState.test.ts | 7 ++++- packages/core/src/preview/getPreviewState.ts | 8 ++++-- .../core/src/preview/resolvePreview.test.ts | 7 +++-- packages/core/src/preview/resolvePreview.ts | 5 ++-- .../src/hooks/preview/useDocumentPreview.tsx | 28 +++++++++++++------ 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/packages/core/src/preview/getPreviewState.test.ts b/packages/core/src/preview/getPreviewState.test.ts index 26865ea7d..ee2b2d937 100644 --- a/packages/core/src/preview/getPreviewState.test.ts +++ b/packages/core/src/preview/getPreviewState.test.ts @@ -1,6 +1,7 @@ import {NEVER} from 'rxjs' import {describe, it} from 'vitest' +import {sourceFor} from '../config/sanityConfig' import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance' import {type StoreState} from '../store/createStoreState' import {insecureRandomId} from '../utils/ids' @@ -18,7 +19,11 @@ vi.mock('./subscribeToStateAndFetchBatches.ts') describe('getPreviewState', () => { let instance: SanityInstance - const docHandle = {documentId: 'exampleId', documentType: 'exampleType'} + const docHandle = { + documentId: 'exampleId', + documentType: 'exampleType', + source: sourceFor({projectId: 'test', dataset: 'test'}), + } let state: StoreState beforeEach(() => { diff --git a/packages/core/src/preview/getPreviewState.ts b/packages/core/src/preview/getPreviewState.ts index d4ad0b988..1c35bcff8 100644 --- a/packages/core/src/preview/getPreviewState.ts +++ b/packages/core/src/preview/getPreviewState.ts @@ -1,6 +1,6 @@ import {omit} from 'lodash-es' -import {type DocumentHandle} from '../config/sanityConfig' +import {type DocumentSource} from '../config/sanityConfig' import {bindActionByDataset} from '../store/createActionBinder' import {type SanityInstance} from '../store/createSanityInstance' import { @@ -20,7 +20,11 @@ import {STABLE_EMPTY_PREVIEW} from './util' /** * @beta */ -export type GetPreviewStateOptions = DocumentHandle +export type GetPreviewStateOptions = { + documentId: string + documentType: string + source: DocumentSource +} /** * @beta diff --git a/packages/core/src/preview/resolvePreview.test.ts b/packages/core/src/preview/resolvePreview.test.ts index 74e19595f..34aed25c2 100644 --- a/packages/core/src/preview/resolvePreview.test.ts +++ b/packages/core/src/preview/resolvePreview.test.ts @@ -1,7 +1,7 @@ import {of} from 'rxjs' import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest' -import {createDocumentHandle} from '../config/handles' +import {sourceFor} from '../config/sanityConfig' import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance' import {type StateSource} from '../store/createStateSourceAction' import {getPreviewState} from './getPreviewState' @@ -31,10 +31,11 @@ describe('resolvePreview', () => { }) it('resolves a preview and returns the first emitted value with results', async () => { - const docHandle = createDocumentHandle({ + const docHandle = { documentId: 'doc123', documentType: 'movie', - }) + source: sourceFor({projectId: 'p', dataset: 'd'}), + } const result = await resolvePreview(instance, docHandle) diff --git a/packages/core/src/preview/resolvePreview.ts b/packages/core/src/preview/resolvePreview.ts index 3378328e1..9aedf980b 100644 --- a/packages/core/src/preview/resolvePreview.ts +++ b/packages/core/src/preview/resolvePreview.ts @@ -1,14 +1,13 @@ import {filter, firstValueFrom} from 'rxjs' -import {type DocumentHandle} from '../config/sanityConfig' import {bindActionByDataset} from '../store/createActionBinder' -import {getPreviewState} from './getPreviewState' +import {getPreviewState, type GetPreviewStateOptions} from './getPreviewState' import {previewStore} from './previewStore' /** * @beta */ -export type ResolvePreviewOptions = DocumentHandle +export type ResolvePreviewOptions = GetPreviewStateOptions /** * @beta diff --git a/packages/react/src/hooks/preview/useDocumentPreview.tsx b/packages/react/src/hooks/preview/useDocumentPreview.tsx index 82e766256..ced5ab3ef 100644 --- a/packages/react/src/hooks/preview/useDocumentPreview.tsx +++ b/packages/react/src/hooks/preview/useDocumentPreview.tsx @@ -1,14 +1,22 @@ -import {type DocumentHandle, getPreviewState, type PreviewValue, resolvePreview} from '@sanity/sdk' -import {useCallback, useSyncExternalStore} from 'react' +import { + getPreviewState, + type GetPreviewStateOptions, + type PreviewValue, + resolvePreview, +} from '@sanity/sdk' +import {useCallback, useMemo, useSyncExternalStore} from 'react' import {distinctUntilChanged, EMPTY, Observable, startWith, switchMap} from 'rxjs' -import {useSanityInstance} from '../context/useSanityInstance' +import {type SourceOptions} from '../../type' +import {useSanityInstanceAndSource} from '../context/useSanityInstance' /** * @public * @category Types */ -export interface useDocumentPreviewOptions extends DocumentHandle { +export interface useDocumentPreviewOptions + extends Omit, + SourceOptions { /** * Optional ref object to track visibility. When provided, preview resolution * only occurs when the referenced element is visible in the viewport. @@ -81,10 +89,14 @@ export interface useDocumentPreviewResults { */ export function useDocumentPreview({ ref, + projectId, + dataset, + source, ...docHandle }: useDocumentPreviewOptions): useDocumentPreviewResults { - const instance = useSanityInstance(docHandle) - const stateSource = getPreviewState(instance, docHandle) + const [instance, actualSource] = useSanityInstanceAndSource({projectId, dataset, source}) + const options = useMemo(() => ({...docHandle, source: actualSource}), [docHandle, actualSource]) + const stateSource = getPreviewState(instance, options) // Create subscribe function for useSyncExternalStore const subscribe = useCallback( @@ -131,9 +143,9 @@ export function useDocumentPreview({ // Create getSnapshot function to return current state const getSnapshot = useCallback(() => { const currentState = stateSource.getCurrent() - if (currentState.data === null) throw resolvePreview(instance, docHandle) + if (currentState.data === null) throw resolvePreview(instance, options) return currentState as useDocumentPreviewResults - }, [docHandle, instance, stateSource]) + }, [instance, options, stateSource]) return useSyncExternalStore(subscribe, getSnapshot) }