@sanity/visual-editing
Version:
[](https://npm-stat.com/charts.html?package=@sanity/visual-editing) [](https://
892 lines (794 loc) • 22.3 kB
TypeScript
import {SanityClient} from '@sanity/client'
import type {SanityDocument} from '@sanity/client'
import type {StudioPathLike} from '@sanity/client/csm'
import type {InsertMenuOptions} from '@sanity/insert-menu'
import {Mutation, NodePatchList} from '@sanity/mutate'
import {createSharedListener, DocumentMutatorMachineInput} from '@sanity/mutate/_unstable_machine'
import type {ArrayOptions, SanityDocument as SanityDocument_2} from '@sanity/types'
import type {
ComponentType,
FunctionComponent,
HTMLAttributes,
PropsWithChildren,
ReactElement,
} from 'react'
/**
* @public
*/
export declare type CreateDataAttribute<T extends CreateDataAttributeProps> =
(T extends WithRequired<CreateDataAttributeProps, 'id' | 'type' | 'path'>
? {
/**
* Returns a string representation of the data attribute
* @param path - An optional path to concatenate with any existing path
* @public
*/
(path?: StudioPathLike): string
/**
* Returns a string representation of the data attribute
* @public
*/
toString(): string
}
: T extends WithRequired<CreateDataAttributeProps, 'id' | 'type'>
? (path: StudioPathLike) => string
: object) & {
/**
* Concatenate the current path with a new path
* @param path - A path to concatenate with any existing path
* @public
*/
scope(path: StudioPathLike): CreateDataAttribute<
T & {
path: StudioPathLike
}
>
/**
* Combines the current props with additional props
* @param props - New props to merge with any existing props
* @public
*/
combine: <U extends CreateDataAttributeProps>(props: U) => CreateDataAttribute<T & U>
}
/**
* A helper function for creating `data-sanity` attributes by explicitly providing metadata.
* @returns An object with methods for incrementally adding and scoping metadata, and for generating a data attribute string.
* @public
*/
export declare function createDataAttribute<T extends CreateDataAttributeProps>(
props: T,
): CreateDataAttribute<T>
/**
* The metadata that can be embedded in a data attribute.
* All values are marked optional in the base type as they can be provided incrementally using the `createDataAttribute` function.
* @public
*/
export declare interface CreateDataAttributeProps {
/** The studio base URL, optional */
baseUrl?: string
/** The dataset, optional */
dataset?: string
/** The document ID, required */
id?: string
/** The field path, required */
path?: StudioPathLike
/** The project ID, optional */
projectId?: string
/** The studio tool name, optional */
tool?: string
/** The document type, required */
type?: string
/** The studio workspace, optional */
workspace?: string
}
/**
* Creates a controller which dispatches overlay related events
*
* @param handler - Dispatched event handler
* @param overlayElement - Parent element containing rendered overlay elements
* @public
*/
export declare function createOverlayController({
handler,
overlayElement,
inFrame,
optimisticActorReady,
}: OverlayOptions): OverlayController
/**
* @public
* @deprecated Use `import type {DatasetMutatorMachineInput} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type DatasetMutatorMachineInput = DatasetMutatorMachineInputDeprecated
export declare interface DatasetMutatorMachineInputDeprecated
extends Omit<DocumentMutatorMachineInput, 'id'> {
client: SanityClient
/** A shared listener can be provided, if not it'll be created using `client.listen()` */
sharedListener?: ReturnType<typeof createSharedListener>
}
/**
* Cleanup function used when e.g. unmounting
* @public
*/
export declare type DisableVisualEditing = () => void
export declare interface DocumentSchema {
type: 'document'
name: string
title?: string
icon?: string
fields: Record<string, SchemaObjectField>
}
/**
* @public
* @deprecated Use `import type {DocumentsGet} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type DocumentsGet = DocumentsGetDeprecated
export declare type DocumentsGetDeprecated = <T extends Record<string, any>>(
documentId: string,
) => OptimisticDocumentDeprecated<T>
/**
* @public
* @deprecated Use `import type {DocumentsMutate} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type DocumentsMutate = DocumentsMutateDeprecated
export declare type DocumentsMutateDeprecated = (
documentId: string,
mutations: Mutation[],
options?: {
commit?:
| boolean
| {
debounce: number
}
},
) => void
/** @public */
export declare interface DragEndEvent {
insertPosition: DragInsertPosition
target: SanityNode
dragGroup: string | null
flow: string
preventInsertDefault: boolean
}
/** @public */
export declare type DragInsertPosition = {
top?: {
rect: OverlayRect
sanity: SanityNode
} | null
left?: {
rect: OverlayRect
sanity: SanityNode
} | null
bottom?: {
rect: OverlayRect
sanity: SanityNode
} | null
right?: {
rect: OverlayRect
sanity: SanityNode
} | null
} | null
/** @public */
export declare type DragSkeleton = {
w: number
h: number
offsetX: number
offsetY: number
childRects: {
x: number
y: number
w: number
h: number
tagName: string
}[]
maxWidth: number
}
/**
* Element focus state
* @public
*/
export declare type ElementFocusedState = 'clicked' | 'duplicate' | boolean
/**
* An element that is safe to parse
* @internal
*/
export declare type ElementNode = HTMLElement | SVGElement
/**
* Element state for consuming applications
* @public
*/
export declare interface ElementState {
id: string
activated: boolean
element: ElementNode
focused: ElementFocusedState
hovered: boolean
rect: OverlayRect
sanity: SanityNode | SanityStegaNode
dragDisabled: boolean
}
/**
* Enables Visual Editing overlay in a page with sourcemap encoding.
*
* This will overlay UI on hovered elements that deep-links to Sanity Studio.
* @public
*/
export declare function enableVisualEditing(options?: VisualEditingOptions): DisableVisualEditing
export declare function getArrayItemKeyAndParentPath(pathOrNode: string | SanityNode): {
path: string
key: string
hasExplicitKey: boolean
}
/**
*
* @public
*/
export declare interface HistoryAdapter {
subscribe: (navigate: HistoryAdapterNavigate) => () => void
update: (update: HistoryUpdate) => void
}
/**
*
* @public
*/
export declare type HistoryAdapterNavigate = (update: HistoryUpdate) => void
/**
* Preview frame history refresh event, emitted by Presentation Tool
* @public
*/
export declare type HistoryRefresh =
| {
/**
* source 'manual' means the refresh button were clicked by the user
*/
source: 'manual'
/**
* If true then there's either preview-kit or a loader connected on the page
*/
livePreviewEnabled: boolean
}
| {
/**
* source 'mutation' means a document were mutated and the preview might need to refresh
*/
source: 'mutation'
/**
* If true then there's either preview-kit or a loader connected on the page
*/
livePreviewEnabled: boolean
/**
* Select metadata about the document that were mutated
* If it's prefixed with `drafts.` then it's a draft document, otherwise it's a published document.
*/
document: {
/**
* If it's prefixed with `drafts.` then it's a draft document, otherwise it's a published document.
*/
_id: string
/**
* The document type is frequently used in `revalidateTag` scenarios with Next.js App Router
*/
_type: string
/**
* The document revision, can be used to dedupe requests, as we always send two due to debouncing and handling Content Lake eventual consistency
*/
_rev: string
/**
* If the document has a top level slug field named `slug` with the type `slug`, then it'll be included here
*/
slug?: {
current?: string | null
}
}
}
/**
* Preview frame history update
* @public
*/
export declare type HistoryUpdate = {
type: 'push' | 'pop' | 'replace'
title?: string
url: string
}
/**
* Base controller dispatched message
* @typeParam T - Type of message
* @public
*/
export declare interface Msg<T extends string> {
type: T
}
/**
* @public
* @deprecated Use `import type {OptimisticDocument} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type OptimisticDocument = OptimisticDocumentDeprecated
export declare type OptimisticDocumentDeprecated<
T extends Record<string, any> = Record<string, any>,
> = {
/**
* The document ID
*/
id: string
/**
* Commits any locally applied mutations to the remote document
*/
commit: () => void
/**
* @deprecated - use `getSnapshot` instead
*/
get: {
(): SanityDocument<T> | undefined
<P extends PathDeprecated<T, keyof T>>(path: P): PathValueDeprecated<T, P> | undefined
}
/**
* Returns a promise that resolves to the current document snapshot
*/
getSnapshot: () => Promise<SanityDocument<T> | null>
/**
* Applies the given patches to the document
*/
patch: (
patches: OptimisticDocumentPatchesDeprecated<T>,
options?: {
commit?:
| boolean
| {
debounce: number
}
},
) => void
}
/**
* @public
* @deprecated Use `import type {OptimisticDocumentPatches} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type OptimisticDocumentPatches = OptimisticDocumentPatchesDeprecated
export declare type OptimisticDocumentPatchesDeprecated<
T extends Record<string, any> = Record<string, any>,
> =
| ((context: {
draftId: string
publishedId: string
/**
* @deprecated - use `getSnapshot` instead
*/
snapshot: SanityDocument<T> | undefined
getSnapshot: () => Promise<SanityDocument<T> | null>
}) => Promise<NodePatchList> | NodePatchList)
| NodePatchList
/**
* @public
* @deprecated Use `import type {OptimisticReducer} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type OptimisticReducer<T, U> = OptimisticReducerDeprecated<T, U>
/**
* @public
* @deprecated Use `import type {OptimisticReducerAction} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type OptimisticReducerAction<T> = OptimisticReducerActionDeprecated<T>
export declare type OptimisticReducerActionDeprecated<T> = {
document: T
id: string
originalId: string
type: 'appear' | 'mutate' | 'disappear'
}
export declare type OptimisticReducerDeprecated<T, U> = (
state: T,
action: OptimisticReducerActionDeprecated<U>,
) => T
/**
* @public
*/
export declare type OverlayComponent<
T extends Record<string, unknown> = Record<string, unknown>,
P extends OverlayElementParent = OverlayElementParent,
> = ComponentType<OverlayComponentProps<P | undefined> & T>
/**
* @public
*/
export declare interface OverlayComponentProps<
P extends OverlayElementParent = OverlayElementParent,
> extends OverlayComponentResolverContext<P> {
PointerEvents: FunctionComponent<PropsWithChildren<HTMLAttributes<HTMLDivElement>>>
}
/**
* @public
*/
export declare type OverlayComponentResolver<
T extends OverlayComponent = OverlayComponent<Record<string, unknown>, any>,
> = (context: OverlayComponentResolverContext) =>
| T
| {
component: T
props?: Record<string, unknown>
}
| Array<
| T
| {
component: T
props?: Record<string, unknown>
}
>
| ReactElement
| undefined
| void
/**
* @public
*/
export declare interface OverlayComponentResolverContext<
P extends OverlayElementParent = OverlayElementParent,
> {
/**
* The resolved field's document schema type
*/
document: DocumentSchema
/**
* The element node that the overlay is attached to
*/
element: ElementNode
/**
* The resolved field schema type
*/
field: OverlayElementField
/**
* Whether the overlay is focused or not
*/
focused: boolean
/**
* The Sanity node data that triggered the overlay
*/
node: SanityNode
/**
* The resolved field's parent schema type
*/
parent: P
/**
* A convience property, equal to `field.value.type`
*/
type: string
}
/**
* Object returned by a controller instantiation
* @public
*/
export declare interface OverlayController {
activate: () => void
deactivate: () => void
destroy: () => void
}
export declare type OverlayElementField =
| SchemaArrayItem
| SchemaObjectField
| SchemaUnionOption
| undefined
export declare type OverlayElementParent =
| DocumentSchema
| SchemaNode
| SchemaArrayItem
| SchemaUnionOption
| SchemaUnionNode
| undefined
/**
* Callback function used for handling dispatched controller messages
* @public
*/
export declare type OverlayEventHandler = (message: OverlayMsg) => void
/**
* Controller dispatched messages
* @public
*/
export declare type OverlayMsg =
| OverlayMsgActivate
| OverlayMsgBlur
| OverlayMsgDeactivate
| OverlayMsgDragEnd
| OverlayMsgDragEndMinimapTransition
| OverlayMsgDragStart
| OverlayMsgDragStartMinimapTransition
| OverlayMsgDragToggleMinimap
| OverlayMsgDragToggleMinimapPrompt
| OverlayMsgDragUpdateCursorPosition
| OverlayMsgDragUpdateGroupRect
| OverlayMsgDragUpdateInsertPosition
| OverlayMsgDragUpdateSkeleton
| OverlayMsgElementActivate
| OverlayMsgElementClick
| OverlayMsgElementContextMenu
| OverlayMsgElementDeactivate
| OverlayMsgElementMouseEnter
| OverlayMsgElementMouseLeave
| OverlayMsgElementRegister
| OverlayMsgElementUnregister
| OverlayMsgElementUpdate
| OverlayMsgElementUpdateRect
| OverlayMsgSetCursor
/** @public */
export declare type OverlayMsgActivate = Msg<'overlay/activate'>
/** @public */
export declare type OverlayMsgBlur = Msg<'overlay/blur'>
/** @public */
export declare type OverlayMsgDeactivate = Msg<'overlay/deactivate'>
/** @public */
export declare type OverlayMsgDragEnd = Msg<'overlay/dragEnd'> & DragEndEvent
/** @public */
export declare type OverlayMsgDragEndMinimapTransition = Msg<'overlay/dragEndMinimapTransition'>
/** @public */
export declare type OverlayMsgDragStart = Msg<'overlay/dragStart'> & {
flow: 'horizontal' | 'vertical'
}
/** @public */
export declare type OverlayMsgDragStartMinimapTransition = Msg<'overlay/dragStartMinimapTransition'>
/** @public */
export declare type OverlayMsgDragToggleMinimap = Msg<'overlay/dragToggleMinimap'> & {
display: boolean
}
/** @public */
export declare type OverlayMsgDragToggleMinimapPrompt = Msg<'overlay/dragToggleMinimapPrompt'> & {
display: boolean
}
/** @public */
export declare type OverlayMsgDragUpdateCursorPosition = Msg<'overlay/dragUpdateCursorPosition'> & {
x: number
y: number
}
/** @public */
export declare type OverlayMsgDragUpdateGroupRect = Msg<'overlay/dragUpdateGroupRect'> & {
groupRect: OverlayRect | null
}
/** @public */
export declare type OverlayMsgDragUpdateInsertPosition = Msg<'overlay/dragUpdateInsertPosition'> & {
insertPosition: DragInsertPosition | null
}
/** @public */
export declare type OverlayMsgDragUpdateSkeleton = Msg<'overlay/dragUpdateSkeleton'> & {
skeleton: DragSkeleton
}
/** @public */
export declare interface OverlayMsgElement<T extends string> extends Msg<`element/${T}`> {
id: string
}
/** @public */
export declare type OverlayMsgElementActivate = OverlayMsgElement<'activate'>
/** @public */
export declare type OverlayMsgElementClick = OverlayMsgElement<'click'> & {
sanity: SanityNode | SanityStegaNode
}
/** @public */
export declare type OverlayMsgElementContextMenu =
| OverlayMsgElement<'contextmenu'>
| (OverlayMsgElement<'contextmenu'> & {
position: {
x: number
y: number
}
sanity: SanityNode
})
/** @public */
export declare type OverlayMsgElementDeactivate = OverlayMsgElement<'deactivate'>
/** @public */
export declare type OverlayMsgElementMouseEnter = OverlayMsgElement<'mouseenter'> & {
rect: OverlayRect
}
/** @public */
export declare type OverlayMsgElementMouseLeave = OverlayMsgElement<'mouseleave'>
/** @public */
export declare type OverlayMsgElementRegister = OverlayMsgElement<'register'> & {
element: ElementNode
sanity: SanityNode | SanityStegaNode
rect: OverlayRect
dragDisabled: boolean
}
/** @public */
export declare type OverlayMsgElementUnregister = OverlayMsgElement<'unregister'>
/** @public */
export declare type OverlayMsgElementUpdate = OverlayMsgElement<'update'> & {
sanity: SanityNode | SanityStegaNode
rect: OverlayRect
}
/** @public */
export declare type OverlayMsgElementUpdateRect = OverlayMsgElement<'updateRect'> & {
rect: OverlayRect
}
/** @public */
export declare type OverlayMsgSetCursor = Msg<'overlay/setCursor'> & {
element: ElementNode
cursor: string | undefined
}
/**
* Options passed when instantiating an overlay controller
* @public
*/
export declare interface OverlayOptions {
handler: OverlayEventHandler
overlayElement: HTMLElement
inFrame: boolean
optimisticActorReady: boolean
}
/**
* @public
*/
export declare interface OverlayRect {
x: number
y: number
w: number
h: number
}
/**
* @public
* @deprecated Use `import type {Path} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type Path<T, K extends keyof T> = PathDeprecated<T, K>
export declare type PathDeprecated<T, K extends keyof T> = K extends string
? T[K] extends Record<string, any>
? `${K}.${PathDeprecated<T[K], keyof T[K]>}` | K
: K
: never
/**
* @public
* @deprecated Use `import type {PathValue} from '@sanity/visual-editing/optimistic'` instead
*/
export declare type PathValue<T, P extends string> = PathValueDeprecated<T, P>
export declare type PathValueDeprecated<T, P extends string> = P extends `${infer K}.${infer Rest}`
? K extends keyof T
? PathValueDeprecated<T[K], Rest>
: never
: P extends keyof T
? T[P]
: never
/**
* Data resolved from a Sanity node
* @public
*/
export declare type SanityNode = {
baseUrl: string
dataset?: string
id: string
isDraft?: string
path: string
projectId?: string
tool?: string
type?: string
workspace?: string
}
/**
* Data resolved from a Sanity Stega node
* @public
*/
export declare type SanityStegaNode = {
origin: string
href: string
data?: unknown
}
export declare interface SchemaArrayItem<T extends SchemaNode = SchemaNode> {
type: 'arrayItem'
name: string
title?: string
value: T
}
export declare interface SchemaArrayNode<T extends SchemaNode = SchemaNode> {
type: 'array'
of: SchemaArrayItem<T>
}
export declare interface SchemaBooleanNode {
type: 'boolean'
value?: boolean
}
export declare interface SchemaInlineNode {
type: 'inline'
/** the name of the referenced type */
name: string
}
export declare type SchemaNode =
| SchemaArrayNode
| SchemaBooleanNode
| SchemaInlineNode
| SchemaNullNode
| SchemaNumberNode
| SchemaObjectNode
| SchemaStringNode
| SchemaUnionNode
| SchemaUnknownNode
export declare interface SchemaNullNode {
type: 'null'
}
export declare interface SchemaNumberNode {
type: 'number'
value?: number
}
export declare interface SchemaObjectField<T extends SchemaNode = SchemaNode> {
type: 'objectField'
name: string
title?: string
value: T
optional?: boolean
}
export declare interface SchemaObjectNode<T extends SchemaNode = SchemaNode> {
type: 'object'
fields: Record<string, SchemaObjectField<T>>
rest?: SchemaObjectNode | SchemaUnknownNode | SchemaInlineNode
dereferencesTo?: string
}
export declare interface SchemaStringNode {
type: 'string'
value?: string
}
export declare interface SchemaUnionNode<T extends SchemaNode = SchemaNode> {
type: 'union'
of: SchemaUnionOption<T>[] | SchemaStringNode[] | SchemaNumberNode[]
options?: SchemaUnionNodeOptions
}
export declare type SchemaUnionNodeOptions = Omit<ArrayOptions, 'insertMenu'> & {
insertMenu?: Omit<InsertMenuOptions, 'views'> & {
views?: Array<
| {
name: 'list'
}
| {
name: 'grid'
previewImageUrls?: Record<string, string | undefined>
}
>
}
}
export declare interface SchemaUnionOption<T extends SchemaNode = SchemaNode> {
type: 'unionOption'
name: string
title?: string
icon?: string
value: T
}
export declare interface SchemaUnknownNode {
type: 'unknown'
}
/**
* @public
* @deprecated Use `import {useDocuments} from '@sanity/visual-editing/react'` instead
*/
export declare const useDocuments: typeof useDocumentsDeprecated
export declare function useDocumentsDeprecated(): {
getDocument: DocumentsGetDeprecated
mutateDocument: DocumentsMutateDeprecated
}
/**
* @public
* @deprecated Use `import {useOptimistic} from '@sanity/visual-editing/react'` instead
*/
export declare const useOptimistic: typeof useOptimisticDeprecated
export declare function useOptimisticDeprecated<T, U = SanityDocument_2>(
passthrough: T,
reducer: OptimisticReducerDeprecated<T, U> | Array<OptimisticReducerDeprecated<T, U>>,
): T
export declare function useSharedState<
T extends boolean | null | number | object | string | undefined | unknown = unknown,
>(key: string): T
/**
* @public
*/
export declare interface VisualEditingOptions {
/**
* @alpha
* This API is unstable and could change at any time.
*/
components?: OverlayComponentResolver
/**
* The history adapter is used for Sanity Presentation to navigate URLs in the preview frame.
*/
history?: HistoryAdapter
/**
* The refresh API allows smarter refresh logic than the default `location.reload()` behavior.
*/
refresh?: (payload: HistoryRefresh) => false | Promise<void>
/**
* The CSS z-index on the root node that renders overlays, tweak it accordingly to what layout you have.
*/
zIndex?: string | number
}
/**
* Helper
* @internal
*/
export declare type WithRequired<T, K extends keyof T> = T & {
[P in K]-?: T[P]
}
export {}