import { Asset as Asset_3 } from "@sanity/media-library-types";
import { AssetInstanceDocument as AssetInstanceDocument_2 } from "@sanity/media-library-types";
import { ClientPerspective } from "@sanity/client";
import { ComponentType } from "react";
import { ElementType } from "react";
import { ReactNode } from "react";
import { SanityClient } from "@sanity/client";
import { StackablePerspective } from "@sanity/client";

/**
 * Types of array actions that can be performed
 * @beta
 */
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 */
declare interface ArrayDefinition extends BaseSchemaDefinition {
  type: "array";
  of: ArrayOfType[];
  initialValue?: InitialValueProperty<any, unknown[]>;
  validation?: ValidationBuilder<ArrayRule<unknown[]>, unknown[]>;
  options?: ArrayOptions;
}

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

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

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

export declare interface Asset<
  AssetInstance extends AssetInstanceDocument = AssetInstanceDocument,
> {
  _id: string;
  _originalId?: string;
  _type: SanityAsset["_type"];
  title: string;
  assetType: AssetInstance["_type"];
  cdnAccessPolicy: SanityAsset["cdnAccessPolicy"];
  currentVersion: {
    _ref: string;
  };
  aspects?: unknown;
  versions: AssetVersion<AssetInstance>[];
  collections: SanityAssetCollection[];
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  url?: string;
}

/** @public */
declare interface Asset_2 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;
}

export declare interface AssetAspectDocument extends BaseDocument {
  _type: "sanity.asset.aspect";
  /**
   * The asset type this aspect definition applies to
   * Undefined means that it applies to all asset types
   */
  assetType?: Asset["assetType"];
  definition: FieldDefinition;
  public?: boolean;
}

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

export declare type AssetInstanceDocument =
  | SanityImageAsset
  | SanityVideoAsset
  | SanityFileAsset;

export declare interface AssetSelectionItem {
  asset: Asset;
  assetInstanceId?: string | null;
}

declare interface AssetSelectionItemWithLegacySupport extends AssetSelectionItem {
  assetId: string;
  assetType: string;
  assetInstanceId: string;
}

/** @public */
declare interface AssetSource {
  name: string;
  /** @deprecated provide `i18nKey` instead */
  title?: string;
  i18nKey?: string;
  component: ComponentType<AssetSourceComponentProps>;
  icon?: ComponentType;
  /** @beta */
  Uploader?: AssetSourceUploaderClass;
  /**
   * Specifies how uploads should be initiated for this source.
   *
   * - `'picker'` (default): The studio opens a native file picker first,
   *   then passes the selected files to the source via the `uploader` prop.
   *   Progress is tracked via the uploader and shown in the studio UI.
   *
   * - `'component'`: The studio renders the source component directly with
   *   `action: 'upload'`. The source provides its own UI for selecting and
   *   uploading files, and tracks progress internally. When complete, the
   *   source calls `onSelect` with the uploaded assets.
   *
   * @beta
   */
  uploadMode?: "picker" | "component";
  /**
   * Resolve how to open an asset in its original source.
   *
   * This function is called for each AssetSource when determining if
   * "Open in Source" should be available. The plugin should check
   * `asset.source.name` to determine if it can handle this asset.
   *
   * Return values:
   * - `{ type: 'url', url: string }` - Open the URL (in new window by default)
   * - `{ type: 'component' }` - Render the asset source component with action='openInSource'
   * - `false` or `undefined` - This plugin cannot handle this asset
   *
   * @beta
   */
  openInSource?: (asset: Asset_2) => AssetSourceOpenInSourceResult;
}

/** @public */
declare type AssetSourceComponentAction = "select" | "upload" | "openInSource";

/** @public */
declare interface AssetSourceComponentProps {
  action?: AssetSourceComponentAction;
  assetSource: AssetSource;
  assetType?: "file" | "image" | "sanity.video";
  accept: string;
  selectionType: "single";
  dialogHeaderTitle?: React.ReactNode;
  selectedAssets: Asset_2[];
  onClose: () => void;
  onSelect: (assetFromSource: AssetFromSource[]) => void;
  onChangeAction?: (action: AssetSourceComponentAction) => void;
  schemaType?: ImageSchemaType | FileSchemaType;
  /**
   * The uploader instance for tracking upload progress.
   *
   * When `action` is `'upload'`:
   * - If `uploader` is provided: Picker mode. Files are available via
   *   `uploader.getFiles()`. The source should upload these files and report
   *   progress via the uploader.
   * - If `uploader` is undefined: Component mode. The source should show its
   *   own file selection UI, handle uploads internally, and call `onSelect`
   *   when complete.
   *
   * @beta
   */
  uploader?: AssetSourceUploader;
  /**
   * The asset to open in source. Only provided when action is 'openInSource'.
   * @beta
   */
  assetToOpen?: Asset_2;
}

