UNPKG

@datalayer/primer-rjsf

Version:

React JSON Schema Form (RJSF) for Primer

46 lines (45 loc) 3.73 kB
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)); }) })] })); }