diff --git a/demo/src/samples/widgets.tsx b/demo/src/samples/widgets.tsx
index a93b236..2f1475c 100644
--- a/demo/src/samples/widgets.tsx
+++ b/demo/src/samples/widgets.tsx
@@ -1,4 +1,4 @@
-import { Sample } from './Sample';
+import { Sample } from './Sample'
const widgets: Sample = {
schema: {
@@ -146,19 +146,19 @@ const widgets: Sample = {
onChange,
options,
}: {
- value: any;
- onChange: (value: any) => void;
- options: { backgroundColor: string };
+ value: any
+ onChange: (value: any) => void
+ options: { backgroundColor: string }
}) => {
- const { backgroundColor } = options;
+ const { backgroundColor } = options
return (
onChange(event.target.value)}
style={{ backgroundColor }}
value={value}
/>
- );
+ )
},
'ui:options': {
backgroundColor: 'yellow',
@@ -170,14 +170,17 @@ const widgets: Sample = {
onChange,
options,
}: {
- value: any;
- onChange: (value: any) => void;
- options: { enumOptions: { label: string; value: any }[]; backgroundColor: string };
+ value: any
+ onChange: (value: any) => void
+ options: {
+ enumOptions: { label: string; value: any }[]
+ backgroundColor: string
+ }
}) => {
- const { enumOptions, backgroundColor } = options;
+ const { enumOptions, backgroundColor } = options
return (
- );
+ )
},
'ui:options': {
backgroundColor: 'pink',
@@ -213,6 +216,6 @@ const widgets: Sample = {
},
secret: "I'm a hidden string.",
},
-};
+}
-export default widgets;
+export default widgets
diff --git a/src/components/TemplateArrayField.tsx b/src/components/TemplateArrayField.tsx
index 0f87208..98a91b8 100644
--- a/src/components/TemplateArrayField.tsx
+++ b/src/components/TemplateArrayField.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, { useState } from 'react'
import { FrIconClassName, RiIconClassName } from '@codegouvfr/react-dsfr'
import Button from '@codegouvfr/react-dsfr/Button'
import Tabs from '@codegouvfr/react-dsfr/Tabs'
@@ -30,59 +30,69 @@ export default function ({
items,
canAdd,
onAddClick,
+ registry,
}: ArrayFieldTemplateProps & { uiSchema?: UiSchemaDSFR }) {
+ const [selectedTabId, setSelectedTabId] = useState('tab0')
const tabLabel = uiSchema?.['ui:tabLabel'] ?? 'Element'
const removeIcon = uiSchema?.['ui:removeIcon'] ?? 'fr-icon-delete-line'
const addIcon = uiSchema?.['ui:addIcon'] ?? 'fr-icon-add-circle-line'
- console.log('items', items)
+
+ // ensure no exception when last selected tab has been destroyed
+ const selectedIndex = Math.min(
+ items.length - 1,
+ parseInt(selectedTabId.replace(/^tab(\d+)$/, '$1')),
+ )
+
+ const tabContent =
+ (items.length && (
+ <>
+
+ {items[selectedIndex].children}
+ >
+ )) ||
+ null
+
+ const onTabChange = (id: string) => {
+ if (id === 'add') {
+ onAddClick()
+ setSelectedTabId(`tab${items.length}`)
+ return
+ }
+ setSelectedTabId(id)
+ }
+
return (
({
label: `${tabLabel} ${element.index + 1}`,
- content: (
- <>
-
- {element.children}
- >
- ),
+ tabId: `tab${element.index}`,
}))
.concat([
{
label: `Ajouter`,
- content: (
- <>
- {canAdd && (
-
- )}
- >
- ),
+ tabId: 'add',
},
])}
- />
+ >
+ {selectedTabId !== 'add' && tabContent}
+
diff --git a/src/components/WidgetCheckBoxes.tsx b/src/components/WidgetCheckBoxes.tsx
new file mode 100644
index 0000000..9f9b919
--- /dev/null
+++ b/src/components/WidgetCheckBoxes.tsx
@@ -0,0 +1,108 @@
+import {
+ enumOptionsDeselectValue,
+ enumOptionsIsSelected,
+ enumOptionsSelectValue,
+ enumOptionsValueForIndex,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+} from '@rjsf/utils'
+import Checkbox from '@codegouvfr/react-dsfr/Checkbox'
+import LabelWithHelp from './LabelWithHelp'
+import { ChangeEvent, FocusEvent } from 'react'
+
+
+export default function CheckboxesWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any,
+>({
+ id,
+ disabled,
+ options,
+ value,
+ autofocus,
+ uiSchema,
+ schema,
+ readonly,
+ required,
+ onChange,
+ onBlur,
+ onFocus,
+}: WidgetProps) {
+ const { enumOptions, enumDisabled, inline, emptyValue } = options
+ const checkboxesValues = Array.isArray(value) ? value : [value]
+
+ const _onChange =
+ (index: number) =>
+ ({ target: { checked } }: ChangeEvent) => {
+ if (checked) {
+ onChange(
+ enumOptionsSelectValue(index, checkboxesValues, enumOptions),
+ )
+ } else {
+ onChange(
+ enumOptionsDeselectValue(index, checkboxesValues, enumOptions),
+ )
+ }
+ }
+
+ const _onBlur = ({ target }: FocusEvent) =>
+ onBlur(
+ id,
+ enumOptionsValueForIndex(
+ target && target.value,
+ enumOptions,
+ emptyValue,
+ ),
+ )
+ const _onFocus = ({ target }: FocusEvent) =>
+ onFocus(
+ id,
+ enumOptionsValueForIndex(
+ target && target.value,
+ enumOptions,
+ emptyValue,
+ ),
+ )
+
+ return (
+
+ {
+ const checked = enumOptionsIsSelected(
+ option.value,
+ checkboxesValues,
+ )
+ const itemDisabled =
+ Array.isArray(enumDisabled) &&
+ enumDisabled.indexOf(option.value) !== -1
+
+ return {
+ label: (
+
+ {option.label + (required ? '*' : '')}
+
+ ),
+ nativeInputProps: {
+ checked,
+ disabled: itemDisabled,
+ onChange: _onChange(index),
+ onBlur: _onBlur,
+ onFocus: _onFocus,
+ },
+ }
+ })) ||
+ []
+ }
+ />
+
+ )
+}
diff --git a/src/components/WidgetRadio.tsx b/src/components/WidgetRadio.tsx
index 0e4bc4d..2c4580f 100644
--- a/src/components/WidgetRadio.tsx
+++ b/src/components/WidgetRadio.tsx
@@ -1,5 +1,6 @@
import { ChangeEvent, FocusEvent } from 'react'
import {
+ enumOptionsIsSelected,
enumOptionsValueForIndex,
FormContextType,
RJSFSchema,
@@ -37,28 +38,41 @@ export default function RadioWidget<
const _onFocus = ({ target: { value } }: FocusEvent) =>
onFocus(id, enumOptionsValueForIndex(value, enumOptions, emptyValue))
+ const radioValues = Array.isArray(value) ? value : [value]
const inline = Boolean(options && options.inline)
-
return (
({
- label: (
-
- {option.label}
-
- ),
- nativeInputProps: {
- checked: value === option.value,
- onChange: (e) => onChange(option.value),
- },
- }))) ||
+ options.enumOptions?.map((option) => {
+ const checked = enumOptionsIsSelected(
+ option.value,
+ radioValues,
+ )
+ const itemDisabled =
+ Array.isArray(enumDisabled) &&
+ enumDisabled.indexOf(option.value) !== -1
+
+ return {
+ label: (
+
+ {option.label}
+
+ ),
+ nativeInputProps: {
+ checked,
+ disabled: itemDisabled,
+ onChange: (e) => onChange(option.value),
+ value: option.value,
+ },
+ }
+ })) ||
[]
}
/>
diff --git a/src/components/WidgetSelect.tsx b/src/components/WidgetSelect.tsx
index 8833675..51b67a1 100644
--- a/src/components/WidgetSelect.tsx
+++ b/src/components/WidgetSelect.tsx
@@ -23,6 +23,7 @@ export default function <
hideError,
hideLabel,
uiSchema,
+ multiple,
...props
}: WidgetProps) {
const { enumOptions, emptyValue: optEmptyVal } = props.options
@@ -58,7 +59,7 @@ export default function <
const uiOptions = getUiOptions(uiSchema)
const backgroundColor = (uiOptions.backgroundColor as string) || 'auto'
-
+ const placeholder = uiOptions.placeholder || props.options.placeholder
return (