Skip to content

Instantly share code, notes, and snippets.

@rexxars
Created February 5, 2021 23:59
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 rexxars/1945c4b1b137cbd6f9b06e147ec4359d to your computer and use it in GitHub Desktop.
Save rexxars/1945c4b1b137cbd6f9b06e147ec4359d to your computer and use it in GitHub Desktop.
Custom product input, barebones
import React from 'react'
import Preview from 'part:@sanity/base/preview'
import FormField from 'part:@sanity/components/formfields/default'
import SearchableSelect from 'part:@sanity/components/selects/searchable'
import PatchEvent, {set, setIfMissing, unset} from 'part:@sanity/form-builder/patch-event'
const products = [
{
title: 'Adidas Superstar Canvas Green',
handle: 'canvas-grene',
image: {asset: {_ref: 'image-b22f453a74b78fcc40daaa3ecab5adb3b2f6b2d4-900x591-png'}},
},
{
title: 'Adidas Superstar Vegan',
handle: 'vegan',
image: {asset: {_ref: 'image-2f6b31098bcc4a7c9824b3279c471a290bd50b0d-1350x778-png'}},
},
]
const searchProducts = (query) =>
products.filter((prod) => prod.title.toLowerCase().includes(query.toLowerCase()))
export default React.forwardRef(function ProductInput(props, forwardedRef) {
const {type, value, level, markers, readOnly, presence, onChange} = props
const inputValue = value ? value.title : undefined
const errors = markers.filter(
(marker) => marker.type === 'validation' && marker.level === 'error'
)
const [hits, setHits] = React.useState([])
const handleSearch = React.useCallback((query) => setHits(searchProducts(query)), [setHits])
const handleOpen = () => handleSearch('')
const handleChange = (item) =>
onChange(PatchEvent.from(setIfMissing({_type: type.name}), set(item)))
const handleClear = () => onChange(PatchEvent.from(unset()))
const renderHit = (item) => <Preview type={type} value={item} layout="default" />
return (
<FormField
markers={markers}
label={type.title}
level={level}
description={type.description}
presence={presence}
>
<SearchableSelect
ref={forwardedRef}
placeholder="Type to search…"
title={inputValue}
customValidity={errors.length > 0 ? errors[0].item.message : ''}
onOpen={handleOpen}
onFocus={props.onFocus}
onSearch={handleSearch}
onChange={handleChange}
onClear={handleClear}
value={value}
inputValue={inputValue === null ? value : inputValue}
renderItem={renderHit}
items={hits}
readOnly={readOnly}
/>
</FormField>
)
})
import ProductInput from './ProductInput'
export default {
name: 'product',
title: 'Product',
type: 'object',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
{
name: 'handle',
title: 'Handle',
type: 'string',
},
{
name: 'image',
title: 'image',
type: 'image',
},
],
preview: {
select: {
title: 'title',
media: 'image',
},
},
inputComponent: ProductInput,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment