Skip to content

Commit e54a620

Browse files
committed
fix #4197 for antd, chakra-ui, fluentui-rc, material-ui, mui, semantic-ui
1 parent eec280a commit e54a620

File tree

9 files changed

+165
-32
lines changed

9 files changed

+165
-32
lines changed

CHANGELOG.md

+30
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,36 @@ should change the heading of the (upcoming) version to include a major version b
1616
1717
-->
1818

19+
# 5.18.5
20+
21+
## @rjsf/antd
22+
23+
- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197)
24+
25+
## @rjsf/chakra-ui
26+
27+
- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197)
28+
29+
## @rjsf/core
30+
31+
- 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)
32+
33+
## @rjsf/fluentui-rc
34+
35+
- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197)
36+
37+
## @rjsf/material-ui
38+
39+
- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197)
40+
41+
## @rjsf/mui
42+
43+
- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197)
44+
45+
## @rjsf/semantic-ui
46+
47+
- SelectWidget now displays an empty option when appropriate, fixing [#4197](https://github.com/rjsf-team/react-jsonschema-form/issues/4197)
48+
1949
# 5.18.4
2050

2151
## Dev / docs / playground

packages/antd/src/widgets/SelectWidget/index.tsx

+21-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
WidgetProps,
1111
} from '@rjsf/utils';
1212
import isString from 'lodash/isString';
13+
import { DefaultOptionType } from 'antd/es/select';
14+
import { useMemo } from 'react';
1315

1416
const SELECT_STYLE = {
1517
width: '100%',
@@ -37,6 +39,7 @@ export default function SelectWidget<
3739
placeholder,
3840
readonly,
3941
value,
42+
schema,
4043
}: WidgetProps<T, S, F>) {
4144
const { readonlyAsDisabled = true } = formContext as GenericObjectType;
4245

@@ -65,6 +68,23 @@ export default function SelectWidget<
6568
const extraProps = {
6669
name: id,
6770
};
71+
72+
const selectOptions: DefaultOptionType[] | undefined = useMemo(() => {
73+
if (Array.isArray(enumOptions)) {
74+
if (!multiple && schema.default === undefined) {
75+
enumOptions.unshift({ value: '', label: placeholder || '' });
76+
}
77+
78+
return enumOptions.map(({ value: optionValue, label: optionLabel }, index) => ({
79+
disabled: Array.isArray(enumDisabled) && enumDisabled.indexOf(optionValue) !== -1,
80+
key: String(index),
81+
value: String(index),
82+
label: optionLabel,
83+
}));
84+
}
85+
return undefined;
86+
}, [enumDisabled, enumOptions, multiple, placeholder, schema.default]);
87+
6888
return (
6989
<Select
7090
autoFocus={autofocus}
@@ -81,16 +101,7 @@ export default function SelectWidget<
81101
{...extraProps}
82102
filterOption={filterOption}
83103
aria-describedby={ariaDescribedByIds<T>(id)}
84-
options={
85-
Array.isArray(enumOptions)
86-
? enumOptions.map(({ value: optionValue, label: optionLabel }, index) => ({
87-
disabled: Array.isArray(enumDisabled) && enumDisabled.indexOf(optionValue) !== -1,
88-
key: String(index),
89-
value: String(index),
90-
label: optionLabel,
91-
}))
92-
: undefined
93-
}
104+
options={selectOptions}
94105
/>
95106
);
96107
}

packages/antd/test/__snapshots__/Form.test.tsx.snap

