From 69d60cd42bbb6693ab53bc6b18ed6677bd92c10f Mon Sep 17 00:00:00 2001 From: Cody Olsen <81981+stipsan@users.noreply.github.com> Date: Mon, 20 Jan 2025 11:02:55 +0100 Subject: [PATCH] refactor: migrate `@sanity/presentation@corel` codebase (#8312) (#8317) --- dev/test-studio/preview/loader.tsx | 2 +- .../src/presentation/PresentationTool.tsx | 43 +----- .../src/presentation/RevisionSwitcher.tsx | 40 ------ packages/sanity/src/presentation/constants.ts | 2 +- .../presentation/editor/DocumentListPane.tsx | 2 +- .../sanity/src/presentation/i18n/resources.ts | 6 - .../src/presentation/loader/LiveQueries.tsx | 10 +- .../src/presentation/loader/LoaderQueries.tsx | 9 +- .../overlays/PostMessageDocuments.tsx | 14 +- .../overlays/schema/PostMessageSchema.tsx | 11 +- .../src/presentation/preview/Preview.tsx | 4 +- .../presentation/preview/PreviewHeader.tsx | 123 +----------------- .../presentation/preview/SharePreviewMenu.tsx | 14 +- packages/sanity/src/presentation/types.ts | 2 +- .../src/presentation/useDocumentsOnPage.ts | 12 +- .../sanity/src/presentation/usePreviewUrl.ts | 7 +- .../src/presentation/useVercelBypassSecret.ts | 5 +- .../util/encodeStudioPerspective.ts | 6 + .../presentation/util/useEffectOnChange.ts | 29 ----- pnpm-lock.yaml | 52 ++++---- 20 files changed, 104 insertions(+), 289 deletions(-) delete mode 100644 packages/sanity/src/presentation/RevisionSwitcher.tsx create mode 100644 packages/sanity/src/presentation/util/encodeStudioPerspective.ts delete mode 100644 packages/sanity/src/presentation/util/useEffectOnChange.ts diff --git a/dev/test-studio/preview/loader.tsx b/dev/test-studio/preview/loader.tsx index 0645b88a26f..c8c2989b317 100644 --- a/dev/test-studio/preview/loader.tsx +++ b/dev/test-studio/preview/loader.tsx @@ -6,7 +6,7 @@ const client = createClient({ projectId: 'ppsg7ml5', dataset: 'playground', useCdn: true, - apiVersion: '2023-02-06', + apiVersion: 'X', stega: { enabled: true, studioUrl: '/presentation', diff --git a/packages/sanity/src/presentation/PresentationTool.tsx b/packages/sanity/src/presentation/PresentationTool.tsx index 418c661f8df..52de6213183 100644 --- a/packages/sanity/src/presentation/PresentationTool.tsx +++ b/packages/sanity/src/presentation/PresentationTool.tsx @@ -25,6 +25,7 @@ import { type SanityDocument, type Tool, useDataset, + usePerspective, useProjectId, useUnique, useWorkspace, @@ -52,7 +53,6 @@ import { presentationReducer, presentationReducerInit, } from './reducers/presentationReducer' -import {RevisionSwitcher} from './RevisionSwitcher' import { type FrameState, type PresentationNavigate, @@ -106,11 +106,15 @@ export default function PresentationTool(props: { state: PresentationStateParams } const routerSearchParams = useUnique(Object.fromEntries(routerState._searchParams || [])) + const {perspectiveStack, selectedPerspectiveName = 'previewDrafts'} = usePerspective() + const perspective = ( + selectedPerspectiveName.startsWith('r') ? perspectiveStack : selectedPerspectiveName + ) as PresentationPerspective const initialPreviewUrl = usePreviewUrl( _previewUrl || '/', name, - routerSearchParams.perspective === 'published' ? 'published' : 'previewDrafts', + perspective, routerSearchParams.preview || null, canCreateUrlPreviewSecrets, ) @@ -180,11 +184,6 @@ export default function PresentationTool(props: { const [state, dispatch] = useReducer(presentationReducer, {}, presentationReducerInit) - const perspective = useMemo( - () => (params.perspective ? 'published' : 'previewDrafts'), - [params.perspective], - ) - const viewport = useMemo(() => (params.viewport ? 'mobile' : 'desktop'), [params.viewport]) const [documentsOnPage, setDocumentsOnPage] = useDocumentsOnPage(perspective, frameStateRef) @@ -308,7 +307,6 @@ export default function PresentationTool(props: { const stop = comlink.start() setVisualEditingComlink(comlink) - return () => { stop() setVisualEditingComlink(null) @@ -436,15 +434,6 @@ export default function PresentationTool(props: { unstable_navigator, }) - // Handle edge case where the `&rev=` parameter gets "stuck" - const idRef = useRef(params.id) - useEffect(() => { - if (params.rev && idRef.current && params.id !== idRef.current) { - navigate({}, {rev: undefined}) - } - idRef.current = params.id - }) - const refreshRef = useRef(undefined) const handleRefresh = useCallback( (fallback: () => void) => { @@ -498,16 +487,6 @@ export default function PresentationTool(props: { [navigate], ) - const setPerspective = useCallback( - (next: PresentationPerspective) => { - // Omit the perspective URL search param if the next perspective state is - // the default: 'previewDrafts' - const perspective = next === 'previewDrafts' ? undefined : next - navigate({}, {perspective}) - }, - [navigate], - ) - return ( <> )} {visualEditingComlink && } - {params.id && params.type && ( - - )} ) diff --git a/packages/sanity/src/presentation/RevisionSwitcher.tsx b/packages/sanity/src/presentation/RevisionSwitcher.tsx deleted file mode 100644 index 8130b7b78e2..00000000000 --- a/packages/sanity/src/presentation/RevisionSwitcher.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import {type FunctionComponent} from 'react' -import {useEditState} from 'sanity' - -import {type PresentationNavigate} from './types' -import {useEffectOnChange} from './util/useEffectOnChange' - -interface RevisionSwitcherProps { - documentId: string - documentRevision: string | undefined - documentType: string - navigate: PresentationNavigate - perspective: 'previewDrafts' | 'published' -} - -/** - * Renderless component to handle displaying the correct revision when the - * perspective is switched. When the perspective changes to 'published', the - * `rev` parameter correpsonding to the published document is resolved from the - * published edit state. When the perspective changes to 'previewDrafts', the - * `rev` parameter is removed, as the latest draft should be displayed. - * @internal - */ -export const RevisionSwitcher: FunctionComponent = function (props) { - const {documentId, documentType, navigate, perspective, documentRevision} = props - - const editState = useEditState(documentId, documentType) - - useEffectOnChange(perspective, (value) => { - let rev: string | undefined = undefined - if (value === 'published' && editState.published) { - const {_updatedAt, _rev} = editState.published - rev = `${_updatedAt}/${_rev}` - } - if (documentRevision !== rev) { - navigate({}, {rev}, true) - } - }) - - return null -} diff --git a/packages/sanity/src/presentation/constants.ts b/packages/sanity/src/presentation/constants.ts index 4451b666211..1704766bfa0 100644 --- a/packages/sanity/src/presentation/constants.ts +++ b/packages/sanity/src/presentation/constants.ts @@ -10,7 +10,7 @@ export const EDIT_INTENT_MODE = 'presentation' export const MAX_TIME_TO_OVERLAYS_CONNECTION = 3_000 // ms // The API version to use when using `@sanity/client` -export const API_VERSION = '2023-10-16' +export const API_VERSION = 'vX' // Heartbeats shouldn't fire on intervals that are so short it causes performance issues export const MIN_LOADER_QUERY_LISTEN_HEARTBEAT_INTERVAL = 1000 // ms diff --git a/packages/sanity/src/presentation/editor/DocumentListPane.tsx b/packages/sanity/src/presentation/editor/DocumentListPane.tsx index b5ca2b98894..13f2cb4994a 100644 --- a/packages/sanity/src/presentation/editor/DocumentListPane.tsx +++ b/packages/sanity/src/presentation/editor/DocumentListPane.tsx @@ -50,7 +50,7 @@ export function DocumentListPane(props: { () => refs .filter((r) => getPublishedId(r._id) !== mainDocumentState?.document?._id) - .map((r) => r._id), + .map((r) => getPublishedId(r._id)), [mainDocumentState, refs], ) diff --git a/packages/sanity/src/presentation/i18n/resources.ts b/packages/sanity/src/presentation/i18n/resources.ts index 8d4eb41cce1..8338101f791 100644 --- a/packages/sanity/src/presentation/i18n/resources.ts +++ b/packages/sanity/src/presentation/i18n/resources.ts @@ -51,14 +51,8 @@ export default { 'preview-frame.overlay.toggle-button.tooltip_disable': 'Disable edit overlay', /** The text shown on the overlay toggle tooltip when overlays are disabled */ 'preview-frame.overlay.toggle-button.tooltip_enable': 'Enable edit overlay', - /** The text description for the previewDrafts perspective switcher menu item */ - 'preview-frame.perspective.previewDrafts.text': 'View this page with latest draft content', - /** The title for the previewDrafts perspective switcher menu item */ - 'preview-frame.perspective.previewDrafts.title': 'Drafts', /** The text description for the published perspective switcher menu item */ 'preview-frame.perspective.published.text': 'View this page with published content', - /** The title for the published perspective switcher menu item */ - 'preview-frame.perspective.published.title': 'Published', /** The `aria-label` for the refresh button */ 'preview-frame.refresh-button.aria-label': 'Refresh preview', /** The tooltip text for the refresh button */ diff --git a/packages/sanity/src/presentation/loader/LiveQueries.tsx b/packages/sanity/src/presentation/loader/LiveQueries.tsx index e293b87309f..45d2f2ec9fb 100644 --- a/packages/sanity/src/presentation/loader/LiveQueries.tsx +++ b/packages/sanity/src/presentation/loader/LiveQueries.tsx @@ -33,7 +33,7 @@ import { import {useEffectEvent} from 'use-effect-event' // import {useEffectEvent} from 'use-effect-event' -import {MIN_LOADER_QUERY_LISTEN_HEARTBEAT_INTERVAL} from '../constants' +import {API_VERSION, MIN_LOADER_QUERY_LISTEN_HEARTBEAT_INTERVAL} from '../constants' import { type LiveQueriesState, type LiveQueriesStateValue, @@ -184,7 +184,7 @@ export default function LoaderQueries(props: LoaderQueriesProps): React.JSX.Elem const [syncTagsInUse] = useState(() => new Set()) const [lastLiveEventId, setLastLiveEventId] = useState(null) - const studioClient = useClient({apiVersion: '2023-10-16'}) + const studioClient = useClient({apiVersion: API_VERSION}) const clientConfig = useMemo(() => studioClient.config(), [studioClient]) const client = useMemo( () => @@ -483,7 +483,11 @@ export function turboChargeResultIfSourceMap( } return changedValue }, - perspective, + // TODO: Update applySourceDocuments to support releases. + Array.isArray(perspective) && + perspective.some((part) => typeof part === 'string' && part.startsWith('r') && part !== 'raw') + ? 'previewDrafts' + : (perspective as ClientPerspective), ) } diff --git a/packages/sanity/src/presentation/loader/LoaderQueries.tsx b/packages/sanity/src/presentation/loader/LoaderQueries.tsx index 103e69e051b..e5c5f44badf 100644 --- a/packages/sanity/src/presentation/loader/LoaderQueries.tsx +++ b/packages/sanity/src/presentation/loader/LoaderQueries.tsx @@ -30,6 +30,7 @@ import { } from 'sanity' import { + API_VERSION, LIVE_QUERY_CACHE_BATCH_SIZE, LIVE_QUERY_CACHE_SIZE, MIN_LOADER_QUERY_LISTEN_HEARTBEAT_INTERVAL, @@ -161,7 +162,7 @@ export default function LoaderQueries(props: LoaderQueriesProps): React.JSX.Elem }, [controller, dataset, onDocumentsOnPage, onLoadersConnection, projectId]) const [cache] = useState(() => new LRUCache(LIVE_QUERY_CACHE_SIZE)) - const studioClient = useClient({apiVersion: '2023-10-16'}) + const studioClient = useClient({apiVersion: API_VERSION}) const clientConfig = useMemo(() => studioClient.config(), [studioClient]) const client = useMemo( () => @@ -553,7 +554,11 @@ export function turboChargeResultIfSourceMap( } return changedValue }, - perspective, + // TODO: Update applySourceDocuments to support releases. + Array.isArray(perspective) && + perspective.some((part) => typeof part === 'string' && part.startsWith('r') && part !== 'raw') + ? 'previewDrafts' + : (perspective as ClientPerspective), ) } diff --git a/packages/sanity/src/presentation/overlays/PostMessageDocuments.tsx b/packages/sanity/src/presentation/overlays/PostMessageDocuments.tsx index e45c4ae8a50..1953f043d9e 100644 --- a/packages/sanity/src/presentation/overlays/PostMessageDocuments.tsx +++ b/packages/sanity/src/presentation/overlays/PostMessageDocuments.tsx @@ -1,7 +1,7 @@ import {type MutationEvent, type ReconnectEvent, type WelcomeEvent} from '@sanity/client' import {type FunctionComponent, memo, useEffect} from 'react' import {filter, first, merge, shareReplay} from 'rxjs' -import {useClient} from 'sanity' +import {isDraftId, useClient} from 'sanity' import {API_VERSION} from '../constants' import {type VisualEditingConnection} from '../types' @@ -79,7 +79,17 @@ const PostMessageDocuments: FunctionComponent = (prop useEffect(() => { return comlink.on('visual-editing/fetch-snapshot', async (data) => { - const snapshot = await client.getDocument(data.documentId, { + /** + * This is a temporary hack to get around the fact that the `drafts.versions.versionName.id` format is not supported + * `versions.` don't have draft documents. + * + * Where is the drafts. prefix coming from and why it's added to the `versions.` documents? + * */ + const cleanId = + data.documentId.includes('versions.') && isDraftId(data.documentId) + ? data.documentId.replace('drafts.', '') + : data.documentId + const snapshot = await client.getDocument(cleanId, { tag: 'document.snapshots', }) return {snapshot} diff --git a/packages/sanity/src/presentation/overlays/schema/PostMessageSchema.tsx b/packages/sanity/src/presentation/overlays/schema/PostMessageSchema.tsx index ece648a7dc5..73446cc09c3 100644 --- a/packages/sanity/src/presentation/overlays/schema/PostMessageSchema.tsx +++ b/packages/sanity/src/presentation/overlays/schema/PostMessageSchema.tsx @@ -3,7 +3,7 @@ import {type ClientPerspective} from '@sanity/client' import {type UnresolvedPath} from '@sanity/presentation-comlink' import {useRootTheme} from '@sanity/ui' import {memo, useEffect} from 'react' -import {useClient, useWorkspace} from 'sanity' +import {getPublishedId, useClient, useWorkspace} from 'sanity' import {API_VERSION} from '../../constants' import {type VisualEditingConnection} from '../../types' @@ -67,7 +67,14 @@ function PostMessageSchema(props: PostMessageSchemaProps): React.JSX.Element | n const arr = Array.from(paths) const projection = arr.map((path, i) => `"${i}": ${path}[0]._type`).join(',') const query = `*[_id == $id][0]{${projection}}` - const result = await client.fetch(query, {id}, {perspective, tag: 'presentation-schema'}) + const result = await client.fetch( + query, + {id: getPublishedId(id)}, + { + tag: 'presentation-schema', + perspective, + }, + ) const mapped = arr.map((path, i) => ({path: path, type: result[i]})) return {id, paths: mapped} }), diff --git a/packages/sanity/src/presentation/preview/Preview.tsx b/packages/sanity/src/presentation/preview/Preview.tsx index 81837f8df87..82692e692a6 100644 --- a/packages/sanity/src/presentation/preview/Preview.tsx +++ b/packages/sanity/src/presentation/preview/Preview.tsx @@ -38,6 +38,7 @@ import { type PresentationViewport, } from '../types' import {usePresentationTool} from '../usePresentationTool' +import {encodeStudioPerspective} from '../util/encodeStudioPerspective' import {IFrame} from './IFrame' import {usePresentationPreviewHeader} from './PreviewHeader' @@ -59,7 +60,6 @@ export interface PreviewProps extends Pick void setViewport: (mode: 'desktop' | 'mobile') => void targetOrigin: string toggleNavigator?: () => void @@ -86,7 +86,7 @@ export const Preview = memo( const url = new URL(initialUrl) // Always set the perspective that's being used, even if preview mode isn't configured if (!url.searchParams.get(urlSearchParamPreviewPerspective)) { - url.searchParams.set(urlSearchParamPreviewPerspective, perspective) + url.searchParams.set(urlSearchParamPreviewPerspective, encodeStudioPerspective(perspective)) } if (vercelProtectionBypass || url.searchParams.get(urlSearchParamVercelProtectionBypass)) { diff --git a/packages/sanity/src/presentation/preview/PreviewHeader.tsx b/packages/sanity/src/presentation/preview/PreviewHeader.tsx index 1a91e8dd8cd..bb9083266c9 100644 --- a/packages/sanity/src/presentation/preview/PreviewHeader.tsx +++ b/packages/sanity/src/presentation/preview/PreviewHeader.tsx @@ -1,37 +1,18 @@ -import { - CheckmarkIcon, - ChevronDownIcon, - DesktopIcon, - EditIcon, - MobileDeviceIcon, - PanelLeftIcon, - PublishIcon, - RefreshIcon, -} from '@sanity/icons' +import {DesktopIcon, MobileDeviceIcon, PanelLeftIcon, RefreshIcon} from '@sanity/icons' import {withoutSecretSearchParams} from '@sanity/preview-url-secret/without-secret-search-params' -import {Box, type ButtonTone, Card, Flex, Hotkeys, Menu, Stack, Switch, Text} from '@sanity/ui' +import {Box, Card, Flex, Hotkeys, Switch, Text} from '@sanity/ui' import {type ReactNode, type RefObject, useCallback, useMemo} from 'react' import {useTranslation} from 'sanity' -import {Button, MenuButton, MenuItem, Tooltip} from '../../ui-components' +import {Button, Tooltip} from '../../ui-components' import {presentationLocaleNamespace} from '../i18n' import {ACTION_IFRAME_RELOAD} from '../reducers/presentationReducer' -import {type HeaderOptions, type PresentationPerspective} from '../types' +import {type HeaderOptions} from '../types' import {OpenPreviewButton} from './OpenPreviewButton' import {type PreviewProps} from './Preview' import {PreviewLocationInput} from './PreviewLocationInput' import {SharePreviewMenu} from './SharePreviewMenu' -const PERSPECTIVE_TITLE_KEY: Record = { - previewDrafts: 'preview-frame.perspective.previewDrafts.title', - published: 'preview-frame.perspective.published.title', -} - -const PERSPECTIVE_TONES: Record = { - previewDrafts: 'caution', - published: 'positive', -} - /** @public */ export interface PreviewHeaderProps extends PreviewProps { iframeRef: RefObject @@ -47,7 +28,6 @@ const PreviewHeaderDefault = (props: Omit) iframe, iframeRef, initialUrl, - loadersConnection, navigatorEnabled, onPathChange, onRefresh, @@ -55,7 +35,6 @@ const PreviewHeaderDefault = (props: Omit) overlaysConnection, perspective, previewUrl, - setPerspective, setViewport, targetOrigin, toggleNavigator, @@ -204,100 +183,6 @@ const PreviewHeaderDefault = (props: Omit) /> - - - } - id="perspective-menu" - menu={ - - setPerspective('previewDrafts')} - pressed={perspective === 'previewDrafts'} - tone={PERSPECTIVE_TONES.previewDrafts} - renderMenuItem={() => ( - - - - - - - - - {t(PERSPECTIVE_TITLE_KEY.previewDrafts)} - - - {t('preview-frame.perspective.previewDrafts.text')} - - - - - - - - - )} - /> - setPerspective('published')} - pressed={perspective === 'published'} - tone={PERSPECTIVE_TONES.published} - renderMenuItem={() => ( - - - - - - - - - {t(PERSPECTIVE_TITLE_KEY.published)} - - - {t('preview-frame.perspective.published.text')} - - - - - - - - - )} - /> - - } - popover={{ - constrainSize: true, - placement: 'bottom', - portal: true, - }} - /> - - import('./QRCodeSVG')) @@ -37,7 +38,7 @@ export interface SharePreviewMenuProps { canUseSharedPreviewAccess: boolean previewLocationRoute: string initialUrl: PreviewProps['initialUrl'] - perspective: string + perspective: ClientPerspective } const QrCodeLogoSize = 24 @@ -78,7 +79,14 @@ export const SharePreviewMenu = memo(function SharePreviewMenuComponent( const busy = enabling || disabling || loading const url = useMemo( () => - secret ? setSecretSearchParams(initialUrl, secret, previewLocationRoute, perspective) : null, + secret + ? setSecretSearchParams( + initialUrl, + secret, + previewLocationRoute, + encodeStudioPerspective(perspective), + ) + : null, [initialUrl, perspective, previewLocationRoute, secret], ) diff --git a/packages/sanity/src/presentation/types.ts b/packages/sanity/src/presentation/types.ts index d1d2c5ebe61..8ae199706e7 100644 --- a/packages/sanity/src/presentation/types.ts +++ b/packages/sanity/src/presentation/types.ts @@ -252,7 +252,7 @@ export type PresentationNavigate = ( ) => void /** @public */ -export type PresentationPerspective = Extract<'published' | 'previewDrafts', ClientPerspective> +export type PresentationPerspective = Exclude /** @public */ export type PresentationViewport = 'desktop' | 'mobile' diff --git a/packages/sanity/src/presentation/useDocumentsOnPage.ts b/packages/sanity/src/presentation/useDocumentsOnPage.ts index 11775da1611..00f0cb5d7e2 100644 --- a/packages/sanity/src/presentation/useDocumentsOnPage.ts +++ b/packages/sanity/src/presentation/useDocumentsOnPage.ts @@ -1,4 +1,4 @@ -import {type ClientPerspective} from '@sanity/client' +import {validateApiPerspective} from '@sanity/client' import isEqual from 'fast-deep-equal' import {type MutableRefObject, useCallback, useMemo, useRef, useState} from 'react' @@ -15,6 +15,10 @@ type KeyedDocumentCache = Record const warnOnceAboutCrossDatasetReference = defineWarnOnce() +/** + * @TODO should be refactored to an lru-cache that is keyed by the perspective, which could be an array (if it is, it should use consistent sorting), + * and the url path (optionally the origin too), so that swapping between perspectives and urls is fast. + */ export function useDocumentsOnPage( perspective: PresentationPerspective, frameStateRef: MutableRefObject, @@ -22,9 +26,7 @@ export function useDocumentsOnPage( DocumentOnPage[], (key: string, perspective: PresentationPerspective, state: DocumentOnPage[]) => void, ] { - if (perspective !== 'published' && perspective !== 'previewDrafts') { - throw new Error(`Invalid perspective: ${perspective}`) - } + validateApiPerspective(perspective) const [published, setPublished] = useState({}) const [previewDrafts, setPreviewDrafts] = useState({}) @@ -35,7 +37,7 @@ export function useDocumentsOnPage( const setDocumentsOnPage = useCallback( // eslint-disable-next-line @typescript-eslint/no-shadow - (key: string, perspective: ClientPerspective, sourceDocuments: DocumentOnPage[] = []) => { + (key: string, perspective: PresentationPerspective, sourceDocuments: DocumentOnPage[] = []) => { const documents = sourceDocuments.filter((sourceDocument) => { if ('_projectId' in sourceDocument && sourceDocument._projectId) { // eslint-disable-next-line no-warning-comments diff --git a/packages/sanity/src/presentation/usePreviewUrl.ts b/packages/sanity/src/presentation/usePreviewUrl.ts index 09a4108d6bd..90fdd71af49 100644 --- a/packages/sanity/src/presentation/usePreviewUrl.ts +++ b/packages/sanity/src/presentation/usePreviewUrl.ts @@ -5,12 +5,13 @@ import {type SanityClient, useActiveWorkspace, useClient, useCurrentUser} from ' import {suspend} from 'suspend-react' import {API_VERSION} from './constants' -import {type PreviewUrlOption} from './types' +import {type PresentationPerspective, type PreviewUrlOption} from './types' +import {encodeStudioPerspective} from './util/encodeStudioPerspective' export function usePreviewUrl( previewUrl: PreviewUrlOption, toolName: string, - studioPreviewPerspective: 'published' | 'previewDrafts', + studioPreviewPerspective: PresentationPerspective, previewSearchParam: string | null, canCreateUrlPreviewSecrets: boolean, ): URL { @@ -53,7 +54,7 @@ export function usePreviewUrl( const resolvedUrl = await resolvePreviewUrl({ client, previewUrlSecret: previewUrlSecret!, - studioPreviewPerspective, + studioPreviewPerspective: encodeStudioPerspective(studioPreviewPerspective), previewSearchParam, studioBasePath: basePath, }) diff --git a/packages/sanity/src/presentation/useVercelBypassSecret.ts b/packages/sanity/src/presentation/useVercelBypassSecret.ts index d807877e570..6dec51116ed 100644 --- a/packages/sanity/src/presentation/useVercelBypassSecret.ts +++ b/packages/sanity/src/presentation/useVercelBypassSecret.ts @@ -1,15 +1,16 @@ -import {apiVersion} from '@sanity/preview-url-secret/constants' import {subcribeToVercelProtectionBypass} from '@sanity/preview-url-secret/toggle-vercel-protection-bypass' import {useEffect, useReducer, useState} from 'react' import {useClient} from 'sanity' +import {API_VERSION} from './constants' + type VercelProtectionBypassReadyState = 'loading' | 'ready' export function useVercelBypassSecret(): [ vercelProtectionBypassSecret: string | null, vercelProtectionBypassReadyState: VercelProtectionBypassReadyState, ] { - const client = useClient({apiVersion}) + const client = useClient({apiVersion: API_VERSION}) const [vercelProtectionBypassReadyState, ready] = useReducer( () => 'ready' as 'ready' | 'loading', 'loading', diff --git a/packages/sanity/src/presentation/util/encodeStudioPerspective.ts b/packages/sanity/src/presentation/util/encodeStudioPerspective.ts new file mode 100644 index 00000000000..c07aa09aafd --- /dev/null +++ b/packages/sanity/src/presentation/util/encodeStudioPerspective.ts @@ -0,0 +1,6 @@ +/** + * When encoding the current studio perspective it's necessary to deal with it sometimes being an array, in a consistent way. + */ +export function encodeStudioPerspective(studioPerspective: string[] | string): string { + return Array.isArray(studioPerspective) ? studioPerspective.join(',') : studioPerspective +} diff --git a/packages/sanity/src/presentation/util/useEffectOnChange.ts b/packages/sanity/src/presentation/util/useEffectOnChange.ts deleted file mode 100644 index cb1d6b92043..00000000000 --- a/packages/sanity/src/presentation/util/useEffectOnChange.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {useEffect, useRef} from 'react' -import {useEffectEvent} from 'use-effect-event' - -/** - * Similar to `useEffect`, but only execute the callback on value change. - * @param value - The value to watch for changes. - * @param callback - The callback to execute when the value changes. - * @param initialValue - An optional initial value to compare against. - * @param comparator - An optional comparator function for determining changes, useful if the value is non-primitive. Should return true if the callback should be executed. - * @internal - */ -export function useEffectOnChange( - value: T, - _callback: (value: T, prevValue: T | undefined) => void | (() => void), - initialValue?: T, - comparator?: (a: T, b?: T) => boolean | undefined, -): void { - const previousValueRef = useRef(initialValue) - const callback = useEffectEvent(_callback) - - useEffect(() => { - const prev = previousValueRef.current - previousValueRef.current = value - if (comparator ? comparator(value, prev) : value !== prev) { - return callback(value, prev) - } - return undefined - }, [callback, comparator, value]) -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1c13e7359c1..f05bce00281 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,7 +123,7 @@ importers: version: 9.1.0(eslint@8.57.1) eslint-config-sanity: specifier: ^7.1.2 - version: 7.1.3(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.2(eslint@8.57.1))(eslint@8.57.1) + version: 7.1.3(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-plugin-import@2.31.0)(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.2(eslint@8.57.1))(eslint@8.57.1) eslint-config-turbo: specifier: ^2.1.2 version: 2.3.3(eslint@8.57.1) @@ -132,7 +132,7 @@ importers: version: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) eslint-plugin-boundaries: specifier: ^4.2.2 - version: 4.2.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + version: 4.2.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) eslint-plugin-import: specifier: ^2.30.0 version: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) @@ -177,7 +177,7 @@ importers: version: 4.1.0 lerna: specifier: ^8.1.9 - version: 8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13) + version: 8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15))(babel-plugin-macros@3.1.0)(encoding@0.1.13) lint-staged: specifier: ^12.1.2 version: 12.5.0(enquirer@2.3.6) @@ -1986,7 +1986,7 @@ importers: version: 0.21.5 ts-node: specifier: ^10.9.2 - version: 10.9.2(@swc/core@1.10.1)(@types/node@18.19.68)(typescript@5.7.3) + version: 10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@18.19.68)(typescript@5.7.3) typescript: specifier: 5.7.3 version: 5.7.3 @@ -13561,12 +13561,12 @@ snapshots: '@juggle/resize-observer@3.4.0': {} - '@lerna/create@8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(typescript@5.7.3)': + '@lerna/create@8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15))(babel-plugin-macros@3.1.0)(encoding@0.1.13)(typescript@5.7.3)': dependencies: '@npmcli/arborist': 7.5.4 '@npmcli/package-json': 5.2.0 '@npmcli/run-script': 8.1.0 - '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1)) + '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15))) '@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/rest': 19.0.11(encoding@0.1.13) aproba: 2.0.0 @@ -13605,7 +13605,7 @@ snapshots: npm-package-arg: 11.0.2 npm-packlist: 8.0.2 npm-registry-fetch: 17.1.0 - nx: 20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1) + nx: 20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15)) p-map: 4.0.0 p-map-series: 2.1.0 p-queue: 6.6.2 @@ -14100,13 +14100,13 @@ snapshots: - bluebird - supports-color - '@nx/devkit@20.2.2(nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1))': + '@nx/devkit@20.2.2(nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15)))': dependencies: ejs: 3.1.10 enquirer: 2.3.6 ignore: 5.3.2 minimatch: 9.0.3 - nx: 20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1) + nx: 20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15)) semver: 7.6.3 tmp: 0.2.3 tslib: 2.8.1 @@ -16156,14 +16156,6 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.8(vite@6.0.7(@types/node@18.19.68)(terser@5.37.0)(yaml@2.6.1))': - dependencies: - '@vitest/spy': 2.1.8 - estree-walker: 3.0.3 - magic-string: 0.30.17 - optionalDependencies: - vite: 6.0.7(@types/node@18.19.68)(terser@5.37.0)(yaml@2.6.1) - '@vitest/mocker@2.1.8(vite@6.0.7(@types/node@22.10.2)(terser@5.37.0)(yaml@2.6.1))': dependencies: '@vitest/spy': 2.1.8 @@ -18001,7 +17993,7 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-config-sanity@7.1.3(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.2(eslint@8.57.1))(eslint@8.57.1): + eslint-config-sanity@7.1.3(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-plugin-import@2.31.0)(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.2(eslint@8.57.1))(eslint@8.57.1): dependencies: eslint: 8.57.1 eslint-plugin-simple-import-sort: 12.1.1(eslint@8.57.1) @@ -18041,7 +18033,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -18052,7 +18044,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -18063,12 +18055,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-boundaries@4.2.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-boundaries@4.2.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): dependencies: chalk: 4.1.2 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) micromatch: 4.0.7 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -18092,7 +18084,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.0 is-glob: 4.0.3 @@ -19918,13 +19910,13 @@ snapshots: dependencies: readable-stream: 2.3.8 - lerna@8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13): + lerna@8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15))(babel-plugin-macros@3.1.0)(encoding@0.1.13): dependencies: - '@lerna/create': 8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(typescript@5.7.3) + '@lerna/create': 8.1.9(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15))(babel-plugin-macros@3.1.0)(encoding@0.1.13)(typescript@5.7.3) '@npmcli/arborist': 7.5.4 '@npmcli/package-json': 5.2.0 '@npmcli/run-script': 8.1.0 - '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1)) + '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15))) '@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/rest': 19.0.11(encoding@0.1.13) aproba: 2.0.0 @@ -19969,7 +19961,7 @@ snapshots: npm-package-arg: 11.0.2 npm-packlist: 8.0.2 npm-registry-fetch: 17.1.0 - nx: 20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1) + nx: 20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15)) p-map: 4.0.0 p-map-series: 2.1.0 p-pipe: 3.1.0 @@ -20740,7 +20732,7 @@ snapshots: nwsapi@2.2.16: {} - nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1)(typescript@5.7.3))(@swc/core@1.10.1): + nx@20.2.2(@swc-node/register@1.10.9(@swc/core@1.10.1(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.3))(@swc/core@1.10.1(@swc/helpers@0.5.15)): dependencies: '@napi-rs/wasm-runtime': 0.2.4 '@yarnpkg/lockfile': 1.1.0 @@ -23132,7 +23124,7 @@ snapshots: dependencies: typescript: 5.7.3 - ts-node@10.9.2(@swc/core@1.10.1)(@types/node@18.19.68)(typescript@5.7.3): + ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@18.19.68)(typescript@5.7.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -23590,7 +23582,7 @@ snapshots: vitest@2.1.8(@types/node@18.19.68)(jsdom@25.0.1)(terser@5.37.0)(yaml@2.6.1): dependencies: '@vitest/expect': 2.1.8 - '@vitest/mocker': 2.1.8(vite@6.0.7(@types/node@18.19.68)(terser@5.37.0)(yaml@2.6.1)) + '@vitest/mocker': 2.1.8(vite@6.0.7(@types/node@22.10.2)(terser@5.37.0)(yaml@2.6.1)) '@vitest/pretty-format': 2.1.8 '@vitest/runner': 2.1.8 '@vitest/snapshot': 2.1.8