@rjsf/core
Version:
A simple React component capable of building HTML forms out of a JSON schema.
81 lines (80 loc) • 3.99 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { getTemplate, getUiOptions, hashObject, toFieldPathId, TranslatableString, useDeepCompareMemo, } from '@rjsf/utils';
import { useMemo, useState } from 'react';
/**
* Get the schema for the type selection component.
* @param title - The translated title for the type selection schema.
*/
function getFallbackTypeSelectionSchema(title) {
return {
type: 'string',
enum: ['string', 'number', 'boolean', 'object', 'array'],
default: 'string',
title: title,
};
}
/**
* Determines the JSON Schema type of the given formData.
* @param formData - The form data whose type is to be determined.
*/
function getTypeOfFormData(formData) {
const dataType = typeof formData;
if (dataType === 'string' || dataType === 'number' || dataType === 'boolean') {
return dataType;
}
if (dataType === 'object') {
return Array.isArray(formData) ? 'array' : 'object';
}
// Treat everything else as a string
return 'string';
}
/**
* Casts the given formData to the specified type.
* @param formData - The form data to be casted.
* @param newType - The target type to which the form data should be casted.
*/
function castToNewType(formData, newType) {
switch (newType) {
case 'string':
return String(formData);
case 'number': {
const castedNumber = Number(formData);
return (isNaN(castedNumber) ? 0 : castedNumber);
}
case 'boolean':
return Boolean(formData);
default:
return formData;
}
}
/**
* The `FallbackField` component is used to render a field for unsupported or unknown schema types. If
* `useFallbackUiForUnsupportedType` is enabled in the `globalUiOptions`, it provides a type selector
*/
export default function FallbackField(props) {
const { id, formData, displayLabel = true, schema, name, uiSchema, required, disabled = false, readonly = false, onBlur, onFocus, registry, fieldPathId, onChange, errorSchema, } = props;
const { translateString, fields, globalFormOptions } = registry;
const [type, setType] = useState(getTypeOfFormData(formData));
const uiOptions = getUiOptions(uiSchema);
const typeSelectorInnerFieldPathId = useDeepCompareMemo(toFieldPathId('__internal_type_selector', globalFormOptions, fieldPathId));
const schemaTitle = translateString(TranslatableString.Type);
const typesOptionSchema = useMemo(() => getFallbackTypeSelectionSchema(schemaTitle), [schemaTitle]);
const onTypeChange = (newType) => {
if (newType != null) {
setType(newType);
onChange(castToNewType(formData, newType), fieldPathId.path, errorSchema, id);
}
};
if (!globalFormOptions.useFallbackUiForUnsupportedType) {
const { reason = translateString(TranslatableString.UnknownFieldType, [String(schema.type)]) } = props;
const UnsupportedFieldTemplate = getTemplate('UnsupportedFieldTemplate', registry, uiOptions);
return _jsx(UnsupportedFieldTemplate, { schema: schema, fieldPathId: fieldPathId, reason: reason, registry: registry });
}
const FallbackFieldTemplate = getTemplate('FallbackFieldTemplate', registry, uiOptions);
const { SchemaField } = fields;
return (_jsx(FallbackFieldTemplate, { schema: schema, registry: registry, typeSelector: _jsx(SchemaField, { fieldPathId: typeSelectorInnerFieldPathId, name: `${name}__fallback_type`, schema: typesOptionSchema, formData: type, onChange: onTypeChange, onBlur: onBlur, onFocus: onFocus, registry: registry, hideLabel: !displayLabel, disabled: disabled, readonly: readonly, required: required }, formData ? hashObject(formData) : '__empty__'), schemaField: _jsx(SchemaField, { ...props, schema: {
type,
title: translateString(TranslatableString.Value),
...(type === 'object' && { additionalProperties: true }),
} }) }));
}