kelt-ui-kit-react 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/addressSearch/AddressSearch.d.ts +20 -0
- package/dist/addressSearch/AddressSearch.view.d.ts +1 -0
- package/dist/dataTable/DataTable.d.ts +1 -0
- package/dist/dataTable/dataTableRow/DataTableRow.d.ts +2 -1
- package/dist/form/Form.d.ts +3 -2
- package/dist/form/form.enum.d.ts +1 -0
- package/dist/form/form.interface.d.ts +15 -0
- package/dist/geocoding/GeocodingService.d.ts +13 -0
- package/dist/geocoding/geocoding.interface.d.ts +20 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2893 -2564
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/App.menu.tsx +8 -0
- package/src/addressSearch/AddressSearch.tsx +246 -0
- package/src/addressSearch/AddressSearch.view.tsx +52 -0
- package/src/addressSearch/addressSearch.css +133 -0
- package/src/dataTable/DataTable.tsx +114 -6
- package/src/dataTable/DataTable.view.tsx +1 -0
- package/src/dataTable/dataTable.css +48 -0
- package/src/dataTable/dataTableRow/DataTableRow.tsx +85 -81
- package/src/expands/expands.css +7 -2
- package/src/form/Form.tsx +166 -101
- package/src/form/form.css +46 -2
- package/src/form/form.enum.ts +1 -0
- package/src/form/form.interface.tsx +21 -0
- package/src/geocoding/GeocodingService.ts +89 -0
- package/src/geocoding/geocoding.interface.ts +25 -0
- package/src/grid/col/colStyled/ColStyled.tsx +6 -4
- package/src/grid/row/row.css +2 -2
- package/src/index.ts +12 -1
|
@@ -7,6 +7,7 @@ type DataTableRowProps = {
|
|
|
7
7
|
idx: number;
|
|
8
8
|
rowIndex: number;
|
|
9
9
|
row: any;
|
|
10
|
+
container?: "cell" | "card";
|
|
10
11
|
onEnterNextColumn?: (columnIndex: number, rowIndex: number) => void;
|
|
11
12
|
};
|
|
12
13
|
export const DataTableRow = ({
|
|
@@ -14,6 +15,7 @@ export const DataTableRow = ({
|
|
|
14
15
|
idx,
|
|
15
16
|
rowIndex,
|
|
16
17
|
row,
|
|
18
|
+
container = "cell",
|
|
17
19
|
onEnterNextColumn,
|
|
18
20
|
}: DataTableRowProps) => {
|
|
19
21
|
const value = (row as any)[column.id]; // On utilise [column.id] pour accéder aux bonnes propriétés
|
|
@@ -24,12 +26,12 @@ export const DataTableRow = ({
|
|
|
24
26
|
typeof column.showStepButtons === "function"
|
|
25
27
|
? column.showStepButtons(row)
|
|
26
28
|
: (column.showStepButtons ??
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
(typeof column.stepControls === "function"
|
|
30
|
+
? column.stepControls(row)
|
|
31
|
+
: (column.stepControls ??
|
|
32
|
+
(typeof column.withStepControls === "function"
|
|
33
|
+
? column.withStepControls(row)
|
|
34
|
+
: column.withStepControls)))),
|
|
33
35
|
);
|
|
34
36
|
|
|
35
37
|
const handleStep = (direction: "plus" | "minus", e: React.MouseEvent) => {
|
|
@@ -50,8 +52,10 @@ export const DataTableRow = ({
|
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
54
|
|
|
55
|
+
const Container = container === "card" ? "div" : "td";
|
|
56
|
+
|
|
53
57
|
return (
|
|
54
|
-
<
|
|
58
|
+
<Container
|
|
55
59
|
className={`${isDisabled ? "disabled" : ""}`}
|
|
56
60
|
data-column-index={idx}
|
|
57
61
|
data-row-index={rowIndex}
|
|
@@ -93,42 +97,83 @@ export const DataTableRow = ({
|
|
|
93
97
|
/>
|
|
94
98
|
</div>
|
|
95
99
|
) : (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
>
|
|
112
|
-
<button
|
|
113
|
-
type="button"
|
|
114
|
-
className="data-table-step-btn data-table-step-btn--minus"
|
|
115
|
-
disabled={
|
|
116
|
-
isDisabled ||
|
|
117
|
-
(column.min !== undefined && Number(value) <= column.min)
|
|
118
|
-
}
|
|
119
|
-
onClick={(e) => handleStep("minus", e)}
|
|
100
|
+
hasStepButtons ? (
|
|
101
|
+
<div
|
|
102
|
+
className="data-table-input-number-wrapper"
|
|
103
|
+
style={{
|
|
104
|
+
display: "inline-flex",
|
|
105
|
+
alignItems: "center",
|
|
106
|
+
gap: "4px",
|
|
107
|
+
justifyContent:
|
|
108
|
+
column.align === "right"
|
|
109
|
+
? "flex-end"
|
|
110
|
+
: column.align === "center"
|
|
111
|
+
? "center"
|
|
112
|
+
: "flex-start",
|
|
113
|
+
}}
|
|
114
|
+
onClick={(e) => e.stopPropagation()}
|
|
120
115
|
>
|
|
121
|
-
<
|
|
122
|
-
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
className="data-table-step-btn data-table-step-btn--minus"
|
|
119
|
+
disabled={
|
|
120
|
+
isDisabled ||
|
|
121
|
+
(column.min !== undefined && Number(value) <= column.min)
|
|
122
|
+
}
|
|
123
|
+
onClick={(e) => handleStep("minus", e)}
|
|
124
|
+
>
|
|
125
|
+
<Icon classIcon="bi-dash-lg" />
|
|
126
|
+
</button>
|
|
127
|
+
<input
|
|
128
|
+
type={column.type}
|
|
129
|
+
value={value}
|
|
130
|
+
step={column.step ?? "0.01"}
|
|
131
|
+
min={column.min}
|
|
132
|
+
max={column.max}
|
|
133
|
+
disabled={isDisabled}
|
|
134
|
+
style={{
|
|
135
|
+
textAlign: column.align || "center",
|
|
136
|
+
minWidth: column.minWidth,
|
|
137
|
+
maxWidth: column.maxWidth,
|
|
138
|
+
width: column.width,
|
|
139
|
+
}}
|
|
140
|
+
onClick={(e) => e.stopPropagation()}
|
|
141
|
+
onKeyDown={(e) => {
|
|
142
|
+
if (e.key === "Enter") {
|
|
143
|
+
if (column.onEnter) {
|
|
144
|
+
column.onEnter(e.currentTarget.value, row);
|
|
145
|
+
}
|
|
146
|
+
if (column.enterToNextColumn) {
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
onEnterNextColumn?.(idx, rowIndex);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}}
|
|
152
|
+
onChange={(e) => {
|
|
153
|
+
if (column.onEdit) {
|
|
154
|
+
column.onEdit(e.target.value, row);
|
|
155
|
+
}
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
<button
|
|
159
|
+
type="button"
|
|
160
|
+
className="data-table-step-btn data-table-step-btn--plus"
|
|
161
|
+
disabled={
|
|
162
|
+
isDisabled ||
|
|
163
|
+
(column.max !== undefined && Number(value) >= column.max)
|
|
164
|
+
}
|
|
165
|
+
onClick={(e) => handleStep("plus", e)}
|
|
166
|
+
>
|
|
167
|
+
<Icon classIcon="bi-plus-lg" />
|
|
168
|
+
</button>
|
|
169
|
+
</div>
|
|
170
|
+
) : (
|
|
123
171
|
<input
|
|
124
172
|
type={column.type}
|
|
125
173
|
value={value}
|
|
126
|
-
step=
|
|
127
|
-
min={column.min}
|
|
128
|
-
max={column.max}
|
|
129
|
-
disabled={isDisabled}
|
|
174
|
+
step="0.01"
|
|
130
175
|
style={{
|
|
131
|
-
textAlign: column.align || "
|
|
176
|
+
textAlign: column.align || "left",
|
|
132
177
|
minWidth: column.minWidth,
|
|
133
178
|
maxWidth: column.maxWidth,
|
|
134
179
|
width: column.width,
|
|
@@ -151,54 +196,13 @@ export const DataTableRow = ({
|
|
|
151
196
|
}
|
|
152
197
|
}}
|
|
153
198
|
/>
|
|
154
|
-
|
|
155
|
-
type="button"
|
|
156
|
-
className="data-table-step-btn data-table-step-btn--plus"
|
|
157
|
-
disabled={
|
|
158
|
-
isDisabled ||
|
|
159
|
-
(column.max !== undefined && Number(value) >= column.max)
|
|
160
|
-
}
|
|
161
|
-
onClick={(e) => handleStep("plus", e)}
|
|
162
|
-
>
|
|
163
|
-
<Icon classIcon="bi-plus-lg" />
|
|
164
|
-
</button>
|
|
165
|
-
</div>
|
|
166
|
-
) : (
|
|
167
|
-
<input
|
|
168
|
-
type={column.type}
|
|
169
|
-
value={value}
|
|
170
|
-
step="0.01"
|
|
171
|
-
style={{
|
|
172
|
-
textAlign: column.align || "left",
|
|
173
|
-
minWidth: column.minWidth,
|
|
174
|
-
maxWidth: column.maxWidth,
|
|
175
|
-
width: column.width,
|
|
176
|
-
}}
|
|
177
|
-
onClick={(e) => e.stopPropagation()}
|
|
178
|
-
onKeyDown={(e) => {
|
|
179
|
-
if (e.key === "Enter") {
|
|
180
|
-
if (column.onEnter) {
|
|
181
|
-
column.onEnter(e.currentTarget.value, row);
|
|
182
|
-
}
|
|
183
|
-
if (column.enterToNextColumn) {
|
|
184
|
-
e.preventDefault();
|
|
185
|
-
onEnterNextColumn?.(idx, rowIndex);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}}
|
|
189
|
-
onChange={(e) => {
|
|
190
|
-
if (column.onEdit) {
|
|
191
|
-
column.onEdit(e.target.value, row);
|
|
192
|
-
}
|
|
193
|
-
}}
|
|
194
|
-
/>
|
|
195
|
-
)
|
|
199
|
+
)
|
|
196
200
|
)
|
|
197
201
|
) : column.format ? (
|
|
198
202
|
column.format(value)
|
|
199
203
|
) : (
|
|
200
204
|
value
|
|
201
205
|
)}
|
|
202
|
-
</
|
|
206
|
+
</Container>
|
|
203
207
|
);
|
|
204
208
|
};
|
package/src/expands/expands.css
CHANGED
|
@@ -39,10 +39,12 @@
|
|
|
39
39
|
height: 300px;
|
|
40
40
|
flex: 1;
|
|
41
41
|
min-height: 200px;
|
|
42
|
+
|
|
42
43
|
.expand-header {
|
|
43
|
-
background-color:
|
|
44
|
+
background-color: color-mix(in srgb, var(--primary-color), white 5%);
|
|
44
45
|
color: #fff;
|
|
45
46
|
}
|
|
47
|
+
|
|
46
48
|
.expand-header-custom {
|
|
47
49
|
.expand-header--children {
|
|
48
50
|
display: flex;
|
|
@@ -65,6 +67,7 @@
|
|
|
65
67
|
padding: 15px;
|
|
66
68
|
color: #333;
|
|
67
69
|
background-color: #fff;
|
|
70
|
+
|
|
68
71
|
&.expand-header-custom {
|
|
69
72
|
margin-bottom: 1rem;
|
|
70
73
|
}
|
|
@@ -81,9 +84,11 @@
|
|
|
81
84
|
font-weight: 500;
|
|
82
85
|
}
|
|
83
86
|
}
|
|
87
|
+
|
|
84
88
|
& .expand-footer {
|
|
85
89
|
padding: 15px;
|
|
86
90
|
}
|
|
91
|
+
|
|
87
92
|
& .expand-body {
|
|
88
93
|
display: none;
|
|
89
94
|
flex: 1;
|
|
@@ -94,4 +99,4 @@
|
|
|
94
99
|
flex-direction: column;
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
|
-
}
|
|
102
|
+
}
|
package/src/form/Form.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import "./form.css";
|
|
|
12
12
|
import {
|
|
13
13
|
FormInterface,
|
|
14
14
|
FormMode,
|
|
15
|
+
FormSection,
|
|
15
16
|
FormValuesInterface,
|
|
16
17
|
} from "./form.interface";
|
|
17
18
|
import { Input } from "./input/Input";
|
|
@@ -20,6 +21,7 @@ import { TextArea } from "./textArea/TextArea";
|
|
|
20
21
|
import { Col } from "../grid/col/Col";
|
|
21
22
|
import { Row } from "../grid/row/Row";
|
|
22
23
|
import { TypeInputEnum } from "./form.enum";
|
|
24
|
+
import { AddressSearch } from "../addressSearch/AddressSearch";
|
|
23
25
|
|
|
24
26
|
const euroFormatter = new Intl.NumberFormat("fr-FR", {
|
|
25
27
|
style: "currency",
|
|
@@ -48,7 +50,8 @@ export type FormProps<
|
|
|
48
50
|
hideSubmit?: boolean;
|
|
49
51
|
autoComplete?: string;
|
|
50
52
|
children?: React.ReactNode;
|
|
51
|
-
initialForm
|
|
53
|
+
initialForm?: FormInterface[];
|
|
54
|
+
sections?: FormSection[];
|
|
52
55
|
disabledSubmit?: boolean;
|
|
53
56
|
mode?: FormMode;
|
|
54
57
|
onSubmit?: (values: FormValuesInterface<T>) => void;
|
|
@@ -59,6 +62,7 @@ export const DynamicForm = forwardRef(
|
|
|
59
62
|
<T extends { [key: string]: string | number | boolean | Date | string[] }>(
|
|
60
63
|
{
|
|
61
64
|
initialForm,
|
|
65
|
+
sections,
|
|
62
66
|
title,
|
|
63
67
|
onSubmit,
|
|
64
68
|
id,
|
|
@@ -79,11 +83,17 @@ export const DynamicForm = forwardRef(
|
|
|
79
83
|
setBtnDisabledSubmit?: (disabled: boolean) => void;
|
|
80
84
|
}>
|
|
81
85
|
) => {
|
|
86
|
+
const formFields = sections
|
|
87
|
+
? sections.reduce<FormInterface[]>(
|
|
88
|
+
(fields, section) => fields.concat(section.fields),
|
|
89
|
+
[],
|
|
90
|
+
)
|
|
91
|
+
: (initialForm ?? []);
|
|
82
92
|
const [btnDisabledSubmit, setBtnDisabledSubmit] = useState(disabledSubmit);
|
|
83
93
|
const [values, setValues] = useState<FormValuesInterface<T>>(() => {
|
|
84
94
|
const initialValues: FormValuesInterface<T> =
|
|
85
95
|
{} as FormValuesInterface<T>;
|
|
86
|
-
|
|
96
|
+
formFields.forEach((field) => {
|
|
87
97
|
(initialValues as any)[field.name] = field.value ?? "";
|
|
88
98
|
});
|
|
89
99
|
return initialValues;
|
|
@@ -164,7 +174,7 @@ export const DynamicForm = forwardRef(
|
|
|
164
174
|
setValues(() => {
|
|
165
175
|
const resetValues: FormValuesInterface<T> =
|
|
166
176
|
{} as FormValuesInterface<T>;
|
|
167
|
-
|
|
177
|
+
formFields.forEach((field) => {
|
|
168
178
|
(resetValues as any)[field.name] = field.value ?? "";
|
|
169
179
|
});
|
|
170
180
|
return resetValues;
|
|
@@ -179,7 +189,7 @@ export const DynamicForm = forwardRef(
|
|
|
179
189
|
}, []);
|
|
180
190
|
|
|
181
191
|
const focusInitialElement = () => {
|
|
182
|
-
const focusedField =
|
|
192
|
+
const focusedField = formFields.find((field) => field.focus);
|
|
183
193
|
if (focusedField && inputRefs.current[focusedField.name]) {
|
|
184
194
|
setTimeout(() => {
|
|
185
195
|
inputRefs.current[focusedField.name]?.select();
|
|
@@ -198,6 +208,17 @@ export const DynamicForm = forwardRef(
|
|
|
198
208
|
}));
|
|
199
209
|
};
|
|
200
210
|
|
|
211
|
+
const updateValues = useCallback(
|
|
212
|
+
(updatedValues: FormValuesInterface<T>) => {
|
|
213
|
+
setValues((previousValues) => {
|
|
214
|
+
const nextValues = { ...previousValues, ...updatedValues };
|
|
215
|
+
onChange?.(nextValues);
|
|
216
|
+
return nextValues;
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
[onChange],
|
|
220
|
+
);
|
|
221
|
+
|
|
201
222
|
useImperativeHandle(ref, () => ({
|
|
202
223
|
resetForm,
|
|
203
224
|
clearInput,
|
|
@@ -207,8 +228,6 @@ export const DynamicForm = forwardRef(
|
|
|
207
228
|
setBtnDisabledSubmit,
|
|
208
229
|
}));
|
|
209
230
|
|
|
210
|
-
const gridEnabled = initialForm.some((field) => field.col !== undefined);
|
|
211
|
-
const FieldsContainer = gridEnabled ? Row : React.Fragment;
|
|
212
231
|
const getReadValue = (field: FormInterface): React.ReactNode => {
|
|
213
232
|
const value = values[field.name];
|
|
214
233
|
|
|
@@ -253,15 +272,13 @@ export const DynamicForm = forwardRef(
|
|
|
253
272
|
: String(value);
|
|
254
273
|
};
|
|
255
274
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
<FieldsContainer>
|
|
264
|
-
{initialForm.map((v, key) => {
|
|
275
|
+
const renderFields = (fields: FormInterface[]) => {
|
|
276
|
+
const gridEnabled = fields.some((field) => field.col !== undefined);
|
|
277
|
+
const FieldsContainer = gridEnabled ? Row : React.Fragment;
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<FieldsContainer>
|
|
281
|
+
{fields.map((v, key) => {
|
|
265
282
|
const required = v.onRequired
|
|
266
283
|
? v.onRequired(v.value)
|
|
267
284
|
: v.required ?? false;
|
|
@@ -270,102 +287,150 @@ export const DynamicForm = forwardRef(
|
|
|
270
287
|
: v.disabled ?? false;
|
|
271
288
|
|
|
272
289
|
return (
|
|
273
|
-
<FormFieldContainer
|
|
290
|
+
<FormFieldContainer
|
|
291
|
+
key={v.name || key}
|
|
292
|
+
field={v}
|
|
293
|
+
gridEnabled={gridEnabled}
|
|
294
|
+
>
|
|
274
295
|
<div
|
|
275
|
-
className={`d-flex flex-column ${
|
|
276
|
-
v.
|
|
277
|
-
} form-group form-group-${v.type}`}
|
|
296
|
+
className={`d-flex flex-column ${v.className ?? ""
|
|
297
|
+
} form-group form-group-${v.type}`}
|
|
278
298
|
>
|
|
279
|
-
|
|
280
|
-
|
|
299
|
+
{v.label && <label>{v.label}</label>}
|
|
300
|
+
{v.icon && <Icon classIcon={v.icon} />}
|
|
281
301
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
v.type === TypeInputEnum.TEXTAREA
|
|
302
|
+
{mode === "read" ? (
|
|
303
|
+
<div
|
|
304
|
+
className={`form-read-value ${v.type === TypeInputEnum.TEXTAREA
|
|
286
305
|
? "form-read-value--textarea"
|
|
287
306
|
: ""
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
307
|
+
}`}
|
|
308
|
+
>
|
|
309
|
+
{getReadValue(v)}
|
|
310
|
+
</div>
|
|
311
|
+
) : v.type === TypeInputEnum.ADDRESS ? (
|
|
312
|
+
<AddressSearch
|
|
313
|
+
id={v.id ?? v.name}
|
|
314
|
+
label=""
|
|
315
|
+
placeholder={v.placeholder}
|
|
316
|
+
value={String(values[v.name] ?? "")}
|
|
317
|
+
disabled={disabled}
|
|
318
|
+
minimumQueryLength={v.addressSearch?.minimumQueryLength}
|
|
319
|
+
debounceTime={v.addressSearch?.debounceTime}
|
|
320
|
+
limit={v.addressSearch?.limit}
|
|
321
|
+
provider={v.addressSearch?.provider}
|
|
322
|
+
allowManualEntry
|
|
323
|
+
manualEntryLabel={v.addressSearch?.manualEntryLabel}
|
|
324
|
+
onChange={(value) =>
|
|
325
|
+
updateValues({ [v.name]: value } as FormValuesInterface<T>)
|
|
326
|
+
}
|
|
327
|
+
onSelect={(address) => {
|
|
328
|
+
const mappedValues =
|
|
329
|
+
v.addressSearch?.mapAddress?.(address) ?? {};
|
|
330
|
+
updateValues(mappedValues as FormValuesInterface<T>);
|
|
331
|
+
v.addressSearch?.onSelect?.(address);
|
|
332
|
+
}}
|
|
333
|
+
/>
|
|
334
|
+
) : v.type === "select" ? (
|
|
335
|
+
<Select
|
|
336
|
+
id={v.id ?? v.name}
|
|
337
|
+
label={undefined}
|
|
338
|
+
name={v.name}
|
|
339
|
+
options={v.options ?? []}
|
|
340
|
+
disabled={disabled}
|
|
341
|
+
multiple={v.multiple}
|
|
342
|
+
value={values[v.name] as any}
|
|
343
|
+
required={required}
|
|
344
|
+
defaultValue={v.value as string | string[]}
|
|
345
|
+
placeholder={v.placeholder}
|
|
346
|
+
onChangeMultiple={(newValue) =>
|
|
347
|
+
handleChangeSelect(newValue, v.name, v)
|
|
348
|
+
}
|
|
349
|
+
onChange={(newValue) =>
|
|
350
|
+
handleChangeSelect(newValue, v.name, v)
|
|
351
|
+
}
|
|
352
|
+
/>
|
|
353
|
+
) : v.type === "textarea" ? (
|
|
354
|
+
<TextArea
|
|
355
|
+
id={v.id ?? v.name}
|
|
356
|
+
name={v.name}
|
|
357
|
+
className="textarea-input"
|
|
358
|
+
placeholder={v.placeholder ?? ""}
|
|
359
|
+
disabled={disabled}
|
|
360
|
+
required={required}
|
|
361
|
+
value={values[v.name] as string}
|
|
362
|
+
onChange={(value, name) =>
|
|
363
|
+
handleChangeTextArea(name, value, v)
|
|
364
|
+
}
|
|
365
|
+
/>
|
|
366
|
+
) : v.type === TypeInputEnum.PRICE ? (
|
|
367
|
+
<InputPrice
|
|
368
|
+
id={v.id ?? v.name}
|
|
369
|
+
ref={(el) => (inputRefs.current[v.name] = el)}
|
|
370
|
+
name={v.name}
|
|
371
|
+
placeholder={v.placeholder ?? ""}
|
|
372
|
+
autoComplete={v.autoComplete}
|
|
373
|
+
tabIndex={0}
|
|
374
|
+
disabled={disabled}
|
|
375
|
+
autoFocus={v.focus ?? false}
|
|
376
|
+
required={required}
|
|
377
|
+
value={String(values[v.name] ?? "")}
|
|
378
|
+
onChange={(value) =>
|
|
379
|
+
handleChangeTextArea(v.name, value, v)
|
|
380
|
+
}
|
|
381
|
+
/>
|
|
382
|
+
) : (
|
|
383
|
+
<Input
|
|
384
|
+
id={v.id ?? v.name}
|
|
385
|
+
ref={(el) => (inputRefs.current[v.name] = el)}
|
|
386
|
+
name={v.name}
|
|
387
|
+
type={v.type}
|
|
388
|
+
placeholder={v.placeholder ?? ""}
|
|
389
|
+
autoComplete={v.autoComplete}
|
|
390
|
+
tabIndex={0}
|
|
391
|
+
disabled={disabled}
|
|
392
|
+
autoFocus={v.focus ?? false}
|
|
393
|
+
required={required}
|
|
394
|
+
step={v.step ?? "0.01"}
|
|
395
|
+
value={values[v.name] as string | number}
|
|
396
|
+
checked={
|
|
397
|
+
v.type === "checkbox" ? !!values[v.name] : undefined
|
|
398
|
+
}
|
|
399
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
400
|
+
handleChangeInput(e, v)
|
|
401
|
+
}
|
|
402
|
+
onInvalid={v.onInvalid ? v.onInvalid : undefined}
|
|
403
|
+
/>
|
|
404
|
+
)}
|
|
363
405
|
</div>
|
|
364
406
|
</FormFieldContainer>
|
|
365
407
|
);
|
|
366
408
|
})}
|
|
409
|
+
</FieldsContainer>
|
|
410
|
+
);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
return (
|
|
414
|
+
<form
|
|
415
|
+
autoComplete={autoComplete ?? "off"}
|
|
416
|
+
onSubmit={handleSubmit}
|
|
417
|
+
className={className ?? ""}
|
|
418
|
+
>
|
|
419
|
+
<div className="form-content">
|
|
420
|
+
{sections
|
|
421
|
+
? sections.map((section, index) => (
|
|
422
|
+
<section
|
|
423
|
+
className={`form-section ${section.className ?? ""}`}
|
|
424
|
+
key={index}
|
|
425
|
+
>
|
|
426
|
+
{section.title && (
|
|
427
|
+
<h3 className="form-section-title">{section.title}</h3>
|
|
428
|
+
)}
|
|
429
|
+
{renderFields(section.fields)}
|
|
430
|
+
</section>
|
|
431
|
+
))
|
|
432
|
+
: renderFields(initialForm ?? [])}
|
|
367
433
|
{children}
|
|
368
|
-
</FieldsContainer>
|
|
369
434
|
</div>
|
|
370
435
|
<div className="d-flex justify-content-end form-footer">
|
|
371
436
|
{mode === "edit" && !hideSubmit && (
|