UNPKG

@rjsf/utils

Version:
116 lines 4.55 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { createElement } from 'react'; import ReactIs from 'react-is'; import get from 'lodash-es/get.js'; import set from 'lodash-es/set.js'; import getSchemaType from './getSchemaType.js'; /** The map of schema types to widget type to widget name */ const widgetMap = { boolean: { checkbox: 'CheckboxWidget', radio: 'RadioWidget', select: 'SelectWidget', hidden: 'HiddenWidget', }, string: { text: 'TextWidget', password: 'PasswordWidget', email: 'EmailWidget', hostname: 'TextWidget', ipv4: 'TextWidget', ipv6: 'TextWidget', uri: 'URLWidget', 'data-url': 'FileWidget', radio: 'RadioWidget', select: 'SelectWidget', textarea: 'TextareaWidget', hidden: 'HiddenWidget', date: 'DateWidget', datetime: 'DateTimeWidget', 'date-time': 'DateTimeWidget', 'alt-date': 'AltDateWidget', 'alt-datetime': 'AltDateTimeWidget', time: 'TimeWidget', color: 'ColorWidget', file: 'FileWidget', }, number: { text: 'TextWidget', select: 'SelectWidget', updown: 'UpDownWidget', range: 'RangeWidget', radio: 'RadioWidget', hidden: 'HiddenWidget', }, integer: { text: 'TextWidget', select: 'SelectWidget', updown: 'UpDownWidget', range: 'RangeWidget', radio: 'RadioWidget', hidden: 'HiddenWidget', }, array: { select: 'SelectWidget', checkboxes: 'CheckboxesWidget', files: 'FileWidget', hidden: 'HiddenWidget', }, }; /** Wraps the given widget with stateless functional component that will merge any `defaultProps.options` with the * `options` that are provided in the props. It will add the wrapper component as a `MergedWidget` property onto the * `Widget` so that future attempts to wrap `AWidget` will return the already existing wrapper. * * @param AWidget - A widget that will be wrapped or one that is already wrapped * @returns - The wrapper widget */ function mergeWidgetOptions(AWidget) { let MergedWidget = get(AWidget, 'MergedWidget'); // cache return value as property of widget for proper react reconciliation if (!MergedWidget) { const defaultOptions = (AWidget.defaultProps && AWidget.defaultProps.options) || {}; MergedWidget = ({ options, ...props }) => { return _jsx(AWidget, { options: { ...defaultOptions, ...options }, ...props }); }; set(AWidget, 'MergedWidget', MergedWidget); } return MergedWidget; } /** Given a schema representing a field to render and either the name or actual `Widget` implementation, returns the * React component that is used to render the widget. If the `widget` is already a React component, then it is wrapped * with a `MergedWidget`. Otherwise an attempt is made to look up the widget inside of the `registeredWidgets` map based * on the schema type and `widget` name. If no widget component can be found an `Error` is thrown. * * @param schema - The schema for the field * @param [widget] - Either the name of the widget OR a `Widget` implementation to use * @param [registeredWidgets={}] - A registry of widget name to `Widget` implementation * @returns - The `Widget` component to use * @throws - An error if there is no `Widget` component that can be returned */ export default function getWidget(schema, widget, registeredWidgets = {}) { const type = getSchemaType(schema); if (typeof widget === 'function' || (widget && ReactIs.isForwardRef(createElement(widget))) || ReactIs.isMemo(widget)) { return mergeWidgetOptions(widget); } if (typeof widget !== 'string') { throw new Error(`Unsupported widget definition: ${typeof widget}`); } if (widget in registeredWidgets) { const registeredWidget = registeredWidgets[widget]; return getWidget(schema, registeredWidget, registeredWidgets); } if (typeof type === 'string') { if (!(type in widgetMap)) { throw new Error(`No widget for type '${type}'`); } if (widget in widgetMap[type]) { const registeredWidget = registeredWidgets[widgetMap[type][widget]]; return getWidget(schema, registeredWidget, registeredWidgets); } } throw new Error(`No widget '${widget}' for type '${type}'`); } //# sourceMappingURL=getWidget.js.map