diff --git a/CHANGELOG.md b/CHANGELOG.md index 428e9c6809..cc42d5852c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,12 +16,36 @@ should change the heading of the (upcoming) version to include a major version b --> -# 5.19.2 +# 5.19.3 + +## @rjsf/antd + +- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197) + +## @rjsf/chakra-ui + +- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197) ## @rjsf/core - Removed `.only` on tests that was accidentally added in `5.19.0` +## @rjsf/fluentui-rc + +- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197) + +## @rjsf/material-ui + +- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197) + +## @rjsf/mui + +- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197) + +## @rjsf/semantic-ui + +- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197) + # 5.19.1 ## Dev / docs / playground @@ -92,6 +116,7 @@ should change the heading of the (upcoming) version to include a major version b - Fix case where NumberField would not properly reset the field when using programmatic form reset (#4202)[https://github.com/rjsf-team/react-jsonschema-form/issues/4202] - Updated widgets to handle undefined `target` in `onFocus` and `onBlur` handlers - Fix field disable or readonly property can't cover globalOptions corresponding property (#4212)[https://github.com/rjsf-team/react-jsonschema-form/pull/4212] +- Added support for `default` values in `additionalProperties` in [#4199](https://github.com/rjsf-team/react-jsonschema-form/issues/4199), fixing [#3195](https://github.com/rjsf-team/react-jsonschema-form/issues/3915) ## @rjsf/fluent-ui diff --git a/packages/antd/src/widgets/SelectWidget/index.tsx b/packages/antd/src/widgets/SelectWidget/index.tsx index 2f6937b773..645e0ebb4e 100644 --- a/packages/antd/src/widgets/SelectWidget/index.tsx +++ b/packages/antd/src/widgets/SelectWidget/index.tsx @@ -10,6 +10,8 @@ import { WidgetProps, } from '@rjsf/utils'; import isString from 'lodash/isString'; +import { DefaultOptionType } from 'antd/es/select'; +import { useMemo } from 'react'; const SELECT_STYLE = { width: '100%', @@ -37,6 +39,7 @@ export default function SelectWidget< placeholder, readonly, value, + schema, }: WidgetProps) { const { readonlyAsDisabled = true } = formContext as GenericObjectType; @@ -65,6 +68,26 @@ export default function SelectWidget< const extraProps = { name: id, }; + + const showPlaceholderOption = !multiple && schema.default === undefined; + + const selectOptions: DefaultOptionType[] | undefined = useMemo(() => { + if (Array.isArray(enumOptions)) { + const options: DefaultOptionType[] = enumOptions.map(({ value: optionValue, label: optionLabel }, index) => ({ + disabled: Array.isArray(enumDisabled) && enumDisabled.indexOf(optionValue) !== -1, + key: String(index), + value: String(index), + label: optionLabel, + })); + + if (showPlaceholderOption) { + options.unshift({ value: '', label: placeholder || '' }); + } + return options; + } + return undefined; + }, [enumDisabled, enumOptions, placeholder, showPlaceholderOption]); + return ( (id)} > - {!multiple && schema.default === undefined && } + {showPlaceholderOption && } {Array.isArray(enumOptions) && enumOptions.map(({ value, label }, i) => { const disabled = enumDisabled && enumDisabled.indexOf(value) !== -1; diff --git a/packages/fluentui-rc/src/SelectWidget/SelectWidget.tsx b/packages/fluentui-rc/src/SelectWidget/SelectWidget.tsx index 52f6b313a8..b0f88acd51 100644 --- a/packages/fluentui-rc/src/SelectWidget/SelectWidget.tsx +++ b/packages/fluentui-rc/src/SelectWidget/SelectWidget.tsx @@ -38,6 +38,8 @@ function SelectWidget) { const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options; @@ -60,6 +62,7 @@ function SelectWidget(newValue, enumOptions, optEmptyVal)); }; + const showPlaceholderOption = !multiple && schema.default === undefined; return ( (id)} > + {showPlaceholderOption && } {Array.isArray(enumOptions) && enumOptions.map(({ value, label }, i) => { const disabled = enumDisabled && enumDisabled.indexOf(value) !== -1; diff --git a/packages/material-ui/src/SelectWidget/SelectWidget.tsx b/packages/material-ui/src/SelectWidget/SelectWidget.tsx index 8abdb1618d..a053b374bb 100644 --- a/packages/material-ui/src/SelectWidget/SelectWidget.tsx +++ b/packages/material-ui/src/SelectWidget/SelectWidget.tsx @@ -59,6 +59,7 @@ export default function SelectWidget< const _onFocus = ({ target }: FocusEvent) => onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, optEmptyVal)); const selectedIndexes = enumOptionsIndexForValue(value, enumOptions, multiple); + const showPlaceholderOption = !multiple && schema.default === undefined; return ( (id)} > + {showPlaceholderOption && {placeholder}} {Array.isArray(enumOptions) && enumOptions.map(({ value, label }, i: number) => { const disabled: boolean = Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1; diff --git a/packages/mui/src/SelectWidget/SelectWidget.tsx b/packages/mui/src/SelectWidget/SelectWidget.tsx index 7b967edc0a..49fe9fe7a9 100644 --- a/packages/mui/src/SelectWidget/SelectWidget.tsx +++ b/packages/mui/src/SelectWidget/SelectWidget.tsx @@ -61,6 +61,7 @@ export default function SelectWidget< onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, optEmptyVal)); const selectedIndexes = enumOptionsIndexForValue(value, enumOptions, multiple); const { InputLabelProps, SelectProps, autocomplete, ...textFieldRemainingProps } = textFieldProps; + const showPlaceholderOption = !multiple && schema.default === undefined; return ( (id)} > + {showPlaceholderOption && {placeholder}} {Array.isArray(enumOptions) && enumOptions.map(({ value, label }, i: number) => { const disabled: boolean = Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1; diff --git a/packages/semantic-ui/src/SelectWidget/SelectWidget.tsx b/packages/semantic-ui/src/SelectWidget/SelectWidget.tsx index a21d7f7ace..3b8e1a886a 100644 --- a/packages/semantic-ui/src/SelectWidget/SelectWidget.tsx +++ b/packages/semantic-ui/src/SelectWidget/SelectWidget.tsx @@ -12,26 +12,33 @@ import { UIOptionsType, } from '@rjsf/utils'; import map from 'lodash/map'; -import { Form, DropdownProps } from 'semantic-ui-react'; +import { Form, DropdownProps, DropdownItemProps } from 'semantic-ui-react'; import { getSemanticProps } from '../util'; /** * Returns and creates an array format required for semantic drop down - * @param {array} enumOptions- array of items for the dropdown + * @param {array} enumOptions - array of items for the dropdown * @param {array} enumDisabled - array of enum option values to disable + * @param {boolean} showPlaceholderOption - whether to show a placeholder option + * @param {string} placeholder - placeholder option label * @returns {*} */ function createDefaultValueOptionsForDropDown( enumOptions?: EnumOptionsType[], - enumDisabled?: UIOptionsType['enumDisabled'] + enumDisabled?: UIOptionsType['enumDisabled'], + showPlaceholderOption?: boolean, + placeholder?: string ) { const disabledOptions = enumDisabled || []; - const options = map(enumOptions, ({ label, value }, index) => ({ + const options: DropdownItemProps[] = map(enumOptions, ({ label, value }, index) => ({ disabled: disabledOptions.indexOf(value) !== -1, key: label, text: label, value: String(index), })); + if (showPlaceholderOption) { + options.unshift({ value: '', text: placeholder || '' }); + } return options; } @@ -61,6 +68,7 @@ export default function SelectWidget({ uiSchema, @@ -76,7 +84,13 @@ export default function SelectWidget(enumOptions, enumDisabled); + const showPlaceholderOption = !multiple && schema.default === undefined; + const dropdownOptions = createDefaultValueOptionsForDropDown( + enumOptions, + enumDisabled, + showPlaceholderOption, + placeholder + ); const _onChange = (_: SyntheticEvent, { value }: DropdownProps) => onChange(enumOptionsValueForIndex(value as string[], enumOptions, optEmptyVal)); // eslint-disable-next-line no-shadow diff --git a/packages/semantic-ui/test/__snapshots__/Form.test.tsx.snap b/packages/semantic-ui/test/__snapshots__/Form.test.tsx.snap index 8148c90382..8f199c68a8 100644 --- a/packages/semantic-ui/test/__snapshots__/Form.test.tsx.snap +++ b/packages/semantic-ui/test/__snapshots__/Form.test.tsx.snap @@ -73,11 +73,27 @@ exports[`semantic-ui specific tests field with special semantic options 1`] = `
+
+ +
+
+ +
+
+ +
+
+ +