mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 12:37:20 +00:00
99 lines
3.4 KiB
TypeScript
99 lines
3.4 KiB
TypeScript
import {
|
|
type FormContextType,
|
|
type RJSFSchema,
|
|
type StrictRJSFSchema,
|
|
type WidgetProps,
|
|
ariaDescribedByIds,
|
|
enumOptionsDeselectValue,
|
|
enumOptionsIsSelected,
|
|
enumOptionsSelectValue,
|
|
enumOptionsValueForIndex,
|
|
optionId
|
|
} from "@rjsf/utils";
|
|
import { type ChangeEvent, type FocusEvent, useCallback } from "react";
|
|
|
|
/** The `CheckboxesWidget` is a widget for rendering checkbox groups.
|
|
* It is typically used to represent an array of enums.
|
|
*
|
|
* @param props - The `WidgetProps` for this component
|
|
*/
|
|
function CheckboxesWidget<
|
|
T = any,
|
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
F extends FormContextType = any
|
|
>({
|
|
id,
|
|
disabled,
|
|
options: { inline = false, enumOptions, enumDisabled, emptyValue },
|
|
value,
|
|
autofocus = false,
|
|
readonly,
|
|
onChange,
|
|
onBlur,
|
|
onFocus
|
|
}: WidgetProps<T, S, F>) {
|
|
const checkboxesValues = Array.isArray(value) ? value : [value];
|
|
|
|
const handleBlur = useCallback(
|
|
({ target }: FocusEvent<HTMLInputElement>) =>
|
|
onBlur(id, enumOptionsValueForIndex<S>(target?.value, enumOptions, emptyValue)),
|
|
[onBlur, id]
|
|
);
|
|
|
|
const handleFocus = useCallback(
|
|
({ target }: FocusEvent<HTMLInputElement>) =>
|
|
onFocus(id, enumOptionsValueForIndex<S>(target?.value, enumOptions, emptyValue)),
|
|
[onFocus, id]
|
|
);
|
|
return (
|
|
<div className="checkboxes" id={id}>
|
|
{Array.isArray(enumOptions) &&
|
|
enumOptions.map((option, index) => {
|
|
const checked = enumOptionsIsSelected<S>(option.value, checkboxesValues);
|
|
const itemDisabled =
|
|
Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) !== -1;
|
|
const disabledCls = disabled || itemDisabled || readonly ? "disabled" : "";
|
|
|
|
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
if (event.target.checked) {
|
|
onChange(enumOptionsSelectValue<S>(index, checkboxesValues, enumOptions));
|
|
} else {
|
|
onChange(enumOptionsDeselectValue<S>(index, checkboxesValues, enumOptions));
|
|
}
|
|
};
|
|
|
|
const checkbox = (
|
|
// biome-ignore lint/correctness/useJsxKeyInIterable: it's wrapped
|
|
<span>
|
|
<input
|
|
type="checkbox"
|
|
id={optionId(id, index)}
|
|
name={id}
|
|
checked={checked}
|
|
value={String(index)}
|
|
disabled={disabled || itemDisabled || readonly}
|
|
autoFocus={autofocus && index === 0}
|
|
onChange={handleChange}
|
|
onBlur={handleBlur}
|
|
onFocus={handleFocus}
|
|
aria-describedby={ariaDescribedByIds<T>(id)}
|
|
/>
|
|
<span>{option.label}</span>
|
|
</span>
|
|
);
|
|
return inline ? (
|
|
<label key={index} className={`checkbox-inline ${disabledCls}`}>
|
|
{checkbox}
|
|
</label>
|
|
) : (
|
|
<div key={index} className={`checkbox ${disabledCls}`}>
|
|
<label>{checkbox}</label>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default CheckboxesWidget;
|