+2-2
Original file line numberDiff line numberDiff line change
@@ -3354,9 +3354,9 @@ exports[`single fields select field single choice formData 1`] = `
33543354
</span>
33553355
<span
33563356
className="ant-select-selection-item"
3357-
title="bar"
3357+
title="foo"
33583358
>
3359-
bar
3359+
foo
33603360
</span>
33613361
</div>
33623362
<span

packages/chakra-ui/src/SelectWidget/SelectWidget.tsx

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FocusEvent } from 'react';
1+
import { FocusEvent, useMemo } from 'react';
22
import { FormControl, FormLabel } from '@chakra-ui/react';
33
import {
44
ariaDescribedByIds,
@@ -34,6 +34,7 @@ export default function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFS
3434
onFocus,
3535
rawErrors = [],
3636
uiSchema,
37+
schema,
3738
} = props;
3839
const { enumOptions, enumDisabled, emptyValue } = options;
3940
const chakraProps = getChakra({ uiSchema });
@@ -61,17 +62,23 @@ export default function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFS
6162
onFocus(id, enumOptionsValueForIndex<S>(value, enumOptions, emptyValue));
6263

6364
const _valueLabelMap: any = {};
64-
const displayEnumOptions: OptionsOrGroups<any, any> = Array.isArray(enumOptions)
65-
? enumOptions.map((option: EnumOptionsType<S>, index: number) => {
65+
const displayEnumOptions: OptionsOrGroups<any, any> = useMemo(() => {
66+
if (Array.isArray(enumOptions)) {
67+
if (!multiple && schema.default === undefined) {
68+
enumOptions.unshift({ value: '', label: placeholder || '' });
69+
}
70+
return enumOptions.map((option: EnumOptionsType<S>, index: number) => {
6671
const { value, label } = option;
6772
_valueLabelMap[index] = label || String(value);
6873
return {
6974
label,
7075
value: String(index),
7176
isDisabled: Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1,
7277
};
73-
})
74-
: [];
78+
});
79+
}
80+
return [];
81+
}, [_valueLabelMap, enumDisabled, enumOptions, multiple, placeholder, schema.default]);
7582

7683
const isMultiple = typeof multiple !== 'undefined' && multiple !== false && Boolean(enumOptions);
7784
const selectedIndex = enumOptionsIndexForValue<S>(value, enumOptions, isMultiple);

packages/fluentui-rc/src/SelectWidget/SelectWidget.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extend
3838
onChange,
3939
onBlur,
4040
onFocus,
41+
schema,
42+
placeholder,
4143
}: WidgetProps<T, S, F>) {
4244
const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options;
4345

@@ -81,6 +83,7 @@ function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extend
8183
selectedOptions={selectedIndexesAsArray}
8284
aria-describedby={ariaDescribedByIds<T>(id)}
8385
>
86+
{!multiple && schema.default === undefined && <Option value=''>{placeholder || ''}</Option>}
8487
{Array.isArray(enumOptions) &&
8588
enumOptions.map(({ value, label }, i) => {
8689
const disabled = enumDisabled && enumDisabled.indexOf(value) !== -1;

packages/material-ui/src/SelectWidget/SelectWidget.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export default function SelectWidget<
8686
}}
8787
aria-describedby={ariaDescribedByIds<T>(id)}
8888
>
89+
{!multiple && schema.default === undefined && <MenuItem value=''>{placeholder || ''}</MenuItem>}
8990
{Array.isArray(enumOptions) &&
9091
enumOptions.map(({ value, label }, i: number) => {
9192
const disabled: boolean = Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1;

packages/mui/src/SelectWidget/SelectWidget.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export default function SelectWidget<
8989
}}
9090
aria-describedby={ariaDescribedByIds<T>(id)}
9191
>
92+
{!multiple && schema.default === undefined && <MenuItem value=''>{placeholder || ''}</MenuItem>}
9293
{Array.isArray(enumOptions) &&
9394
enumOptions.map(({ value, label }, i: number) => {
9495
const disabled: boolean = Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1;

packages/semantic-ui/src/SelectWidget/SelectWidget.tsx

+25-9
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
UIOptionsType,
1313
} from '@rjsf/utils';
1414
import map from 'lodash/map';
15-
import { Form, DropdownProps } from 'semantic-ui-react';
15+
import { Form, DropdownProps, DropdownItemProps } from 'semantic-ui-react';
1616
import { getSemanticProps } from '../util';
1717

1818
/**
@@ -22,16 +22,25 @@ import { getSemanticProps } from '../util';
2222
* @returns {*}
2323
*/
2424
function createDefaultValueOptionsForDropDown<S extends StrictRJSFSchema = RJSFSchema>(
25+
schema: S,
2526
enumOptions?: EnumOptionsType<S>[],
26-
enumDisabled?: UIOptionsType['enumDisabled']
27+
enumDisabled?: UIOptionsType['enumDisabled'],
28+
multiple?: boolean,
29+
placeholder?: string
2730
) {
2831
const disabledOptions = enumDisabled || [];
29-
const options = map(enumOptions, ({ label, value }, index) => ({
30-
disabled: disabledOptions.indexOf(value) !== -1,
31-
key: label,
32-
text: label,
33-
value: String(index),
34-
}));
32+
const options: DropdownItemProps[] = [];
33+
if (!multiple && schema.default === undefined) {
34+
options.push({ value: '', text: placeholder || '' });
35+
}
36+
options.push(
37+
...map(enumOptions, ({ label, value }, index) => ({
38+
disabled: disabledOptions.indexOf(value) !== -1,
39+
key: label,
40+
text: label,
41+
value: String(index),
42+
}))
43+
);
3544
return options;
3645
}
3746

@@ -61,6 +70,7 @@ export default function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFS
6170
onBlur,
6271
onFocus,
6372
rawErrors = [],
73+
schema,
6474
} = props;
6575
const semanticProps = getSemanticProps<T, S, F>({
6676
uiSchema,
@@ -76,7 +86,13 @@ export default function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFS
7686
});
7787
const { enumDisabled, enumOptions, emptyValue: optEmptyVal } = options;
7888
const emptyValue = multiple ? [] : '';
79-
const dropdownOptions = createDefaultValueOptionsForDropDown<S>(enumOptions, enumDisabled);
89+
const dropdownOptions = createDefaultValueOptionsForDropDown<S>(
90+
schema,
91+
enumOptions,
92+
enumDisabled,
93+
multiple,
94+
placeholder
95+
);
8096
const _onChange = (_: SyntheticEvent<HTMLElement>, { value }: DropdownProps) =>
8197
onChange(enumOptionsValueForIndex<S>(value as string[], enumOptions, optEmptyVal));
8298
// eslint-disable-next-line no-shadow

packages/semantic-ui/test/__snapshots__/Form.test.tsx.snap

+70-6
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,27 @@ exports[`semantic-ui specific tests field with special semantic options 1`] = `
7373
<div
7474
className="menu transition"
7575
>
76+
<div
77+
aria-checked={true}
78+
aria-selected={true}
79+
className="active selected item"
80+
onClick={[Function]}
81+
role="option"
82+
style={
83+
{
84+
"pointerEvents": "all",
85+
}
86+
}
87+
>
88+
<span
89+
className="text"
90+
/>
91+
</div>
7692
<div
7793
aria-checked={false}
7894
aria-disabled={false}
79-
aria-selected={true}
80-
className="selected item"
95+
aria-selected={false}
96+
className="item"
8197
onClick={[Function]}
8298
role="option"
8399
style={
@@ -1278,11 +1294,27 @@ exports[`single fields select field 1`] = `
12781294
<div
12791295
className="menu transition"
12801296
>
1297+
<div
1298+
aria-checked={true}
1299+
aria-selected={true}
1300+
className="active selected item"
1301+
onClick={[Function]}
1302+
role="option"
1303+
style={
1304+
{
1305+
"pointerEvents": "all",
1306+
}
1307+
}
1308+
>
1309+
<span
1310+
className="text"
1311+
/>
1312+
</div>
12811313
<div
12821314
aria-checked={false}
12831315
aria-disabled={false}
1284-
aria-selected={true}
1285-
className="selected item"
1316+
aria-selected={false}
1317+
className="item"
12861318
onClick={[Function]}
12871319
role="option"
12881320
style={
@@ -1887,11 +1919,27 @@ exports[`single fields select field single choice enumDisabled 1`] = `
18871919
<div
18881920
className="menu transition"
18891921
>
1922+
<div
1923+
aria-checked={true}
1924+
aria-selected={true}
1925+
className="active selected item"
1926+
onClick={[Function]}
1927+
role="option"
1928+
style={
1929+
{
1930+
"pointerEvents": "all",
1931+
}
1932+
}
1933+
>
1934+
<span
1935+
className="text"
1936+
/>
1937+
</div>
18901938
<div
18911939
aria-checked={false}
18921940
aria-disabled={false}
1893-
aria-selected={true}
1894-
className="selected item"
1941+
aria-selected={false}
1942+
className="item"
18951943
onClick={[Function]}
18961944
role="option"
18971945
style={
@@ -1991,6 +2039,22 @@ exports[`single fields select field single choice formData 1`] = `
19912039
<div
19922040
className="menu transition"
19932041
>
2042+
<div
2043+
aria-checked={false}
2044+
aria-selected={false}
2045+
className="item"
2046+
onClick={[Function]}
2047+
role="option"
2048+
style={
2049+
{
2050+
"pointerEvents": "all",
2051+
}
2052+
}
2053+
>
2054+
<span
2055+
className="text"
2056+
/>
2057+
</div>
19942058
<div
19952059
aria-checked={false}
19962060
aria-disabled={false}

0 commit comments

Comments
 (0)