import {ClientPerspective} from '@sanity/client'
import {ComponentType} from 'react'
import {ElementType} from 'react'
import {ReactNode} from 'react'
import {SanityClient} from '@sanity/client'

/**
 * Types of array actions that can be performed
 * @beta
 */
export declare type ArrayActionName =
  /**
   * Add any item to the array at any position
   */
  | 'add'
  /**
   * Add item after an existing item
   */
  | 'addBefore'
  /**
   * Add item after an existing item
   */
  | 'addAfter'
  /**
   * Remove any item
   */
  | 'remove'
  /**
   * Duplicate item
   */
  | 'duplicate'
  /**
   * Copy item
   */
  | 'copy'

/** @public */
export declare interface ArrayDefinition extends BaseSchemaDefinition {
  type: 'array'
  of: ArrayOfType[]
  initialValue?: InitialValueProperty<any, unknown[]>
  validation?: ValidationBuilder<ArrayRule<unknown[]>, unknown[]>
  options?: ArrayOptions
}

/** @public */
export declare type ArrayOfEntry<T> = Omit<T, 'name' | 'hidden'> & {
  name?: string
}

/** @public */
export declare type ArrayOfType<
  TType extends IntrinsicTypeName = IntrinsicTypeName,
  TAlias extends IntrinsicTypeName | undefined = undefined,
> = IntrinsicArrayOfDefinition[TType] | ArrayOfEntry<TypeAliasDefinition<string, TAlias>>

/** @public */
export declare interface ArrayOptions<V = unknown>
  extends SearchConfiguration,
    BaseSchemaTypeOptions {
  list?: TitledListValue<V>[] | V[]
  layout?: 'list' | 'tags' | 'grid'
  /** @deprecated This option does not have any effect anymore */
  direction?: 'horizontal' | 'vertical'
  sortable?: boolean
  modal?: {
    type?: 'dialog' | 'popover'
    width?: number | 'auto'
  }
  /** @alpha This API may change */
  insertMenu?: InsertMenuOptions
  /**
   * A boolean flag to enable or disable tree editing for the array.
   * If there are any nested arrays, they will inherit this value.
   * @deprecated tree editing beta feature has been disabled
   */
  treeEditing?: boolean
  /**
   * A list of array actions to disable
   * Possible options are defined by {@link ArrayActionName}
   * @beta
   */
  disableActions?: ArrayActionName[]
}

/** @public */
export declare interface ArrayRule<Value> extends RuleDef<ArrayRule<Value>, Value> {
  min: (length: number | FieldReference) => ArrayRule<Value>
  max: (length: number | FieldReference) => ArrayRule<Value>
  length: (length: number | FieldReference) => ArrayRule<Value>
  unique: () => ArrayRule<Value>
}

/** @public */
export declare interface ArraySchemaType<V = unknown> extends BaseSchemaType {
  jsonType: 'array'
  of: (Exclude<SchemaType, ArraySchemaType> | ReferenceSchemaType)[]
  options?: ArrayOptions<V> & {
    layout?: V extends string ? 'tag' : 'grid'
  }
}

/** @internal */
export declare type ArraySchemaTypeOf<TSchemaType extends ArraySchemaType['of'][number]> = Omit<
  ArraySchemaType,
  'of'
> & {
  of: TSchemaType[]
}

/** @public */
export declare interface Asset extends SanityDocument {
  url: string
  path: string
  assetId: string
  extension: string
  mimeType: string
  sha1hash: string
  size: number
  originalFilename?: string
  label?: string
  title?: string
  description?: string
  creditLine?: string
  source?: AssetSourceSpec
}

/** @public */
export declare type AssetFromSource = {
  kind: 'assetDocumentId' | 'file' | 'base64' | 'url'
  value: string | File_2
  assetDocumentProps?: ImageAsset
  mediaLibraryProps?: {
    mediaLibraryId: string
    assetId: string
    assetInstanceId: string
  }
}

/** @public */
export declare type AssetMetadataType =
  | 'location'
  | 'exif'
  | 'image'
  | 'palette'
  | 'lqip'
  | 'blurhash'
  | 'none'

/** @public */
export declare interface AssetSchemaTypeOptions {
  accept?: string
  storeOriginalFilename?: boolean
}

/** @public */
export declare interface AssetSource {
  name: string
  /** @deprecated provide `i18nKey` instead */
  title?: string
  i18nKey?: string
  component: ComponentType<AssetSourceComponentProps>
  icon?: ComponentType<EmptyProps>
  /** @beta */
  uploader?: AssetSourceUploader
}

/** @public */
export declare interface AssetSourceComponentProps {
  action?: 'select' | 'upload'
  assetSource: AssetSource
  assetType?: 'file' | 'image'
  accept: string
  selectionType: 'single'
  dialogHeaderTitle?: React.ReactNode
  selectedAssets: Asset[]
  onClose: () => void
  onSelect: (assetFromSource: AssetFromSource[]) => void
  schemaType?: ImageSchemaType | FileSchemaType
}

/** @public */
export declare interface AssetSourceSpec {
  id: string
  name: string
  url?: string
}

/** @beta */
export declare interface AssetSourceUploader {
  upload(
    files: globalThis.File[],
    options?: {
      /**
       * The schema type of the field the asset is being uploaded to.
       * May be of interest to the uploader to read file and image options.
       */
      schemaType?: SchemaType
      /**
       * The uploader may send patches directly to the field
       * Typed 'unknown' as we don't have patch definitions in sanity/types yet.
       */
      onChange?: (patch: unknown) => void
    },
  ): AssetSourceUploadFile[]
  /**
   * Abort the upload of a file
   */
  abort(file?: AssetSourceUploadFile): void
  /**
   * Get the files that are currently being uploaded
   */
  getFiles(): AssetSourceUploadFile[]
  /**
   * Subscribe to upload events from the uploader
   */
  subscribe(subscriber: (event: AssetSourceUploadEvent) => void): () => void
  /**
   * Update the status of a file. Will be emitted to subscribers.
   */
  updateFile(
    fileId: string,
    data: {
      progress?: number
      status?: string
      error?: Error
    },
  ): void
  /**
   * Reset the uploader (clear files). Should be called by the uploader when all files are done.
   */
  reset(): void
}

/** @beta */
export declare type AssetSourceUploadEvent =
  | AssetSourceUploadEventProgress
  | AssetSourceUploadEventStatus
  | AssetSourceUploadEventAllComplete
  | AssetSourceUploadEventError
  | AssetSourceUploadEventAbort

/**
 * Emitted when all files are done, either successfully, aborted or with errors
 * @beta */
export declare type AssetSourceUploadEventAbort = {
  type: 'abort'
  /**
   * Files aborted
   */
  files: AssetSourceUploadFile[]
}

/**
 * Emitted when all files are done, either successfully, aborted or with errors
 * @beta */
export declare type AssetSourceUploadEventAllComplete = {
  type: 'all-complete'
  files: AssetSourceUploadFile[]
}

/**
 * Emitted when all files are done, either successfully, aborted or with errors
 * @beta */
export declare type AssetSourceUploadEventError = {
  type: 'error'
  /**
   * Files errored
   */
  files: AssetSourceUploadFile[]
}

/**
 * Emitted when a file upload is progressing
 * @beta */
export declare type AssetSourceUploadEventProgress = {
  type: 'progress'
  file: AssetSourceUploadFile
  progress: number
}

/**
 * Emitted when a file upload is changing status
 * @beta */
export declare type AssetSourceUploadEventStatus = {
  type: 'status'
  file: AssetSourceUploadFile
  status: AssetSourceUploadFile['status']
}

/** @beta */
export declare interface AssetSourceUploadFile {
  id: string
  file: globalThis.File
  progress: number
  status: 'pending' | 'uploading' | 'complete' | 'error' | 'aborted'
  error?: Error
  result?: unknown
}

/** @beta */
export declare type AssetSourceUploadSubscriber = (event: AssetSourceUploadEvent) => void

/**
 * Enhances VSCode autocomplete by using a distinct type for strings.
 *
 * `AllowOtherStrings` is defined as `string & {}`, an intersection that behaves
 * like `string` but is treated differently by TypeScript's type system for
 * internal processing. This helps in improving the specificity and relevance of
 * autocomplete suggestions by potentially prioritizing `IntrinsicTypeName`
 * over general string inputs, addressing issues where `string` type suggestions
 * might overshadow more useful specific literals.
 *
 * @beta
 */
export declare type AutocompleteString = string & {}

/** @public */
export declare interface BaseSchemaDefinition {
  name: string
  title?: string
  description?: string | React.JSX.Element
  hidden?: ConditionalProperty
  readOnly?: ConditionalProperty
  icon?: ComponentType | ReactNode
  validation?: unknown
  initialValue?: unknown
  deprecated?: DeprecatedProperty
}

/** @public */
export declare interface BaseSchemaType extends Partial<DeprecationConfiguration> {
  name: string
  title?: string
  description?: string
  type?: SchemaType
  liveEdit?: boolean
  readOnly?: ConditionalProperty
  hidden?: ConditionalProperty
  icon?: ComponentType
  initialValue?: InitialValueProperty<any, any>
  validation?: SchemaValidationValue
  preview?: PreviewConfig
  /** @beta */
  components?: {
    block?: ComponentType<any>
    inlineBlock?: ComponentType<any>
    annotation?: ComponentType<any>
    diff?: ComponentType<any>
    field?: ComponentType<any>
    input?: ComponentType<any>
    item?: ComponentType<any>
    preview?: ComponentType<any>
    portableText?: {
      plugins?: ComponentType<any>
    }
  }
  /**
   * @deprecated This will be removed.
   */
  placeholder?: string
}

/**
 * `BaseOptions` applies to all type options.
 *
 *  It can be extended by interface declaration merging in plugins to provide generic options to all types and fields.
 *
 *  @public
 *  */
export declare interface BaseSchemaTypeOptions {
  sanityCreate?: SanityCreateOptions
  canvasApp?: CanvasAppOptions
}

/**
 * Schema definition for a text block annotation object.
 *
 * @public
 * @example The default link annotation
 * ```ts
 * {
 *   name: 'blockContent',
 *   title: 'Content',
 *   type: 'array',
 *   of: [
 *     {
 *       type: 'block',
 *       marks: {
 *         annotations: [
 *           {
 *             type: 'object',
 *             name: 'link',
 *             fields: [
 *               {
 *                 type: 'string',
 *                 name: 'href',
 *               },
 *             ],
 *           },
 *         ]
 *       },
 *     }
 *   ]
 * }
 * ```
 */
export declare interface BlockAnnotationDefinition extends ObjectDefinition {
  icon?: ReactNode | ComponentType
}

/**
 * The specific `children` field of a `block` type (`BlockSchemaType`)
 * @see BlockSchemaType
 *
 * @internal
 */
export declare type BlockChildrenObjectField = {
  name: 'children'
} & ObjectField<ArraySchemaType>

/**
 * Schema definition for text block decorators.
 *
 * @public
 * @example The default set of decorators
 * ```ts
 * {
 *   name: 'blockContent',
 *   title: 'Content',
 *   type: 'array',
 *   of: [
 *     {
 *       type: 'block',
 *       marks: {
 *         decorators: [
 *           {title: 'Strong', value: 'strong'},
 *           {title: 'Emphasis', value: 'em'},
 *           {title: 'Underline', value: 'underline'},
 *           {title: 'Strike', value: 'strike'},
 *           {title: 'Code', value: 'code'},
 *         ]
 *       }
 *     }
 *   ]
 * }
 * ```
 */
export declare interface BlockDecoratorDefinition {
  title: string
  i18nTitleKey?: string
  value: string
  icon?: ReactNode | ComponentType
}

/**
 * Schema definition for text blocks.
 *
 * @public
 * @example the default block definition
 * ```ts
 * {
 *   name: 'blockContent',
 *   title: 'Content',
 *   type: 'array',
 *   of: [
 *     {
 *       type: 'block',
 *       marks: {
 *         decorators: [
 *           {title: 'Strong', value: 'strong'},
 *           {title: 'Emphasis', value: 'em'},
 *           {title: 'Underline', value: 'underline'},
 *           {title: 'Strike', value: 'strike'},
 *           {title: 'Code', value: 'code'},
 *         ],
 *         annotations: [
 *           {
 *             type: 'object',
 *             name: 'link',
 *             fields: [
 *               {
 *                 type: 'string',
 *                 name: 'href',
 *               },
 *             ],
 *           },
 *         ]
 *       },
 *       styles: [
 *         {title: 'Normal', value: 'normal'},
 *         {title: 'H1', value: 'h1'},
 *         {title: 'H2', value: 'h2'},
 *         {title: 'H3', value: 'h3'},
 *         {title: 'H4', value: 'h4'},
 *         {title: 'H5', value: 'h5'},
 *         {title: 'H6', value: 'h6'},
 *         {title: 'Quote', value: 'blockquote'}
 *       ],
 *       lists: [
 *         {title: 'Bullet', value: 'bullet'},
 *         {title: 'Number', value: 'number'},
 *       ],
 *     },
 *   ]
 * }
 * ```
 */
