Skip to content

Instantly share code, notes, and snippets.

@SimeonGriggs
Created December 10, 2021 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SimeonGriggs/55522557a834db113eec35e1c9690760 to your computer and use it in GitHub Desktop.
Save SimeonGriggs/55522557a834db113eec35e1c9690760 to your computer and use it in GitHub Desktop.
Sanity.io Custom Input that will still resolve the default UI for field editing
/**
* Custom Input that will resolve Sanity's default UI for field editing
* As well as display some contextual information from the document
* This is example is for an `array` field of `car` type fields
* For which the default UI is shown below an image from the first array item
*
* The implementation is *not* bulletproof and only has basic handling
* of the potential pitfalls of recursive rendering of the
* <FormBuilderInput /> component
*/
/* eslint-disable react/prop-types */
/* eslint-disable react/display-name */
import React from 'react'
import {Stack, Text} from '@sanity/ui'
import {FormBuilderInput} from '@sanity/form-builder/lib/FormBuilderInput'
import {withDocument} from 'part:@sanity/form-builder'
import imageUrlBuilder from '@sanity/image-url'
import sanityClient from 'part:@sanity/base/client'
const builder = imageUrlBuilder(sanityClient)
const urlFor = (source) => builder.image(source)
const imageStyle = {width: `100%`, height: `auto`}
const DecoratedArray = React.forwardRef((props, ref) => {
const {type, document: sanityDocument} = props
// Attempt prevention of infinite loop in <FormBuilderInput />
// Re-renders can still occur if this Component is used again in a nested field
const typeWithoutInputComponent = React.useMemo(() => ({...type, inputComponent: null}), [type])
// Using some data from the document to decorate the UI
// This part can be removed and replaced with whatever contextual info you want to display
const displayImage = React.useMemo(
() =>
sanityDocument?.cars?.length && sanityDocument.cars[0]?.image
? {
name: sanityDocument.cars[0].name,
url: urlFor(sanityDocument.cars[0].image).width(800).url(),
}
: null,
[sanityDocument]
)
return (
<Stack space={2}>
{displayImage?.url ? (
<img src={displayImage.url} alt={displayImage.name} style={imageStyle} />
) : (
<Text>No images or first item does not have an image</Text>
)}
<FormBuilderInput {...props} type={typeWithoutInputComponent} ref={ref} />
</Stack>
)
})
export default withDocument(DecoratedArray)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment