Skip to content

Instantly share code, notes, and snippets.

@rudfoss
Last active August 28, 2021 14:14
Show Gist options
  • Save rudfoss/dfe0addd179328345b936c52c2009bb2 to your computer and use it in GitHub Desktop.
Save rudfoss/dfe0addd179328345b936c52c2009bb2 to your computer and use it in GitHub Desktop.
A starter file of typescript types for Sanity CMS schema definitions. It is by no means complete, but covers most of the basic use cases I've run into.
import React from "react"
import { SanityDocument as SanityQueryDocument, SanityDocumentStub } from "@sanity/client"
/**
* A Sanity name string. Can only a-z A-Z 0-9 and underscore.
*/
export type SanityName = string
export interface SanitySelectorSet {
[key: string]: string
}
export type SanityPreviewPreparerFunc = (selection: { [key: string]: any }) => {
title: any
subtitle?: any
media?: React.ReactNode
}
export type BaseTypes =
| "array"
| "block"
| "boolean"
| "date"
| "datetime"
| "file"
| "geopoint"
| "image"
| "number"
| "object"
| "reference"
| "slug"
| "string"
| "span"
| "text"
| "url"
| "document"
export interface SanityFieldSet {
title: string
name: SanityName
description?: string | React.ReactNode
options?: {
collapsible?: boolean
collapsed?: boolean
}
}
export interface SanityPreview {
select?: { [key: string]: string }
prepare?: SanityPreviewPreparerFunc
component?: React.ReactNode
}
export interface SanityValidatorContext<TDocument = SanityQueryDocument, TParentFieldType = any> {
document: TDocument
parent: TParentFieldType
path: any
type: {
name: string
}
}
export type SanityValidatorFunctionResult =
| boolean
| string
| {
message: string
paths: (string | number | { _key: string } | (string | number | { _key: string })[])[]
}
export type SanityValidatorFunction<
TValueType = any,
TParentFieldType = any,
TDocument = SanityQueryDocument
> = (
value: TValueType | undefined,
context: SanityValidatorContext<TDocument, TParentFieldType>
) => SanityValidatorFunctionResult | Promise<SanityValidatorFunctionResult>
interface SanityFieldHiddenArgs<TParent = Record<string, any>, TValue = any> {
document?: SanityDocumentStub
parent?: TParent
value?: TValue
currentUser: {
email: string
id: string
name: string
profileImage: string
role: string
roes: { name: string; title: string; description: string }[]
}
}
export type FieldHiddenValue<TParent = Record<string, any>, TValue = any> =
| boolean
| ((args: SanityFieldHiddenArgs<TParent, TValue>) => boolean)
export interface SanityFieldBase {
title: string
name: SanityName
type: BaseTypes
hidden?: FieldHiddenValue
description?: string | React.ReactNode
readOnly?: boolean
/**
* A list of fieldsets for this schema.
*/
fieldsets?: SanityFieldSet[]
/**
* The name of the fieldset to associate with this field.
*/
fieldset?: string
preview?: SanityPreview
inputComponent?: React.ReactNode
validation?: (rule: any) => true | string | Promise<true | string>
options?: { [key: string]: any }
initialValue?: any
}
export interface SanityFieldArray extends SanityFieldBase {
type: "array"
of: SanityFieldOf[]
options?: {
sortable?: boolean
layout?: "tags" | "grid"
list?: any[]
editModal?: "dialog" | "fullScreen" | "popover"
}
}
export interface SanityFieldReference extends SanityFieldBase {
type: "reference"
to: any[]
weak?: boolean
options?: {
filter?: string
filterParams?: any
}
}
export interface SanityFieldSlug extends SanityFieldBase {
type: "slug"
options?: {
source?: ((doc: Record<string, any>, options: any) => string) | string
slugify?: (input: string, type: SanityFieldSlug) => string
}
}
export interface SanitySlugValue {
current?: string
}
export const isSlugValue = (value: any): value is SanitySlugValue => !!value.current
export interface SanityFieldTextOptionsListItem {
title: string | React.ReactNode
value: string
[k: string]: any
}
export interface SanityFieldText extends SanityFieldBase {
type: "string"
options?: {
list?: string[] | SanityFieldTextOptionsListItem[]
layout?: "radio" | "dropdown"
direction?: "horizontal" | "vertical"
}
}
export interface SanityFieldBlock extends SanityFieldBase {
type: "block"
styles?: any[]
lists?: any[]
marks?: {
decorators?: any[]
annotations?: any[]
}
}
export interface SanityFieldBoolean extends SanityFieldBase {
type: "boolean"
options?: {
layout?: "switch" | "checkbox"
}
}
export interface SanityFieldCustom extends Omit<SanityFieldBase, "type"> {
type: string
}
export interface SanityDocumentOrdering {
title: string
name: string
by: {
field: string
direction?: "asc" | "desc"
}[]
}
export type SanityField =
| SanityFieldArray
| SanityFieldReference
| SanityFieldObject
| SanityFieldSlug
| SanityFieldBoolean
| SanityFieldText
| SanityFieldBlock
| SanityFieldCustom
type SanityFieldOf = SanityField
export interface SanityDocument extends SanityFieldBase {
type: "document"
fields: SanityField[]
initialValue?: Record<string, any>
icon?: React.ReactNode
orderings?: SanityDocumentOrdering[]
/**
* Experimental control of which actions should be allowed for a given document type.
* Add elements to the array to define which actions should be enabled.
*/
__experimental_actions?: ("create" | "update" | "delete" | "publish")[]
}
export interface SanityFieldObject extends SanityFieldBase {
type: "object"
fields: SanityField[]
}
export interface SanityPatch<TValueType = any> {
type: "set" | "unset" | "setIfMissing"
path?: string[]
value?: TValueType
}
export interface SanityMarker {
level: string
path: string[]
type: string
}
export interface SanityPatchEvent<TValueType = any> extends SanityPatch<TValueType> {
prepend: (...patches: any[]) => SanityPatchEvent<TValueType>
append: (...patches: any[]) => SanityPatchEvent<TValueType>
prefixAll: (segment: any) => SanityPatchEvent<TValueType>
}
interface SanityActionDialogBase {
type: string
}
export interface SanityActionDialogConfirm extends SanityActionDialogBase {
type: "confirm"
color?: "warning" | "success" | "danger" | "info"
message: string | React.ReactNode
onConfirm: () => unknown
onCancel: () => unknown
}
export interface SanityActionDialogPopover extends SanityActionDialogBase {
type: "popover"
content: string | React.ReactNode
onClose: () => unknown
}
export interface SanityActionDialogModal extends SanityActionDialogBase {
type: "modal"
title: string
content: string | React.ReactNode
onClose: () => unknown
}
export interface SanityActionDescription {
label: string
onHandle: () => unknown
icon?: React.ReactNode
disabled?: boolean
shortcut?: string
title?: string
dialog?: SanityActionDialogConfirm | SanityActionDialogPopover | SanityActionDialogModal
}
export interface SanityActionResolverProps<TDocument = SanityDocumentStub> {
draft: TDocument | null
id: string
liveEdit: boolean
publised: TDocument | null
type: string
}
export interface SanityCustomActionProps<TDocument = SanityDocumentStub>
extends SanityActionResolverProps<TDocument> {
/**
* Call this to signal that the action is complete
*/
onComplete: () => void
}
export type SanityCustomActionImpl<TDocument = SanityDocumentStub> = (
props: SanityCustomActionProps<TDocument>
) => SanityActionDescription
export type SanityActionResolverImpl<TDocument = SanityDocumentStub> = (
prop: SanityActionResolverProps<TDocument>
) => SanityCustomActionImpl<TDocument>[]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment