UNPKG

@plone/volto

Version:
211 lines (186 loc) 5.61 kB
/** * Field component. * @module components/manage/Form/Field */ import React from 'react'; import PropTypes from 'prop-types'; import { injectIntl } from 'react-intl'; import config from '@plone/volto/registry'; const MODE_HIDDEN = 'hidden'; //hidden mode. If mode is hidden, field is not rendered /** * Get default widget * @method getViewDefault * @param {object} widgets Widgets config * @returns {string} Widget component. */ const getWidgetDefault = (widgets) => widgets.default; /** * Get widget by field's `id` attribute * @method getWidgetById * @param {object} widgets Widgets config * @param {string} id Id * @returns {string} Widget component. */ const getWidgetByFieldId = (widgets, id) => widgets.id[id] || null; /** * Get widget by factory attribute * @method getWidgetByFactory * @param {object} widgets Widgets config * @param {string} id Id * @returns {string} Widget component. */ const getWidgetByFactory = (widgets, factory) => widgets.factory?.[factory] || null; /** * Get widget by field's `widget` attribute * @method getWidgetByName * @param {object} widgets Widgets config * @param {string} widget Widget * @returns {string} Widget component. */ const getWidgetByName = (widgets, widget) => typeof widget === 'string' ? widgets.widget[widget] || getWidgetDefault(widgets) : null; /** * Get widget by tagged values * @param {object} widgetOptions * @param {object} widgets Widgets config * @returns {string} Widget component. * directives.widget( 'fieldname', frontendOptions={ "widget": 'specialwidget', "version": 'extra' }) */ const getWidgetFromTaggedValues = (widgets, widgetOptions) => typeof widgetOptions?.frontendOptions?.widget === 'string' ? widgets.widget[widgetOptions.frontendOptions.widget] : null; /** * Get widget props from tagged values * @param {object} widgets Widgets config * @param {object} widgetOptions * @returns {string} Widget component. * directives.widget( "fieldname", frontendOptions={ "widget": "specialwidget", "widgetProps": {"prop1": "specialprop"} }) */ const getWidgetPropsFromTaggedValues = (widgets, widgetOptions) => typeof widgetOptions?.frontendOptions?.widgetProps === 'object' ? widgetOptions.frontendOptions.widgetProps : null; /** * Get widget by field's `vocabulary` attribute * @method getWidgetByVocabulary * @param {object} widgets Widgets config * @param {string} vocabulary Widget * @returns {string} Widget component. */ const getWidgetByVocabulary = (widgets, vocabulary) => vocabulary && vocabulary['@id'] ? widgets.vocabulary[vocabulary['@id'].replace(/^.*\/@vocabularies\//, '')] : null; /** * Get widget by field's hints `vocabulary` attribute in widgetOptions * @method getWidgetByVocabularyFromHint * @param {object} widgets Widgets config * @param {string} props Widget props * @returns {string} Widget component. */ const getWidgetByVocabularyFromHint = (widgets, props) => props.widgetOptions && props.widgetOptions.vocabulary ? widgets.vocabulary[ props.widgetOptions.vocabulary['@id'].replace( /^.*\/@vocabularies\//, '', ) ] : null; /** * Get widget by field's `choices` attribute * @method getWidgetByChoices * @param {object} widgets Widgets config * @param {string} choices Widget * @returns {string} Widget component. */ const getWidgetByChoices = (widgets, props) => { if (props.choices) { return widgets.choices; } if (props.vocabulary) { // If vocabulary exists, then it means it's a choice field in disguise with // no widget specified that probably contains a string then we force it // to be a select widget instead return widgets.choices; } return null; }; /** * Get widget by field's `type` attribute * @method getWidgetByType * @param {object} widgets Widgets config * @param {string} type Type * @returns {string} Widget component. */ const getWidgetByType = (widgets, type) => widgets.type[type] || null; /** * Field component class. * @function Field * @param {Object} props Properties. * @returns {string} Markup of the component. */ const Field = (props, { intl }) => { const widgets = props.widgets || config.widgets; const Widget = getWidgetByFieldId(widgets, props.id) || getWidgetFromTaggedValues(widgets, props.widgetOptions) || getWidgetByName(widgets, props.widget) || getWidgetByChoices(widgets, props) || getWidgetByVocabulary(widgets, props.vocabulary) || getWidgetByVocabularyFromHint(widgets, props) || getWidgetByFactory(widgets, props.factory) || getWidgetByType(widgets, props.type) || getWidgetDefault(widgets); if (props.mode === MODE_HIDDEN) { return null; } // Adding the widget props from tagged values (if any) const widgetProps = { ...props, ...getWidgetPropsFromTaggedValues(widgets, props.widgetOptions), }; return <Widget {...widgetProps} />; }; /** * Property types. * @property {Object} propTypes Property types. * @static */ Field.propTypes = { widget: PropTypes.string, vocabulary: PropTypes.shape({ '@id': PropTypes.string }), choices: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)), type: PropTypes.string, id: PropTypes.string.isRequired, focus: PropTypes.bool, }; /** * Default properties. * @property {Object} defaultProps Default properties. * @static */ Field.defaultProps = { widget: null, vocabulary: null, choices: null, type: 'string', focus: false, }; export default injectIntl(Field);