export declare interface BlockDefinition extends BaseSchemaDefinition {
  type: 'block'
  styles?: BlockStyleDefinition[]
  lists?: BlockListDefinition[]
  marks?: BlockMarksDefinition
  of?: ArrayOfType<'object' | 'reference'>[]
  initialValue?: InitialValueProperty<any, any[]>
  options?: BlockOptions
  validation?: ValidationBuilder<BlockRule, any[]>
}

/**
 * Schema definition for a text block list style.
 *
 * @public
 * @example The defaults lists
 * ```ts
 * {
 *   name: 'blockContent',
 *   title: 'Content',
 *   type: 'array',
 *   of: [
 *     {
 *       type: 'block',
 *       lists: [
 *         {title: 'Bullet', value: 'bullet'},
 *         {title: 'Number', value: 'number'},
 *       ]
 *     }
 *   ]
 * }
 * ```
 */
export declare interface BlockListDefinition {
  title: string
  i18nTitleKey?: string
  value: string
  icon?: ReactNode | ComponentType
}

/**
 * A specific `ObjectField` for `list` in `BlockSchemaType`
 * @see BlockSchemaType
 *
 * @internal
 */
export declare type BlockListObjectField = {
  name: 'list'
} & ObjectField<StringSchemaType>

/**
 * Schema definition for text block marks (decorators and annotations).
 *
 * @public */
export declare interface BlockMarksDefinition {
  decorators?: BlockDecoratorDefinition[]
  annotations?: ArrayOfType<'object' | 'reference'>[]
}

/**
 * Schema options for a Block schema definition
 * @public */
export declare interface BlockOptions extends BaseSchemaTypeOptions {
  /**
   * Turn on or off the builtin browser spellchecking. Default is on.
   */
  spellCheck?: boolean
  unstable_whitespaceOnPasteMode?: 'preserve' | 'normalize' | 'remove'
}

/** @public */
export declare interface BlockRule extends RuleDef<BlockRule, any[]> {}

/**
 * Represents the compiled schema shape for `block`s for portable text.
 *
 * Note: this does _not_ represent the schema definition shape.
 *
 * @internal
 */
export declare interface BlockSchemaType extends ObjectSchemaType {
  fields: [BlockChildrenObjectField, BlockStyleObjectField, BlockListObjectField, ...ObjectField[]]
  options?: BlockOptions
}

/**
 * Schema definition for a text block style.
 * A text block may have a block style like 'header', 'normal', 'lead'
 * attached to it, which is stored on the `.style` property for that block.
 *
 * @public
 * @remarks The first defined style will become the default style.´´
 * @example The default set of styles
 * ```ts
 * {
 *   name: 'blockContent',
 *   title: 'Content',
 *   type: 'array',
 *   of: [
 *     {
 *       type: 'block',
 *       styles: [
 *         {title: 'Normal', value: 'normal'},
 *         {title: 'H1', value: 'h1'},
 *         {title: 'H2', value: 'h2'},
 *         {title: 'H3', value: 'h3'},
 *         {title: 'H4', value: 'h4'},
 *         {title: 'H5', value: 'h5'},
 *         {title: 'H6', value: 'h6'},
 *         {title: 'Quote', value: 'blockquote'}
 *       ]
 *     }
 *   ]
 * }
 * ```
 * @example Example of defining a block type with custom styles and render components.
 * ```ts
 * defineArrayMember({
 *   type: 'block',
 *   styles: [
 *     {
 *       title: 'Paragraph',
 *       value: 'paragraph',
 *       component: ParagraphStyle,
 *     },
 *     {
 *       title: 'Lead',
 *       value: 'lead',
 *       component: LeadStyle,
 *     },
 *     {
 *       title: 'Heading',
 *       value: 'heading',
 *       component: HeadingStyle,
 *     },
 *   ],
 * })
 * ```
 */
export declare interface BlockStyleDefinition {
  title: string
  value: string
  i18nTitleKey?: string
  icon?: ReactNode | ComponentType
}

/**
 * A specific `ObjectField` for `style` in `BlockSchemaType`
 * @see BlockSchemaType
 *
 * @internal
 */
export declare type BlockStyleObjectField = {
  name: 'style'
} & ObjectField<StringSchemaType>

/** @public */
export declare interface BooleanDefinition extends BaseSchemaDefinition {
  type: 'boolean'
  options?: BooleanOptions
  initialValue?: InitialValueProperty<any, boolean>
  validation?: ValidationBuilder<BooleanRule, boolean>
}

/** @public */
export declare interface BooleanOptions extends BaseSchemaTypeOptions {
  layout?: 'switch' | 'checkbox'
}

/** @public */
export declare interface BooleanRule extends RuleDef<BooleanRule, boolean> {}

/** @public */
export declare interface BooleanSchemaType extends BaseSchemaType {
  jsonType: 'boolean'
  options?: BooleanOptions
  initialValue?: InitialValueProperty<any, boolean>
}

/**
 * Options for configuring how Canvas app interfaces with the type or field.
 *
 * @public
 */
export declare interface CanvasAppOptions {
  /** Set to true to exclude a type or field from appearing in Canvas */
  exclude?: boolean
  /**
   * A short description of what the type or field is used for.
   * Purpose can be used to improve how and when content mapping uses the field.
   * */
  purpose?: string
}

/** @public */
export declare interface CollapseOptions {
  collapsed?: boolean
  collapsible?: boolean
  /**
   * @deprecated Use `collapsible` instead
   */
  collapsable?: boolean
}

/**
 * this is used to get allow index access (e.g. `RuleSpec['constraint']`) to
 * constraint when a rule spec might not have a `constraint` prop
 *
 * @internal
 */
export declare type ConditionalIndexAccess<T, U> = U extends keyof T ? T[U] : undefined

/** @public */
export declare type ConditionalProperty = boolean | ConditionalPropertyCallback | undefined

/** @public */
export declare type ConditionalPropertyCallback = (
  context: ConditionalPropertyCallbackContext,
) => boolean

/** @public */
export declare interface ConditionalPropertyCallbackContext {
  document: SanityDocument | undefined
  parent: any
  value: any
  currentUser: Omit<CurrentUser, 'role'> | null
}

/** @internal */
export declare interface CreateIfNotExistsMutation {
  createIfNotExists: {
    _id: string
    _type: string
    [key: string]: unknown
  }
}

/** @internal */
export declare interface CreateMutation {
  create: {
    _id?: string
    _type: string
    [key: string]: unknown
  }
}

/** @internal */
export declare interface CreateOrReplaceMutation {
  createOrReplace: {
    _id: string
    _type: string
    [key: string]: unknown
  }
}

/**
 * Mutation type used when the document has passed the threshold of the
 * "history retention" - any transactions done prior to the threshold gets "squashed"
 * into a single "create" transaction.
 *
 * @internal
 */
export declare interface CreateSquashedMutation {
  createSquashed: {
    /**
     * The user IDs of all the users who contributed to the document prior to the squashing
     */
    authors: string[]
    /**
     * User ID of the person who initially created the document
     */
    createdBy: string
    /**
     * ISO-formatted timestamp (zulu-time) of when the document as initially created
     */
    createdAt: string
    /**
     * The document as it exists after squashing has occurred
     */
    document: {
      _id: string
      _type: string
      [key: string]: unknown
    }
  }
}

/** @public */
export declare interface CrossDatasetReferenceDefinition extends BaseSchemaDefinition {
  type: 'crossDatasetReference'
  weak?: boolean
  to: {
    type: string
    title?: string
    icon?: ComponentType
    preview?: PreviewConfig
    /**
     * @deprecated Unused. Configuring search is no longer supported.
     */
    __experimental_search?: {
      path: string | string[]
      weight?: number
      mapWith?: string
    }[]
  }[]
  dataset: string
  studioUrl?: (document: {id: string; type?: string}) => string | null
  tokenId?: string
  options?: ReferenceOptions
  /**
   * @deprecated Cross-project references are no longer supported, only cross-dataset
   */
  projectId?: string
}

/** @beta */
export declare type CrossDatasetReferenceFilterResolver = (options: {
  document: SanityDocument
  parent?: Record<string, unknown> | Record<string, unknown>[]
  parentPath: Path
}) => CrossDatasetReferenceFilterSearchOptions | Promise<CrossDatasetReferenceFilterSearchOptions>

/** @beta */
export declare type CrossDatasetReferenceFilterSearchOptions = {
  filter?: string
  params?: Record<string, unknown>
  tag?: string
}

/** @beta */
export declare interface CrossDatasetReferenceSchemaType extends Omit<ObjectSchemaType, 'options'> {
  jsonType: 'object'
  to: CrossDatasetType[]
  dataset: string
  studioUrl?: (document: {id: string; type?: string}) => string | null
  weak?: boolean
  options?: ReferenceFilterOptions
}

/** @beta */
export declare interface CrossDatasetReferenceValue {
  _type: string
  _dataset: string
  _projectId: string
  _ref: string
  _key?: string
  _weak?: boolean
}

/** @beta */
export declare interface CrossDatasetType {
  type: string
  title?: string
  icon: ComponentType
  preview: PreviewConfig
  /** @deprecated Unused. Configuring search is no longer supported for cross-dataset references. */
  __experimental_search: ObjectSchemaType['__experimental_search']
}

/** @public */
export declare interface CurrentUser {
  id: string
  name: string
  email: string
  profileImage?: string
  provider?: string
  /** @deprecated use `roles` instead */
  role: string
  roles: Role[]
}

/** @public */
export declare interface CustomValidator<T = unknown> {
  (value: T, context: ValidationContext): CustomValidatorResult | Promise<CustomValidatorResult>
  bypassConcurrencyLimit?: boolean
}

/** @public */
export declare type CustomValidatorResult =
  | true
  | string
  | ValidationError
  | ValidationError[]
  | LocalizedValidationMessages

