Skip to content

Instantly share code, notes, and snippets.

@geball
Created June 4, 2021 15:14
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geball/715734b4bb4956da8bfaba27fdf3f187 to your computer and use it in GitHub Desktop.
Save geball/715734b4bb4956da8bfaba27fdf3f187 to your computer and use it in GitHub Desktop.
Custom snippet to override the array function in Sanity.io
// Ported from https://gist.github.com/Grsmto/cc4db257d05898ca60a9572511fa9bcf and adapted to a functional component.
//
// Overrides the array's Add item button based on an integer-based validation rule.
//
// Add the following to sanity.json:
//
// {
// "implements": "part:@sanity/form-builder/input/array/functions",
// "path": "./src/components/customArrayFunctions.js"
// }
import React from "react";
import {isReferenceSchemaType} from '@sanity/types'
import {AddIcon} from '@sanity/icons'
import {Button, Grid, Menu, MenuButton, MenuItem} from '@sanity/ui'
import {useId} from '@reach/auto-id'
export default function ArrayFunctions(props) {
const {type, readOnly, children, onCreateValue, onAppendItem, value} = props
const menuButtonId = useId()
const insertItem = React.useCallback(
(itemType) => {
const item = onCreateValue(itemType)
onAppendItem(item)
},
[onCreateValue, onAppendItem]
)
const handleAddBtnClick = React.useCallback(() => {
insertItem(type.of[0])
}, [type, insertItem])
if (readOnly) {
return null
}
const maxLength = type.validation[0]._rules.find(
(rule) => rule.flag === "max"
);
if (maxLength && value && value.length >= maxLength.constraint) {
return null;
}
return (
<Grid gap={1} style={{gridTemplateColumns: 'repeat(auto-fit, minmax(100px, 1fr))'}}>
{type.of.length === 1 ? (
<Button icon={AddIcon} mode="ghost" onClick={handleAddBtnClick} text="Add item" />
) : (
<MenuButton
button={<Button icon={AddIcon} mode="ghost" text="Add item…" />}
id={menuButtonId || ''}
menu={
<Menu>
{type.of.map((memberDef, i) => {
const referenceIcon =
isReferenceSchemaType(memberDef) &&
(memberDef.to || []).length === 1 &&
memberDef.to[0].icon
const icon = memberDef.icon || memberDef.type?.icon || referenceIcon
return (
<MenuItem
key={i}
text={memberDef.title || memberDef.type?.name}
onClick={() => insertItem(memberDef)}
icon={icon}
/>
)
})}
</Menu>
}
/>
)}
{children}
</Grid>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment