UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

1 lines • 62.9 kB
{"version":3,"file":"presentation.mjs","sources":["../../src/presentation/overlays/useSharedState.ts","../../src/presentation/constants.ts","../../src/presentation/util/props.ts","../../src/presentation/useDocumentLocations.ts","../../src/presentation/i18n/index.ts","../../src/presentation/usePresentationTool.ts","../../src/presentation/document/useCurrentPresentationToolName.ts","../../src/presentation/document/LocationsBanner.tsx","../../src/presentation/document/PresentationDocumentHeader.tsx","../../src/presentation/document/PresentationDocumentProvider.tsx","../../src/presentation/fieldActions/openInStructure.ts","../../src/presentation/getIntentState.ts","../../src/presentation/PresentationSpinner.tsx","../../src/presentation/router.ts","../../src/presentation/plugin.tsx","../../src/presentation/reducers/presentationReducer.ts","../../src/presentation/usePresentationNavigate.ts","../../src/presentation/usePresentationParams.ts"],"sourcesContent":["import {type Serializable} from '@sanity/presentation-comlink'\nimport {useContext, useEffect} from 'react'\nimport {PresentationSharedStateContext} from 'sanity/_singletons'\n\n/** @public */\nexport const useSharedState = (key: string, value: Serializable): undefined => {\n const context = useContext(PresentationSharedStateContext)\n\n if (!context) {\n throw new Error('Preview Snapshots context is missing')\n }\n\n const {setValue} = context\n\n useEffect(() => {\n setValue(key, value)\n }, [key, value, setValue])\n\n return undefined\n}\n","import {ComposeIcon} from '@sanity/icons'\nimport {apiVersion} from '@sanity/preview-url-secret/constants'\n\nexport const DEFAULT_TOOL_ICON = ComposeIcon\nexport const DEFAULT_TOOL_NAME = 'presentation'\nexport const DEFAULT_TOOL_TITLE = 'Presentation'\n\nexport const EDIT_INTENT_MODE = 'presentation'\n\n// How long we wait until an iframe is loaded until we consider it to be slow and possibly failed\nexport const MAX_TIME_TO_OVERLAYS_CONNECTION = 3_000 // ms\n\n// The API version to use when using `@sanity/client`\nexport const API_VERSION = apiVersion\n\n// Heartbeats shouldn't fire on intervals that are so short it causes performance issues\nexport const MIN_LOADER_QUERY_LISTEN_HEARTBEAT_INTERVAL = 1000 // ms\n\n// How often the list over loader queries should be garbage collected\nexport const LOADER_QUERY_GC_INTERVAL = 30_000 // ms\n\n// The interval at which we check if existing popups have been closed\nexport const POPUP_CHECK_INTERVAL = 1000 // ms\n","import {\n combineLatest,\n from,\n isObservable,\n map,\n mergeAll,\n Observable,\n of,\n scan,\n switchMap,\n} from 'rxjs'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Props<K extends keyof any, T> = {\n [P in K]: T | Observable<T>\n}\n\nfunction keysOf<T extends object>(value: T) {\n return Object.keys(value) as (keyof T)[]\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction setKey(source: Record<string, unknown>, key: any, value: unknown) {\n return {\n ...source,\n [key]: value,\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function props<K extends keyof any, T>(options: {wait?: boolean} = {}) {\n return (source: Observable<Props<K, T>>): Observable<Record<string, unknown>> => {\n return new Observable<Props<K, T>>((observer) => source.subscribe(observer)).pipe(\n switchMap((object) => {\n const keyObservables = keysOf(object).map((key) => {\n const value = object[key]\n return isObservable(value) ? from(value).pipe(map((val) => [key, val])) : of([key, value])\n })\n\n return options.wait\n ? combineLatest(keyObservables).pipe(\n map((pairs) => pairs.reduce((acc, [key, value]) => setKey(acc, key, value), {})),\n )\n : from(keyObservables).pipe(\n mergeAll(),\n scan((acc, [key, value]) => setKey(acc, key, value), {}),\n )\n }),\n )\n }\n}\n","/* eslint-disable @typescript-eslint/no-shadow */\nimport {get} from 'lodash'\nimport {useEffect, useMemo, useState} from 'react'\nimport {isObservable, map, type Observable, of, switchMap} from 'rxjs'\nimport {\n type DocumentStore,\n getDraftId,\n isRecord,\n isReference,\n type Previewable,\n type SanityDocument,\n useDocumentStore,\n usePerspective,\n} from 'sanity'\n\nimport {\n type DocumentLocationResolver,\n type DocumentLocationResolverObject,\n type DocumentLocationResolvers,\n type DocumentLocationsState,\n type DocumentLocationsStatus,\n} from './types'\nimport {props} from './util/props'\n\nconst INITIAL_STATE: DocumentLocationsState = {locations: []}\n\nfunction getDocumentId(value: Previewable) {\n if (isReference(value)) {\n return value._ref\n }\n return '_id' in value ? value._id : undefined\n}\n\nfunction cleanPreviewable(id: string | undefined, previewable: Previewable) {\n const clean: Record<string, unknown> = id ? {...previewable, _id: id} : {...previewable}\n\n if (clean._type === 'reference') {\n delete clean._type\n delete clean._ref\n delete clean._weak\n delete clean._dataset\n delete clean._projectId\n delete clean._strengthenOnPublish\n }\n\n return clean\n}\n\nfunction listen(id: string, fields: string[], store: DocumentStore) {\n const projection = fields.join(', ')\n const query = {\n fetch: `*[_id==$id][0]{${projection}}`,\n // TODO: is it more performant to use `||` instead of `in`?\n listen: `*[_id in [$id,$draftId]]`,\n }\n const params = {id, draftId: getDraftId(id)}\n return store.listenQuery(query, params, {\n perspective: 'drafts',\n tag: 'drafts',\n }) as Observable<SanityDocument | null>\n}\n\nfunction observeDocument(\n value: Previewable | null,\n paths: string[][],\n store: DocumentStore,\n): Observable<Record<string, unknown> | null> {\n if (!value || typeof value !== 'object') {\n return of(value)\n }\n\n const id = getDocumentId(value)\n const currentValue = cleanPreviewable(id, value)\n\n const headlessPaths = paths.filter((path) => !(path[0] in currentValue))\n\n if (id && headlessPaths.length) {\n const fields = [...new Set(headlessPaths.map((path: string[]) => path[0]))]\n return listen(id, fields, store).pipe(\n switchMap((snapshot) => {\n if (snapshot) {\n return observeDocument(snapshot, paths, store)\n }\n return of(null)\n }),\n )\n }\n\n const leads: Record<string, string[][]> = {}\n paths.forEach((path) => {\n const [head, ...tail] = path\n if (!leads[head]) {\n leads[head] = []\n }\n leads[head].push(tail)\n })\n const next = Object.keys(leads).reduce((res: Record<string, unknown>, head) => {\n const tails = leads[head].filter((tail) => tail.length > 0)\n if (tails.length === 0) {\n res[head] = isRecord(value) ? (value as Record<string, unknown>)[head] : undefined\n } else {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n res[head] = observeDocument((value as any)[head], tails, store)\n }\n return res\n }, currentValue)\n\n return of(next).pipe(props({wait: true}))\n}\n\nfunction observeForLocations(\n documentId: string,\n resolver: DocumentLocationResolverObject<string>,\n documentStore: DocumentStore,\n) {\n const {select} = resolver\n const paths = Object.values(select).map((value) => String(value).split('.')) || []\n const doc = {_type: 'reference', _ref: documentId}\n return observeDocument(doc, paths, documentStore).pipe(\n map((doc) => {\n return Object.keys(select).reduce<Record<string, unknown>>((acc, key) => {\n acc[key] = get(doc, select[key])\n return acc\n }, {})\n }),\n map(resolver.resolve),\n )\n}\n\nexport function useDocumentLocations(props: {\n id: string\n version: string | undefined\n resolvers?: DocumentLocationResolver | DocumentLocationResolvers\n type: string\n}): {\n state: DocumentLocationsState\n status: DocumentLocationsStatus\n} {\n const {id, resolvers, type, version} = props\n const documentStore = useDocumentStore()\n const {perspectiveStack} = usePerspective()\n const [locationsState, setLocationsState] = useState<DocumentLocationsState>(INITIAL_STATE)\n\n const resolver = resolvers && (typeof resolvers === 'function' ? resolvers : resolvers[type])\n\n const [locationsStatus, setLocationsStatus] = useState<DocumentLocationsStatus>(\n resolver ? 'resolving' : 'empty',\n )\n\n const result = useMemo(() => {\n if (!resolver) return undefined\n\n // Original/advanced resolver which requires explicit use of Observables\n if (typeof resolver === 'function') {\n const params = {id, type, version, perspectiveStack}\n const context = {documentStore}\n const _result = resolver(params, context)\n return isObservable(_result) ? _result : of(_result)\n }\n\n // Simplified resolver pattern which abstracts away Observable logic\n if ('select' in resolver && 'resolve' in resolver) {\n return observeForLocations(id, resolver, documentStore)\n }\n\n // Resolver is explicitly provided state\n return of(resolver)\n }, [documentStore, id, resolver, type, version, perspectiveStack])\n\n useEffect(() => {\n const sub = result?.subscribe((state) => {\n setLocationsState(state || INITIAL_STATE)\n setLocationsStatus(state ? 'resolved' : 'empty')\n })\n\n return () => sub?.unsubscribe()\n }, [result])\n\n return {\n state: locationsState,\n status: locationsStatus,\n }\n}\n","import {defineLocaleResourceBundle} from 'sanity'\n\n/**\n * The locale namespace for the presentation tool\n *\n * @public\n */\nexport const presentationLocaleNamespace = 'presentation' as const\n\n/**\n * The default locale bundle for the presentation tool, which is US English.\n *\n * @internal\n */\nexport const presentationUsEnglishLocaleBundle = defineLocaleResourceBundle({\n locale: 'en-US',\n namespace: presentationLocaleNamespace,\n resources: () => import('./resources'),\n})\n","import {useContext} from 'react'\nimport {PresentationContext} from 'sanity/_singletons'\n\nimport {type PresentationContextValue} from './types'\n\nexport function usePresentationTool(throwOnMissingContext?: true): PresentationContextValue\nexport function usePresentationTool(throwOnMissingContext: false): PresentationContextValue | null\nexport function usePresentationTool(throwOnMissingContext = true): PresentationContextValue | null {\n const presentation = useContext(PresentationContext)\n\n if (throwOnMissingContext && !presentation) {\n throw new Error('Presentation context is missing')\n }\n\n return presentation\n}\n","import {usePresentationTool} from '../usePresentationTool'\n\nexport function useCurrentPresentationToolName(): string | undefined {\n return usePresentationTool(false)?.name ?? undefined\n}\n","import {\n ChevronRightIcon,\n DesktopIcon,\n ErrorOutlineIcon,\n InfoOutlineIcon,\n WarningOutlineIcon,\n} from '@sanity/icons'\nimport {Box, Card, Flex, Spinner, Stack, Text} from '@sanity/ui'\nimport {type ComponentType, type ReactNode, useCallback, useContext, useState} from 'react'\nimport {type ObjectSchemaType, useTranslation} from 'sanity'\nimport {PresentationContext} from 'sanity/_singletons'\nimport {useIntentLink} from 'sanity/router'\n\nimport {DEFAULT_TOOL_NAME, DEFAULT_TOOL_TITLE} from '../constants'\nimport {presentationLocaleNamespace} from '../i18n'\nimport {\n type DocumentLocation,\n type DocumentLocationsState,\n type PresentationPluginOptions,\n} from '../types'\nimport {useCurrentPresentationToolName} from './useCurrentPresentationToolName'\n\nconst TONE_ICONS: Record<'positive' | 'caution' | 'critical', ComponentType> = {\n positive: InfoOutlineIcon,\n caution: WarningOutlineIcon,\n critical: ErrorOutlineIcon,\n}\n\nexport function LocationsBanner(props: {\n documentId: string\n isResolving: boolean\n options: PresentationPluginOptions\n schemaType: ObjectSchemaType\n showPresentationTitle: boolean\n state: DocumentLocationsState\n}): ReactNode {\n const {documentId, isResolving, options, schemaType, showPresentationTitle} = props\n const {locations, message, tone} = props.state\n const len = locations?.length || 0\n\n const {t} = useTranslation(presentationLocaleNamespace)\n const presentation = useContext(PresentationContext)\n const presentationName = presentation?.name\n const [expanded, setExpanded] = useState(false)\n const toggle = useCallback(() => {\n if (!len) return\n setExpanded((v) => !v)\n }, [len])\n\n const title = isResolving\n ? t('locations-banner.resolving.text')\n : message || t('locations-banner.locations-count', {count: len})\n\n const ToneIcon = tone ? TONE_ICONS[tone] : undefined\n\n return (\n <Card padding={1} radius={2} border tone={tone}>\n <div style={{margin: -1}}>\n {!locations && (\n <Flex align=\"flex-start\" gap={3} padding={3}>\n {tone && ToneIcon && (\n <Box flex=\"none\">\n <Text size={1}>\n <ToneIcon />\n </Text>\n </Box>\n )}\n <Box flex={1}>\n <Text size={1} weight=\"medium\">\n {showPresentationTitle && <>{options.title || DEFAULT_TOOL_TITLE} &middot; </>}\n {title}\n </Text>\n </Box>\n </Flex>\n )}\n {locations && (\n <>\n <Card\n as={len ? 'button' : undefined}\n onClick={toggle}\n padding={3}\n radius={1}\n tone=\"inherit\"\n >\n <Flex gap={3}>\n <Box flex=\"none\">\n {isResolving ? (\n <Spinner size={1} />\n ) : (\n <Text size={1}>\n {len === 0 ? (\n <InfoOutlineIcon />\n ) : (\n <ChevronRightIcon\n style={{\n transform: `rotate(${expanded ? '90deg' : 0})`,\n transition: 'transform 100ms ease-in-out',\n }}\n />\n )}\n </Text>\n )}\n </Box>\n <Box flex={1}>\n <Text size={1} weight=\"medium\">\n {showPresentationTitle && <>{options.title || DEFAULT_TOOL_TITLE} &middot; </>}\n {title}\n </Text>\n </Box>\n </Flex>\n </Card>\n <Stack hidden={!expanded} marginTop={1} space={1}>\n {locations.map((l, index) => (\n <LocationItem\n active={\n (options.name || DEFAULT_TOOL_NAME) === presentationName &&\n l.href === presentation?.params.preview\n }\n documentId={documentId}\n documentType={schemaType.name}\n key={index}\n node={l}\n toolName={options.name || DEFAULT_TOOL_NAME}\n />\n ))}\n </Stack>\n </>\n )}\n </div>\n </Card>\n )\n}\n\nfunction LocationItem(props: {\n active: boolean\n documentId: string\n documentType: string\n node: DocumentLocation\n toolName: string\n}) {\n const {documentId, documentType, node, active, toolName} = props\n const presentation = useContext(PresentationContext)\n const currentPresentationToolName = useCurrentPresentationToolName()\n const isCurrentTool = toolName === currentPresentationToolName\n const navigate = presentation?.navigate\n\n const presentationLinkProps = useIntentLink({\n intent: 'edit',\n params: {\n id: documentId,\n type: documentType,\n mode: 'presentation',\n presentation: toolName,\n ...presentation?.structureParams,\n preview: node.href,\n },\n })\n\n const handleCurrentToolClick = useCallback(() => {\n navigate?.({}, {preview: node.href})\n }, [node.href, navigate])\n\n return (\n <Card\n {...(isCurrentTool ? {} : presentationLinkProps)}\n as=\"a\"\n key={node.href}\n onClick={isCurrentTool ? handleCurrentToolClick : presentationLinkProps.onClick}\n padding={3}\n radius={1}\n pressed={active}\n tone=\"inherit\"\n >\n <Flex gap={3}>\n <Box flex=\"none\">\n <Text size={1}>\n <DesktopIcon />\n </Text>\n </Box>\n <Stack flex={1} space={2}>\n <Text size={1} weight=\"medium\">\n {node.title}\n </Text>\n <Text muted size={1} textOverflow=\"ellipsis\">\n {node.href}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )\n}\n","import {rem, Stack} from '@sanity/ui'\nimport {type ReactNode, useContext} from 'react'\nimport {type ObjectSchemaType, type PublishedId} from 'sanity'\nimport {PresentationDocumentContext} from 'sanity/_singletons'\nimport {styled} from 'styled-components'\n\nimport {type PresentationPluginOptions} from '../types'\nimport {useDocumentLocations} from '../useDocumentLocations'\nimport {LocationsBanner} from './LocationsBanner'\n\nconst LocationStack = styled(Stack)`\n min-height: ${rem(42)};\n\n & + &:empty {\n display: none;\n }\n`\n\nexport function PresentationDocumentHeader(props: {\n documentId: PublishedId\n version: string | undefined\n options: PresentationPluginOptions\n schemaType: ObjectSchemaType\n}): ReactNode {\n const {documentId, options, schemaType, version} = props\n const context = useContext(PresentationDocumentContext)\n const {state, status} = useDocumentLocations({\n id: documentId,\n version,\n resolvers: options.resolve?.locations || options.locate,\n type: schemaType.name,\n })\n\n if ((context && context.options[0] !== options) || status === 'empty') {\n return null\n }\n\n const contextOptions = context?.options || []\n\n return (\n <LocationStack marginBottom={5} space={5}>\n <Stack space={2}>\n {contextOptions.map(\n (\n // eslint-disable-next-line @typescript-eslint/no-shadow\n options,\n idx,\n ) => (\n <LocationsBanner\n documentId={documentId}\n isResolving={status === 'resolving'}\n key={idx}\n options={options}\n schemaType={schemaType}\n showPresentationTitle={contextOptions.length > 1}\n state={state}\n />\n ),\n )}\n </Stack>\n </LocationStack>\n )\n}\n","import {type ReactNode, useCallback, useContext, useLayoutEffect, useMemo, useState} from 'react'\nimport {PresentationDocumentContext} from 'sanity/_singletons'\nimport {useEffectEvent} from 'use-effect-event'\n\nimport {type PresentationPluginOptions} from '../types'\nimport {type PresentationDocumentContextValue} from './types'\n\n/** @internal */\nexport function PresentationDocumentProvider(props: {\n children?: ReactNode\n options: PresentationPluginOptions\n}): React.JSX.Element {\n const {children, options} = props\n const parent = useContext(PresentationDocumentContext)\n const parentRegister = parent?.register\n\n const [optionsArray, setOptionsArray] = useState<PresentationPluginOptions[]>(() => [])\n\n const register = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-shadow\n (options: PresentationPluginOptions) => {\n if (parentRegister) {\n return parentRegister(options)\n }\n\n setOptionsArray((prev) => [options].concat(prev))\n\n return () => {\n setOptionsArray((prev) => prev.filter((o) => o !== options))\n }\n },\n [parentRegister],\n )\n\n const context: PresentationDocumentContextValue = useMemo(\n () => ({\n options: parent?.options || optionsArray,\n register,\n }),\n [optionsArray, parent, register],\n )\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const registerEffectEvent = useEffectEvent((options: PresentationPluginOptions) =>\n register(options),\n )\n useLayoutEffect(() => registerEffectEvent(options), [options])\n\n return (\n <PresentationDocumentContext.Provider value={context}>\n {children}\n </PresentationDocumentContext.Provider>\n )\n}\n","import {MasterDetailIcon} from '@sanity/icons'\nimport {useContext, useMemo} from 'react'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionGroup,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n isRecord,\n pathToString,\n type Tool,\n useWorkspace,\n} from 'sanity'\nimport {PresentationContext} from 'sanity/_singletons'\nimport {useRouter} from 'sanity/router'\n\nimport {DEFAULT_TOOL_NAME} from '../constants'\n\nfunction useOpenInStructureAction(\n props: DocumentFieldActionProps,\n): DocumentFieldActionItem | DocumentFieldActionGroup {\n const {documentId, documentType, path} = props\n const workspace = useWorkspace()\n const {navigateIntent} = useRouter()\n const presentation = useContext(PresentationContext)\n\n const defaultStructureTool = useMemo(\n () =>\n findStructureTool(\n workspace.tools,\n documentId,\n documentType,\n presentation?.name || DEFAULT_TOOL_NAME,\n ),\n [documentId, documentType, workspace.tools, presentation],\n )\n\n return {\n type: 'action',\n hidden: !presentation || path.length > 0 || !defaultStructureTool,\n icon: defaultStructureTool?.icon || MasterDetailIcon,\n title: `Open in ${defaultStructureTool?.title || 'Structure'}`,\n onAction() {\n navigateIntent('edit', {\n id: documentId,\n type: documentType,\n mode: 'structure',\n path: pathToString(path),\n })\n },\n renderAsButton: true,\n }\n}\n\nexport const openInStructure = defineDocumentFieldAction({\n name: 'presentation/openInStructure',\n useAction: useOpenInStructureAction,\n})\n\nfunction findStructureTool(\n tools: Tool[],\n documentId: string,\n documentType: string,\n presentationToolName?: string,\n): Tool | undefined {\n const results = tools\n .filter((t) => t.name !== presentationToolName)\n .map((t) => {\n const match = t.canHandleIntent?.(\n 'edit',\n {\n id: documentId,\n type: documentType,\n mode: 'structure',\n },\n {},\n )\n\n return {tool: t, match}\n })\n\n const modeMatches = results.filter((t) => isRecord(t.match) && t.match.mode)\n\n if (modeMatches.length > 0) {\n return modeMatches[0].tool\n }\n\n const matches = results.filter((t) => t.match)\n\n return matches[0]?.tool\n}\n","import {uuid} from '@sanity/uuid'\nimport {getPublishedId} from 'sanity'\nimport {encodeJsonParams, type RouterState, type SearchParam} from 'sanity/router'\n\nimport {type PresentationSearchParams, type PresentationStateParams} from './types'\n\nconst preservedSearchParamKeys: Array<keyof PresentationSearchParams> = ['preview', 'viewport']\n\n/**\n * @internal\n */\nexport function getIntentState(\n intent: string,\n params: Record<string, string>,\n routerState: RouterState | undefined,\n payload: unknown,\n):\n | (PresentationStateParams & {_searchParams: SearchParam[]})\n | {intent: string; params: Record<string, string>; payload: unknown} {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {id, mode, path, presentation, type, ...searchParams} = params\n\n const preservedSearchParams = (routerState?._searchParams || [])\n // @todo Casting https://github.com/microsoft/TypeScript/issues/14520\n .filter(([key]) => preservedSearchParamKeys.includes(key as keyof PresentationSearchParams))\n .reduce((acc, [key, value]) => ({...acc, [key]: value}), {} as Record<string, string>)\n\n const _searchParams = {\n ...preservedSearchParams,\n ...searchParams,\n }\n\n if (intent === 'edit' && id) {\n _searchParams.preview =\n _searchParams.preview || new URLSearchParams(window.location.search).get('preview') || '/'\n return {\n type: type || '*',\n id: getPublishedId(id),\n path,\n _searchParams: Object.entries(_searchParams),\n }\n }\n\n if (intent === 'create') {\n _searchParams.preview =\n _searchParams.preview || new URLSearchParams(window.location.search).get('preview') || '/'\n\n if (payload && typeof payload === 'object') {\n _searchParams.templateParams = encodeJsonParams(payload as Record<string, unknown>)\n }\n\n return {\n type: type || '*',\n id: id || uuid(),\n _searchParams: Object.entries(_searchParams),\n }\n }\n return {intent, params, payload}\n}\n","import {Flex, Spinner} from '@sanity/ui'\n\nexport function PresentationSpinner(): React.JSX.Element {\n return (\n <Flex align=\"center\" direction=\"column\" height=\"fill\" justify=\"center\" style={{width: '100%'}}>\n <Spinner />\n </Flex>\n )\n}\n","import {route} from 'sanity/router'\n\n// eslint-disable-next-line camelcase\nexport const router = route.create('/', {__unsafe_disableScopedSearchParams: true}, [\n route.intents('/intent'),\n route.create(':type', [route.create(':id', [route.create(':path')])]),\n])\n","import {type SanityDocument} from '@sanity/client'\nimport {lazy, Suspense} from 'react'\nimport {\n definePlugin,\n getPublishedId,\n getVersionFromId,\n type InputProps,\n isDocumentSchemaType,\n} from 'sanity'\n\nimport {DEFAULT_TOOL_ICON, DEFAULT_TOOL_NAME, EDIT_INTENT_MODE} from './constants'\nimport {PresentationDocumentHeader} from './document/PresentationDocumentHeader'\nimport {PresentationDocumentProvider} from './document/PresentationDocumentProvider'\nimport {openInStructure} from './fieldActions/openInStructure'\nimport {getIntentState} from './getIntentState'\nimport {presentationUsEnglishLocaleBundle} from './i18n'\nimport {PresentationSpinner} from './PresentationSpinner'\nimport {router} from './router'\nimport {\n type DocumentLocationResolverObject,\n type DocumentLocationsState,\n type DocumentResolver,\n type PresentationPluginOptions,\n} from './types'\n\nconst PresentationTool = lazy(() => import('./PresentationToolGrantsCheck'))\nconst BroadcastDisplayedDocument = lazy(() => import('./loader/BroadcastDisplayedDocument'))\n\n/**\n * Define locations for a given document type.\n * This function doesn't do anything itself, it is used to provide type information.\n * @param resolver - resolver that return locations for a document.\n * @public\n */\nexport function defineLocations<K extends string>(\n resolver: DocumentLocationResolverObject<K> | DocumentLocationsState,\n): typeof resolver {\n return resolver\n}\n\n/**\n * Define documents for a given location.\n * This function doesn't do anything itself, it is used to provide type information.\n * @param resolvers - resolvers that return documents.\n * @public\n */\nexport function defineDocuments(resolvers: DocumentResolver[]): typeof resolvers {\n return resolvers\n}\n\n/** @public */\nexport const presentationTool = definePlugin<PresentationPluginOptions>((options) => {\n const toolName = options.name || DEFAULT_TOOL_NAME\n\n if ('locate' in options) {\n // eslint-disable-next-line no-console\n console.warn('Presentation’s `locate` option is deprecated. Use `resolve.locations` instead.')\n }\n\n const hasLocationsResolver = !!(options.resolve?.locations || options.locate)\n\n function PresentationDocumentInput(props: InputProps) {\n const value = props.value as SanityDocument\n const documentId = value?._id ? getPublishedId(value?._id) : undefined\n const documentVersion = value?._id ? getVersionFromId(value._id) : undefined\n if (isDocumentSchemaType(props.schemaType)) {\n return (\n <PresentationDocumentProvider options={options}>\n {hasLocationsResolver && documentId && (\n <PresentationDocumentHeader\n documentId={documentId}\n version={documentVersion}\n options={options}\n schemaType={props.schemaType}\n />\n )}\n <Suspense fallback={<PresentationSpinner />}>{props.renderDefault(props)}</Suspense>\n <Suspense key=\"broadcast-displayed-document\">\n <BroadcastDisplayedDocument key={documentId} value={value} />\n </Suspense>\n </PresentationDocumentProvider>\n )\n }\n\n return props.renderDefault(props)\n }\n\n function canHandleCreateIntent(params: Record<string, unknown>) {\n // We can't handle create intents without a `type` parameter\n if (!('type' in params)) {\n return false\n }\n\n if ('presentation' in params && params.presentation !== toolName) {\n return false\n }\n\n return 'template' in params ? {template: true} : true\n }\n\n function canHandleEditIntent(params: Record<string, unknown>) {\n // We can't handle edit intents without `type` or `id` parameters\n if (!('type' in params) || !('id' in params)) {\n return false\n }\n\n if ('presentation' in params && params.presentation !== toolName) {\n return false\n }\n\n return 'mode' in params ? {mode: params.mode === EDIT_INTENT_MODE} : true\n }\n\n return {\n i18n: {\n bundles: [presentationUsEnglishLocaleBundle],\n },\n document: {\n unstable_fieldActions: (prev) => {\n return [\n ...prev.filter((a) => a.name !== openInStructure.name), // prevent duplication\n openInStructure,\n ]\n },\n },\n\n form: {\n components: {\n input: PresentationDocumentInput,\n },\n },\n\n tools: [\n {\n icon: options.icon || DEFAULT_TOOL_ICON,\n name: toolName,\n title: options.title,\n component: PresentationTool,\n options,\n canHandleIntent(intent, params) {\n if (intent === 'create') return canHandleCreateIntent(params)\n if (intent === 'edit') return canHandleEditIntent(params)\n return false\n },\n getIntentState,\n router,\n __internalApplicationType: 'sanity/presentation',\n },\n ],\n }\n})\n","import {type Dispatch, type Reducer} from 'react'\nimport {boolean, fallback, object, parse, picklist} from 'valibot'\n\n/** @public */\nexport interface PresentationState {\n mainDocument: boolean\n iframe: {\n status: 'loading' | 'loaded' | 'refreshing' | 'reloading'\n }\n visualEditing: {\n overlaysEnabled: boolean\n }\n}\n\n/** @public */\nexport const ACTION_IFRAME_LOADED = 'ACTION_IFRAME_LOADED'\n/** @public */\nexport const ACTION_IFRAME_REFRESH = 'ACTION_IFRAME_REFRESH'\n/** @public */\nexport const ACTION_IFRAME_RELOAD = 'ACTION_IFRAME_RELOAD'\n/** @public */\nexport const ACTION_VISUAL_EDITING_OVERLAYS_TOGGLE = 'ACTION_VISUAL_EDITING_OVERLAYS_TOGGLE'\n\n/** @public */\nexport interface IframeLoadedAction {\n type: typeof ACTION_IFRAME_LOADED\n}\n/** @public */\nexport interface IframeRefreshAction {\n type: typeof ACTION_IFRAME_REFRESH\n}\n/** @public */\nexport interface IframeReloadAction {\n type: typeof ACTION_IFRAME_RELOAD\n}\n/** @public */\nexport interface VisualEditingOverlaysToggleAction {\n type: typeof ACTION_VISUAL_EDITING_OVERLAYS_TOGGLE\n enabled: boolean\n}\n\n/** @public */\nexport type PresentationAction =\n | IframeLoadedAction\n | IframeRefreshAction\n | IframeReloadAction\n | VisualEditingOverlaysToggleAction\n\nexport const presentationReducer: Reducer<\n Readonly<PresentationState>,\n Readonly<PresentationAction>\n> = (state, action) => {\n switch (action.type) {\n case ACTION_IFRAME_LOADED:\n return state.iframe.status === 'loaded'\n ? state\n : {\n ...state,\n iframe: {\n ...state.iframe,\n status: 'loaded',\n },\n }\n case ACTION_IFRAME_REFRESH:\n return state.iframe.status === 'refreshing'\n ? state\n : {\n ...state,\n iframe: {\n ...state.iframe,\n status: 'refreshing',\n },\n }\n case ACTION_IFRAME_RELOAD:\n return state.iframe.status === 'reloading'\n ? state\n : {\n ...state,\n iframe: {\n ...state.iframe,\n status: 'reloading',\n },\n }\n case ACTION_VISUAL_EDITING_OVERLAYS_TOGGLE:\n return toggleVisualEditingOverlays(state, action)\n default:\n return state\n }\n}\n\nconst toggleVisualEditingOverlays: Reducer<\n Readonly<PresentationState>,\n Readonly<VisualEditingOverlaysToggleAction>\n> = (state, action) => {\n if (state.visualEditing.overlaysEnabled === action.enabled) return state\n return {\n ...state,\n visualEditing: {\n ...state.visualEditing,\n overlaysEnabled: action.enabled,\n },\n }\n}\n\nconst mainDocumentSchema = fallback(boolean(), false)\n\nconst iframeStatusSchema = picklist(['loading', 'loaded', 'refreshing', 'reloading'])\n\nconst initStateSchema = object({\n mainDocument: mainDocumentSchema,\n iframe: object({\n status: iframeStatusSchema,\n }),\n visualEditing: object({overlaysEnabled: boolean()}),\n})\n\nconst INITIAL_PRESENTATION_STATE = {\n mainDocument: false,\n iframe: {\n status: 'loading',\n },\n visualEditing: {\n overlaysEnabled: false,\n },\n} as const satisfies PresentationState\n\nexport function presentationReducerInit(\n state: Readonly<Partial<PresentationState>>,\n): Readonly<PresentationState> {\n return parse(initStateSchema, {...INITIAL_PRESENTATION_STATE, ...state})\n}\n\n/** @public */\nexport type DispatchPresentationAction = Dispatch<Readonly<PresentationAction>>\n","import {useContext} from 'react'\nimport {PresentationNavigateContext} from 'sanity/_singletons'\n\nimport {type PresentationNavigateContextValue} from './types'\n\n/** @public */\nexport function usePresentationNavigate(): PresentationNavigateContextValue {\n const navigate = useContext(PresentationNavigateContext)\n\n if (!navigate) {\n throw new Error('Presentation navigate context is missing')\n }\n\n return navigate\n}\n\nexport type {PresentationNavigateContextValue}\n","import {useContext} from 'react'\nimport {PresentationParamsContext} from 'sanity/_singletons'\n\nimport {type PresentationParamsContextValue} from './types'\n\n/** @public */\nexport function usePresentationParams(throwOnMissingContext?: true): PresentationParamsContextValue\n/** @public */\nexport function usePresentationParams(\n throwOnMissingContext: false,\n): PresentationParamsContextValue | null\n/** @public */\nexport function usePresentationParams(\n throwOnMissingContext = true,\n): PresentationParamsContextValue | null {\n const params = useContext(PresentationParamsContext)\n\n if (throwOnMissingContext && !params) {\n throw new Error('Presentation params context is missing')\n }\n\n return params\n}\n"],"names":["useSharedState","key","value","$","_c","context","useContext","PresentationSharedStateContext","Error","setValue","t0","t1","useEffect","DEFAULT_TOOL_ICON","ComposeIcon","DEFAULT_TOOL_NAME","DEFAULT_TOOL_TITLE","EDIT_INTENT_MODE","MAX_TIME_TO_OVERLAYS_CONNECTION","API_VERSION","apiVersion","MIN_LOADER_QUERY_LISTEN_HEARTBEAT_INTERVAL","LOADER_QUERY_GC_INTERVAL","POPUP_CHECK_INTERVAL","keysOf","Object","keys","setKey","source","props","options","Observable","observer","subscribe","pipe","switchMap","object","keyObservables","map","isObservable","from","val","of","wait","combineLatest","pairs","reduce","acc","mergeAll","scan","INITIAL_STATE","locations","getDocumentId","isReference","_ref","_id","undefined","cleanPreviewable","id","previewable","clean","_type","_weak","_dataset","_projectId","_strengthenOnPublish","listen","fields","store","query","fetch","join","params","draftId","getDraftId","listenQuery","perspective","tag","observeDocument","paths","currentValue","headlessPaths","filter","path","length","Set","snapshot","leads","forEach","head","tail","push","next","res","tails","isRecord","observeForLocations","documentId","resolver","documentStore","select","values","String","split","doc","get","resolve","useDocumentLocations","resolvers","type","version","useDocumentStore","perspectiveStack","usePerspective","locationsState","setLocationsState","useState","locationsStatus","setLocationsStatus","bb0","_result","result","t2","sub","state","unsubscribe","t3","status","presentationLocaleNamespace","presentationUsEnglishLocaleBundle","defineLocaleResourceBundle","locale","namespace","resources","usePresentationTool","throwOnMissingContext","presentation","PresentationContext","useCurrentPresentationToolName","name","TONE_ICONS","positive","InfoOutlineIcon","caution","WarningOutlineIcon","critical","ErrorOutlineIcon","LocationsBanner","isResolving","schemaType","showPresentationTitle","message","tone","len","t","useTranslation","presentationName","expanded","setExpanded","_temp","toggle","count","title","ToneIcon","Symbol","for","margin","t4","transform","transition","l","index","href","preview","t5","t6","v","LocationItem","documentType","node","active","toolName","currentPresentationToolName","isCurrentTool","navigate","structureParams","intent","mode","presentationLinkProps","useIntentLink","handleCurrentToolClick","onClick","t7","t8","t9","LocationStack","styled","Stack","rem","PresentationDocumentHeader","PresentationDocumentContext","locate","contextOptions","options_0","idx","PresentationDocumentProvider","children","parent","parentRegister","register","optionsArray","setOptionsArray","prev","concat","prev_0","o","options_1","registerEffectEvent","useEffectEvent","useLayoutEffect","useOpenInStructureAction","workspace","useWorkspace","navigateIntent","useRouter","tools","findStructureTool","defaultStructureTool","icon","MasterDetailIcon","hidden","onAction","pathToString","renderAsButton","openInStructure","defineDocumentFieldAction","useAction","presentationToolName","results","match","canHandleIntent","tool","modeMatches","preservedSearchParamKeys","getIntentState","routerState","payload","searchParams","_searchParams","includes","URLSearchParams","window","location","search","getPublishedId","entries","templateParams","encodeJsonParams","uuid","PresentationSpinner","width","router","route","create","__unsafe_disableScopedSearchParams","intents","PresentationTool","lazy","BroadcastDisplayedDocument","defineLocations","defineDocuments","presentationTool","definePlugin","console","warn","hasLocationsResolver","PresentationDocumentInput","getVersionFromId","documentVersion","isDocumentSchemaType","renderDefault","canHandleCreateIntent","template","canHandleEditIntent","i18n","bundles","document","unstable_fieldActions","a","form","components","input","component","__internalApplicationType","ACTION_IFRAME_LOADED","ACTION_IFRAME_REFRESH","ACTION_IFRAME_RELOAD","ACTION_VISUAL_EDITING_OVERLAYS_TOGGLE","presentationReducer","action","iframe","toggleVisualEditingOverlays","visualEditing","overlaysEnabled","enabled","mainDocumentSchema","fallback","boolean","iframeStatusSchema","picklist","initStateSchema","mainDocument","INITIAL_PRESENTATION_STATE","presentationReducerInit","parse","usePresentationNavigate","PresentationNavigateContext","usePresentationParams","PresentationParamsContext"],"mappings":"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