diff --git a/packages/@sanity/form-builder/src/inputs/NumberInput.js b/packages/@sanity/form-builder/src/inputs/NumberInput.js index 1686a059474..4842c00aded 100644 --- a/packages/@sanity/form-builder/src/inputs/NumberInput.js +++ b/packages/@sanity/form-builder/src/inputs/NumberInput.js @@ -2,6 +2,7 @@ import React from 'react' import TextInput from 'part:@sanity/components/textinputs/default' import FormField from 'part:@sanity/components/formfields/default' +import {getValidationRule} from '../utils/getValidationRule' import PatchEvent, {set, unset} from '../PatchEvent' import type {Type, Marker} from '../typedefs' @@ -39,18 +40,8 @@ export default class NumberInput extends React.Component { const errors = validation.filter(marker => marker.level === 'error') // Show numpad on mobile if only positive numbers is preferred - let onlyPositiveNumber = false - if (type && type.validation && type.validation.length) { - type.validation.forEach(rule => { - if (rule._rules && rule._rules.length) { - rule._rules.forEach(_r => { - if (_r.flag === 'min' && _r.constraint >= 0) { - onlyPositiveNumber = true - } - }) - } - }) - } + const minRule = getValidationRule(type, 'min') + const onlyPositiveNumber = minRule && minRule.constraint >= 0 return ( @@ -63,7 +54,7 @@ export default class NumberInput extends React.Component { onChange={this.handleChange} onFocus={onFocus} ref={this.setInput} - pattern={onlyPositiveNumber ? '[\d]*' : undefined} + pattern={onlyPositiveNumber ? '[d]*' : undefined} /> ) diff --git a/packages/@sanity/form-builder/src/inputs/UrlInput.js b/packages/@sanity/form-builder/src/inputs/UrlInput.js index 21406801c7b..be00bbd560f 100644 --- a/packages/@sanity/form-builder/src/inputs/UrlInput.js +++ b/packages/@sanity/form-builder/src/inputs/UrlInput.js @@ -1,7 +1,9 @@ //@flow import React from 'react' +import {get} from 'lodash' import TextInput from 'part:@sanity/components/textinputs/default' import FormField from 'part:@sanity/components/formfields/default' +import {getValidationRule} from '../utils/getValidationRule' import PatchEvent, {set, unset} from '../PatchEvent' import type {Type, Marker} from '../typedefs' @@ -38,11 +40,15 @@ export default class UrlInput extends React.Component { const validation = markers.filter(marker => marker.type === 'validation') const errors = validation.filter(marker => marker.level === 'error') + // Use text input for relative URIs + const uriRule = getValidationRule(type, 'uri') + const inputType = uriRule && get(uriRule, 'constraint.options.allowRelative') ? 'text' : 'url' + return ( 0 ? errors[0].item.message : ''} - type="url" + type={inputType} value={value} readOnly={readOnly} placeholder={type.placeholder} diff --git a/packages/@sanity/form-builder/src/utils/getValidationRule.js b/packages/@sanity/form-builder/src/utils/getValidationRule.js new file mode 100644 index 00000000000..251316609a4 --- /dev/null +++ b/packages/@sanity/form-builder/src/utils/getValidationRule.js @@ -0,0 +1,23 @@ +import type {Type} from '../typedefs' + +export function getValidationRule(type: Type, ruleName: string) { + if (!type || !type.validation || !type.validation.length) { + return null + } + + for (let i = 0; i < type.validation.length; i++) { + const validation = type.validation[i] + if (!validation || !validation._rules) { + continue + } + + for (let r = 0; r < validation._rules.length; r++) { + const rule = validation._rules[r] + if (rule.flag === ruleName) { + return rule + } + } + } + + return null +} diff --git a/packages/test-studio/schemas/validation.js b/packages/test-studio/schemas/validation.js index 56ec18cafce..7dc5283de39 100644 --- a/packages/test-studio/schemas/validation.js +++ b/packages/test-studio/schemas/validation.js @@ -52,6 +52,13 @@ export default { description: 'URL that only allows mailto: and tel: schemes', validation: Rule => Rule.uri({scheme: ['mailto', 'tel']}) }, + { + name: 'relativeUrl', + type: 'url', + title: 'Relative URL', + description: 'URL that allows relative URLs', + validation: Rule => Rule.uri({allowRelative: true}) + }, { name: 'date', type: 'datetime', @@ -89,6 +96,12 @@ export default { description: 'Only positive numbers larger than lowest temperature', validation: Rule => Rule.positive().min(Rule.valueOfField('lowestTemperature')) }, + { + name: 'onlyPositive', + type: 'number', + title: 'Only positive', + validation: Rule => Rule.positive() + }, { name: 'someInteger', type: 'number',