@rjsf/antd
Version:
Ant Design theme, fields and widgets for react-jsonschema-form
62 lines • 3.99 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useMemo, useState } from 'react';
import { ariaDescribedByIds, enumOptionSelectedValue, enumOptionValueDecoder, enumOptionValueEncoder, getOptionValueFormat, } from '@rjsf/utils';
import { Select } from 'antd';
import isString from 'lodash-es/isString.js';
const SELECT_STYLE = {
width: '100%',
};
/** The `SelectWidget` is a widget for rendering dropdowns.
* It is typically used with string properties constrained with enum options.
*
* @param props - The `WidgetProps` for this component
*/
export default function SelectWidget({ autofocus, disabled, registry, id, htmlName, multiple, onBlur, onChange, onFocus, options, placeholder, readonly, value, schema, }) {
const [open, setOpen] = useState(false);
const { formContext } = registry;
const { readonlyAsDisabled = true } = formContext;
const { enumOptions, enumDisabled, emptyValue } = options;
const optionValueFormat = getOptionValueFormat(options);
const handleChange = (nextValue) => onChange(enumOptionValueDecoder(nextValue, enumOptions, optionValueFormat, emptyValue));
const handleBlur = () => onBlur(id, enumOptionValueDecoder(value, enumOptions, optionValueFormat, emptyValue));
const handleFocus = () => onFocus(id, enumOptionValueDecoder(value, enumOptions, optionValueFormat, emptyValue));
const filterOption = (input, option) => {
if (option && isString(option.label)) {
// labels are strings in this context
return option.label.toLowerCase().includes(input.toLowerCase());
}
return false;
};
const getPopupContainer = SelectWidget.getPopupContainerCallback();
const selectValue = enumOptionSelectedValue(value, enumOptions, !!multiple, optionValueFormat, emptyValue);
// Antd's typescript definitions do not contain the following props that are actually necessary and, if provided,
// they are used, so hacking them in via by spreading `extraProps` on the component to avoid typescript errors
const extraProps = {
name: htmlName || id,
};
const showPlaceholderOption = !multiple && schema.default === undefined;
const selectOptions = useMemo(() => {
if (Array.isArray(enumOptions)) {
const enumOptionsList = enumOptions.map(({ value: optionValue, label: optionLabel }, index) => ({
disabled: Array.isArray(enumDisabled) && enumDisabled.includes(optionValue),
key: String(index),
value: enumOptionValueEncoder(optionValue, index, optionValueFormat),
label: optionLabel,
}));
if (showPlaceholderOption) {
enumOptionsList.unshift({ value: '', label: placeholder || '' });
}
return enumOptionsList;
}
return undefined;
}, [enumDisabled, enumOptions, placeholder, showPlaceholderOption, optionValueFormat]);
return (_jsx(Select, { open: open, autoFocus: autofocus, disabled: disabled || (readonlyAsDisabled && readonly), getPopupContainer: getPopupContainer, id: id, mode: multiple ? 'multiple' : undefined, onBlur: !readonly ? handleBlur : undefined, onChange: !readonly ? handleChange : undefined, onFocus: !readonly ? handleFocus : undefined, placeholder: placeholder, style: SELECT_STYLE, value: selectValue, ...extraProps,
// When the open change is called, set the open state, needed so that the select opens properly in the playground
onOpenChange: setOpen, showSearch: { filterOption }, "aria-describedby": ariaDescribedByIds(id), options: selectOptions }));
}
/** Give the playground a place to hook into the `getPopupContainer` callback generation function so that it can be
* disabled while in the playground. Since the callback is a simple function, it can be returned by this static
* "generator" function.
*/
SelectWidget.getPopupContainerCallback = () => (node) => node.parentElement;
//# sourceMappingURL=index.js.map