/**
 * The result of calling `AssetSource.openInSource`.
 * @beta
 */
declare type AssetSourceOpenInSourceResult =
  | {
      type: "url";
      url: string;
      target?: "_blank" | "_self";
    }
  | {
      type: "component";
    }
  | false
  | undefined;

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

/** @beta */
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 */
declare type AssetSourceUploaderClass = new (
  ...args: any[]
) => AssetSourceUploader;

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

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

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

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

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

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

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

export declare interface AssetVersion<
  AssetInstance extends AssetInstanceDocument = AssetInstanceDocument,
> {
  _key: string;
  _type: SanityAssetVersion["_type"];
  title?: string;
  instance: AssetInstance;
}

/**
 * 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
 */
declare type AutocompleteString = string & {};

export declare type BaseDocument = {
  _id: string;
  _type: string;
  _rev: string;
  _createdAt: string;
  _updatedAt: string;
  [key: string]: any;
};

/** @public */
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 */
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
 *  */
declare interface BaseSchemaTypeOptions {
  sanityCreate?: SanityCreateOptions;
  canvasApp?: CanvasAppOptions;
}

/**
 * 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-through'},
 *           {title: 'Code', value: 'code'},
 *         ]
 *       }
 *     }
 *   ]
 * }
 * ```
 */
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-through'},
 *           {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'},
 *       ],
 *     },
 *   ]
 * }
 * ```
 */
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'},
 *       ]
 *     }
 *   ]
 * }
 * ```
 */
declare interface BlockListDefinition {
  title: string;
  i18nTitleKey?: string;
  value: string;
  icon?: ReactNode | ComponentType;
}

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

/**
 * Schema options for a Block schema definition
 * @public */
declare interface BlockOptions extends BaseSchemaTypeOptions {
  /**
   * Turn on or off the builtin browser spellchecking. Default is on.
   */
  spellCheck?: boolean;
  unstable_whitespaceOnPasteMode?: "preserve" | "normalize" | "remove";
  /**
   * When enabled, the editor will restrict all line breaks and soft breaks,
   * forcing content to remain on a single line. This will also update
   * the styling of the editor to reflect the single-line constraint.
   *
   * Pasting content that is on multiple lines will be normalized to a single line, if possible.
   *
   * @defaultValue false
   */
  oneLine?: boolean;
}

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

/**
 * 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,
 *     },
 *   ],
 * })
 * ```
 */
declare interface BlockStyleDefinition {
  title: string;
  value: string;
  i18nTitleKey?: string;
  icon?: ReactNode | ComponentType;
}

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

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

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

/** @public */
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
 */
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 */
declare interface CollapseOptions {
  collapsed?: boolean;
  collapsible?: boolean;
  /**
   * @deprecated Use `collapsible` instead
   */
  collapsable?: boolean;
}

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

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

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

/** @public */
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;
}

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

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

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

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

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

/** @public */
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 */
declare interface DatetimeDefinition extends BaseSchemaDefinition {
  type: "datetime";
  options?: DatetimeOptions;
  placeholder?: string;
  validation?: ValidationBuilder<DatetimeRule, string>;
  initialValue?: InitialValueProperty<any, string>;
}

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

/** @public */
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;
}

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

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

/** @public */
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
 */
declare interface DocumentOptions extends BaseSchemaTypeOptions {}

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

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

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

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

/** @public */
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
 */
declare type FieldDefinition<
  TType extends IntrinsicTypeName = IntrinsicTypeName,
  TAlias extends IntrinsicTypeName | undefined = undefined,
> = (
  | InlineFieldDefinition[TType]
  | TypeAliasDefinition<AutocompleteString, TAlias>
) &
  FieldDefinitionBase;

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

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

/** @public */
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
 */
declare interface FieldReference {
  type: symbol;
  path: string | string[];
}

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

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

/** @public */
declare interface 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;
}

