Skip to content

Commit

Permalink
refactor(core/form): add block and annotation component schema extens…
Browse files Browse the repository at this point in the history
…ions

Object types can now be rendered as .block or .annotation in the PT-input through their Studio schema extension
  • Loading branch information
skogsmaskin committed Dec 20, 2022
1 parent acc0e79 commit bbd32ae
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 136 deletions.
8 changes: 8 additions & 0 deletions packages/sanity/src/core/form/types/asserters.ts
@@ -1,4 +1,5 @@
import {
isArrayOfBlocksSchemaType,
isArrayOfObjectsSchemaType,
isArrayOfPrimitivesSchemaType,
isBooleanSchemaType,
Expand Down Expand Up @@ -59,6 +60,13 @@ export function isArrayOfObjectsInputProps(
return isArrayOfObjectsSchemaType(inputProps.schemaType)
}

/** @beta */
export function isArrayOfBlocksInputProps(
inputProps: InputProps | Omit<InputProps, 'renderDefault'>
): inputProps is ArrayOfObjectsInputProps {
return isArrayOfBlocksSchemaType(inputProps.schemaType)
}

/** @beta */
export function isArrayOfPrimitivesInputProps(
inputProps: InputProps | Omit<InputProps, 'renderDefault'>
Expand Down
62 changes: 62 additions & 0 deletions packages/sanity/src/core/form/types/blockProps.ts
@@ -0,0 +1,62 @@
import {Path, PortableTextBlock, PortableTextObject, PortableTextTextBlock} from '@sanity/types'

/** @alpha */
export interface BlockDecoratorProps {
children: React.ReactElement
focused: boolean
renderDefault: (props: BlockDecoratorProps) => React.ReactElement
selected: boolean
title: string
value: string
}

/** @alpha */
export interface BlockStyleProps {
block: PortableTextTextBlock
children: React.ReactElement
focused: boolean
renderDefault: (props: BlockStyleProps) => React.ReactElement
selected: boolean
title: string
value: string
}

/** @alpha */
export interface BlockListItemProps {
block: PortableTextTextBlock
children: React.ReactElement
focused: boolean
level: number
renderDefault: (props: BlockListItemProps) => React.ReactElement
selected: boolean
title: string
value: string
}

/** @alpha */
export interface BlockAnnotationProps {
children: React.ReactElement
focused: boolean
onClose: () => void
onOpen: () => void
onRemove: () => void
open: boolean
path: Path
renderDefault: (props: BlockAnnotationProps) => React.ReactElement
selected: boolean
value: PortableTextObject
}

/** @alpha */
export interface BlockProps {
children: React.ReactElement
focused: boolean
onClose: () => void
onOpen: () => void
onRemove: () => void
open: boolean
path: Path
renderDefault: (props: BlockProps) => React.ReactElement
selected: boolean
value: PortableTextBlock
}
125 changes: 1 addition & 124 deletions packages/sanity/src/core/form/types/definitionExtensions.test.ts
Expand Up @@ -13,6 +13,7 @@ import {
} from '@sanity/types'
import {defineConfig} from '../../config'
import {PreviewProps} from '../../components'
import {CrossDatasetReferenceInputProps, ReferenceInputProps} from '../studio'
import {
ArrayOfObjectsInputProps,
ArrayOfPrimitivesInputProps,
Expand All @@ -35,7 +36,6 @@ import {ObjectItem, ObjectItemProps, PrimitiveItemProps} from './itemProps'
import {
ArrayOfObjectsComponents,
ArrayOfPrimitivesComponents,
BlockComponents,
BooleanComponents,
CrossDatasetReferenceComponents,
DateComponents,
Expand All @@ -54,7 +54,6 @@ import {
TextComponents,
UrlComponents,
} from './definitionExtensions'
import {CrossDatasetReferenceInputProps, ReferenceInputProps} from '../studio'

describe('definitionExtensions', () => {
describe('array-like types', () => {
Expand Down Expand Up @@ -152,101 +151,6 @@ describe('definitionExtensions', () => {
},
})
})

it('should extend components for block', () => {
const type = defineType({
type: 'block',
name: 'test',
of: [{type: 'some-object'}],
components: {
diff: (props) => null,
field: (props) => {
const obj: ArrayFieldProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
input: (props) => {
const obj: ArrayOfObjectsInputProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
item: (props) => {
const obj: ObjectItemProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
preview: (props) => {
const obj: PreviewProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
},
})

// this typing is not ideal, but leaving it as this until we decide to narrow array type
const components: ArrayOfObjectsComponents | undefined = type.components

// ensure we can assign this to config.schema.types
defineConfig({
name: 'test',
projectId: 'test',
dataset: 'test',
schema: {
types: [type],
},
})
})

it('should extend components for block', () => {
const type = defineType({
type: 'block',
name: 'test',
of: [{type: 'some-object'}],
components: {
diff: (props) => null,
field: (props) => {
const obj: ArrayFieldProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
input: (props) => {
const obj: ArrayOfObjectsInputProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
item: (props) => {
const obj: ObjectItemProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
preview: (props) => {
const obj: PreviewProps = props
//@ts-expect-error ensures props is not any
const notObj: string = props
return null
},
},
})

const components: BlockComponents | undefined = type.components

// ensure we can assign this to config.schema.types
defineConfig({
name: 'test',
projectId: 'test',
dataset: 'test',
schema: {
types: [type],
},
})
})
})

it('should extend components for boolean', () => {
Expand Down Expand Up @@ -691,33 +595,6 @@ describe('definitionExtensions', () => {
})
const components: SlugComponents | undefined = type.components
})

it('should extend components for span', () => {
const type = defineType({
type: 'span',
name: 'test',
components: {
diff: (props) => null,
field: (props) => {
const obj: ObjectFieldProps = props
return null
},
input: (props) => {
const obj: ObjectInputProps = props
return null
},
item: (props) => {
const obj: ObjectItemProps = props
return null
},
preview: (props) => {
const obj: PreviewProps = props
return null
},
},
})
const components: SpanComponents | undefined = type.components
})
})

it('should allow components for fields without defineField', () => {
Expand Down
65 changes: 53 additions & 12 deletions packages/sanity/src/core/form/types/definitionExtensions.ts
Expand Up @@ -26,11 +26,20 @@ import {
StringInputProps,
} from './inputProps'
import {ObjectItem, ObjectItemProps, PrimitiveItemProps} from './itemProps'
import {
BlockAnnotationProps,
BlockDecoratorProps,
BlockListItemProps,
BlockProps,
BlockStyleProps,
} from './blockProps'

/**
* @beta
*/
export interface ArrayOfObjectsComponents {
annotation?: ComponentType<any>
block?: ComponentType<any>
diff?: ComponentType<any>
field?: ComponentType<ArrayFieldProps>
input?: ComponentType<ArrayOfObjectsInputProps>
Expand All @@ -49,17 +58,6 @@ export interface ArrayOfPrimitivesComponents {
preview?: ComponentType<PreviewProps>
}

/**
* @beta
*/
export interface BlockComponents {
diff?: ComponentType<any>
field?: ComponentType<ArrayFieldProps>
input?: ComponentType<ArrayOfObjectsInputProps>
item?: ComponentType<ObjectItemProps>
preview?: ComponentType<PreviewProps>
}

/**
* @beta
*/
Expand Down Expand Up @@ -152,6 +150,8 @@ export interface NumberComponents {
* @beta
*/
export interface ObjectComponents {
annotation?: ComponentType<any>
block?: ComponentType<any>
diff?: ComponentType<any>
field?: ComponentType<ObjectFieldProps>
input?: ComponentType<ObjectInputProps>
Expand All @@ -163,6 +163,8 @@ export interface ObjectComponents {
* @beta
*/
export interface ReferenceComponents {
annotation?: ComponentType<any>
block?: ComponentType<any>
diff?: ComponentType<any>
field?: ComponentType<ObjectFieldProps<ReferenceValue>>
input?: ComponentType<ReferenceInputProps>
Expand All @@ -174,6 +176,8 @@ export interface ReferenceComponents {
* @beta
*/
export interface CrossDatasetReferenceComponents {
annotation?: ComponentType<any>
block?: ComponentType<any>
diff?: ComponentType<any>
field?: ComponentType<ObjectFieldProps<CrossDatasetReferenceValue>>
input?: ComponentType<CrossDatasetReferenceInputProps>
Expand Down Expand Up @@ -260,7 +264,44 @@ declare module '@sanity/types' {
/**
* @beta
*/
components?: BlockComponents
components?: {
block?: ComponentType<BlockProps>
}
}

export interface BlockDecoratorDefinition {
/**
* @beta
*/
components?: {
item?: ComponentType<BlockDecoratorProps>
}
}

export interface BlockStyleDefinition {
/**
* @beta
*/
components?: {
item?: ComponentType<BlockStyleProps>
}
}
export interface BlockListDefinition {
/**
* @beta
*/
components?: {
item?: ComponentType<BlockListItemProps>
}
}

export interface BlockAnnotationDefinition {
/**
* @beta
*/
components?: {
annotation?: ComponentType<BlockAnnotationProps>
}
}

export interface BooleanDefinition {
Expand Down
1 change: 1 addition & 0 deletions packages/sanity/src/core/form/types/index.ts
@@ -1,5 +1,6 @@
export * from './_transitional'
export * from './asserters'
export * from './blockProps'
export * from './event'
export * from './fieldProps'
export * from './inputProps'
Expand Down

0 comments on commit bbd32ae

Please sign in to comment.