Skip to content

Commit 218c5bf

Browse files
committed
feat: add WidgetCheckBoxes
1 parent 30cc2fe commit 218c5bf

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import {
2+
enumOptionsDeselectValue,
3+
enumOptionsIsSelected,
4+
enumOptionsSelectValue,
5+
enumOptionsValueForIndex,
6+
FormContextType,
7+
RJSFSchema,
8+
StrictRJSFSchema,
9+
WidgetProps,
10+
} from '@rjsf/utils'
11+
import Checkbox from '@codegouvfr/react-dsfr/Checkbox'
12+
import LabelWithHelp from './LabelWithHelp'
13+
import { ChangeEvent, FocusEvent } from 'react'
14+
15+
//export default function (props: WidgetProps) {
16+
17+
export default function CheckboxesWidget<
18+
T = any,
19+
S extends StrictRJSFSchema = RJSFSchema,
20+
F extends FormContextType = any,
21+
>({
22+
id,
23+
disabled,
24+
options,
25+
value,
26+
autofocus,
27+
uiSchema,
28+
schema,
29+
readonly,
30+
required,
31+
onChange,
32+
onBlur,
33+
onFocus,
34+
}: WidgetProps<T, S, F>) {
35+
const { enumOptions, enumDisabled, inline, emptyValue } = options
36+
const checkboxesValues = Array.isArray(value) ? value : [value]
37+
38+
const _onChange =
39+
(index: number) =>
40+
({ target: { checked } }: ChangeEvent<HTMLInputElement>) => {
41+
if (checked) {
42+
onChange(
43+
enumOptionsSelectValue<S>(index, checkboxesValues, enumOptions),
44+
)
45+
} else {
46+
onChange(
47+
enumOptionsDeselectValue<S>(index, checkboxesValues, enumOptions),
48+
)
49+
}
50+
}
51+
52+
const _onBlur = ({ target }: FocusEvent<HTMLInputElement>) =>
53+
onBlur(
54+
id,
55+
enumOptionsValueForIndex<S>(
56+
target && target.value,
57+
enumOptions,
58+
emptyValue,
59+
),
60+
)
61+
const _onFocus = ({ target }: FocusEvent<HTMLInputElement>) =>
62+
onFocus(
63+
id,
64+
enumOptionsValueForIndex<S>(
65+
target && target.value,
66+
enumOptions,
67+
emptyValue,
68+
),
69+
)
70+
71+
return (
72+
<div style={{ marginTop: '1rem', marginBottom: '-1rem' }}>
73+
<Checkbox
74+
options={
75+
(Array.isArray(enumOptions) &&
76+
enumOptions.map((option, index: number) => {
77+
const checked = enumOptionsIsSelected<S>(
78+
option.value,
79+
checkboxesValues,
80+
)
81+
const itemDisabled =
82+
Array.isArray(enumDisabled) &&
83+
enumDisabled.indexOf(option.value) !== -1
84+
85+
return {
86+
label: (
87+
<LabelWithHelp
88+
helpText={
89+
uiSchema !== undefined ? uiSchema['ui:help'] : undefined
90+
}
91+
>
92+
{option.label + (required ? '*' : '')}
93+
</LabelWithHelp>
94+
),
95+
nativeInputProps: {
96+
checked,
97+
disabled: itemDisabled,
98+
onChange: _onChange(index),
99+
onBlur: _onBlur,
100+
onFocus: _onFocus,
101+
},
102+
}
103+
})) ||
104+
[]
105+
}
106+
/>
107+
</div>
108+
)
109+
}

src/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import defaultValidator from '@rjsf/validator-ajv8'
1111
import { Button } from '@codegouvfr/react-dsfr/Button'
1212

1313
import WidgetCheckBox from './components/WidgetCheckBox'
14+
import WidgetCheckBoxes from './components/WidgetCheckBoxes'
1415
import WidgetRadio from './components/WidgetRadio'
1516
import WidgetSelect from './components/WidgetSelect'
1617
import WidgetTextarea from './components/WidgetTextarea'
@@ -89,13 +90,16 @@ export default function FormDSFR<
8990
)
9091
}
9192

93+
// https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-widgets-fields
9294
export const widgetsDSFR = {
9395
CheckboxWidget: WidgetCheckBox,
96+
CheckboxesWidget: WidgetCheckBoxes,
9497
RadioWidget: WidgetRadio,
9598
SelectWidget: WidgetSelect,
9699
TextareaWidget: WidgetTextarea,
97100
}
98101

102+
// https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-templates
99103
export const templatesDSFR = {
100104
ArrayFieldTemplate: TemplateArrayField,
101105
BaseInputTemplate: TemplateBaseInput,

0 commit comments

Comments
 (0)