/** @public */
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 */
declare interface FileOptions extends ObjectOptions {
  storeOriginalFilename?: boolean;
  accept?: string;
  sources?: AssetSource[];
  mediaLibrary?: MediaLibraryOptions;
  /**
   * When set to `true`, hides the upload UI, only allowing selection of existing assets from the media library.
   * Useful for centralized asset management workflows where ad-hoc uploads should be prevented.
   */
  disableNew?: boolean;
}

/** @public */
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 */
declare interface FileSchemaType extends Omit<ObjectSchemaType, "options"> {
  options?: FileOptions;
}

export declare type FileStatus =
  | "pending"
  | "uploading"
  | "complete"
  | "error"
  | "alreadyExists";

/**
 * Wrapper object for the file upload with progress and status
 */
export declare interface FileUpload {
  id: string;
  file: File;
  status: FileStatus;
  progress: number;
  error?: Error;
}

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

declare type Geopoint = {
  _type: "geopoint";
  lat?: number;
  lng?: number;
  alt?: number;
};

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

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

/** @public */
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
 */
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 */
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);
}

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

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

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

/** @public */
declare interface ImageAsset extends Asset_2 {
  _type: "sanity.imageAsset";
  metadata: ImageMetadata;
}

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

/** @public */
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 */
declare interface ImageDimensions {
  _type: "sanity.imageDimensions";
  height: number;
  width: number;
  aspectRatio: number;
}

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

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

/** @public */
declare type ImageMetadataType =
  | "blurhash"
  | "thumbhash"
  | "lqip"
  | "palette"
  | "exif"
  | "image"
  | "location";

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

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

/** @public */
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 */
declare interface ImageSchemaType extends Omit<ObjectSchemaType, "options"> {
  options?: ImageOptions;
}

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

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

/** @public */
declare type IndexTuple = [number | "", number | ""];

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

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

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

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

/** @alpha This API may change */
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 | undefined;
  groups?:
    | Array<{
        name: string;
        title?: string;
        of?: Array<string>;
      }>
    | undefined;
  /** defaultValue `true` */
  showIcons?: boolean | undefined;
  /** @defaultValue `[{name: 'list'}]` */
  views?:
    | Array<
        | {
            name: "list";
          }
        | {
            name: "grid";
            previewImageUrl?: (schemaTypeName: string) => string | undefined;
          }
      >
    | undefined;
}

declare const internalGroqTypeReferenceTo: unique symbol;

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

/**
 * `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
 */
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
 */
declare type IntrinsicTypeName =
  IntrinsicDefinitions[keyof IntrinsicDefinitions]["type"];

/** @public */
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
 */
declare interface LocalizedValidationMessages {
  [locale: string]: string;
}

/** @public */
declare type MediaAssetTypes = AssetInstanceDocument_2["_type"];

/** @public */
declare interface MediaLibraryFilter {
  name: string;
  query: string;
}

/** @public */
declare interface MediaLibraryOptions {
  filters?: MediaLibraryFilter[];
}

/** @public */
declare interface MediaValidationValue<
  T extends MediaAssetTypes = MediaAssetTypes,
> {
  /**
   * Media information
   */
  media: {
    /**
     * The Media Library Asset.
     */
    asset: Asset_3 & {
      currentVersion: Extract<
        AssetInstanceDocument_2,
        {
          _type: T;
        }
      >;
    };
  };
  /**
   * The field value which the media is used in.
   */
  value: unknown;
}

/** @public */
declare interface MediaValidator<T extends MediaAssetTypes = MediaAssetTypes> {
  (
    value: MediaValidationValue<T>,
    context: ValidationContext,
  ): CustomValidatorResult | Promise<CustomValidatorResult>;
}

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

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

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

/** @public */
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 */
declare interface NumberSchemaType extends BaseSchemaType {
  jsonType: "number";
  options?: NumberOptions;
  initialValue?: InitialValueProperty<any, number>;
}

/** @public */
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 */
declare interface ObjectField<T extends SchemaType = SchemaType> {
  name: string;
  fieldset?: string;
  group?: string | string[];
  type: ObjectFieldType<T>;
}

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

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

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

/** @public */
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;
}

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

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

/**
 * Media Library capabilities that the consumer can declare it supports
 */
export declare type PluginCapabilities = {
  privateAssets?: boolean;
};

/**
 * Filter that the plugin consumer can use to limit the assets shown
 */