/** @public */
export declare interface DateDefinition extends BaseSchemaDefinition {
  type: 'date'
  options?: DateOptions
  placeholder?: string
  validation?: ValidationBuilder<DateRule, string>
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare interface DateOptions extends BaseSchemaTypeOptions {
  dateFormat?: string
}

/** @public */
export declare interface DateRule extends RuleDef<DateRule, string> {
  /**
   * @param minDate - Minimum date (inclusive). minDate should be in ISO 8601 format.
   */
  min: (minDate: string | FieldReference) => DateRule
  /**
   * @param maxDate - Maximum date (inclusive). maxDate should be in ISO 8601 format.
   */
  max: (maxDate: string | FieldReference) => DateRule
}

/** @public */
export declare interface DatetimeDefinition extends BaseSchemaDefinition {
  type: 'datetime'
  options?: DatetimeOptions
  placeholder?: string
  validation?: ValidationBuilder<DatetimeRule, string>
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare interface DatetimeOptions extends BaseSchemaTypeOptions {
  dateFormat?: string
  timeFormat?: string
  timeStep?: number
  displayTimeZone?: string
  allowTimeZoneSwitch?: boolean
}

/** @public */
export declare interface DatetimeRule extends RuleDef<DatetimeRule, string> {
  /**
   * @param minDate - Minimum date (inclusive). minDate should be in ISO 8601 format.
   */
  min: (minDate: string | FieldReference) => DatetimeRule
  /**
   * @param maxDate - Maximum date (inclusive). maxDate should be in ISO 8601 format.
   */
  max: (maxDate: string | FieldReference) => DatetimeRule
}

/**
 * Define an array item member type within an array definition `of`-array.
 *
 * This function will narrow the schema type down to fields and options based on the provided
 * `type` string.
 *
 * Using `defineArrayMember` is optional, but should provide improved autocompletion in your IDE, when building your schema.
 * Field properties like `validation` and `initialValue` will also be more specific.
 *
 * See {@link defineType} for example usage.
 *
 * @param arrayOfSchema - should be a valid `array.of` member definition.
 * @param defineOptions - optional param to provide type hints for `arrayOfSchema`.
 *
 * @see defineType
 * @see defineField
 * @see typed
 *
 * @beta
 */
export declare function defineArrayMember<
  const TType extends IntrinsicTypeName | AutocompleteString,
  const TName extends string,
  TSelect extends Record<string, string> | undefined,
  TPrepareValue extends Record<keyof TSelect, any> | undefined,
  TAlias extends IntrinsicTypeName | undefined,
  TStrict extends StrictDefinition,
>(
  arrayOfSchema: {
    type: TType
    /**
     * When provided, `name` is used as `_type` for the array item when stored.
     *
     * Necessary when an array contains multiple entries with the same `type`, each with
     * different configuration (title and initialValue for instance).
     */
    name?: TName
  } & DefineArrayMemberBase<TType, TAlias> &
    NarrowPreview<TType, TAlias, TSelect, TPrepareValue> &
    MaybeAllowUnknownProps<TStrict>,
  defineOptions?: DefineSchemaOptions<TStrict, TAlias>,
): typeof arrayOfSchema & WidenValidation & WidenInitialValue

/** @beta */
export declare type DefineArrayMemberBase<
  TType extends string,
  TAlias extends IntrinsicTypeName | undefined,
> = TType extends IntrinsicTypeName
  ? IntrinsicArrayOfBase[TType]
  : ArrayOfEntry<TypeAliasDefinition<string, TAlias>>

/**
 * Define a Media Library asset aspect.
 *
 * Aspects can be deployed using the `sanity media deploy-aspect` CLI command.
 *
 * @public
 * @beta
 */
export declare function defineAssetAspect(
  definition: MediaLibraryAssetAspectDefinition,
): MediaLibraryAssetAspectDocument

/**
 * Define a field within a document, object, image or file definition `fields` array.
 *
 * This function will narrow the schema type down to fields and options based on the provided
 * type-string.
 *
 * Using `defineField` is optional, but should provide improved autocompletion in your IDE, when building your schema.
 * Field-properties like `validation` and `initialValue`will also be more specific.
 *
 * See {@link defineType} for more examples.
 *
 * @param schemaField - should be a valid field type definition.
 * @param defineOptions - optional param to provide type hints for `schemaField`.
 *
 * @see defineField
 * @see defineArrayMember
 * @see typed
 *
 * @beta
 */
export declare function defineField<
  const TType extends IntrinsicTypeName | AutocompleteString,
  const TName extends string,
  TSelect extends Record<string, string> | undefined,
  TPrepareValue extends Record<keyof TSelect, any> | undefined,
  TAlias extends IntrinsicTypeName | undefined,
  TStrict extends StrictDefinition,
>(
  schemaField: {
    type: TType
    name: TName
  } & DefineSchemaBase<TType, TAlias> &
    NarrowPreview<TType, TAlias, TSelect, TPrepareValue> &
    MaybeAllowUnknownProps<TStrict> &
    FieldDefinitionBase,
  defineOptions?: DefineSchemaOptions<TStrict, TAlias>,
): typeof schemaField & WidenValidation & WidenInitialValue

/** @beta */
export declare type DefineSchemaBase<
  TType extends string,
  TAlias extends IntrinsicTypeName | undefined,
> = TType extends IntrinsicTypeName ? IntrinsicBase[TType] : TypeAliasDefinition<TType, TAlias>

/** @beta */
export declare interface DefineSchemaOptions<
  TStrict extends StrictDefinition,
  TAlias extends IntrinsicTypeName | undefined,
> {
  /**
   * `strict: false` allows unknown properties in the schema.
   * Use this when adding customizations to the schema that are not part of sanity core.
   *
   * If you want to extend the Sanity Schema types with your own properties or options to make them typesafe,
   * you can use [TypeScript declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html).
   *
   * See {@link defineType} for more.
   *
   * @see defineType
   */
  strict?: TStrict
  /** Should be provided when type is a non-intrinsic type, ie type is a type alias */
  aliasFor?: TAlias extends IntrinsicTypeName ? TAlias : never
}

/** @beta */
export declare type DefineSchemaType<
  TType extends string,
  TAlias extends IntrinsicTypeName | undefined,
> = TType extends IntrinsicTypeName
  ? IntrinsicDefinitions[TType]
  : TypeAliasDefinition<TType, TAlias>

/**
 * Helper function for defining a Sanity type definition. This function does not do anything on its own;
 * it exists to check that your schema definition is correct, and help autocompletion in your IDE.
 *
 * This function will narrow the schema type down to fields and options based on the provided type-string.
 *
 * Schema types defined using `defineType` should typically be added to the Studio config under `schema.types`.
 * Defined types can be referenced by their `name`. This is referred to as a type-alias.
 *
 * When using type-aliases as `type`, `defineType` cannot know the base-type, so type-safety will be reduced.
 * If you know the base type of the type-alias, provide `defineOptions.aliasFor: <base type name>`.
 * This will enforce that the schema definition conforms with the provided type.
 *
 * By default, `defineType` only allows known properties and options.
 * Use `defineOptions.strict: false` to allow unknown properties and options.
 *
 * ### Basic usage
 *
 * ```ts
 * defineType({
 *   type: 'object',
 *   name: 'custom-object',
 *   fields: [ {type: 'string', name: 'title', title: 'Title'}],
 * })
 * ```
 *
 * ### Usage with aliasFor narrowing
 *
 * ```ts
 * defineType({
 *   type: 'custom-object',
 *   name: 'redefined-custom-object',
 *   options: {
 *     columns: 2
 *   }
 * }, {aliasFor: 'object' })
 * ```
 *
 * ### Allow unknown properties
 *
 * ```ts
 * defineType({
 *   type: 'custom-object',
 *   name: 'redefined-custom-object',
 *   allowsUnknownProperties: true
 *   options: {
 *     columns: 2,
 *     allowsUnknownOptions: true
 *   }
 * }, {strict: false})
 * ```
 * ### Maximum safety and best autocompletion
 *
 * Use {@link defineType}, {@link defineField} and {@link defineArrayMember}:
 *
 * ```ts
 *  defineType({
 *    type: 'object',
 *    name: 'custom-object',
 *    fields: [
 *      defineField({
 *        type: 'array',
 *        name: 'arrayField',
 *        title: 'Things',
 *        of: [
 *          defineArrayMember({
 *            type: 'object',
 *            name: 'type-name-in-array',
 *            fields: [defineField({type: 'string', name: 'title', title: 'Title'})],
 *          }),
 *        ],
 *      }),
 *    ],
 *  })
 * ```
 *
 * ## Note on type-safety in the current implementation
 *
 * Type-safety inside array-like properties (schema properties like `fields` and `of`) can only be guaranteed when
 * {@link defineField} and {@link defineArrayMember} are used to wrap each value in the array.
 *
 * For array-values without a function-wrapper, TypeScript will resolve to a union type of all possible properties across
 * all schema types. This result in less precise typing.
 *
 * ### Extending the Sanity Schema types
 *
 * If you want to extend the Sanity Schema types with your own properties or options to make them typesafe,
 * you can use [TypeScript declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html).
 *
 * With declaration merging, properties and options will be available in a type-safe manner, and
 * `strict: false` will not be necessary.
 *
 * #### Example: Add option to StringOptions
 *
 * ```ts
 * // string.ts
 *
 * //redeclare the sanity module
 * declare module 'sanity' {
 *  // redeclare StringOptions; it will be merged with StringOptions in the sanity module
 *  export interface StringOptions {
 *    myCustomOption?: boolean
 *  }
 * }
 *
 * // the option is now part of the StringOptions type, just as if it was declared in the sanity codebase:
 * defineType({
 *   type: 'string',
 *   name: 'my-string',
 *   options: {
 *     myCustomOption: true // this does not give an error anymore
 *   }
 * })
 *
 * ```
 *
 * #### Example: Add a schema definition to "intrinsic-types"
 *
 * ```ts
 * //my-custom-type-definition.ts
 *
 * // create a new schema definition based on object (we remove the ability to assign field, change the type add some options)
 *  export type MagicallyAddedDefinition = Omit<Schema.ObjectDefinition, 'type' | 'fields'> & {
 *    type: 'magically-added-type'
 *    options?: {
 *      sparkles?: boolean
 *    }
 *  }
 *
 *  // redeclares sanity module so we can add interfaces props to it
 * declare module 'sanity' {
 *     // redeclares IntrinsicDefinitions and adds a named definition to it
 *     // it is important that the key is the same as the type in the definition ('magically-added-type')
 *     export interface IntrinsicDefinitions {
 *       'magically-added-type': MagicallyAddedDefinition
 *     }
 * }
 *
 * // defineType will now narrow `type: 'magically-added-type'` to `MagicallyAddedDefinition`
 * defineType({
 *   type: 'magically-added-type'
 *   name: 'magic',
 *   options: {
 *     sparkles: true // this is allowed,
 *     //@ts-expect-error this is not allowed in MagicallyAddedDefinition.options
 *     sparks: true
 *   }
 * })
 * ```
 *
 * @param schemaDefinition - should be a valid schema type definition.
 * @param defineOptions - optional param to provide type hints for `schemaDefinition`.
 *
 * @see defineField
 * @see defineArrayMember
 * @see typed
 *
 * @beta
 */
export declare function defineType<
  const TType extends IntrinsicTypeName | AutocompleteString,
  const TName extends string,
  TSelect extends Record<string, string> | undefined,
  TPrepareValue extends Record<keyof TSelect, any> | undefined,
  TAlias extends IntrinsicTypeName | undefined,
  TStrict extends StrictDefinition,
>(
  schemaDefinition: {
    type: TType
    name: TName
  } & DefineSchemaBase<TType, TAlias> &
    NarrowPreview<TType, TAlias, TSelect, TPrepareValue> &
    MaybeAllowUnknownProps<TStrict>,
  defineOptions?: DefineSchemaOptions<TStrict, TAlias>,
): typeof schemaDefinition

/** @internal */
export declare interface DeleteMutation {
  delete: MutationSelection
}

/** @public */
export declare interface DeprecatedProperty {
  reason: string
}

/** @public */
export declare type DeprecatedSchemaType<TSchemaType extends BaseSchemaType = BaseSchemaType> =
  TSchemaType & DeprecationConfiguration

/**
 * @public
 */
export declare interface DeprecationConfiguration {
  deprecated: DeprecatedProperty
}

/** @public */
export declare interface DocumentDefinition extends Omit<ObjectDefinition, 'type'> {
  type: 'document'
  liveEdit?: boolean
  /** @beta */
  orderings?: SortOrdering[]
  options?: DocumentOptions
  validation?: ValidationBuilder<DocumentRule, SanityDocument>
  initialValue?: InitialValueProperty<any, Record<string, unknown>>
  /** @deprecated Unused. Use the new field-level search config. */
  __experimental_search?: {
    path: string
    weight: number
    mapWith?: string
  }[]
  /** @alpha */
  __experimental_omnisearch_visibility?: boolean
  /**
   * Determines whether the large preview title is displayed in the document pane form
   * @alpha
   * */
  __experimental_formPreviewTitle?: boolean
}

/**
 * This exists only to allow for extensions using declaration-merging.
 *
 * @public
 */
export declare interface DocumentOptions extends BaseSchemaTypeOptions {}

/** @public */
export declare interface DocumentRule extends RuleDef<DocumentRule, SanityDocument> {}

/** @public */
export declare interface EmailDefinition extends BaseSchemaDefinition {
  type: 'email'
  options?: EmailOptions
  placeholder?: string
  validation?: ValidationBuilder<EmailRule, string>
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare interface EmailOptions extends BaseSchemaTypeOptions {}

/** @public */
export declare interface EmailRule extends RuleDef<EmailRule, string> {}

/** @public */
export declare interface EmptyProps {}

/** @public */
export declare interface EnumListProps<V = unknown> {
  list?: Array<TitledListValue<V> | V>
  layout?: 'radio' | 'dropdown'
  direction?: 'horizontal' | 'vertical'
}

/**
 * The shape of a field definition. Note, it's recommended to use the
 * `defineField` function instead of using this type directly.
 *
 * Where `defineField` infers the exact field type,
 * FieldDefinition is a compromise union of all types a field can have.
 *
 * A field definition can be a reference to another registered top-level type
 * or a inline type definition.
 *
 * @public
 */
export declare type FieldDefinition<
  TType extends IntrinsicTypeName = IntrinsicTypeName,
  TAlias extends IntrinsicTypeName | undefined = undefined,
> = (InlineFieldDefinition[TType] | TypeAliasDefinition<string, TAlias>) & FieldDefinitionBase

/** @public */
export declare interface FieldDefinitionBase {
  fieldset?: string
  group?: string | string[]
}

/** @public */
export declare interface FieldGroup {
  name: string
  icon?: ComponentType
  title?: string
  description?: string
  i18n?: I18nTextRecord<'title'>
  hidden?: ConditionalProperty
  default?: boolean
  fields?: ObjectField[]
}

/** @public */
export declare type FieldGroupDefinition = {
  name: string
  title?: string
  hidden?: ConditionalProperty
  icon?: ComponentType
  default?: boolean
  i18n?: I18nTextRecord<'title'>
}

/**
 * Holds a reference to a different field
 * NOTE: Only use this through {@link Rule.valueOfField}
 *
 * @public
 */
export declare interface FieldReference {
  type: symbol
  path: string | string[]
}

/** @public */
export declare type FieldRules = {
  [fieldKey: string]: SchemaValidationValue
}

/** @public */
export declare type Fieldset = SingleFieldSet | MultiFieldSet

/** @public */
export declare type FieldsetDefinition = {
  name: string
  title?: string
  description?: string
  group?: string
  hidden?: ConditionalProperty
  readOnly?: ConditionalProperty
  options?: ObjectOptions
}

/** @public */
declare interface File_2 {
  [key: string]: unknown
  asset?: Reference
}
export {File_2 as File}

/** @public */
export declare interface FileAsset extends Asset {
  _type: 'sanity.fileAsset'
  metadata: Record<string, unknown>
}

/** @public */
export declare interface FileDefinition
  extends Omit<ObjectDefinition, 'type' | 'fields' | 'options' | 'groups' | 'validation'> {
  type: 'file'
  fields?: ObjectDefinition['fields']
  options?: FileOptions
  validation?: ValidationBuilder<FileRule, FileValue>
  initialValue?: InitialValueProperty<any, FileValue>
}

/** @public */
export declare interface FileOptions extends ObjectOptions {
  storeOriginalFilename?: boolean
  accept?: string
  sources?: AssetSource[]
}

/** @public */
export declare interface FileRule extends RuleDef<FileRule, FileValue> {
  /**
   * Require a file field has an asset.
   *
   * @example
   * ```ts
   * defineField({
   *  name: 'file',
   *  title: 'File',
   *  type: 'file',
   *  validation: (Rule) => Rule.required().assetRequired(),
   * })
   * ```
   */
  assetRequired(): FileRule
}

/** @public */
export declare interface FileSchemaType extends Omit<ObjectSchemaType, 'options'> {
  options?: FileOptions
}

/** @public */
export declare interface FileValue {
  asset?: Reference
  [index: string]: unknown
}

/** @public */
export declare interface FormNodeValidation {
  level: 'error' | 'warning' | 'info'
  message: string
  path: Path
}

/** @public */
export declare interface GeopointDefinition extends BaseSchemaDefinition {
  type: 'geopoint'
  options?: GeopointOptions
  validation?: ValidationBuilder<GeopointRule, GeopointValue>
  initialValue?: InitialValueProperty<any, Omit<GeopointValue, '_type'>>
}

/** @public */
export declare interface GeopointOptions extends BaseSchemaTypeOptions {}

/** @public */
export declare interface GeopointRule extends RuleDef<GeopointRule, GeopointValue> {}

/**
 * Geographical point representing a pair of latitude and longitude coordinates,
 * stored as degrees, in the World Geodetic System 1984 (WGS 84) format. Also
 * includes an optional `alt` property representing the altitude in meters.
 *
 * @public
 */
export declare interface GeopointValue {
  /**
   * Type of the object. Must be `geopoint`.
   */
  _type: 'geopoint'
  /**
   * Latitude in degrees
   */
  lat: number
  /**
   * Longitude in degrees
   */
  lng: number
  /**
   * Altitude in meters
   */
  alt?: number
}

/** @public */
export declare interface GlobalDocumentReferenceDefinition extends BaseSchemaDefinition {
  type: 'globalDocumentReference'
  weak?: boolean
  to: {
    type: string
    title?: string
    icon?: ComponentType
    preview?: PreviewConfig
  }[]
  resourceType: string
  resourceId: string
  options?: ReferenceOptions
  studioUrl?: string | ((document: {id: string; type?: string}) => string | null)
}

/** @beta */
export declare type GlobalDocumentReferenceFilterResolver = (options: {
  document: SanityDocument
  parent?: Record<string, unknown> | Record<string, unknown>[]
  parentPath: Path
}) =>
  | GlobalDocumentReferenceFilterSearchOptions
  | Promise<GlobalDocumentReferenceFilterSearchOptions>

/** @beta */
export declare type GlobalDocumentReferenceFilterSearchOptions = {
  filter?: string
  params?: Record<string, unknown>
  tag?: string
}

/** @beta */
export declare interface GlobalDocumentReferenceSchemaType
  extends Omit<ObjectSchemaType, 'options'> {
  jsonType: 'object'
  to: GlobalDocumentReferenceType[]
  resourceType: string
  resourceId: string
  studioUrl?: string | ((document: {id: string; type?: string}) => string | null)
  weak?: boolean
  options?: ReferenceFilterOptions
}

/** @beta */
export declare interface GlobalDocumentReferenceType {
  type: string
  title?: string
  icon: ComponentType
  preview: PreviewConfig
  /** @deprecated Unused. It's only here for the type to be compatible with createSearchQuery.ts */
  __experimental_search: never
}

/** @beta */
export declare interface GlobalDocumentReferenceValue {
  _type: string
  /** The reference to the document. This is a string of the form `a:b:c`,
   * where:
   * - `a` is the resource type, for example `dataset` or `media-library`
   * - `b` is the resource ID, for example data set name or media library ID
   * - `c` is the document ID */
  _ref: `${string}:${string}:${string}`
  _key?: string
  _weak?: boolean
}

/** @public */
export declare interface HotspotOptions {
  previews?: HotspotPreview[]
}

/** @public */
export declare interface HotspotPreview {
  title: string
  aspectRatio: number
}

/** @public */
export declare type I18nTextRecord<K extends string> = {
  [P in K]?: {
    key: string
    ns: string
  }
}

/** @public */
export declare interface I18nTitledListValue<V = unknown> {
  _key?: string
  title: string
  i18nTitleKey?: string
  value?: V
}

/** @public */
declare interface Image_2 {
  [key: string]: unknown
  asset?: Reference
  crop?: ImageCrop
  hotspot?: ImageHotspot
}
export {Image_2 as Image}

/** @public */
export declare interface ImageAsset extends Asset {
  _type: 'sanity.imageAsset'
  metadata: ImageMetadata
}

/** @public */
export declare interface ImageCrop {
  _type?: 'sanity.imageCrop'
  left: number
  bottom: number
  right: number
  top: number
}

/** @public */
export declare interface ImageDefinition
  extends Omit<ObjectDefinition, 'type' | 'fields' | 'options' | 'groups' | 'validation'> {
  type: 'image'
  fields?: FieldDefinition[]
  options?: ImageOptions
  validation?: ValidationBuilder<ImageRule, ImageValue>
  initialValue?: InitialValueProperty<any, ImageValue>
}

/** @public */
export declare interface ImageDimensions {
  _type: 'sanity.imageDimensions'
  height: number
  width: number
  aspectRatio: number
}

/** @public */
export declare interface ImageHotspot {
  _type?: 'sanity.imageHotspot'
  width: number
  height: number
  x: number
  y: number
}

/** @public */
export declare interface ImageMetadata {
  [key: string]: unknown
  _type: 'sanity.imageMetadata'
  dimensions: ImageDimensions
  palette?: ImagePalette
  lqip?: string
  blurHash?: string
  hasAlpha: boolean
  isOpaque: boolean
}

/** @public */
export declare type ImageMetadataType =
  | 'blurhash'
  | 'lqip'
  | 'palette'
  | 'exif'
  | 'image'
  | 'location'

/** @public */
export declare interface ImageOptions extends FileOptions {
  metadata?: ImageMetadataType[]
  hotspot?: boolean | HotspotOptions
}

/** @public */
export declare interface ImagePalette {
  _type: 'sanity.imagePalette'
  darkMuted?: ImageSwatch
  darkVibrant?: ImageSwatch
  dominant?: ImageSwatch
  lightMuted?: ImageSwatch
  lightVibrant?: ImageSwatch
  muted?: ImageSwatch
  vibrant?: ImageSwatch
}

/** @public */
export declare interface ImageRule extends RuleDef<ImageRule, ImageValue> {
  /**
   * Require an image field has an asset.
   *
   * @example
   * ```ts
   * defineField({
   *  name: 'image',
   *  title: 'Image',
   *  type: 'image',
   *  validation: (Rule) => Rule.required().assetRequired(),
   * })
   * ```
   */
  assetRequired(): ImageRule
}

/** @public */
export declare interface ImageSchemaType extends Omit<ObjectSchemaType, 'options'> {
  options?: ImageOptions
}

/** @public */
export declare interface ImageSwatch {
  _type: 'sanity.imagePaletteSwatch'
  background: string
  foreground: string
  population: number
  title?: string
}

/** @internal */
export declare type ImageUrlAutoMode = 'format'

/** @internal */
export declare type ImageUrlCropMode =
  | 'top'
  | 'bottom'
  | 'left'
  | 'right'
  | 'center'
  | 'focalpoint'
  | 'entropy'

/** @internal */
export declare type ImageUrlFitMode = 'clip' | 'crop' | 'fill' | 'fillmax' | 'max' | 'scale' | 'min'

/** @internal */
export declare type ImageUrlFormat = 'jpg' | 'pjpg' | 'png' | 'webp'

/** @internal */
export declare type ImageUrlOrientation = '0' | '90' | '180' | '270'

/**
 * NOTE: These are query parameters, so they will eventually be encoded as strings.
 * However, since most/all query parameter encoders will accept numbers and encode
 * them as strings, we'll use `string| number` where applicable, as it makes it easier
 * to use in places that do calculations and such.
 *
 * @internal
 */
export declare interface ImageUrlParams {
  'bg'?: string
  'dpr'?: number | string
  'w'?: number | string
  'h'?: number | string
  'q'?: number | string
  'dl'?: string
  'dlRaw'?: string
  'fp-x'?: number | string
  'fp-y'?: number | string
  'max-w'?: number | string
  'max-h'?: number | string
  'min-w'?: number | string
  'min-h'?: number | string
  'blur'?: number | string
  'sharp'?: number | string
  'rect'?: string
  'fm'?: ImageUrlFormat
  'or'?: ImageUrlOrientation
  'fit'?: ImageUrlFitMode
  'crop'?: ImageUrlCropMode
  'auto'?: ImageUrlAutoMode
  'invert'?: 'true' | 'false'
  'quality'?: number | string
  'flip'?: 'h' | 'v' | 'hv'
  'sat'?: number | string
  'pad'?: number | string
  'colorquant'?: number | string
  'border'?: string
}

/** @public */
export declare interface ImageValue extends FileValue {
  crop?: ImageCrop
  hotspot?: ImageHotspot
  [index: string]: unknown
}

/** @public */
export declare type IndexTuple = [number | '', number | '']

/** @public */
export declare type InitialValueProperty<Params, Value> =
  | Value
  | InitialValueResolver<Params, Value>
  | undefined

/** @public */
export declare type InitialValueResolver<Params, Value> = (
  params: Params | undefined,
  context: InitialValueResolverContext,
) => Promise<Value> | Value

/** @public */
export declare interface InitialValueResolverContext {
  projectId: string
  dataset: string
  schema: Schema
  currentUser: CurrentUser | null
  getClient: (options: {apiVersion: string}) => SanityClient
}

/** @public */
export declare type InlineFieldDefinition = {
  [K in keyof IntrinsicDefinitions]: Omit<
    IntrinsicDefinitions[K],
    'initialValue' | 'validation'
  > & {
    validation?: SchemaValidationValue
    initialValue?: InitialValueProperty<any, any>
  }
}

/** @alpha This API may change */
export declare interface InsertMenuOptions {
  /**
   * @defaultValue `'auto'`
   * `filter: 'auto'` automatically turns on filtering if there are more than 5
   * schema types added to the menu.
   */
  filter?: 'auto' | boolean
  groups?: Array<{
    name: string
    title?: string
    of?: Array<string>
  }>
  /** defaultValue `true` */
  showIcons?: boolean
  /** @defaultValue `[{name: 'list'}]` */
  views?: Array<
    | {
        name: 'list'
      }
    | {
        name: 'grid'
        previewImageUrl?: (schemaTypeName: string) => string | undefined
      }
  >
}

/** @internal */
export declare type InsertPatch =
  | {
      before: string
      items: unknown[]
    }
  | {
      after: string
      items: unknown[]
    }
  | {
      replace: string
      items: unknown[]
    }

/** @beta */
export declare type IntrinsicArrayOfBase = {
  [K in keyof IntrinsicDefinitions]: Omit<ArrayOfEntry<IntrinsicDefinitions[K]>, 'preview'>
}

/** @public */
export declare type IntrinsicArrayOfDefinition = {
  [K in keyof IntrinsicDefinitions]: Omit<
    ArrayOfEntry<IntrinsicDefinitions[K]>,
    'validation' | 'initialValue'
  > & {
    validation?: SchemaValidationValue
    initialValue?: InitialValueProperty<any, any>
  }
}

/** @beta */
export declare type IntrinsicBase = {
  [K in keyof IntrinsicDefinitions]: Omit<IntrinsicDefinitions[K], 'preview'>
}

/**
 * `IntrinsicDefinitions` is a lookup map for "predefined" schema definitions.
 * Schema types in `IntrinsicDefinitions` will have good type-completion and type-safety in {@link defineType},
 * {@link defineField} and {@link defineArrayMember} once the `type` property is provided.
 *
 * By default, `IntrinsicDefinitions` contains all standard Sanity schema types (`array`, `string`, `number` ect),
 * but it is an interface and as such, open for extension.
 *
 * This type can be extended using declaration merging; this way new entries can be added.
 * See {@link defineType} for examples on how this can be accomplished.
 *
 * @see defineType
 *
 * @public
 */
export declare interface IntrinsicDefinitions {
  array: ArrayDefinition
  block: BlockDefinition
  boolean: BooleanDefinition
  date: DateDefinition
  datetime: DatetimeDefinition
  document: DocumentDefinition
  file: FileDefinition
  geopoint: GeopointDefinition
  image: ImageDefinition
  number: NumberDefinition
  object: ObjectDefinition
  reference: ReferenceDefinition
  crossDatasetReference: CrossDatasetReferenceDefinition
  globalDocumentReference: GlobalDocumentReferenceDefinition
  slug: SlugDefinition
  string: StringDefinition
  text: TextDefinition
  url: UrlDefinition
  email: EmailDefinition
}

/**
 * A union of all intrinsic types allowed natively in the schema.
 *
 * @see IntrinsicDefinitions
 *
 * @public
 */
export declare type IntrinsicTypeName = IntrinsicDefinitions[keyof IntrinsicDefinitions]['type']

/** @internal */
export declare function isArrayOfBlocksSchemaType(
  type: unknown,
): type is ArraySchemaType<ObjectSchemaType>

/** @internal */
export declare function isArrayOfObjectsSchemaType(
  type: unknown,
): type is ArraySchemaType<ObjectSchemaType>

/** @internal */
export declare function isArrayOfPrimitivesSchemaType(type: unknown): type is ArraySchemaType

/** @internal */
export declare function isArraySchemaType(type: unknown): type is ArraySchemaType

/**
 * Check whether the provided value resembles a Media Library asset aspect document.
 *
 * Note: This function does not perform a comprehensive check.
 *
 * @see validateMediaLibraryAssetAspect
 *
 * @internal
 */
export declare function isAssetAspect(
  maybeAssetAspect: unknown,
): maybeAssetAspect is MediaLibraryAssetAspectDocument

/** @internal */
export declare function isBlockChildrenObjectField(
  field: unknown,
): field is BlockChildrenObjectField

/** @internal */
export declare function isBlockListObjectField(field: unknown): field is BlockListObjectField

/** @internal */
export declare function isBlockSchemaType(type: unknown): type is BlockSchemaType

/** @internal */
export declare function isBlockStyleObjectField(field: unknown): field is BlockStyleObjectField

/** @internal */
export declare function isBooleanSchemaType(type: unknown): type is BooleanSchemaType

/** @internal */
export declare function isCreateIfNotExistsMutation(
  mutation: Mutation | TransactionLogMutation,
): mutation is CreateIfNotExistsMutation

/** @internal */
export declare function isCreateMutation(
  mutation: Mutation | TransactionLogMutation,
): mutation is CreateMutation

/** @internal */
export declare function isCreateOrReplaceMutation(
  mutation: Mutation | TransactionLogMutation,
): mutation is CreateOrReplaceMutation

/** @internal */
export declare function isCreateSquashedMutation(
  mutation: Mutation | TransactionLogMutation,
): mutation is CreateSquashedMutation

/** @beta */
export declare function isCrossDatasetReference(
  reference: unknown,
): reference is CrossDatasetReferenceValue

/** @internal */
export declare function isCrossDatasetReferenceSchemaType(
  type: unknown,
): type is CrossDatasetReferenceSchemaType

/** @internal */
export declare function isDateTimeSchemaType(type: unknown): type is StringSchemaType

/** @internal */
export declare function isDeleteMutation(
  mutation: Mutation | TransactionLogMutation,
): mutation is DeleteMutation

/** @internal */
export declare function isDeprecatedSchemaType<TSchemaType extends BaseSchemaType>(
  type: TSchemaType,
): type is DeprecatedSchemaType<TSchemaType>

/** @internal */
export declare function isDeprecationConfiguration(type: unknown): type is DeprecationConfiguration

/**
 * Returns wether or not the given type is a document type
 * (eg that it was defined as `type: 'document'`)
 *
 * @param type - Schema type to test
 * @returns True if type is a document type, false otherwise
 *
 * @public
 */
export declare function isDocumentSchemaType(type: unknown): type is ObjectSchemaType

/** @internal */
export declare function isFileSchemaType(type: unknown): type is FileSchemaType

/** @beta */
export declare function isGlobalDocumentReference(
  reference: unknown,
): reference is GlobalDocumentReferenceValue

/** @public */
export declare function isImage(value: unknown): value is Image_2

/** @internal */
export declare function isImageSchemaType(type: unknown): type is ImageSchemaType

/** @internal */
export declare function isIndexSegment(segment: PathSegment): segment is number

/** @internal */
export declare function isIndexTuple(segment: PathSegment): segment is IndexTuple

/** @public */
export declare function isKeyedObject(obj: unknown): obj is KeyedObject

/** @internal */
export declare function isKeySegment(segment: PathSegment): segment is KeyedSegment

/** @internal */
export declare function isNumberSchemaType(type: unknown): type is NumberSchemaType

/** @internal */
export declare function isObjectSchemaType(type: unknown): type is ObjectSchemaType

/** @internal */
export declare function isPatchMutation(
  mutation: Mutation | TransactionLogMutation,
): mutation is PatchMutation

/**
 * Assert that a given object is a portable-text list-text-block-type object
 *
 * @remarks
 * Uses `isPortableTextTextBlock` and checks for `listItem` and `level`
 *
 * @see isPortableTextTextBlock
 *
 * @alpha
 */
export declare function isPortableTextListBlock<T = PortableTextSpan | PortableTextObject>(
  value: unknown,
): value is PortableTextTextBlock<T>

/**
 * Assert that a given object is a portable-text span-type object
 *
 * @remarks
 * The `marks` property of a block is optional.
 *
 * @alpha
 */
export declare function isPortableTextSpan(value: unknown): value is PortableTextSpan

/**
 * Assert that a given object is a portable-text text-block type object
 *
 * @remarks
 * * The `markDefs` and `style` property of a block is optional.
 * * Block types can be named, so expect anything of the _type property.
 *
 * @alpha
 */
export declare function isPortableTextTextBlock<T = PortableTextSpan | PortableTextObject>(
  value: unknown,
): value is PortableTextTextBlock<T>

/** @internal */
export declare function isPrimitiveSchemaType(
  type: unknown,
): type is BooleanSchemaType | StringSchemaType | NumberSchemaType

/** @internal */
export declare function isReference(reference: unknown): reference is Reference

/** @internal */
export declare function isReferenceSchemaType(type: unknown): type is ReferenceSchemaType

/** @public */
export declare function isSanityDocument(document: unknown): document is SanityDocument

/**
 * @internal
 */
export declare function isSearchStrategy(
  maybeSearchStrategy: unknown,
): maybeSearchStrategy is SearchStrategy

/**
 * Checks whether the given `thing` is a slug, eg an object with a `current` string property.
 *
 * @param thing - The thing to check
 * @returns True if slug, false otherwise
 * @public
 */
export declare function isSlug(thing: unknown): thing is Slug

/** @internal */
export declare function isSpanSchemaType(type: unknown): type is SpanSchemaType

/** @internal */
export declare function isStringSchemaType(type: unknown): type is StringSchemaType

/** @internal */
export declare function isTitledListValue(item: unknown): item is TitledListValue

/** @public */
export declare function isTypedObject(obj: unknown): obj is TypedObject

/** @internal */
export declare function isValidationError(node: FormNodeValidation): node is FormNodeValidation & {
  level: 'error'
}

/** @internal */
export declare function isValidationErrorMarker(
  marker: ValidationMarker,
): marker is ValidationMarker & {
  level: 'error'
}

/** @internal */
export declare function isValidationInfo(node: FormNodeValidation): node is FormNodeValidation & {
  level: 'info'
}

/** @internal */
export declare function isValidationInfoMarker(
  marker: ValidationMarker,
): marker is ValidationMarker & {
  level: 'info'
}

/** @internal */
export declare function isValidationWarning(
  node: FormNodeValidation,
): node is FormNodeValidation & {
  level: 'warning'
}

/** @internal */
export declare function isValidationWarningMarker(
  marker: ValidationMarker,
): marker is ValidationMarker & {
  level: 'warning'
}

/** @public */
export declare interface KeyedObject {
  [key: string]: unknown
  _key: string
}

/** @public */
export declare type KeyedSegment = {
  _key: string
}

/**
 * Holds localized validation messages for a given field.
 *
 * @example Custom message for English (US) and Norwegian (Bokmål):
 * ```
 * {
 *   'en-US': 'Needs to start with a capital letter',
 *   'no-NB': 'Må starte med stor bokstav',
 * }
 * ```
 * @public
 */
export declare interface LocalizedValidationMessages {
  [locale: string]: string
}

/** @beta */
export declare type MaybeAllowUnknownProps<TStrict extends StrictDefinition> = TStrict extends false
  ? {
      options?: {
        [index: string]: any
      }
      [index: string]: any
    }
  : unknown

/** @beta */
export declare type MaybePreview<
  Select extends Record<string, string> | undefined,
  PrepareValue extends Record<keyof Select, any> | undefined,
> =
  Select extends Record<string, string>
    ? PrepareValue extends Record<keyof Select, any>
      ? PreviewConfig<Select, PrepareValue>
      : never
    : never

/**
 * @public
 */
export declare const MEDIA_LIBRARY_ASSET_ASPECT_TYPE_NAME = 'sanity.asset.aspect'

/**
 * @public
 */
export declare type MediaLibraryAssetAspectDefinition =
  MediaLibraryAssetAspectSupportedFieldDefinitions & {
    assetType?: MediaLibraryAssetType | MediaLibraryAssetType[]
  }

/**
 * A document representing a Media Library asset aspect.
 *
 * Each aspect provides a schema describing custom data that can be assigned to assets.
 *
 * @public
 */
export declare interface MediaLibraryAssetAspectDocument extends SanityDocumentLike {
  _type: MediaLibraryAssetAspectTypeName
  /**
   * Asset types the aspect can be assigned to.
   *
   * If no `assetType` is defined, the aspect may be assigned to any asset type.
   */
  assetType?: MediaLibraryAssetType[]
  definition: FieldDefinition
}

/**
 * @public
 */
export declare type MediaLibraryAssetAspectSupportedFieldDefinitions = FieldDefinition<
  Exclude<IntrinsicTypeName, 'document' | 'image' | 'file' | 'reference' | 'crossDatasetReference'>
>

/**
 * @public
 */
export declare type MediaLibraryAssetAspectTypeName = typeof MEDIA_LIBRARY_ASSET_ASPECT_TYPE_NAME

/**
 * @public
 */
export declare type MediaLibraryAssetType = ImageAsset['_type'] | FileAsset['_type']

/**
 * A pair of mendoza patches that can either be _applied_ (to perform the effect),
 * or _reverted_ (to undo the effect). Requires the exact, previous version of the
 * document when applying - any difference might have unexpected consequences.
 *
 * @internal
 */
export declare interface MendozaEffectPair {
  apply: MendozaPatch
  revert: MendozaPatch
}

/**
 * A mendoza patch. These are not human-readable patches, but are optimized to
 * take as little space as possible, while still being represented by plain JSON.
 * See {@link https://www.sanity.io/blog/mendoza}
 *
 * @internal
 */
export declare type MendozaPatch = unknown[]

/** @public */
export declare interface MultiFieldSet {
  name: string
  title?: string
  description?: string
  single?: false
  group?: string | string[]
  options?: CollapseOptions & {
    columns?: number
  }
  fields: ObjectField[]
  hidden?: ConditionalProperty
  readOnly?: ConditionalProperty
}

/** @internal */
export declare interface MultipleMutationResult {
  transactionId: string
  documentIds: string[]
  results: {
    id: string
  }[]
}

/** @internal */
export declare type Mutation =
  | CreateMutation
  | CreateOrReplaceMutation
  | CreateIfNotExistsMutation
  | DeleteMutation
  | PatchMutation

/** @internal */
export declare type MutationOperationName =
  | 'create'
  | 'createOrReplace'
  | 'createIfNotExists'
  | 'delete'
  | 'patch'

/** @internal */
export declare type MutationSelection =
  | {
      query: string
      params?: Record<string, unknown>
    }
  | {
      id: string
    }

/** @beta */
export declare type NarrowPreview<
  TType extends string,
  TAlias extends IntrinsicTypeName | undefined,
  TSelect extends Record<string, string> | undefined,
  TPrepareValue extends Record<keyof TSelect, any> | undefined,
> =
  DefineSchemaType<TType, TAlias> extends {
    preview?: Record<string, any>
  }
    ? {
        preview?: MaybePreview<TSelect, TPrepareValue>
      }
    : unknown

/** @public */
export declare interface NumberDefinition extends BaseSchemaDefinition {
  type: 'number'
  options?: NumberOptions
  placeholder?: string
  validation?: ValidationBuilder<NumberRule, number>
  initialValue?: InitialValueProperty<any, number>
}

/** @public */
export declare interface NumberOptions extends EnumListProps<number>, BaseSchemaTypeOptions {}

/** @public */
export declare interface NumberRule extends RuleDef<NumberRule, number> {
  min: (minNumber: number | FieldReference) => NumberRule
  max: (maxNumber: number | FieldReference) => NumberRule
  lessThan: (limit: number | FieldReference) => NumberRule
  greaterThan: (limit: number | FieldReference) => NumberRule
  integer: () => NumberRule
  precision: (limit: number | FieldReference) => NumberRule
  positive: () => NumberRule
  negative: () => NumberRule
}

/** @public */
export declare interface NumberSchemaType extends BaseSchemaType {
  jsonType: 'number'
  options?: NumberOptions
  initialValue?: InitialValueProperty<any, number>
}

/** @public */
export declare interface ObjectDefinition extends BaseSchemaDefinition {
  type: 'object'
  /**
   * Object must have at least one field. This is validated at Studio startup.
   */
  fields: FieldDefinition[]
  groups?: FieldGroupDefinition[]
  fieldsets?: FieldsetDefinition[]
  preview?: PreviewConfig
  options?: ObjectOptions
  validation?: ValidationBuilder<ObjectRule, Record<string, unknown>>
  initialValue?: InitialValueProperty<any, Record<string, unknown>>
}

/** @public */
export declare interface ObjectField<T extends SchemaType = SchemaType> {
  name: string
  fieldset?: string
  group?: string | string[]
  type: ObjectFieldType<T>
}

/** @public */
export declare type ObjectFieldType<T extends SchemaType = SchemaType> = T & {
  hidden?: ConditionalProperty
  readOnly?: ConditionalProperty
}

/** @public */
export declare interface ObjectOptions extends BaseSchemaTypeOptions {
  collapsible?: boolean
  collapsed?: boolean
  columns?: number
  modal?: {
    type?: 'dialog' | 'popover'
    width?: number | number[] | 'auto'
  }
}

/** @public */
export declare interface ObjectRule extends RuleDef<ObjectRule, Record<string, unknown>> {}

/** @public */
export declare interface ObjectSchemaType extends BaseSchemaType {
  jsonType: 'object'
  fields: ObjectField[]
  groups?: FieldGroup[]
  fieldsets?: Fieldset[]
  initialValue?: InitialValueProperty<any, Record<string, unknown>>
  weak?: boolean
  /** @deprecated Unused. Use the new field-level search config. */
  __experimental_search?: {
    path: (string | number)[]
    weight: number
    mapWith?: string
  }[]
  /** @alpha */
  __experimental_omnisearch_visibility?: boolean
  /** @alpha */
  __experimental_actions?: string[]
  /** @alpha */
  __experimental_formPreviewTitle?: boolean
  /**
   * @beta
   */
  orderings?: SortOrdering[]
  options?: any
}

/** @internal */
export declare interface ObjectSchemaTypeWithOptions extends Omit<ObjectSchemaType, 'options'> {
  options?: CollapseOptions & {
    columns?: number
  }
}

/** @internal */
export declare interface PatchMutation {
  patch: PatchMutationOperation
}

/** @internal */
export declare type PatchMutationOperation = PatchOperations & MutationSelection

/**
 * NOTE: this is actually incorrect/invalid, but implemented as-is for backwards compatibility
 *
 * @internal
 */
export declare interface PatchOperations {
  set?: {
    [key: string]: unknown
  }
  setIfMissing?: {
    [key: string]: unknown
  }
  merge?: {
    [key: string]: unknown
  }
  diffMatchPatch?: {
    [key: string]: string
  }
  unset?: string[]
  inc?: {
    [key: string]: number
  }
  dec?: {
    [key: string]: number
  }
  insert?: InsertPatch
  ifRevisionID?: string
}

/** @public */
export declare type Path = PathSegment[]

/** @public */
export declare type PathSegment = string | number | KeyedSegment | IndexTuple

/** @alpha */
export declare type PortableTextBlock = PortableTextTextBlock | PortableTextObject

/** @alpha */
export declare type PortableTextChild = PortableTextObject | PortableTextSpan

/** @alpha */
export declare interface PortableTextListBlock extends PortableTextTextBlock {
  listItem: string
  level: number
}

/** @alpha */
export declare interface PortableTextObject {
  _type: string
  _key: string
  [other: string]: unknown
}

/** @alpha */
export declare interface PortableTextSpan {
  _key: string
  _type: 'span'
  text: string
  marks?: string[]
}

/** @alpha */
export declare interface PortableTextTextBlock<TChild = PortableTextSpan | PortableTextObject> {
  _type: string
  _key: string
  children: TChild[]
  markDefs?: PortableTextObject[]
  listItem?: string
  style?: string
  level?: number
}

/** @public */
export declare interface PrepareViewOptions {
  /** @beta */
  ordering?: SortOrdering
}

/** @public */
export declare interface PreviewConfig<
  Select extends Record<string, string> = Record<string, string>,
  PrepareValue extends Record<keyof Select, any> = Record<keyof Select, any>,
> {
  select?: Select
  prepare?: (value: PrepareValue, viewOptions?: PrepareViewOptions) => PreviewValue
}

/** @public */
export declare interface PreviewValue {
  _id?: string
  _createdAt?: string
  _updatedAt?: string
  title?: string
  subtitle?: string
  description?: string
  media?: ReactNode | ElementType
  imageUrl?: string
}

/** @public */
export declare interface Reference {
  _type: string
  _ref: string
  _key?: string
  _weak?: boolean
  _strengthenOnPublish?: {
    type: string
    weak?: boolean
    template?: {
      id: string
      params: Record<string, string | number | boolean>
    }
  }
}

/** @public */
export declare interface ReferenceBaseOptions extends BaseSchemaTypeOptions {
  disableNew?: boolean
}

/** @public */
export declare interface ReferenceDefinition extends BaseSchemaDefinition {
  type: 'reference'
  to: ReferenceTo
  weak?: boolean
  options?: ReferenceOptions
  validation?: ValidationBuilder<ReferenceRule, ReferenceValue>
  initialValue?: InitialValueProperty<any, Omit<ReferenceValue, '_type'>>
}

/** @public */
export declare type ReferenceFilterOptions =
  | ReferenceFilterResolverOptions
  | ReferenceFilterQueryOptions

/** @public */
export declare interface ReferenceFilterQueryOptions {
  filter: string
  filterParams?: Record<string, unknown>
}

/** @public */
export declare type ReferenceFilterResolver = (
  context: ReferenceFilterResolverContext,
) => ReferenceFilterSearchOptions | Promise<ReferenceFilterSearchOptions>

/** @public */
export declare interface ReferenceFilterResolverContext {
  document: SanityDocument
  parent?: Record<string, unknown> | Record<string, unknown>[]
  parentPath: Path
  getClient: (options: {apiVersion: string}) => SanityClient
}

/** @public */
export declare interface ReferenceFilterResolverOptions {
  filter?: ReferenceFilterResolver
  filterParams?: never
}

/** @public */
export declare type ReferenceFilterSearchOptions = {
  filter?: string
  params?: Record<string, unknown>
  tag?: string
  maxFieldDepth?: number
  strategy?: SearchStrategy
  perspective?: ClientPerspective
}

/**
 * Types are closed for extension. To add properties via declaration merging to this type,
 * redeclare and add the properties to the interfaces that make up ReferenceOptions type.
 *
 * @see ReferenceFilterOptions
 * @see ReferenceFilterResolverOptions
 * @see ReferenceBaseOptions
 *
 * @public
 */
export declare type ReferenceOptions = ReferenceBaseOptions & ReferenceFilterOptions

/** @public */
export declare interface ReferenceRule extends RuleDef<ReferenceRule, ReferenceValue> {}

/** @public */
export declare interface ReferenceSchemaType extends Omit<ObjectSchemaType, 'options'> {
  jsonType: 'object'
  to: ObjectSchemaType[]
  weak?: boolean
  options?: ReferenceOptions
}

/** @public */
export declare type ReferenceTo =
  | SchemaTypeDefinition
  | TypeReference
  | Array<SchemaTypeDefinition | TypeReference>

/** @public */
export declare type ReferenceValue = Reference

/** @public */
export declare interface Role {
  name: string
  title: string
  description?: string
}

/** @public */
export declare interface Rule {
  /**
   * @internal
   * @deprecated internal use only
   */
  _type: RuleTypeConstraint | undefined
  /**
   * @internal
   * @deprecated internal use only
   */
  _level: 'error' | 'warning' | 'info' | undefined
  /**
   * @internal
   * @deprecated internal use only
   */
  _required: 'required' | 'optional' | undefined
  /**
   * @internal
   * @deprecated internal use only
   */
  _typeDef: SchemaType | undefined
  /**
   * @internal
   * @deprecated internal use only
   */
  _message: string | LocalizedValidationMessages | undefined
  /**
   * @internal
   * @deprecated internal use only
   */
  _rules: RuleSpec[]
  /**
   * @internal
   * @deprecated internal use only
   */
  _fieldRules: FieldRules | undefined
  /**
   * Takes in a path and returns an object with a symbol.
   *
   * When the validation lib sees this symbol, it will use the provided path to
   * get a value from the current field's parent and use that value as the input
   * to the Rule.
   *
   * The path that's given is forwarded to `lodash/get`
   *
   * ```js
   * fields: [
   * // ...
   *   {
   *     // ...
   *     name: 'highestTemperature',
   *     type: 'number',
   *     validation: (Rule) => Rule.positive().min(Rule.valueOfField('lowestTemperature')),
   *     // ...
   *   },
   * ]
   * ```
   */
  valueOfField: (path: string | string[]) => FieldReference
  error(message?: string | LocalizedValidationMessages): Rule
  warning(message?: string | LocalizedValidationMessages): Rule
  info(message?: string | LocalizedValidationMessages): Rule
  reset(): this
  isRequired(): boolean
  clone(): Rule
  cloneWithRules(rules: RuleSpec[]): Rule
  merge(rule: Rule): Rule
  type(targetType: RuleTypeConstraint | Lowercase<RuleTypeConstraint>): Rule
  all(children: Rule[]): Rule
  either(children: Rule[]): Rule
  optional(): Rule
  required(): Rule
  custom<T = unknown>(
    fn: CustomValidator<T>,
    options?: {
      bypassConcurrencyLimit?: boolean
    },
  ): Rule
  min(len: number | string | FieldReference): Rule
  max(len: number | string | FieldReference): Rule
  length(len: number | FieldReference): Rule
  valid(value: unknown | unknown[]): Rule
  integer(): Rule
  precision(limit: number | FieldReference): Rule
  positive(): Rule
  negative(): Rule
  greaterThan(num: number | FieldReference): Rule
  lessThan(num: number | FieldReference): Rule
  uppercase(): Rule
  lowercase(): Rule
  regex(
    pattern: RegExp,
    name: string,
    options: {
      name?: string
      invert?: boolean
    },
  ): Rule
  regex(
    pattern: RegExp,
    options: {
      name?: string
      invert?: boolean
    },
  ): Rule
  regex(pattern: RegExp, name: string): Rule
  regex(pattern: RegExp): Rule
  email(): Rule
  uri(options?: UriValidationOptions): Rule
  unique(): Rule
  reference(): Rule
  fields(rules: FieldRules): Rule
  assetRequired(): Rule
  validate(
    value: unknown,
    options: ValidationContext & {
      /**
       * @deprecated Internal use only
       * @internal
       */
      __internal?: {
        customValidationConcurrencyLimiter?: {
          ready: () => Promise<void>
          release: () => void
        }
      }
    },
  ): Promise<ValidationMarker[]>
}

/** @public */
export declare type RuleBuilder<T extends RuleDef<T, FieldValue>, FieldValue = unknown> = T | T[]

/**
 * Note: `RuleClass` and `Rule` are split to fit the current `@sanity/types`
 * setup. Classes are a bit weird in the `@sanity/types` package because classes
 * create an actual javascript class while simultaneously creating a type
 * definition.
 *
 * This implicitly creates two types:
 * 1. the instance type — `Rule` and
 * 2. the static/class type - `RuleClass`
 *
 * The `RuleClass` type contains the static methods and the `Rule` instance
 * contains the instance methods. Downstream in the validation package, the Rule
 * implementation asserts the class declaration is of this type.
 *
 * @internal
 */
export declare interface RuleClass {
  FIELD_REF: symbol
  array: (def?: SchemaType) => Rule
  object: (def?: SchemaType) => Rule
  string: (def?: SchemaType) => Rule
  number: (def?: SchemaType) => Rule
  boolean: (def?: SchemaType) => Rule
  dateTime: (def?: SchemaType) => Rule
  valueOfField: Rule['valueOfField']
  new (typeDef?: SchemaType): Rule
}

/** @public */
export declare interface RuleDef<T, FieldValue = unknown> {
  required: () => T
  custom: <LenientFieldValue extends FieldValue>(
    fn: CustomValidator<LenientFieldValue | undefined>,
  ) => T
  info: (message?: string | LocalizedValidationMessages) => T
  error: (message?: string | LocalizedValidationMessages) => T
  warning: (message?: string | LocalizedValidationMessages) => T
  valueOfField: (path: string | string[]) => FieldReference
}

/** @public */
export declare type RuleSpec =
  | {
      flag: 'integer'
    }
  | {
      flag: 'email'
    }
  | {
      flag: 'unique'
    }
  | {
      flag: 'reference'
    }
  | {
      flag: 'type'
      constraint: RuleTypeConstraint
    }
  | {
      flag: 'all'
      constraint: Rule[]
    }
  | {
      flag: 'either'
      constraint: Rule[]
    }
  | {
      flag: 'presence'
      constraint: 'optional' | 'required'
    }
  | {
      flag: 'custom'
      constraint: CustomValidator
    }
  | {
      flag: 'min'
      constraint: number | string | FieldReference
    }
  | {
      flag: 'max'
      constraint: number | string | FieldReference
    }
  | {
      flag: 'length'
      constraint: number | FieldReference
    }
  | {
      flag: 'valid'
      constraint: unknown[]
    }
  | {
      flag: 'precision'
      constraint: number | FieldReference
    }
  | {
      flag: 'lessThan'
      constraint: number | FieldReference
    }
  | {
      flag: 'greaterThan'
      constraint: number | FieldReference
    }
  | {
      flag: 'stringCasing'
      constraint: 'uppercase' | 'lowercase'
    }
  | {
      flag: 'assetRequired'
      constraint: {
        assetType: 'asset' | 'image' | 'file'
      }
    }
  | {
      flag: 'regex'
      constraint: {
        pattern: RegExp
        name?: string
        invert: boolean
      }
    }
  | {
      flag: 'uri'
      constraint: {
        options: {
          scheme: RegExp[]
          allowRelative: boolean
          relativeOnly: boolean
          allowCredentials: boolean
        }
      }
    }

/** @internal */
export declare type RuleSpecConstraint<T extends RuleSpec['flag']> = ConditionalIndexAccess<
  Extract<
    RuleSpec,
    {
      flag: T
    }
  >,
  'constraint'
>

/** @public */
export declare type RuleTypeConstraint =
  | 'Array'
  | 'Boolean'
  | 'Date'
  | 'Number'
  | 'Object'
  | 'String'

/**
 * Options for configuring how Sanity Create interfaces with the type or field.
 *
 * @public
 */
export declare interface SanityCreateOptions {
  /** Set to true to exclude a type or field from appearing in Sanity Create */
  exclude?: boolean
  /**
   * A short description of what the type or field is used for.
   * Purpose can be used to improve how and when content mapping uses the field.
   * */
  purpose?: string
}

/** @public */
export declare interface SanityDocument {
  _id: string
  _type: string
  _createdAt: string
  _updatedAt: string
  _rev: string
  [key: string]: unknown
}

/**
 * Similar to `SanityDocument` but only requires the `_id` and `_type`
 *
 * @see SanityDocument
 *
 * @public
 */
export declare interface SanityDocumentLike {
  _id: string
  _type: string
  _createdAt?: string
  _updatedAt?: string
  _rev?: string
  _system?: {
    delete?: boolean
  }
  [key: string]: unknown
}

/** @public */
export declare interface Schema {
  /** @internal */
  _original?: {
    name: string
    types: SchemaTypeDefinition[]
  }
  /** @internal */
  _registry: {
    [typeName: string]: any
  }
  /** @internal */
  _validation?: SchemaValidationProblemGroup[]
  name: string
  get: (name: string) => SchemaType | undefined
  has: (name: string) => boolean
  getTypeNames: () => string[]
  /**
   * Returns the types which were explicitly defined in this schema,
   * as opposed to the types which were inherited from the parent.
   */
  getLocalTypeNames: () => string[]
  /**
   * Returns the parent schema.
   */
  parent?: Schema
}

/**
 * Note: you probably want `SchemaTypeDefinition` instead
 * @see SchemaTypeDefinition
 *
 * @public
 */
export declare type SchemaType =
  | ArraySchemaType
  | BooleanSchemaType
  | FileSchemaType
  | NumberSchemaType
  | ObjectSchemaType
  | StringSchemaType
  | ReferenceSchemaType

/**
 * Represents a Sanity schema type definition with an optional type parameter.
 *
 * It's recommend to use the `defineType` helper instead of this type by
 * itself.
 *
 * @see defineType
 *
 * @public
 */
export declare type SchemaTypeDefinition<TType extends IntrinsicTypeName = IntrinsicTypeName> =
  | IntrinsicDefinitions[IntrinsicTypeName]
  | TypeAliasDefinition<string, TType>

/** @public */
export declare interface SchemaValidationError {
  helpId?: string
  message: string
  severity: 'error'
}

/** @internal */
export declare type SchemaValidationProblem = SchemaValidationError | SchemaValidationWarning

/** @internal */
export declare interface SchemaValidationProblemGroup {
  path: SchemaValidationProblemPath
  problems: SchemaValidationProblem[]
}

/** @internal */
export declare type SchemaValidationProblemPath = Array<
  | {
      kind: 'type'
      type: string
      name?: string
    }
  | {
      kind: 'property'
      name: string
    }
>

/**
 * Represents the possible values of a schema type's `validation` field.
 *
 * If the schema has not been run through `inferFromSchema` from
 * `sanity/validation` then value could be a function.
 *
 * `inferFromSchema` mutates the schema converts this value to an array of
 * `Rule` instances.
 *
 * @privateRemarks
 *
 * Usage of the schema inside the studio will almost always be from the compiled
 * `createSchema` function. In this case, you can cast the value or throw to
 * narrow the type. E.g.:
 *
 * ```ts
 * if (typeof type.validation === 'function') {
 *   throw new Error(
 *     `Schema type "${type.name}"'s \`validation\` was not run though \`inferFromSchema\``
 *   )
 * }
 * ```
 *
 * @public
 */
export declare type SchemaValidationValue =
  | false
  | undefined
  | Rule
  | SchemaValidationValue[]
  | ((rule: Rule) => SchemaValidationValue)

/** @internal */
export declare interface SchemaValidationWarning {
  helpId?: string
  message: string
  severity: 'warning'
}

/** @public */
export declare interface SearchConfiguration {
  search?: {
    /**
     * Defines a search weight for this field to prioritize its importance
     * during search operations in the Studio. This setting allows the specified
     * field to be ranked higher in search results compared to other fields.
     *
     * By default, all fields are assigned a weight of 1. However, if a field is
     * chosen as the `title` in the preview configuration's `select` option, it
     * will automatically receive a default weight of 10. Similarly, if selected
     * as the `subtitle`, the default weight is 5. Fields marked as
     * `hidden: true` (no function) are assigned a weight of 0 by default.
     *
     * Note: Search weight configuration is currently supported only for fields
     * of type string or portable text arrays.
     */
    weight?: number
  }
}

/**
 * @public
 */
export declare const searchStrategies: readonly ['groqLegacy', 'groq2024']

/**
 * @public
 */
export declare type SearchStrategy = (typeof searchStrategies)[number]

/** @public */
export declare interface SingleFieldSet {
  single: true
  field: ObjectField
  hidden?: ConditionalProperty
  readOnly?: ConditionalProperty
  group?: string | string[]
}

/** @internal */
export declare interface SingleMutationResult {
  transactionId: string
  documentId: string
  results: {
    id: string
  }[]
}

/**
 * A slug object, currently holding a `current` property
 *
 * In the future, this may be extended with a `history` property
 *
 * @public
 */
export declare interface Slug {
  _type: 'slug'
  current: string
}

/** @public */
export declare interface SlugDefinition extends BaseSchemaDefinition {
  type: 'slug'
  options?: SlugOptions
  validation?: ValidationBuilder<SlugRule, SlugValue>
  initialValue?: InitialValueProperty<any, Omit<SlugValue, '_type'>>
}

/** @public */
export declare type SlugifierFn = (
  source: string,
  schemaType: SlugSchemaType,
  context: SlugSourceContext,
) => string | Promise<string>

/** @public */
export declare type SlugIsUniqueValidator = (
  slug: string,
  context: SlugValidationContext,
) => boolean | Promise<boolean>

/** @public */
export declare interface SlugOptions extends SearchConfiguration, BaseSchemaTypeOptions {
  source?: string | Path | SlugSourceFn
  maxLength?: number
  slugify?: SlugifierFn
  isUnique?: SlugIsUniqueValidator
  disableArrayWarning?: boolean
}

/** @public */
export declare type SlugParent = Record<string, unknown> | Record<string, unknown>[]

/** @public */
export declare interface SlugRule extends RuleDef<SlugRule, SlugValue> {}

/** @public */
export declare interface SlugSchemaType extends ObjectSchemaType {
  jsonType: 'object'
  options?: SlugOptions
}

/** @public */
export declare interface SlugSourceContext {
  parentPath: Path
  parent: SlugParent
  projectId: string
  dataset: string
  schema: Schema
  currentUser: CurrentUser | null
  getClient: (options: {apiVersion: string}) => SanityClient
}

/** @public */
export declare type SlugSourceFn = (
  document: SanityDocument,
  context: SlugSourceContext,
) => string | Promise<string>

/** @public */
export declare interface SlugValidationContext extends ValidationContext {
  parent: SlugParent
  type: SlugSchemaType
  defaultIsUnique: SlugIsUniqueValidator
}

/** @public */
export declare interface SlugValue {
  _type: 'slug'
  current?: string
}

/** @beta */
export declare type SortOrdering = {
  title: string
  i18n?: I18nTextRecord<'title'>
  name: string
  by: SortOrderingItem[]
}

/** @beta */
export declare interface SortOrderingItem {
  field: string
  direction: 'asc' | 'desc'
}

/**
 * A specific `ObjectField` for `marks` in `SpanSchemaType`
 * @see SpanSchemaType
 *
 * @internal
 */
export declare type SpanMarksObjectField = {
  name: 'marks'
} & ObjectField<ArraySchemaTypeOf<StringSchemaType>>

/**
 * Represents the compiled schema shape for `span`s for portable text.
 *
 * Note: this does _not_ represent the schema definition shape.
 *
 * @internal
 */
export declare interface SpanSchemaType extends Omit<ObjectSchemaType, 'fields'> {
  annotations: (ObjectSchemaType & {
    icon?: string | ComponentType
    components?: {
      item?: ComponentType
    }
  })[]
  decorators: BlockDecoratorDefinition[]
  fields: [SpanMarksObjectField, SpanTextObjectField]
}

/**
 * A specific `ObjectField` for `text` in `SpanSchemaType`
 * @see SpanSchemaType
 *
 * @internal
 */
export declare type SpanTextObjectField = {
  name: 'text'
} & ObjectField<TextSchemaType>

/** @beta */
export declare type StrictDefinition = boolean | undefined

/** @public */
export declare interface StringDefinition extends BaseSchemaDefinition {
  type: 'string'
  options?: StringOptions
  placeholder?: string
  validation?: ValidationBuilder<StringRule, string>
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare interface StringOptions
  extends EnumListProps<string>,
    SearchConfiguration,
    BaseSchemaTypeOptions {}

/** @public */
export declare interface StringRule extends RuleDef<StringRule, string> {
  min: (minNumber: number | FieldReference) => StringRule
  max: (maxNumber: number | FieldReference) => StringRule
  length: (exactLength: number | FieldReference) => StringRule
  uppercase: () => StringRule
  lowercase: () => StringRule
  regex(
    pattern: RegExp,
    name: string,
    options: {
      name?: string
      invert?: boolean
    },
  ): StringRule
  regex(
    pattern: RegExp,
    options: {
      name?: string
      invert?: boolean
    },
  ): StringRule
  regex(pattern: RegExp, name: string): StringRule
  regex(pattern: RegExp): StringRule
  email(): StringRule
}

/**
 * This is used for string, text, date and datetime.
 * This interface represent the compiled version at runtime, when accessed through Schema.
 *
 * @public
 */
export declare interface StringSchemaType extends BaseSchemaType {
  jsonType: 'string'
  options?: StringOptions & TextOptions & DateOptions & DatetimeOptions
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare type SwatchName =
  | 'darkMuted'
  | 'darkVibrant'
  | 'dominant'
  | 'lightMuted'
  | 'lightVibrant'
  | 'muted'
  | 'vibrant'

/** @public */
export declare interface TextDefinition extends BaseSchemaDefinition {
  type: 'text'
  rows?: number
  options?: TextOptions
  placeholder?: string
  validation?: ValidationBuilder<TextRule, string>
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare interface TextOptions extends StringOptions {}

/** @public */
export declare interface TextRule extends StringRule {}

/** @public */
export declare interface TextSchemaType extends StringSchemaType {
  rows?: number
}

/** @public */
export declare interface TitledListValue<V = unknown> {
  _key?: string
  title: string
  value?: V
}

/**
 * An entry in the transaction log
 *
 * @internal
 */
export declare interface TransactionLogEvent {
  /**
   * ID of transaction
   */
  id: string
  /**
   * ISO-formatted timestamp (zulu-time) of when the transaction happened
   */
  timestamp: string
  /**
   * User ID of the user who performed the transaction
   */
  author: string
  /**
   * Document IDs involved in this transaction
   */
  documentIDs: string[]
}

/**
 * An entry in the transaction log that includes the effects of the transaction.
 * Used when asking the transaction log to include effects in mendoza format,
 * eg `?effectFormat=mendoza`
 *
 * @internal
 */
export declare interface TransactionLogEventWithEffects extends TransactionLogEvent {
  /**
   * Object of effects, where the key is the document ID affected and the value
   * is the effect pair, eg `{apply: MendozaPatch, revert: MendozaPatch}`
   */
  effects: Record<string, MendozaEffectPair | undefined>
}

/**
 * An entry in the transaction log that includes the mutations that were performed.
 * Used when asking the transaction log not to exclude the mutations,
 * eg `excludeMutations=false`
 *
 * @internal
 */
export declare interface TransactionLogEventWithMutations extends TransactionLogEvent {
  /**
   * Array of mutations that occurred in this transaction. Note that the transaction
   * log has an additional mutation type not typically seen in other APIs;
   * `createSquashed` ({@link CreateSquashedMutation}).
   */
  mutations: TransactionLogMutation[]
}

/**
 * A mutation that can occur in the transaction log, which includes the
 * {@link CreateSquashedMutation} mutation type.
 *
 * @internal
 */
export declare type TransactionLogMutation = Mutation | CreateSquashedMutation

/**
 * Represents a type definition that is an alias/extension of an existing type
 * in your schema. Creating a type alias will re-register that existing type
 * under a different name. You can also override the default type options with
 * a type alias definition.
 *
 * @public
 */
export declare interface TypeAliasDefinition<
  TType extends string,
  TAlias extends IntrinsicTypeName | undefined,
> extends BaseSchemaDefinition {
  type: TType
  options?: TAlias extends IntrinsicTypeName ? IntrinsicDefinitions[TAlias]['options'] : unknown
  validation?: SchemaValidationValue
  initialValue?: InitialValueProperty<any, any>
  preview?: PreviewConfig
  components?: {
    annotation?: ComponentType<any>
    block?: ComponentType<any>
    inlineBlock?: ComponentType<any>
    diff?: ComponentType<any>
    field?: ComponentType<any>
    input?: ComponentType<any>
    item?: ComponentType<any>
    preview?: ComponentType<any>
  }
}

/**
 * `typed` can be used to ensure that an object conforms to an exact interface.
 *
 * It can be useful when working with `defineType` and `defineField` on occasions where a wider type with
 * custom options or properties is required.
 *
 * ## Example  usage
 * ```ts
 *  defineField({
 *    type: 'string',
 *    name: 'nestedField',
 *    options: typed<StringOptions & {myCustomOption: boolean}>({
 *      layout: 'radio',
 *      // allowed
 *      myCustomOption: true,
 *      //@ts-expect-error unknownProp is not part of StringOptions & {myCustomOption: boolean}
 *      unknownProp: 'not allowed in typed context',
 *    }),
 *  }),
 * ```
 *
 * @param input - returned directly
 *
 * @internal
 */
export declare function typed<T>(input: T): T

/** @public */
export declare interface TypedObject {
  [key: string]: unknown
  _type: string
}

/**
 * Represents a reference to another type registered top-level in your schema.
 *
 * @public
 */
export declare interface TypeReference {
  type: string
  name?: string
  icon?: ComponentType | ReactNode
  options?: {
    [key: string]: unknown
  }
}

/** @internal */
export declare interface UploadState {
  progress: number
  /** @deprecated use createdAt instead */
  initiated?: string
  /** @deprecated use updatedAt instead */
  updated?: string
  createdAt: string
  updatedAt: string
  file: {
    name: string
    type: string
  }
  previewImage?: string
}

/** @public */
export declare interface UriValidationOptions {
  scheme?: (string | RegExp) | Array<string | RegExp>
  allowRelative?: boolean
  relativeOnly?: boolean
  allowCredentials?: boolean
}

/** @public */
export declare interface UrlDefinition extends BaseSchemaDefinition {
  type: 'url'
  options?: UrlOptions
  placeholder?: string
  validation?: ValidationBuilder<UrlRule, string>
  initialValue?: InitialValueProperty<any, string>
}

/** @public */
export declare interface UrlOptions extends BaseSchemaTypeOptions {}

/** @public */
export declare interface UrlRule extends RuleDef<UrlRule, string> {
  uri(options: UriValidationOptions): UrlRule
}

/** @public */
export declare interface User {
  id: string
  displayName?: string
  imageUrl?: string
  email?: string
}

/** @public */
export declare type ValidationBuilder<T extends RuleDef<T, FieldValue>, FieldValue = unknown> = (
  rule: T,
) => RuleBuilder<T, FieldValue>

/**
 * A context object passed around during validation. This includes the
 * `Rule.custom` context.
 *
 * e.g.
 *
 * ```js
 * Rule.custom((_, validationContext) => {
 *   // ...
 * })`
 * ```
 *
 * @public
 */
export declare interface ValidationContext {
  getClient: (options: {apiVersion: string}) => SanityClient
  schema: Schema
  parent?: unknown
  type?: SchemaType
  document?: SanityDocument
  path?: Path
  getDocumentExists?: (options: {id: string}) => Promise<boolean>
  environment: 'cli' | 'studio'
}

/**
 * The shape that can be returned from a custom validator to be converted into
 * a validation marker by the validation logic. Inside of a custom validator,
 * you can return an array of these in order to specify multiple paths within
 * an object or array.
 *
 * @public
 */
export declare interface ValidationError {
  /**
   * The message describing why the value is not valid. This message will be
   * included in the validation markers after validation has finished running.
   */
  message: string
  /**
   * If writing a custom validator, you can return validation messages to
   * specific path inside of the current value (object or array) by populating
   * this `path` prop.
   *
   * NOTE: This path is relative to the current value and _not_ relative to
   * the document.
   */
  path?: Path
  /**
   * Same as `path` but allows more than one value. If provided, the same
   * message will create two markers from each path with the same message
   * provided.
   *
   * @deprecated prefer `path`
   */
  paths?: Path[]
  /**
   * @deprecated Unused. Was used to store the results from `.either()` /`.all()`
   */
  children?: ValidationMarker[]
  /**
   * @deprecated Unused. Was used to signal if this error came from an `.either()`/`.all()`.
   */
  operation?: 'AND' | 'OR'
  /**
   * @deprecated Unused. Was relevant when validation error was used as a class.
   */
  cloneWithMessage?(message: string): ValidationError
}

/**
 * This follows the same pattern as `RuleClass` and `Rule` above
 * Note: this class does not actually extend `Error` since it's never thrown
 * within the validation library
 *
 * @deprecated It is preferred to a plain object that adheres to `ValidationError`
 * @internal
 */
export declare interface ValidationErrorClass {
  new (message: string, options?: ValidationErrorOptions): ValidationError
}

/** @internal */
export declare interface ValidationErrorOptions {
  paths?: Path[]
  children?: ValidationMarker[]
  operation?: 'AND' | 'OR'
}

/** @public */
export declare interface ValidationMarker {
  level: 'error' | 'warning' | 'info'
  /**
   * The validation message for this marker. E.g. "Must be greater than 0"
   */
  message: string
  /**
   * @deprecated use `message` instead
   */
  item?: ValidationError
  /**
   * The sanity path _relative to the root of the current document_ to this
   * marker.
   *
   * NOTE: Sanity paths may contain keyed segments (i.e. `{_key: string}`) that
   * are not compatible with deep getters like lodash/get
   */
  path: Path
}

/**
 * The base type for all validators in the validation library. Takes in a
 * `RuleSpec`'s constraint, the value to check, an optional override message,
 * and the validation context.
 *
 * @see Rule.validate from `sanity/src/core/validation/Rule`
 *
 * @internal
 */
export declare type Validator<T = any, Value = any> = (
  constraint: T,
  value: Value,
  message: string | undefined,
  context: ValidationContext,
) =>
  | ValidationError[]
  | ValidationError
  | string
  | true
  | Promise<ValidationError[] | ValidationError | string | true>

/**
 * A type helper used to define a group of validators. The type of the
 * `RuleSpec` constraint is inferred via the key.
 *
 * E.g.
 *
 * ```ts
 * const booleanValidators: Validators = {
 *   ...genericValidator,
 *
 *   presence: (v, value, message) => {
 *     if (v === 'required' && typeof value !== 'boolean') return message || 'Required'
 *     return true
 *   },
 * }
 * ```
 *
 * @internal
 */
export declare type Validators = Partial<{
  [P in RuleSpec['flag']]: Validator<
    Exclude<
      ConditionalIndexAccess<
        Extract<
          RuleSpec,
          {
            flag: P
          }
        >,
        'constraint'
      >,
      FieldReference
    >
  >
}>

/** @beta */
export declare interface WeakCrossDatasetReferenceValue extends CrossDatasetReferenceValue {
  _weak: true
}

/** @beta */
export declare interface WeakGlobalDocumentReferenceValue extends GlobalDocumentReferenceValue {
  _weak: true
}

/** @internal */
export declare interface WeakReference extends Reference {
  _weak: true
}

/** @beta */
export declare interface WidenInitialValue {
  initialValue?: InitialValueProperty<any, any>
}

/** @beta */
export declare interface WidenValidation {
  validation?: SchemaValidationValue
}

export {}
