Geoff Ball
Support Engineer at Sanity.io
A custom input component that lets the schema creator control max, min, and step values on a number input.
This recipe is for an older version of Sanity Studio (v2), which is deprecated.
Learn how to migrate to the new Studio v3 →import React from 'react';
import { TextInput } from '@sanity/ui';
import { FormField } from '@sanity/base/components';
import PatchEvent, { set, unset } from '@sanity/form-builder/PatchEvent';
import { useId } from '@reach/auto-id';
export const ControlledNumber = React.forwardRef((props, ref) => {
const {
type,
value,
readOnly,
markers,
presence,
compareValue,
onFocus,
onBlur,
onChange,
} = props;
const { title, description, placeholder, options } = type;
const { min, max, step } = options ?? { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER, step: 1 };
const handleChange = React.useCallback((event) => {
let inputValue = Number.parseFloat(event.currentTarget.value);
if (Math.abs(inputValue) > Number.MAX_SAFE_INTEGER) inputValue = Math.sign(inputValue) * Number.MAX_SAFE_INTEGER;
onChange(PatchEvent.from(inputValue ? set(inputValue) : unset()))
}, [onChange]);
const inputId = useId();
return (
<FormField
inputId={inputId}
compareValue={compareValue}
description={description}
title={title}
__unstable_markers={markers}
__unstable_presence={presence}
>
<TextInput
id={inputId}
onChange={handleChange}
value={value}
readOnly={readOnly}
placeholder={placeholder}
onFocus={onFocus}
onBlur={onBlur}
ref={ref}
type="number"
min={min || -Number.MAX_SAFE_INTEGER}
max={max || Number.MAX_SAFE_INTEGER}
step={step || 1}
/>
</FormField>
);
});import { ControlledNumber } from '../path/to/controlled-number';
export default {
name: "documentName",
title: "Document Name",
type: "document",
fields: [
// ...,
{
name: 'numberField',
title: 'Number Field',
type: 'number',
// description: 'Optional description',
// placeholder: 'Optional placeholder value',
// validation: Rule => Rule.required().min(1),
inputComponent: ControlledNumber,
options: {
min: 1,
max: 10,
step: 1,
}
},
// ...
],
}Using a custom input component, we can add an HTML input with type="number" that lets the schema developer control the min, max, and/or step values of that input.
The name and file location of your input component do not matter—you just need to be able to import the file into your schema.
The options property is optional. When omitted, step will default to 1 and max and min will default to positive and negative Number.MAX_SAFE_INTEGER, respectively. However, at that point use of the custom component is moot.
Steps:
controlled-number.js and put it in a components/ directory in the root of my studio) and add the input component code from above.ControlledNumber:import { ControlledNumber } from '../components/controlled-number';
number and an inputComponent property of ControlledNumber. Specify max, min, and step in an options object, as required.Support Engineer at Sanity.io
Your block styles will normally look the same in the editor and the styles dropdown. For the times you don't want that, this workaround lets you configure them differently.
Go to Create different block styles for the dropdown and editorSometimes, you just need to migrate a document or two.
Go to Ad hoc document migrationGROQ doesn't yet include a function to match the end of a string, but we can simulate it by splitting our string on our term.
Go to Matching the end of a string in GROQSimplify your Studio experience by hiding deprecated fields when you create new documents.
Go to Hide a deprecated field in new documents