export declare type PluginFilter = {
  type: "groq";
  name: string;
  query: string;
};

/**
 * Payload used to configure the plugin behavior
 */
export declare type PluginPayload = {
  auth: "token" | "cookie";
  capabilities?: PluginCapabilities;
  disableNavigation?: boolean;
  pluginFilters?: PluginFilter[];
  scheme: "light" | "dark";
  selectAssetTypes: PluginSelectAssetType[];
  selectionType: "single" | "multiple";
  /**
   * Opaque string the host generates to **partition persisted picker UI state** (e.g. folder path,
   * search query, filters) in the Media Library iframe. Huey derives `localStorage` key suffixes
   * from this value; embedders often derive it from project + dataset + workspace (or any stable
   * context).
   */
  pickerPersistenceKey?: string;
};

export declare type PluginPostMessage =
  | PluginPostMessageAbortUploadRequest
  | PluginPostMessageAssetSelection
  | PluginPostMessageDocumentUpdate
  | PluginPostMessagePageLoaded
  | PluginPostMessagePageUnloaded
  | PluginPostMessageTokenRequest
  | PluginPostMessageTokenResponse
  | PluginPostMessageUploadFilesProgress
  | PluginPostMessageUploadFilesRequest
  | PluginPostMessageUploadFilesResponse;

export declare type PluginPostMessageAbortUploadRequest = {
  type: "abortUploadRequest";
  files?: {
    id: string;
  }[];
};

export declare type PluginPostMessageAssetSelection = {
  type: "assetSelection";
  selection: AssetSelectionItemWithLegacySupport[];
};

/**
 * Message sent from the plugin that a document has been updated
 */
export declare type PluginPostMessageDocumentUpdate = {
  type: "documentUpdate";
  document: {
    _id: string;
    _type: string;
    _rev: string;
  };
};

/**
 * Message sent from a plugin page to notify the host that the page is loaded and ready to be interacted with
 */
export declare type PluginPostMessagePageLoaded = {
  type: "pageLoaded";
  page: string;
};

/**
 * Message sent from a plugin page that a page is unloaded by the user (for closing the dialog and similar)
 */
export declare type PluginPostMessagePageUnloaded = {
  type: "pageUnloaded";
  page: string;
};

export declare type PluginPostMessageTokenRequest = {
  type: "tokenRequest";
};

export declare type PluginPostMessageTokenResponse = {
  type: "tokenResponse";
  token: string | null;
};

/**
 * Message sent from the plugin when files are uploading
 */
export declare type PluginPostMessageUploadFilesProgress = {
  type: "uploadProgress";
  files: FileUpload[];
};

/**
 * Message sent from the plugin that the user wants to upload files
 */
export declare type PluginPostMessageUploadFilesRequest = {
  type: "uploadRequest";
  files: {
    id: string;
    file: File;
  }[];
};

/**
 * Message sent from the app that the pending uploads are uploaded
 */
export declare type PluginPostMessageUploadFilesResponse = {
  type: "uploadResponse";
  assets: AssetSelectionItemWithLegacySupport[];
};

/**
 * Asset types that can be selected by the plugin
 */
export declare type PluginSelectAssetType = "file" | "image" | "video";

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

/** @public */
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 */
declare interface PreviewValue {
  _id?: string;
  _createdAt?: string;
  _updatedAt?: string;
  title?: string;
  subtitle?: string;
  description?: string;
  media?: ReactNode | ElementType;
  imageUrl?: string;
}

/** @public */
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 */
declare interface ReferenceBaseOptions extends BaseSchemaTypeOptions {
  /**
   * When `true`, hides the "Create new" button in the reference input,
   * preventing users from creating new documents from this field.
   *
   * For more granular control (e.g., allowing creation of only specific types,
   * or conditionally hiding the button based on document state), use the
   * `creationTypeFilter` option instead.
   */
  disableNew?: boolean;
  /**
   * Callback function to dynamically filter which document types can be created
   * from this reference field based on the current document state.
   *
   * This allows you to conditionally restrict the types available in the
   * "Create new" dropdown based on other field values in the document.
   *
   * **Important**: This only affects document creation, not which existing documents
   * appear in search results. To filter search results, use the `filter` option instead.
   *
   * @param context - Contains the current document, parent value, and field path
   * @param toTypes - Array of all types configured in the reference field's `to` property
   * @returns Array of type options that should be available for creation. Return the
   *          original `toTypes` array to allow all types, a filtered subset to restrict
   *          available types, or an empty array `[]` to hide the "Create new" button entirely.
   */
  creationTypeFilter?: ReferenceTypeFilter;
}

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

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

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

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

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

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

