@datalayer/primer-rjsf
Version:
React JSON Schema Form (RJSF) for Primer
46 lines (45 loc) • 3.73 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { TriangleDownIcon } from "@primer/octicons-react";
import { Button, FormControl, Select, SelectPanel } from "@primer/react";
import { ariaDescribedByIds, enumOptionsIndexForValue, enumOptionsValueForIndex, } from "@rjsf/utils";
import { useState } from "react";
/** 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({ schema, id, options, label, required, disabled, placeholder, readonly, value, multiple, autofocus, onChange, onBlur, onFocus, rawErrors = [], registry, uiSchema, hideError, formContext, ...selectFieldProps }) {
const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options;
const [open, setOpen] = useState(false);
multiple = typeof multiple === "undefined" ? false : !!multiple;
const emptyValue = multiple ? [] : "";
const isEmpty = typeof value === "undefined" ||
(multiple && value.length < 1) ||
(!multiple && value === emptyValue);
const items = enumOptions?.map(({ value, label }, i) => {
const disabled = Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1;
return {
text: label,
id: i,
disabled,
};
});
const _onChange = ({ target: { value }, }) => onChange(enumOptionsValueForIndex(value, enumOptions, optEmptyVal));
const _onBlur = ({ target: { value }, }) => onBlur(id, enumOptionsValueForIndex(value, enumOptions, optEmptyVal));
const _onFocus = ({ target: { value }, }) => onFocus(id, enumOptionsValueForIndex(value, enumOptions, optEmptyVal));
const selectedIndexes = enumOptionsIndexForValue(value, enumOptions, multiple);
return (_jsxs(FormControl, { id: id, required: required, children: [_jsx(FormControl.Label, { visuallyHidden: !(label || schema.title), htmlFor: id, children: label || schema.title }), (multiple && Array.isArray(enumOptions)) ? _jsx(SelectPanel, { placeholderText: (label || schema.title) ?? "", renderAnchor: ({ children, 'aria-labelledby': ariaLabelledBy, ...anchorProps }) => (_jsx(Button, { trailingAction: TriangleDownIcon, "aria-labelledby": ` ${ariaLabelledBy}`, ...anchorProps, onClick: (e) => {
setOpen(!open);
e.preventDefault();
}, children: children || `Select ${label || schema.title}` })), open: open, onOpenChange: setOpen, items: items ?? [], selected: (items ?? []).filter((val, i) => {
return selectedIndexes?.includes(String(i));
}), onSelectedChange: (selected) => {
onChange(enumOptionsValueForIndex(selected.map((v) => v.id), enumOptions, optEmptyVal));
}, onFilterChange: () => null,
// showDividers
overlayProps: { width: 'small' } }) : _jsx(Select, { name: id, value: isEmpty ? emptyValue : selectedIndexes, disabled: disabled || readonly, autoFocus: autofocus, placeholder: label || schema.title, validationStatus: rawErrors.length > 0 ? "error" : undefined, onChange: _onChange, onBlur: _onBlur, onFocus: _onFocus, defaultValue: undefined, ...selectFieldProps, "aria-describedby": ariaDescribedByIds(id), children: Array.isArray(enumOptions) &&
enumOptions.map(({ value, label }, i) => {
const disabled = Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1;
return (_jsx(Select.Option, { value: String(i), disabled: disabled, children: label }, i));
}) })] }));
}