/** @public */
declare type ReferenceFilterSearchOptions = {
  filter?: string;
  params?: Record<string, unknown>;
  tag?: string;
  maxFieldDepth?: number;
  strategy?: SearchStrategy;
  perspective?: Exclude<ClientPerspective, "raw" | "previewDrafts">;
};

/**
 * 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
 */
declare type ReferenceOptions = ReferenceBaseOptions & ReferenceFilterOptions;

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

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

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

/**
 * Function type for filtering which document types can be created from a reference field.
 *
 * The `creationTypeFilter` specifically controls the types
 * available when clicking "Create new" in the reference input.
 *
 * This is distinct from the `filter` option, which controls which existing documents appear in search results.
 *
 * @param context - Information about the current document and field location
 * @param toTypes - Array of type options from the reference field's `to` configuration
 * @returns Filtered array of type options that should be available for creation
 *
 * @public
 */
declare type ReferenceTypeFilter = (
  context: ReferenceTypeFilterContext,
  toTypes: ReferenceTypeOption[],
) => ReferenceTypeOption[];

/**
 * Context object passed to the creationTypeFilter callback.
 *
 * @public
 */
declare interface ReferenceTypeFilterContext {
  /** The current document being edited */
  document: SanityDocument;
  /** The parent value containing this reference field */
  parent?: Record<string, unknown> | Record<string, unknown>[];
  /** The path to the parent value in the document */
  parentPath: Path;
}

/** @public */
declare interface ReferenceTypeOption {
  type: string;
}

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

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

/** @public */
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;
  skip(): Rule;
  custom<T = unknown>(
    fn: CustomValidator<T>,
    options?: {
      bypassConcurrencyLimit?: boolean;
    },
  ): Rule;
  media<T extends MediaAssetTypes = MediaAssetTypes>(
    fn: MediaValidator<T>,
  ): 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 */
declare type RuleBuilder<
  T extends RuleDef<T, FieldValue>,
  FieldValue = unknown,
> = T | T[];

/** @public */
declare interface RuleDef<T, FieldValue = unknown> {
  required: () => T;
  skip: () => 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 */
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: "media";
      constraint: MediaValidator<any>;
    }
  | {
      flag: "regex";
      constraint: {
        pattern: RegExp;
        name?: string;
        invert: boolean;
      };
    }
  | {
      flag: "uri";
      constraint: {
        options: {
          scheme: RegExp[];
          allowRelative: boolean;
          relativeOnly: boolean;
          allowCredentials: boolean;
        };
      };
    };

/** @public */
declare type RuleTypeConstraint =
  | "Array"
  | "Boolean"
  | "Date"
  | "Number"
  | "Object"
  | "String";

declare type SanityAsset = {
  _id: string;
  _type: "sanity.asset";
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  title?: string;
  aspects?: Record<string, unknown>;
  currentVersion: SanityAssetVersionReference;
  versions: Array<
    {
      _key: string;
    } & SanityAssetVersion
  >;
  assetType: "sanity.imageAsset" | "sanity.videoAsset" | "sanity.fileAsset";
  cdnAccessPolicy: "public" | "private";
  parent?: SanityDirectoryReference | SanityTreeReference;
  rootDirectory?: SanityDirectoryReference;
  url?: string;
  _system?: SanitySystem;
};

declare type SanityAssetCollection = {
  _id: string;
  _type: "sanity.asset.collection";
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  title: string;
  description?: string;
  parent?: SanityDirectoryReference | SanityTreeReference;
  rootDirectory?: SanityDirectoryReference;
  assets?: Array<
    {
      _key: string;
    } & SanityAssetReference
  >;
};

declare type SanityAssetInstanceState = string;

declare type SanityAssetReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.asset";
};

declare type SanityAssetSubtitleReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.asset.subtitle";
};

declare type SanityAssetVersion = {
  _type: "sanity.asset.version";
  title?: string;
  instance:
    | SanityImageAssetReference
    | SanityFileAssetReference
    | SanityVideoAssetReference;
};

declare type SanityAssetVersionReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.asset.version";
};

/**
 * Options for configuring how Sanity Create interfaces with the type or field.
 *
 * @public
 */
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;
}

declare type SanityDirectoryReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.directory";
};

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

declare type SanityFileAsset = {
  _id: string;
  _type: "sanity.fileAsset";
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  title?: string;
  description?: Array<{
    children?: Array<{
      marks?: Array<string>;
      text?: string;
      _type: "span";
      _key: string;
    }>;
    style?: "normal" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "blockquote";
    listItem?: "bullet" | "number";
    markDefs?: Array<{
      href?: string;
      _type: "link";
      _key: string;
    }>;
    level?: number;
    _type: "block";
    _key: string;
  }>;
  state: SanityAssetInstanceState;
  sha1hash?: string;
  mimeType?: string;
  originalFilename?: string;
  size?: number;
  uploadId?: string;
  path: string;
  extension?: string;
  url: string;
  previewUrl?: string;
  rootDirectory?: SanityDirectoryReference;
  _system?: SanitySystem;
};

declare type SanityFileAssetReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.fileAsset";
};

declare type SanityImageAsset = {
  _id: string;
  _type: "sanity.imageAsset";
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  altText?: string;
  state: SanityAssetInstanceState;
  sha1hash?: string;
  mimeType?: string;
  originalFilename?: string;
  size?: number;
  uploadId?: string;
  path?: string;
  extension?: string;
  url: string;
  metadata: SanityImageMetadata;
  rootDirectory?: SanityDirectoryReference;
  _system?: SanitySystem;
};

declare type SanityImageAssetReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.imageAsset";
};

declare type SanityImageDimensions = {
  _type: "sanity.imageDimensions";
  height: number;
  width: number;
  aspectRatio: number;
};

declare type SanityImageExifMetadata = {
  _type: "sanity.imageExifMetadata";
  ApertureValue?: number;
  BrightnessValue?: number;
  DateTimeDigitized?: string;
  DateTimeOriginal?: string;
  ExposureBiasValue?: number;
  ExposureMode?: number;
  ExposureProgram?: number;
  ExposureTime?: number;
  FNumber?: number;
  Flash?: number;
  FocalLength?: number;
  FocalLengthIn35mmFormat?: number;
  ISO?: number;
  LensModel?: string;
  WhiteBalance?: number;
  GPSLatitude?: number;
  GPSLongitude?: number;
  GPSAltitude?: number;
  Copyright?: string;
  Artist?: string;
};

declare type SanityImageExifTags = {
  _type: "sanity.imageExifTags";
  Make?: string;
  Model?: string;
  Orientation?: number;
  XResolution?: number;
  YResolution?: number;
  ResolutionUnit?: number;
  Software?: string;
  ModifyDate?: string;
  ExifOffset?: number;
  GPSInfo?: number;
};

declare type SanityImageMetadata = {
  _type: "sanity.imageMetadata";
  location?: Geopoint;
  dimensions: SanityImageDimensions;
  exif?: SanityImageExifMetadata;
  image?: SanityImageExifTags;
  palette: SanityImagePalette;
  lqip: string;
  blurHash: string;
  hasAlpha: boolean;
  isOpaque: boolean;
};

declare type SanityImagePalette = {
  _type: "sanity.imagePalette";
  darkMuted?: SanityImagePaletteSwatch;
  lightVibrant?: SanityImagePaletteSwatch;
  darkVibrant?: SanityImagePaletteSwatch;
  vibrant?: SanityImagePaletteSwatch;
  dominant?: SanityImagePaletteSwatch;
  lightMuted?: SanityImagePaletteSwatch;
  muted?: SanityImagePaletteSwatch;
};

declare type SanityImagePaletteSwatch = {
  _type: "sanity.imagePaletteSwatch";
  background?: string;
  foreground?: string;
  population?: number;
  title?: string;
};

declare type SanitySystem = {
  _type: "sanity.system";
  createdBy?: string;
};

declare type SanityTreeReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.tree";
};

export declare type SanityVideoAsset = {
  _id: string;
  _type: "sanity.videoAsset";
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  title?: string;
  description?: Array<{
    children?: Array<{
      marks?: Array<string>;
      text?: string;
      _type: "span";
      _key: string;
    }>;
    style?: "normal" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "blockquote";
    listItem?: "bullet" | "number";
    markDefs?: Array<{
      href?: string;
      _type: "link";
      _key: string;
    }>;
    level?: number;
    _type: "block";
    _key: string;
  }>;
  state: SanityAssetInstanceState;
  sha1hash?: string;
  mimeType?: string;
  originalFilename?: string;
  size?: number;
  uploadId?: string;
  path?: string;
  url?: string;
  extension?: string;
  source?: {
    id?: string;
    name?: string;
    url?: string;
  };
  metadata: SanityVideoMetadata;
  rootDirectory?: SanityDirectoryReference;
  _system?: SanitySystem;
};

declare type SanityVideoAssetReference = {
  _ref: string;
  _type: "reference";
  _weak?: boolean;
  [internalGroqTypeReferenceTo]?: "sanity.videoAsset";
};

declare type SanityVideoMetadata = {
  _type: "sanity.videoMetadata";
  aspectRatio?: string;
  duration?: number;
  framerate?: number;
  playbacks?: Array<
    {
      _key: string;
    } & SanityVideoMetadataPlayback
  >;
  renditions?: Array<
    {
      _key: string;
    } & SanityVideoMetadataRendition
  >;
  subtitles?: Array<
    {
      _key: string;
    } & SanityAssetSubtitleReference
  >;
};

declare type SanityVideoMetadataPlayback = {
  _type: "sanity.videoMetadata.playback";
  _id: string;
  name?: string;
  policy: string;
};

export declare type SanityVideoMetadataRendition = {
  _type: "sanity.videoMetadata.rendition";
  name: string;
  resolution: string;
};

/** @public */
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
 */
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
 */
declare type SchemaTypeDefinition<
  TType extends IntrinsicTypeName = IntrinsicTypeName,
> =
  | IntrinsicDefinitions[IntrinsicTypeName]
  | TypeAliasDefinition<AutocompleteString, TType>;

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

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

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

/** @internal */
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
 */
declare type SchemaValidationValue =
  | false
  | undefined
  | Rule
  | SchemaValidationValue[]
  | ((rule: Rule, context?: ValidationContext) => SchemaValidationValue);

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

/** @public */
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
 */
declare const searchStrategies: readonly ["groqLegacy", "groq2024"];

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

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

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

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

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

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

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

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

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

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

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

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

/** @public */
declare interface SlugValue {
  _type: "slug";
  current?: string;
}

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

/** @beta */
declare interface SortOrderingItem {
  field: string;
  direction: "asc" | "desc";
  /**
   * Controls whether null/undefined values appear first or last in the sort order.
   *
   * Defaults match PostgreSQL behavior:
   * - `'desc'` direction → nulls first
   * - `'asc'` direction → nulls last
   *
   * Only specify this to override the default (e.g. `nulls: 'last'` with `direction: 'desc'`).
   *
   * ### ❗This is an experimental feature.
   * Overriding the default may have performance implications for document types
   * with hundreds of documents.
   * @alpha
   */
  nulls?: "first" | "last";
}

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

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

/** @public */
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
 */
declare interface StringSchemaType extends BaseSchemaType {
  jsonType: "string";
  options?: StringOptions & TextOptions & DateOptions & DatetimeOptions;
  initialValue?: InitialValueProperty<any, string>;
}

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

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

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

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

/**
 * 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
 */
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>;
  };
}

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

export declare type UploadSession = {
  _id: string;
  _type: "sanity.asset.upload-session";
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  title: string;
  assets?: Array<
    {
      _key: string;
    } & SanityAssetReference
  >;
  _system?: SanitySystem;
};

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

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

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

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

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

/**
 * A context object passed around during validation. This includes the
 * `Rule.custom` context.
 *
 * e.g.
 *
 * ```js
 * Rule.custom((_, validationContext) => {
 *   // ...
 * })`
 * ```
 *
 * @public
 */
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";
  /**
   * Whether this field is hidden for any reason (either itself or any of its ancestors).
   */
  hidden?: boolean;
}

/**
 * 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
 */
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;
  /**
   * Extra metadata for the validation error. Currently used by the Media Library asset source to ignore
   * certain validation markers when validating asset source media library assets.
   *
   * @internal
   */
  __internal_metadata?: unknown;
  /**
   * 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;
}

/** @public */
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;
  /**
   * Extra metadata for the validation marker. Currently used by the Media Library asset source to ignore
   * certain validation markers when validating asset source media library assets.
   *
   * @internal
   */
  __internal_metadata?: unknown;
}

export {};
