@itcase/forms 1.1.24 → 1.1.26

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.
@@ -1,21 +1,16 @@
1
1
  import { isPossiblePhoneNumber } from 'libphonenumber-js';
2
- import React$1, { useMemo, useEffect, useCallback, useState } from 'react';
2
+ import React$1, { useMemo, useEffect, useState, useCallback } from 'react';
3
3
  import { setIn, FORM_ERROR, getIn } from 'final-form';
4
4
  import { useForm, Field, Form, FormSpy } from 'react-final-form';
5
5
  export { Field, useForm, useFormState } from 'react-final-form';
6
6
  import clsx from 'clsx';
7
- import { Checkbox } from '@itcase/ui/components/Checkbox';
7
+ import { useDevicePropsGenerator } from '@itcase/ui/hooks/useDevicePropsGenerator';
8
+ import camelCase from 'lodash/camelCase';
9
+ import snakeCase from 'lodash/snakeCase';
8
10
  import { Divider } from '@itcase/ui/components/Divider';
9
11
  import { Text } from '@itcase/ui/components/Text';
10
12
  import { useDeviceTargetClass } from '@itcase/ui/hooks/useDeviceTargetClass';
11
13
  import { useStyles } from '@itcase/ui/hooks/useStyles';
12
- import camelCase from 'lodash/camelCase';
13
- import snakeCase from 'lodash/snakeCase';
14
- import { Choice } from '@itcase/ui/components/Choice';
15
- import { Icon } from '@itcase/ui/components/Icon';
16
- import { Code } from '@itcase/ui/components/Code';
17
- import { DatePickerInput } from '@itcase/ui/components/DatePicker';
18
- import { useDevicePropsGenerator } from '@itcase/ui/hooks/useDevicePropsGenerator';
19
14
  import axios from 'axios';
20
15
  import { fromEvent } from 'file-selector';
21
16
  import castArray from 'lodash/castArray';
@@ -24,15 +19,20 @@ import { createFileFromDataURL } from '@itcase/common';
24
19
  import { Button } from '@itcase/ui/components/Button';
25
20
  import { Loader } from '@itcase/ui/components/Loader';
26
21
  import { Title } from '@itcase/ui/components/Title';
22
+ import { Checkbox } from '@itcase/ui/components/Checkbox';
23
+ import { ChipsGroup, Chips } from '@itcase/ui/components/Chips';
24
+ import { Choice } from '@itcase/ui/components/Choice';
25
+ import { Code } from '@itcase/ui/components/Code';
26
+ import { Icon } from '@itcase/ui/components/Icon';
27
+ import { DatePickerInput } from '@itcase/ui/components/DatePicker';
27
28
  import { Input } from '@itcase/ui/components/Input';
28
- import { Radio } from '@itcase/ui/components/Radio';
29
29
  import { Segmented } from '@itcase/ui/components/Segmented';
30
30
  import { Select } from '@itcase/ui/components/Select';
31
31
  import { Switch } from '@itcase/ui/components/Switch';
32
32
  import { Textarea } from '@itcase/ui/components/Textarea';
33
33
  import { useIMask } from 'react-imask';
34
- import { ChipsGroup, Chips } from '@itcase/ui/components/Chips';
35
- import { Group as Group$1 } from '@itcase/ui/components/Group';
34
+ import { Radio } from '@itcase/ui/components/Radio';
35
+ import { Group } from '@itcase/ui/components/Group';
36
36
  import { Notification } from '@itcase/ui/components/Notification';
37
37
  import createDecorator from 'final-form-focus';
38
38
 
@@ -116,29 +116,149 @@ function useYupValidationSchema(schema, language) {
116
116
  return validate;
117
117
  }
118
118
 
119
+ // Whether to display an error message based on "fieldProps" and meta-objects
120
+ function useFieldValidationState(props) {
121
+ const {
122
+ fieldProps = {},
123
+ meta = {},
124
+ input = {}
125
+ } = props;
126
+ // Determines if there's a submission error that hasn't been rectified since the last submission.
127
+ const submitError = !meta.modifiedSinceLastSubmit && meta.submitError;
128
+
129
+ // Determines a key for the error, defaulting to 'error' if no specific key is found.
130
+ const errorKey = meta.error?.key || 'error';
131
+ const successKey = 'success';
132
+
133
+ // Determines if the field is in an error state based on various conditions.
134
+ const isErrorState = useMemo(() => {
135
+ if (fieldProps.showErrorsOnSubmit) {
136
+ return Boolean(meta.submitFailed && meta.touched && (meta.error || submitError));
137
+ } else {
138
+ return Boolean(meta.touched && (meta.error || submitError));
139
+ }
140
+ }, [fieldProps.showErrorsOnSubmit, meta.submitFailed, meta.touched, meta.error, submitError]);
141
+
142
+ // Determines if the field's input state is valid
143
+ const isValidState = useMemo(() => {
144
+ const hasValue = Array.isArray(input?.value) ? input?.value.length : input?.value;
145
+ const isModifiedAfterSubmit = meta.modifiedSinceLastSubmit && !meta.error && submitError;
146
+ return Boolean(hasValue && (meta.valid || isModifiedAfterSubmit));
147
+ }, [input?.value, meta.valid, meta.error, submitError, meta.modifiedSinceLastSubmit]);
148
+ const errorMessage = useMemo(() => {
149
+ // If final-form field has error in "meta" render-property.
150
+ // If field not modified after last form submit - use submit error
151
+ const error = meta.error || submitError || false;
152
+ if (error) {
153
+ // And error in "meta" is string
154
+ if (typeof error === 'string') {
155
+ // Return error as message
156
+ return error;
157
+ }
158
+ // Or if error in "meta" has "message" property(is object of error)
159
+ if (error.message) {
160
+ // Return message from error
161
+ return error.message;
162
+ }
163
+ }
164
+
165
+ // Field doesn't have error message
166
+ return '';
167
+ }, [meta.error, submitError]);
168
+ return {
169
+ errorKey,
170
+ successKey,
171
+ isErrorState,
172
+ isValidState,
173
+ errorMessage
174
+ };
175
+ }
176
+
177
+ // This hook changes the props of the child component depending on the type of error,
178
+ // looks at what props were in initialProps, if they are there then changes
179
+ function useValidationAppearanceInputProps(props) {
180
+ const {
181
+ validationStateKey,
182
+ inputProps
183
+ } = props;
184
+
185
+ // TODO: need to add props that can change during errors in this field
186
+ const validationAppearanceInputProps = useMemo(() => {
187
+ // const resultAppearanceProps = {
188
+ // messageTextColor: props.errorMessageTextColor,
189
+ // messageTextSize: props.errorMessageTextSize,
190
+ // messageTextWeight: props.errorMessageTextWeight,
191
+ // // Override appearance(styled) props for child input
192
+ // inputProps: {},
193
+ // }
194
+ const updatedInputProps = {};
195
+ if (validationStateKey) {
196
+ Object.entries(inputProps).forEach(([propKey, propValue]) => {
197
+ // Convert the input property key to "snake_case" format.
198
+ // e.g. "requiredBorderColor" -> "required_border_color".
199
+ const propKeySnake = snakeCase(propKey);
200
+ // Check if this property is for appearance.
201
+ // Key maybe starts with: "error", "required", "success", etc from validation config.
202
+ const isPropForValidationState = propKeySnake.startsWith(`${validationStateKey}_`);
203
+
204
+ // If property is for appearance
205
+ if (isPropForValidationState) {
206
+ // Remove validation state part from begin of property key, to make clean appearance property.
207
+ // e.g. "required_border_color" -> "border_color".
208
+ const stateTargetKeySnake = propKeySnake.replace(`${validationStateKey}_`, '');
209
+ // Convert clean appearance property key to "camelCase" format.
210
+ // e.g. "border_color" -> "borderColor"
211
+ const stateTargetKey = camelCase(stateTargetKeySnake);
212
+ // And save the value with a new clean property key
213
+ updatedInputProps[stateTargetKey] = propValue;
214
+ // Else if not already added earlier
215
+ } else if (!updatedInputProps[propKey]) {
216
+ // Just save original property
217
+ updatedInputProps[propKey] = propValue;
218
+ }
219
+ });
220
+ }
221
+ return updatedInputProps;
222
+ }, [validationStateKey, inputProps]);
223
+ return validationAppearanceInputProps;
224
+ }
225
+
119
226
  const defaultFieldProps = {
120
227
  width: 'fill',
121
228
  direction: 'vertical',
122
- size: 'm',
123
229
  labelTextColor: 'surfaceTextPrimary',
124
- labelTextSize: 's',
125
230
  messageTextColor: 'surfaceTextSecondary',
126
- messageTextSize: 's',
127
231
  errorMessageTextColor: 'errorTextSecondary',
128
- errorMessageTextSize: 's',
129
232
  dividerFill: 'errorPrimary',
130
233
  helpTextColor: 'surfaceTextQuaternary',
131
- helpTextSize: 's',
132
234
  requiredMessageTextColor: 'warningTextSecondary',
133
- requiredMessageTextSize: 's',
134
235
  showMessage: true
135
236
  };
237
+ const defaultFieldSizeM = {
238
+ size: 'm',
239
+ labelTextSize: 's',
240
+ messageTextSize: 's',
241
+ errorMessageTextSize: 's',
242
+ helpTextSize: 's',
243
+ requiredMessageTextSize: 's',
244
+ ...defaultFieldProps
245
+ };
246
+ const defaultFieldSizeXL = {
247
+ size: 'xl',
248
+ labelTextSize: 's',
249
+ messageTextSize: 's',
250
+ errorMessageTextSize: 's',
251
+ helpTextSize: 's',
252
+ requiredMessageTextSize: 's',
253
+ ...defaultFieldProps
254
+ };
136
255
 
137
256
  function FieldWrapperBase(props) {
138
257
  const {
139
258
  id,
259
+ dataTour,
140
260
  className,
141
- type = 'normal',
261
+ type,
142
262
  label,
143
263
  labelHidden,
144
264
  labelTextColor,
@@ -146,6 +266,7 @@ function FieldWrapperBase(props) {
146
266
  labelTextSizeMobile,
147
267
  labelTextSizeTablet,
148
268
  labelTextWeight,
269
+ messageTextSize,
149
270
  desc,
150
271
  descTextColor,
151
272
  descTextSize,
@@ -158,7 +279,6 @@ function FieldWrapperBase(props) {
158
279
  isDisabled,
159
280
  afterItem,
160
281
  beforeItem,
161
- dataTour,
162
282
  dividerDirection,
163
283
  dividerFill,
164
284
  dividerSize,
@@ -171,7 +291,6 @@ function FieldWrapperBase(props) {
171
291
  helpTextWeight,
172
292
  inputName,
173
293
  inputValue,
174
- messageTextSize,
175
294
  metaActive,
176
295
  showDivider,
177
296
  showMessage,
@@ -220,13 +339,13 @@ function FieldWrapperBase(props) {
220
339
  const errorTextColor = props[`${errorKey}MessageTextColor`];
221
340
  const errorTextWeight = props[`${errorKey}MessageTextWeight`];
222
341
  return /*#__PURE__*/React$1.createElement(Tag, {
342
+ dataTestId: `${inputName}Field`,
343
+ dataTour: dataTour,
223
344
  className: clsx(formFieldClass, 'form__item', 'form-field', type && `form-field_type_${type}`, sizeClass, fillClass, shapeClass, isDisabled && `form-field_state_disabled`, isHidden && `form-field_state_hidden`, directionClass, widthClass),
224
- "data-test-id": `${inputName}Field`,
225
- "data-tour": dataTour,
226
345
  style: formFieldStyles
227
346
  }, before, (label || labelHidden) && /*#__PURE__*/React$1.createElement("div", {
347
+ dataTestId: `${inputName}FieldLabel`,
228
348
  className: clsx('form-field__label'),
229
- "data-test-id": `${inputName}FieldLabel`,
230
349
  htmlFor: id
231
350
  }, /*#__PURE__*/React$1.createElement(Text, {
232
351
  size: labelTextSize,
@@ -236,7 +355,7 @@ function FieldWrapperBase(props) {
236
355
  sizeTablet: labelTextSizeTablet
237
356
  }, label, labelHidden && '\u00A0')), desc && /*#__PURE__*/React$1.createElement("div", {
238
357
  className: "form-field__desc",
239
- "data-test-id": `${inputName}FieldDesc`
358
+ dataTestId: `${inputName}FieldDesc`
240
359
  }, /*#__PURE__*/React$1.createElement(Text, {
241
360
  size: descTextSize,
242
361
  textColor: descTextColor,
@@ -252,26 +371,26 @@ function FieldWrapperBase(props) {
252
371
  size: dividerSize,
253
372
  fill: dividerFill
254
373
  })), showMessage && /*#__PURE__*/React$1.createElement("div", {
255
- className: "form-field__message",
256
- "data-test-id": `${inputName}FieldMessage`
374
+ dataTestId: `${inputName}FieldMessage`,
375
+ className: "form-field__message"
257
376
  }, isErrorState && errorMessage && /*#__PURE__*/React$1.createElement(Text, {
258
377
  id: `${inputName}-error`,
378
+ dataTestId: `${inputName}FieldMessageError`,
259
379
  className: "form-field__message-item form-field__message-item_type-error",
260
380
  size: errorTextSize,
261
381
  textColor: errorTextColor,
262
- textWeight: errorTextWeight,
263
- dataTestId: `${inputName}FieldMessageError`
382
+ textWeight: errorTextWeight
264
383
  }, errorMessage), Boolean(helpText) && (!isErrorState || !errorMessage) && /*#__PURE__*/React$1.createElement(Text, {
384
+ dataTestId: `${inputName}FieldMessageHelpText`,
265
385
  className: "form-field__message-item form-field__message-item_type_help-text",
266
386
  size: helpTextSize,
267
387
  textColor: isValidState ? helpTextColorSuccess : helpTextColor,
268
388
  textWeight: helpTextWeight,
269
- dataTestId: `${inputName}FieldMessageHelpText`,
270
389
  sizeMobile: helpTextSizeMobile
271
390
  }, helpText), (!isErrorState && !helpText || isErrorState && !helpText && !errorMessage) && /*#__PURE__*/React$1.createElement(Text, {
391
+ dataTestId: `${inputName}FieldMessageHelpText`,
272
392
  className: "form-field__message-item form-field__message-item_type_help-text",
273
- size: messageTextSize,
274
- dataTestId: `${inputName}FieldMessageHelpText`
393
+ size: messageTextSize
275
394
  }, '\u00A0')), after);
276
395
  }
277
396
  function FieldWrapper(props) {
@@ -290,242 +409,425 @@ function FieldWrapper(props) {
290
409
  return /*#__PURE__*/React$1.createElement(FieldWrapperBase, props);
291
410
  }
292
411
 
293
- // Whether to display an error message based on "fieldProps" and meta-objects
294
- function useFieldValidationState(props) {
412
+ const defaultDropzoneProps = {
413
+ fill: 'surfacePrimary',
414
+ borderColor: 'surfaceBorderTertiary',
415
+ borderColorHover: 'surfaceBorderQuaternary',
416
+ hintTitle: 'Перетащите изображение или выберите файл с компьютера',
417
+ hintTitleTextColor: 'surfaceTextPrimary',
418
+ hintTitleTextSize: 'm',
419
+ removeThumbText: 'удалить',
420
+ removeThumbTextColor: 'errorTextPrimary',
421
+ removeThumbTextHoverColor: 'errorTextPrimaryHover',
422
+ removeThumbTextSize: 's',
423
+ shape: 'rounded',
424
+ showFilename: true,
425
+ thumbBorderColor: 'surfaceBorderTertiary',
426
+ thumbBorderColorHover: 'surfaceBorderQuaternary',
427
+ thumbBorderWidth: 1,
428
+ thumbNameTextColor: 'surfaceTextPrimary',
429
+ thumbNameTextSize: 's',
430
+ isPreviews: true
431
+ };
432
+
433
+ const FileInputDropzone = /*#__PURE__*/React$1.memo(function FileInputDropzone(props) {
295
434
  const {
296
- fieldProps = {},
297
- meta = {},
298
- input = {}
435
+ className,
436
+ maxFiles,
437
+ maxSize,
438
+ size,
439
+ fileErrorText,
440
+ dropzoneProps = {},
441
+ hintDescription,
442
+ hintTitle,
443
+ inputName,
444
+ inputValue,
445
+ showFilename,
446
+ thumbColumn,
447
+ isPreviews,
448
+ onAddFiles,
449
+ onDeleteFile
299
450
  } = props;
300
- // Determines if there's a submission error that hasn't been rectified since the last submission.
301
- const submitError = !meta.modifiedSinceLastSubmit && meta.submitError;
302
451
 
303
- // Determines a key for the error, defaulting to 'error' if no specific key is found.
304
- const errorKey = meta.error?.key || 'error';
305
- const successKey = 'success';
452
+ // TODO: delete react-final-form things out of here?
453
+ const {
454
+ change
455
+ } = useForm();
456
+ const [fileError, setFileError] = useState('');
457
+ const [fileIsLoading, setFileIsLoading] = useState(false);
458
+ const filesList = useMemo(() => inputValue ? castArray(inputValue) : [], [inputValue]);
459
+ const changeFormState = useCallback(newFiles => {
460
+ // If max files in dropzone is 1 - return file as it self, else as array of files
461
+ // ps: for old projects compatibility
462
+ const toSave = dropzoneProps.maxFiles == 1 ? newFiles[0] : newFiles;
463
+ change(inputName, toSave);
464
+ return toSave;
465
+ },
466
+ // If "inputName" will be changes, then it should be a different field
467
+ // eslint-disable-next-line react-hooks/exhaustive-deps
468
+ [dropzoneProps, change]);
306
469
 
307
- // Determines if the field is in an error state based on various conditions.
308
- const isErrorState = useMemo(() => {
309
- if (fieldProps.showErrorsOnSubmit) {
310
- return Boolean(meta.submitFailed && meta.touched && (meta.error || submitError));
311
- } else {
312
- return Boolean(meta.touched && (meta.error || submitError));
470
+ //
471
+ const convertFiledValueAndSaveAsFiles = useCallback(async currentFilesList => {
472
+ setFileIsLoading(true);
473
+ const newFiles = [];
474
+ for (const fileItem of currentFilesList) {
475
+ if (typeof fileItem === 'string') {
476
+ const newFile = await convertToFile(fileItem, isPreviews);
477
+ if (newFile) {
478
+ newFiles.push(newFile);
479
+ }
480
+ } else {
481
+ newFiles.push(fileItem);
482
+ }
313
483
  }
314
- }, [fieldProps.showErrorsOnSubmit, meta.submitFailed, meta.touched, meta.error, submitError]);
484
+ changeFormState(newFiles);
485
+ setFileIsLoading(false);
486
+ }, [isPreviews, changeFormState]);
315
487
 
316
- // Determines if the field's input state is valid
317
- const isValidState = useMemo(() => {
318
- const hasValue = Array.isArray(input?.value) ? input?.value.length : input?.value;
319
- const isModifiedAfterSubmit = meta.modifiedSinceLastSubmit && !meta.error && submitError;
320
- return Boolean(hasValue && (meta.valid || isModifiedAfterSubmit));
321
- }, [input?.value, meta.valid, meta.error, submitError, meta.modifiedSinceLastSubmit]);
322
- const errorMessage = useMemo(() => {
323
- // If final-form field has error in "meta" render-property.
324
- // If field not modified after last form submit - use submit error
325
- const error = meta.error || submitError || false;
326
- if (error) {
327
- // And error in "meta" is string
328
- if (typeof error === 'string') {
329
- // Return error as message
330
- return error;
331
- }
332
- // Or if error in "meta" has "message" property(is object of error)
333
- if (error.message) {
334
- // Return message from error
335
- return error.message;
336
- }
488
+ // Delete file from dropzone
489
+ const removeFile = useCallback((event, index) => {
490
+ event.stopPropagation();
491
+ event.preventDefault();
492
+ const newFiles = [...filesList];
493
+ newFiles.splice(index, 1);
494
+ if (onDeleteFile) {
495
+ onDeleteFile(filesList[index], inputName);
337
496
  }
497
+ changeFormState(newFiles);
498
+ },
499
+ // If "inputName" will be changes, then it should be a different field
500
+ // eslint-disable-next-line react-hooks/exhaustive-deps
501
+ [filesList, changeFormState, onDeleteFile]);
338
502
 
339
- // Field doesn't have error message
340
- return '';
341
- }, [meta.error, submitError]);
342
- return {
343
- errorKey,
344
- successKey,
345
- isErrorState,
346
- isValidState,
347
- errorMessage
348
- };
349
- }
350
-
351
- // This hook changes the props of the child component depending on the type of error,
352
- // looks at what props were in initialProps, if they are there then changes
353
- function useValidationAppearanceInputProps(props) {
503
+ // Create dropzone options
354
504
  const {
355
- validationStateKey,
356
- inputProps
357
- } = props;
358
-
359
- // TODO: need to add props that can change during errors in this field
360
- const validationAppearanceInputProps = useMemo(() => {
361
- // const resultAppearanceProps = {
362
- // messageTextColor: props.errorMessageTextColor,
363
- // messageTextSize: props.errorMessageTextSize,
364
- // messageTextWeight: props.errorMessageTextWeight,
365
- // // Override appearance(styled) props for child input
366
- // inputProps: {},
367
- // }
368
- const updatedInputProps = {};
369
- if (validationStateKey) {
370
- Object.entries(inputProps).forEach(([propKey, propValue]) => {
371
- // Convert the input property key to "snake_case" format.
372
- // e.g. "requiredBorderColor" -> "required_border_color".
373
- const propKeySnake = snakeCase(propKey);
374
- // Check if this property is for appearance.
375
- // Key maybe starts with: "error", "required", "success", etc from validation config.
376
- const isPropForValidationState = propKeySnake.startsWith(`${validationStateKey}_`);
505
+ getInputProps,
506
+ getRootProps
507
+ } = useDropzone({
508
+ maxFiles: maxFiles || 5,
509
+ maxSize: maxSize || 10485760,
510
+ // 10mb
511
+ // accept: { 'image/*': [] },
512
+ ...dropzoneProps,
513
+ getFilesFromEvent: async event => {
514
+ const result = await fromEvent(event);
515
+ const newFiles = result.filter(item => item instanceof File);
516
+ // Add exists and new files to accepted(or rejected)
517
+ return [...filesList, ...newFiles];
518
+ },
519
+ onDropAccepted: acceptedFiles => {
520
+ // If dropped files has accepted and we need a previews
521
+ if (isPreviews) {
522
+ // Add preview to every file
523
+ acceptedFiles.forEach(file => {
524
+ if (!file.error) {
525
+ file.preview = URL.createObjectURL(file);
526
+ }
527
+ });
528
+ }
529
+ // Save to form data (including empty when files are not valid)
530
+ const filesToSave = changeFormState(acceptedFiles);
531
+ setFileError('');
377
532
 
378
- // If property is for appearance
379
- if (isPropForValidationState) {
380
- // Remove validation state part from begin of property key, to make clean appearance property.
381
- // e.g. "required_border_color" -> "border_color".
382
- const stateTargetKeySnake = propKeySnake.replace(`${validationStateKey}_`, '');
383
- // Convert clean appearance property key to "camelCase" format.
384
- // e.g. "border_color" -> "borderColor"
385
- const stateTargetKey = camelCase(stateTargetKeySnake);
386
- // And save the value with a new clean property key
387
- updatedInputProps[stateTargetKey] = propValue;
388
- // Else if not already added earlier
389
- } else if (!updatedInputProps[propKey]) {
390
- // Just save original property
391
- updatedInputProps[propKey] = propValue;
533
+ // Save DataURL for all files
534
+ const readerPromisesList = acceptedFiles.map(file => {
535
+ return new Promise(resolve => setFileDataURL(file, resolve));
536
+ });
537
+ // Save files to form values
538
+ Promise.all(readerPromisesList).then(() => {
539
+ if (onAddFiles) {
540
+ onAddFiles(filesToSave, inputName);
392
541
  }
393
542
  });
394
- }
395
- return updatedInputProps;
396
- }, [validationStateKey, inputProps]);
397
- return validationAppearanceInputProps;
398
- }
399
-
400
- const defaultCheckboxProps = {
401
- appearance: 'defaultPrimary',
402
- width: 'fill',
403
- errorBorderColor: 'errorBorderSecondary',
404
- requiredBorderColor: 'warningBorderSecondary'
405
- };
406
-
407
- const CheckboxField = /*#__PURE__*/React$1.memo(function CheckboxField(props) {
408
- const {
409
- name,
410
- initialValue,
411
- isDisabled,
412
- classNameGroupItem,
413
- fieldProps = {},
414
- inputProps = {},
415
- showMessage,
416
- isRequired,
417
- onChange
418
- } = props;
419
- return /*#__PURE__*/React$1.createElement(Field, {
420
- type: "checkbox",
421
- name: name,
422
- initialValue: initialValue
423
- }, function Render({
424
- input,
425
- meta
426
- }) {
427
- /** Note:
428
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
429
- * React Hooks cannot be called inside a callback.
430
- * React Hooks must be called in a React function component or a
431
- * custom React Hook function.
432
- */
433
-
434
- const onChangeField = useCallback(event => {
435
- input.onChange(event);
436
- if (onChange) {
437
- onChange(event.target.checked, input.name);
543
+ },
544
+ onDropRejected: rejectedFiles => {
545
+ // If dropped files has rejected
546
+ if (rejectedFiles.length) {
547
+ let fileErrorMessage = 'Ошибка при добавлении файла';
548
+ const firstFileErrorItem = rejectedFiles[0].errors[0];
549
+ if (firstFileErrorItem) {
550
+ if (firstFileErrorItem.code === ErrorCode.TooManyFiles) {
551
+ fileErrorMessage = `Максимальное количество файлов: ${maxFiles}`;
552
+ } else {
553
+ fileErrorMessage = firstFileErrorItem.message;
554
+ }
555
+ }
556
+ // Show error
557
+ setFileError(fileErrorMessage);
558
+ } else {
559
+ // Else clean error
560
+ setFileError('');
438
561
  }
439
- }, [onChange, input.onChange]);
440
- const {
441
- errorKey,
442
- errorMessage,
443
- isErrorState,
444
- isValidState
445
- } = useFieldValidationState({
446
- fieldProps: fieldProps,
447
- input: input,
448
- meta: meta
449
- });
450
- const updatedInputProps = useValidationAppearanceInputProps({
451
- inputProps: inputProps,
452
- validationStateKey: isErrorState ? errorKey : 'success'
453
- });
454
- return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
455
- className: clsx('form-field_type_checkbox', 'form__item_type_checkbox', classNameGroupItem),
456
- errorKey: errorKey,
457
- errorMessage: errorMessage,
458
- isErrorState: isErrorState,
459
- metaError: meta.error,
460
- isDisabled: isDisabled,
461
- fieldClassName: "form-checkbox",
462
- inputName: input.name,
463
- inputValue: input.checked,
464
- metaActive: meta.active,
465
- showMessage: showMessage,
466
- tag: "label",
467
- isRequired: isRequired,
468
- isValidState: isValidState
469
- }, fieldProps), /*#__PURE__*/React$1.createElement(Checkbox, Object.assign({
470
- type: "checkbox",
471
- name: input.name,
472
- isDisabled: isDisabled,
473
- autoComplete: "nope",
474
- checked: input.checked,
475
- onBlur: input.onBlur,
476
- onChange: onChangeField,
477
- onFocus: input.onFocus
478
- }, updatedInputProps)));
562
+ }
479
563
  });
480
- });
481
-
482
- const defaultChoiceProps = {
483
- width: 'fill',
484
- borderColor: 'surfaceBorderTertiary',
485
- // error
486
- errorBorderColor: 'errorBorderPrimary',
487
- fill: 'surfaceSecondary',
488
- fillActive: 'accentPrimary',
489
- fillActiveDisabled: 'surfaceTertiary',
490
- fillHover: 'surfacePrimaryHover',
491
- indicatorFill: 'accentPrimary',
492
- labelTextActiveColor: 'accentTextPrimary',
493
- labelTextActiveColorDisabled: 'surfaceTextDisabled',
494
- labelTextColor: 'surfaceTextPrimary',
495
- labelTextColorDisabled: 'surfaceTextDisabled',
496
- labelTextSize: 'm',
497
- requiredBorderColor: 'warningBorderPrimary',
498
- shape: 'rounded'
499
- };
564
+ useEffect(() => {
565
+ const currentFilesList = castArray(inputValue);
566
+ const isNeedToConvert = currentFilesList.some(fileItem => typeof fileItem === 'string');
567
+ if (isNeedToConvert) {
568
+ // First time convert value to Files and save to local and form state
569
+ convertFiledValueAndSaveAsFiles(currentFilesList);
570
+ }
500
571
 
501
- const ChoiceField = /*#__PURE__*/React$1.memo(function ChoiceField(props) {
502
- const {
503
- name,
504
- initialValue,
505
- label,
506
- isDisabled,
507
- classNameGroupItem,
508
- fieldProps,
509
- inputProps,
510
- messageType,
511
- options,
512
- placeholder,
513
- showMessage,
514
- isCheckbox,
515
- isRequired,
516
- onChange
517
- } = props;
572
+ // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
573
+ return () => {
574
+ filesList.forEach(file => {
575
+ if (file?.preview) {
576
+ URL.revokeObjectURL(file.preview);
577
+ }
578
+ });
579
+ };
580
+ // eslint-disable-next-line react-hooks/exhaustive-deps
581
+ }, [inputValue]);
582
+ const propsGenerator = useDevicePropsGenerator(props);
518
583
  const {
519
- change
520
- } = useForm();
521
- const setActiveSegment = useCallback((option, isChecked) => {
522
- change(name, isChecked && option.value);
523
- if (onChange) {
524
- onChange(option.value, name, isChecked);
584
+ fillClass,
585
+ fillHoverClass,
586
+ borderColorClass,
587
+ borderColorHoverClass,
588
+ borderTypeClass,
589
+ borderWidthClass,
590
+ errorMessageTextColor,
591
+ errorMessageTextSize,
592
+ errorMessageTextWeight,
593
+ hintDescriptionTextColor,
594
+ hintDescriptionTextSize,
595
+ hintDescriptionTextWeight,
596
+ hintDescriptionTextWrap,
597
+ hintTitleTextColor,
598
+ hintTitleTextSize,
599
+ hintTitleTextWeight,
600
+ hintTitleTextWrap,
601
+ removeThumbAppearance,
602
+ removeThumbShape,
603
+ removeThumbText,
604
+ removeThumbTextWeight,
605
+ shapeClass,
606
+ thumbBorderColorClass,
607
+ thumbBorderColorHoverClass,
608
+ thumbBorderTypeClass,
609
+ thumbBorderWidthClass,
610
+ thumbDirectionClass,
611
+ thumbNameTextColor,
612
+ thumbNameTextSize,
613
+ thumbNameTextWeight,
614
+ thumbNameTextWrap
615
+ } = propsGenerator;
616
+ return /*#__PURE__*/React$1.createElement(React$1.Fragment, null, /*#__PURE__*/React$1.createElement("div", getRootProps({
617
+ className: `form-dropzone__dropzone dropzone ${className} form-dropzone__dropzone_size_${size} ${shapeClass}`
618
+ }), /*#__PURE__*/React$1.createElement("input", Object.assign({}, getInputProps(), {
619
+ name: inputName
620
+ })), /*#__PURE__*/React$1.createElement("div", {
621
+ className: clsx('form-dropzone__dropzone-wrapper', thumbColumn && `form-dropzone__dropzone-wrapper_column_${thumbColumn}`, fillClass, fillHoverClass, borderWidthClass, borderColorClass, borderColorHoverClass, borderTypeClass)
622
+ }, filesList.map((file, index) => /*#__PURE__*/React$1.createElement("aside", {
623
+ className: clsx('form-dropzone__thumb', fillClass, thumbDirectionClass, thumbBorderWidthClass, thumbBorderColorClass, thumbBorderColorHoverClass, thumbBorderTypeClass),
624
+ key: file.id || `${file.name}_${index}`
625
+ }, isPreviews && !file.error && /*#__PURE__*/React$1.createElement("div", {
626
+ className: "form-dropzone__thumb-image"
627
+ }, /*#__PURE__*/React$1.createElement("img", {
628
+ className: "form-dropzone__thumb-image-inner",
629
+ src: file.preview || file.image,
630
+ onLoad: () => {
631
+ // Revoke data uri after image is loaded
632
+ URL.revokeObjectURL(file.preview);
525
633
  }
526
- }, [change, onChange]);
634
+ })), file.error && /*#__PURE__*/React$1.createElement("div", null, /*#__PURE__*/React$1.createElement(Text, {
635
+ size: thumbNameTextSize,
636
+ textColor: thumbNameTextColor,
637
+ textWeight: thumbNameTextWeight,
638
+ textWrap: thumbNameTextWrap
639
+ }, fileErrorText || file.error)), showFilename && /*#__PURE__*/React$1.createElement("div", {
640
+ className: "form-dropzone__thumb-name"
641
+ }, /*#__PURE__*/React$1.createElement(Text, {
642
+ className: "form-dropzone__thumb-name-inner",
643
+ size: thumbNameTextSize,
644
+ textColor: thumbNameTextColor,
645
+ textWeight: thumbNameTextWeight,
646
+ textWrap: thumbNameTextWrap
647
+ }, file.name)), fileIsLoading && /*#__PURE__*/React$1.createElement("div", {
648
+ className: "form-dropzone__thumb-loader"
649
+ }, /*#__PURE__*/React$1.createElement(Loader, {
650
+ width: "fill",
651
+ height: "fill",
652
+ fill: "surfacePrimary",
653
+ itemFill: "surfaceItemAccent",
654
+ set: "simple"
655
+ })), /*#__PURE__*/React$1.createElement("div", {
656
+ className: clsx('form-dropzone__thumb-remove')
657
+ }, /*#__PURE__*/React$1.createElement(Button, {
658
+ className: "form-dropzone__thumb-remove-text",
659
+ appearance: removeThumbAppearance,
660
+ label: removeThumbText || 'Удалить',
661
+ labelTextWeight: removeThumbTextWeight,
662
+ shape: removeThumbShape,
663
+ onClick: event => removeFile(event, index)
664
+ })))), !filesList.length ? /*#__PURE__*/React$1.createElement("div", {
665
+ className: "form-dropzone__hint"
666
+ }, /*#__PURE__*/React$1.createElement(Text, {
667
+ className: "form-dropzone__hint-title",
668
+ size: hintTitleTextSize,
669
+ textColor: hintTitleTextColor,
670
+ textWeight: hintTitleTextWeight,
671
+ textWrap: hintTitleTextWrap
672
+ }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React$1.createElement(Text, {
673
+ className: "form-dropzone__hint-text",
674
+ size: hintDescriptionTextSize,
675
+ textColor: hintDescriptionTextColor,
676
+ textWeight: hintDescriptionTextWeight,
677
+ textWrap: hintDescriptionTextWrap
678
+ }, hintDescription)) : /*#__PURE__*/React$1.createElement("div", {
679
+ className: "form-dropzone__hint form-dropzone__hint_type_add-more"
680
+ }, /*#__PURE__*/React$1.createElement(Text, {
681
+ className: "form-dropzone__hint-title",
682
+ size: hintTitleTextSize,
683
+ textColor: hintTitleTextColor,
684
+ textWeight: hintTitleTextWeight,
685
+ textWrap: hintTitleTextWrap
686
+ }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React$1.createElement(Text, {
687
+ className: "form-dropzone__hint-text",
688
+ size: hintDescriptionTextSize,
689
+ textColor: hintDescriptionTextColor,
690
+ textWeight: hintDescriptionTextWeight,
691
+ textWrap: hintDescriptionTextWrap
692
+ }, hintDescription)))), fileError && /*#__PURE__*/React$1.createElement("div", {
693
+ className: "form-field__message"
694
+ }, /*#__PURE__*/React$1.createElement(Text, {
695
+ className: "form-field__message-item form-field__message-item_type_message",
696
+ size: errorMessageTextSize,
697
+ textColor: errorMessageTextColor,
698
+ textWeight: errorMessageTextWeight
699
+ }, fileError)));
700
+ });
701
+ async function getFileByURL(url) {
702
+ try {
703
+ const response = await axios({
704
+ url: url,
705
+ responseType: 'blob'
706
+ });
707
+ const blobObject = response.data;
708
+ const dirtyFilename = response.headers['content-disposition']?.split('filename=')[1];
709
+ // Remove double quotes
710
+ let filename = dirtyFilename?.substring(1).slice(0, -1);
711
+ if (!filename) {
712
+ filename = url.split('/').at(-1);
713
+ // const typeParts = blobObject.type.split('/')
714
+ // const fileType = typeParts[typeParts.length - 1]
715
+ // filename = `${new Date().getTime()}.${fileType}`
716
+ }
717
+ return new File([blobObject], filename, {
718
+ type: blobObject.type
719
+ });
720
+ } catch (error) {
721
+ console.log('error: ', error);
722
+ return null;
723
+ }
724
+ }
725
+ async function convertToFile(inputValue, isPreviews) {
726
+ let newFile = null;
727
+
728
+ // Download image by url and save as File instance
729
+ const isURL = typeof inputValue === 'string' && inputValue.includes('/');
730
+ if (inputValue.image || isURL) {
731
+ newFile = await getFileByURL(inputValue.image || inputValue);
732
+ if (newFile) {
733
+ setFileDataURL(newFile);
734
+ }
735
+ }
736
+
737
+ // Convert dataURL to File instance
738
+ if (inputValue.dataURL) {
739
+ newFile = createFileFromDataURL(inputValue.name || inputValue.path, inputValue.dataURL);
740
+ newFile.dataURL = inputValue.dataURL;
741
+ }
742
+
743
+ // Save new File to state
744
+ if (newFile) {
745
+ newFile.id = inputValue.id;
746
+ if (isPreviews) {
747
+ newFile.preview = URL.createObjectURL(newFile);
748
+ }
749
+ }
750
+ return newFile;
751
+ }
752
+ function setFileDataURL(file, resolve) {
753
+ resolve = resolve || (() => {});
754
+ // Init reader and save his file
755
+ const reader = new FileReader();
756
+ reader._readedFile = file;
757
+
758
+ // Set handlers
759
+ reader.onabort = () => resolve();
760
+ reader.onerror = () => resolve();
761
+ reader.onload = event => {
762
+ event.target._readedFile.dataURL = reader.result;
763
+ resolve();
764
+ };
765
+ // Run reader
766
+ if (file instanceof File) {
767
+ reader.readAsDataURL(file);
768
+ } else {
769
+ resolve();
770
+ }
771
+ }
772
+
773
+ const FileInput = /*#__PURE__*/React$1.memo(function FileInput(props) {
774
+ const {
775
+ className,
776
+ name,
777
+ width,
778
+ maxFiles,
779
+ maxSize,
780
+ label,
781
+ fileErrorText,
782
+ classNameGroupItem,
783
+ dropzoneProps,
784
+ fieldProps,
785
+ hintDescription,
786
+ hintTitle,
787
+ showFilename,
788
+ showMessage,
789
+ isPreviews,
790
+ isRequired,
791
+ onAddFiles,
792
+ onDeleteFile
793
+ } = props;
794
+ const propsGenerator = useDevicePropsGenerator(props);
795
+ const {
796
+ size,
797
+ fill,
798
+ fillHover,
799
+ labelTextColor,
800
+ borderColorHover,
801
+ borderType,
802
+ borderWidth,
803
+ errorMessageTextColor,
804
+ errorMessageTextSize,
805
+ errorMessageTextWeight,
806
+ hintDescriptionTextColor,
807
+ hintDescriptionTextSize,
808
+ hintDescriptionTextWeight,
809
+ hintDescriptionTextWrap,
810
+ hintTitleTextColor,
811
+ hintTitleTextSize,
812
+ hintTitleTextWeight,
813
+ hintTitleTextWrap,
814
+ removeThumbAppearance,
815
+ removeThumbText,
816
+ removeThumbTextWeight,
817
+ removeThumbShape,
818
+ shape,
819
+ thumbBorderColor,
820
+ thumbBorderColorHover,
821
+ thumbBorderType,
822
+ thumbBorderWidth,
823
+ thumbColumn = 1,
824
+ thumbDirection = 'vertical',
825
+ thumbNameTextColor,
826
+ thumbNameTextSize,
827
+ thumbNameTextWeight,
828
+ thumbNameTextWrap
829
+ } = propsGenerator;
527
830
  return /*#__PURE__*/React$1.createElement(Field, {
528
- initialValue: initialValue,
529
831
  name: name
530
832
  }, function Render({
531
833
  input,
@@ -537,81 +839,127 @@ const ChoiceField = /*#__PURE__*/React$1.memo(function ChoiceField(props) {
537
839
  * React Hooks must be called in a React function component or a
538
840
  * custom React Hook function.
539
841
  */
540
- const activeOption = useMemo(() => {
541
- const emptyOption = {
542
- value: null,
543
- label: null
544
- };
545
- if (input.value) {
546
- const currentOption = options.find(option => option.value === input.value);
547
- return currentOption || emptyOption;
548
- }
549
- return emptyOption;
550
- }, [input.value]);
842
+
551
843
  const {
552
- isErrorState,
553
- isValidState,
554
844
  errorKey,
555
- errorMessage
845
+ errorMessage,
846
+ isErrorState,
847
+ isValidState
556
848
  } = useFieldValidationState({
557
849
  fieldProps: fieldProps,
558
850
  input: input,
559
851
  meta: meta
560
852
  });
561
853
  const updatedInputProps = useValidationAppearanceInputProps({
562
- inputProps: inputProps,
854
+ inputProps: props,
563
855
  validationStateKey: isErrorState ? errorKey : 'success'
564
856
  });
857
+
858
+ /** TODO:
859
+ * REFACTOR PROPERTIES
860
+ */
565
861
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
566
- className: clsx('form-field_type_choice', 'form__item_type_choice', classNameGroupItem),
862
+ className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
863
+ width: width,
567
864
  label: label,
865
+ labelTextColor: labelTextColor,
568
866
  errorKey: errorKey,
569
867
  errorMessage: errorMessage,
570
868
  isErrorState: isErrorState,
571
869
  metaError: meta.error,
572
- isDisabled: isDisabled,
573
- fieldClassName: "form-choice",
870
+ fieldClassName: "form-dropzone",
574
871
  inputName: input.name,
575
- inputValue: input.value || [],
576
- messageType: messageType,
872
+ inputValue: input.value,
577
873
  metaActive: meta.active,
874
+ metaTouched: meta.touched,
578
875
  showMessage: showMessage,
579
876
  isRequired: isRequired,
580
877
  isValidState: isValidState
581
- }, fieldProps), /*#__PURE__*/React$1.createElement(Choice, Object.assign({
582
- className: clsx(meta.active && 'form-choice_state_focus', meta.error && meta.touched && `form-choice_state_${errorKey}`),
583
- name: input.name,
584
- isDisabled: isDisabled,
585
- active: activeOption,
586
- inputValue: input.value || [],
587
- options: options,
588
- placeholder: placeholder,
589
- isCheckbox: isCheckbox,
590
- isRequired: isRequired,
591
- setActiveSegment: setActiveSegment
592
- }, updatedInputProps)));
878
+ }, fieldProps), /*#__PURE__*/React$1.createElement(FileInputDropzone, {
879
+ className: className,
880
+ maxFiles: maxFiles,
881
+ maxSize: maxSize,
882
+ size: size,
883
+ fill: fill,
884
+ fillHover: fillHover,
885
+ borderColor: updatedInputProps.borderColor,
886
+ borderColorHover: borderColorHover,
887
+ borderType: borderType,
888
+ borderWidth: borderWidth,
889
+ errorMessageTextColor: errorMessageTextColor,
890
+ errorMessageTextSize: errorMessageTextSize,
891
+ errorMessageWeight: errorMessageTextWeight,
892
+ fileErrorText: fileErrorText,
893
+ metaError: meta.error,
894
+ dropzoneProps: dropzoneProps,
895
+ hintDescription: hintDescription,
896
+ hintDescriptionTextColor: hintDescriptionTextColor,
897
+ hintDescriptionTextSize: hintDescriptionTextSize,
898
+ hintDescriptionTextWeight: hintDescriptionTextWeight,
899
+ hintDescriptionTextWrap: hintDescriptionTextWrap,
900
+ hintTitle: hintTitle,
901
+ hintTitleTextColor: hintTitleTextColor,
902
+ hintTitleTextSize: hintTitleTextSize,
903
+ hintTitleTextWeight: hintTitleTextWeight,
904
+ hintTitleTextWrap: hintTitleTextWrap,
905
+ inputName: input.name,
906
+ inputValue: input.value,
907
+ metaTouched: meta.touched,
908
+ removeThumbAppearance: removeThumbAppearance,
909
+ removeThumbText: removeThumbText,
910
+ removeThumbTextWeight: removeThumbTextWeight,
911
+ removeThumbShape: removeThumbShape,
912
+ shape: shape,
913
+ showFilename: showFilename,
914
+ thumbBorderColor: thumbBorderColor,
915
+ thumbBorderColorHover: thumbBorderColorHover,
916
+ thumbBorderType: thumbBorderType,
917
+ thumbBorderWidth: thumbBorderWidth,
918
+ thumbColumn: thumbColumn,
919
+ thumbDirection: thumbDirection,
920
+ thumbNameTextColor: thumbNameTextColor,
921
+ thumbNameTextSize: thumbNameTextSize,
922
+ thumbNameTextWeight: thumbNameTextWeight,
923
+ thumbNameTextWrap: thumbNameTextWrap,
924
+ isPreviews: isPreviews,
925
+ onAddFiles: onAddFiles,
926
+ onDeleteFile: onDeleteFile
927
+ }));
593
928
  });
594
929
  });
595
930
 
596
- const CustomField = /*#__PURE__*/React$1.memo(function CustomField(props) {
931
+ const defaultGroupProps = {
932
+ width: 'fill',
933
+ labelTextColor: 'surfaceTextPrimary',
934
+ labelTextSize: 'h5',
935
+ labelTextWeight: 500
936
+ };
937
+
938
+ const FormBlockGroup = /*#__PURE__*/React$1.memo(function Group(props) {
597
939
  const {
598
- Component,
599
- isDisabled,
600
- isRequired,
940
+ className,
601
941
  name,
602
- initialValue,
603
- fieldProps = {},
604
- classNameGroupItem,
605
- showMessage,
606
- clearIcon,
607
- clearIconFill,
608
- clearIconFillHover,
609
- clearIconShape,
610
- clearIconSize,
611
- onClickClearIcon
942
+ label,
943
+ labelTextColor,
944
+ labelTextSize,
945
+ labelTextWeight,
946
+ message,
947
+ column,
948
+ dataTour,
949
+ title,
950
+ titleTextSize,
951
+ titleTextColor,
952
+ titleTextWeight,
953
+ messageTextColor = 'surfaceTextTertiary',
954
+ messageTextSize = 's',
955
+ messageTextWeight,
956
+ showGroupMessage,
957
+ before,
958
+ after,
959
+ isHidden,
960
+ children
612
961
  } = props;
613
962
  return /*#__PURE__*/React$1.createElement(Field, {
614
- initialValue: initialValue,
615
963
  name: name
616
964
  }, function Render({
617
965
  input,
@@ -623,84 +971,70 @@ const CustomField = /*#__PURE__*/React$1.memo(function CustomField(props) {
623
971
  * React Hooks must be called in a React function component or a
624
972
  * custom React Hook function.
625
973
  */
626
-
627
974
  const {
628
975
  isErrorState,
629
- isValidState,
630
976
  errorKey,
631
977
  errorMessage
632
978
  } = useFieldValidationState({
633
- fieldProps: fieldProps,
979
+ fieldProps: props,
980
+ // or fieldProps?
634
981
  input: input,
635
982
  meta: meta
636
983
  });
637
- const updatedInputProps = useValidationAppearanceInputProps({
638
- validationStateKey: isErrorState ? errorKey : 'success',
639
- // For "Custom" field we pass all props. Can contain some special props, we don't known.
640
- inputProps: props
984
+ const updatedProps = useValidationAppearanceInputProps({
985
+ inputProps: props,
986
+ validationStateKey: isErrorState ? errorKey : 'success'
641
987
  });
642
- return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
643
- className: clsx('form-field_type_custom', 'form__item_type_custom', classNameGroupItem),
644
- errorKey: errorKey,
645
- errorMessage: errorMessage,
646
- fieldClassName: 'form-custom',
647
- inputName: input.name,
648
- inputValue: input.value,
649
- isDisabled: isDisabled,
650
- isErrorState: isErrorState,
651
- isRequired: isRequired,
652
- isValidState: isValidState,
653
- metaActive: meta.active,
654
- metaError: meta.error,
655
- showMessage: showMessage
656
- }, fieldProps), /*#__PURE__*/React$1.createElement(Component, Object.assign({}, updatedInputProps, {
657
- input: input,
658
- isDisabled: isDisabled,
659
- meta: meta
660
- })), clearIcon && /*#__PURE__*/React$1.createElement(Icon, {
661
- className: "form-field__icon",
662
- iconFill: clearIconFill,
663
- iconFillHover: clearIconFillHover,
664
- imageSrc: clearIcon,
665
- shape: clearIconShape,
666
- size: clearIconSize,
667
- SvgImage: clearIcon,
668
- onClick: onClickClearIcon
669
- }));
988
+ return /*#__PURE__*/React$1.createElement("div", {
989
+ className: clsx('form__group', className, isHidden && 'form__group_hidden', column && `form__group_column_${column}`),
990
+ "data-tour": dataTour
991
+ }, /*#__PURE__*/React$1.createElement("div", {
992
+ className: "form__group-wrapper"
993
+ }, before, title && /*#__PURE__*/React$1.createElement("div", {
994
+ className: "form__group-title"
995
+ }, /*#__PURE__*/React$1.createElement(Title, {
996
+ size: titleTextSize,
997
+ textColor: titleTextColor,
998
+ textWeight: titleTextWeight
999
+ }, title)), label && /*#__PURE__*/React$1.createElement("div", {
1000
+ className: "form__group-label"
1001
+ }, /*#__PURE__*/React$1.createElement(Text, {
1002
+ size: labelTextSize,
1003
+ textColor: labelTextColor,
1004
+ textWeight: labelTextWeight
1005
+ }, label)), /*#__PURE__*/React$1.createElement("div", {
1006
+ className: "form__group-items"
1007
+ }, children), after), showGroupMessage && /*#__PURE__*/React$1.createElement(React$1.Fragment, null, isErrorState && errorMessage && /*#__PURE__*/React$1.createElement(Text, {
1008
+ className: `form__group-message form__group-message_type-${errorKey}`,
1009
+ id: `${name}-error`,
1010
+ size: updatedProps.messageTextSize,
1011
+ textColor: updatedProps.messageTextColor,
1012
+ textWeight: updatedProps.messageTextWeight
1013
+ }, errorMessage), Boolean(message) && (!isErrorState || !errorMessage) && /*#__PURE__*/React$1.createElement(Text, {
1014
+ className: "form__group-message",
1015
+ size: messageTextSize,
1016
+ textColor: messageTextColor,
1017
+ textWeight: messageTextWeight
1018
+ }, message), !isErrorState && !message && /*#__PURE__*/React$1.createElement(Text, {
1019
+ className: "form__group-message",
1020
+ size: messageTextSize
1021
+ }, '\u00A0')));
670
1022
  });
671
1023
  });
672
1024
 
673
- const defaultCodeProps = {
674
- fieldProps: {
675
- size: 'l',
676
- labelTextColor: 'surfaceTextPrimary',
677
- labelTextSize: 's',
678
- labelTextWeight: 'normal',
679
- helpText: 'Supporting text',
680
- helpTextColor: 'surfaceTextPrimary',
681
- helpTextSize: 's',
682
- helpTextWeight: 'normal',
683
- showMessage: true
684
- },
685
- inputProps: {
686
- width: 'fill',
687
- size: 'l',
688
- fill: 'surfaceSecondary',
689
- inputBorderColor: 'surfaceBorderTertiary',
690
- inputBorderColorHover: 'surfaceBorderQuaternary',
691
- inputBorderFocusColor: 'surfaceBorderAccent',
692
- inputCaretColor: 'surfaceItemAccent',
693
- inputFill: 'surfacePrimary',
694
- inputFillHover: 'surfaceSecondary',
695
- inputPlaceholderTextColor: 'surfaceSecondary',
696
- inputSize: 'l',
697
- inputTextColor: 'surfaceSecondary',
698
- inputTextSize: 'xxl',
699
- inputTextWeight: 'normal'
700
- }
1025
+ const defaultCheckboxProps = {
1026
+ appearance: 'defaultPrimary',
1027
+ width: 'fill',
1028
+ size: 'm',
1029
+ labelTextColor: 'surfaceTextPrimary',
1030
+ labelTextColorDisabled: 'surfaceTextDisabled',
1031
+ labelTextSize: 's',
1032
+ descTextSize: 's',
1033
+ errorBorderColor: 'errorBorderSecondary',
1034
+ requiredBorderColor: 'warningBorderSecondary'
701
1035
  };
702
1036
 
703
- const CodeField = /*#__PURE__*/React$1.memo(function CodeField(props) {
1037
+ const FormFieldCheckbox = /*#__PURE__*/React$1.memo(function FormFieldCheckbox(props) {
704
1038
  const {
705
1039
  name,
706
1040
  initialValue,
@@ -709,9 +1043,11 @@ const CodeField = /*#__PURE__*/React$1.memo(function CodeField(props) {
709
1043
  fieldProps = {},
710
1044
  inputProps = {},
711
1045
  showMessage,
712
- isRequired
1046
+ isRequired,
1047
+ onChange
713
1048
  } = props;
714
1049
  return /*#__PURE__*/React$1.createElement(Field, {
1050
+ type: "checkbox",
715
1051
  name: name,
716
1052
  initialValue: initialValue
717
1053
  }, function Render({
@@ -725,10 +1061,18 @@ const CodeField = /*#__PURE__*/React$1.memo(function CodeField(props) {
725
1061
  * custom React Hook function.
726
1062
  */
727
1063
 
1064
+ const onChangeField = useCallback(event => {
1065
+ input.onChange(event);
1066
+ if (onChange) {
1067
+ onChange(event.target.checked, input.name);
1068
+ }
1069
+ }, [onChange, input.onChange]);
728
1070
  const {
1071
+ errorKey,
1072
+ errorMessage,
729
1073
  isErrorState,
730
- isValidState,
731
- errorKey} = useFieldValidationState({
1074
+ isValidState
1075
+ } = useFieldValidationState({
732
1076
  fieldProps: fieldProps,
733
1077
  input: input,
734
1078
  meta: meta
@@ -738,79 +1082,78 @@ const CodeField = /*#__PURE__*/React$1.memo(function CodeField(props) {
738
1082
  validationStateKey: isErrorState ? errorKey : 'success'
739
1083
  });
740
1084
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
741
- className: clsx('form-field_type_code', 'form__item_type_code', classNameGroupItem),
742
- fieldClassName: 'form-code',
1085
+ className: clsx('form-field_type_checkbox', 'form__item_type_checkbox', classNameGroupItem),
1086
+ errorKey: errorKey,
1087
+ errorMessage: errorMessage,
1088
+ isErrorState: isErrorState,
1089
+ metaError: meta.error,
1090
+ isDisabled: isDisabled,
1091
+ fieldClassName: "form-checkbox",
743
1092
  inputName: input.name,
744
- inputValue: input.value,
1093
+ inputValue: input.checked,
745
1094
  metaActive: meta.active,
746
1095
  showMessage: showMessage,
1096
+ tag: "label",
747
1097
  isRequired: isRequired,
748
1098
  isValidState: isValidState
749
- }, fieldProps), /*#__PURE__*/React$1.createElement(Code, Object.assign({
1099
+ }, fieldProps), /*#__PURE__*/React$1.createElement(Checkbox, Object.assign({
1100
+ type: "checkbox",
750
1101
  name: input.name,
751
1102
  isDisabled: isDisabled,
752
1103
  autoComplete: "nope",
753
- value: input.value,
1104
+ checked: input.checked,
754
1105
  onBlur: input.onBlur,
755
- onChange: input.onChange,
1106
+ onChange: onChangeField,
756
1107
  onFocus: input.onFocus
757
1108
  }, updatedInputProps)));
758
1109
  });
759
1110
  });
760
1111
 
761
- const defaultDatepickerProps = {
762
- dateFormat: 'dd/MM/yyyy - HH:mm',
763
- readOnly: false,
764
- selectsRange: false,
765
- showTimeSelect: true,
766
- timeCaption: 'Время',
767
- timeFormat: 'p',
768
- timeIntervals: 60,
769
- isClearable: true,
770
- isStartDefaultNull: true
1112
+ const defaultChipsProps = {
1113
+ appearance: 'surfacePrimary sizeM rounded',
1114
+ width: 'fill',
1115
+ errorBorderColor: 'errorBorderSecondary',
1116
+ requiredBorderColor: 'warningBorderSecondary'
771
1117
  };
772
1118
 
773
- function DatePickerField(props) {
1119
+ function FormFieldChips(props) {
774
1120
  const {
775
1121
  name,
1122
+ initialValue,
776
1123
  isDisabled,
777
1124
  classNameGroupItem,
778
- datePickerProps,
779
- fieldProps = {},
780
- inputProps = {},
1125
+ emptyMessage,
1126
+ emptyMessageTextColor,
1127
+ emptyMessageTextSize,
1128
+ fieldProps,
1129
+ inputProps,
1130
+ options,
781
1131
  showMessage,
782
1132
  isRequired,
783
1133
  onChange
784
1134
  } = props;
1135
+ const {
1136
+ change
1137
+ } = useForm();
1138
+
1139
+ // Callback for value changes
1140
+ const onChangeSomeInput = useCallback((inputValue, newOptionValue) => {
1141
+ const updatedValues = inputValue.includes(newOptionValue) ? inputValue.filter(selectedValue => selectedValue !== newOptionValue) : [...inputValue, newOptionValue];
1142
+ change(name, updatedValues);
1143
+ onChange && onChange(updatedValues);
1144
+ }, [change, name, onChange]);
1145
+ useEffect(() => {
1146
+ initialValue && change(name, initialValue);
1147
+ // update the form value only when the initialValue changes, so use disable eslint to ignore the warning
1148
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1149
+ }, [initialValue]);
785
1150
  return /*#__PURE__*/React$1.createElement(Field, {
786
- name: name
1151
+ name: name,
1152
+ initialValue: initialValue
787
1153
  }, function Render({
788
1154
  input,
789
1155
  meta
790
1156
  }) {
791
- /** Note:
792
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
793
- * React Hooks cannot be called inside a callback.
794
- * React Hooks must be called in a React function component or a
795
- * custom React Hook function.
796
- */
797
-
798
- const onChangeField = useCallback((startDate, endDate) => {
799
- if (!datePickerProps.selectsRange) {
800
- // When we need to save single date, value is date
801
- // TODO: make object with one date? need to check all forms with DatePickerField
802
- input.onChange(startDate);
803
- } else {
804
- // When we need to save range, value is object with two date
805
- input.onChange({
806
- endDate,
807
- startDate
808
- });
809
- }
810
- if (onChange) {
811
- onChange(startDate, endDate);
812
- }
813
- }, [input.onChange, onChange]);
814
1157
  const {
815
1158
  errorKey,
816
1159
  errorMessage,
@@ -825,454 +1168,170 @@ function DatePickerField(props) {
825
1168
  inputProps: inputProps,
826
1169
  validationStateKey: isErrorState ? errorKey : 'success'
827
1170
  });
1171
+ const activeOptionsList = useMemo(() => {
1172
+ const emptyOptionsList = [{
1173
+ label: null,
1174
+ value: null
1175
+ }];
1176
+ if (input?.value) {
1177
+ const currentOptions = options.filter(option => input.value?.includes(option.value));
1178
+ return currentOptions || emptyOptionsList;
1179
+ }
1180
+ return emptyOptionsList;
1181
+ }, [input.value]);
828
1182
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
829
- className: clsx('form-field_type_datepicker', 'form__item_type_datepicker', classNameGroupItem),
1183
+ className: clsx('form-field_type_chips', 'form__item_type_chips', classNameGroupItem),
830
1184
  errorKey: errorKey,
831
1185
  errorMessage: errorMessage,
832
1186
  isErrorState: isErrorState,
833
1187
  metaError: meta.error,
834
1188
  isDisabled: isDisabled,
835
- fieldClassName: "form-datepicker",
1189
+ fieldClassName: "form-chips",
836
1190
  inputName: input.name,
837
- inputValue: input.value || '',
1191
+ inputValue: input.value,
838
1192
  metaActive: meta.active,
839
1193
  showMessage: showMessage,
840
1194
  isRequired: isRequired,
841
1195
  isValidState: isValidState
842
- }, fieldProps), /*#__PURE__*/React$1.createElement(DatePickerInput, {
843
- name: input.name,
844
- isDisabled: isDisabled,
845
- datePickerProps: datePickerProps,
846
- endValue: datePickerProps.selectsRange ? input.value.endDate : null,
847
- inputProps: updatedInputProps,
848
- value: datePickerProps.selectsRange ? input.value.startDate : input.value,
849
- onBlur: input.onBlur,
850
- onChange: onChangeField,
851
- onFocus: input.onFocus
852
- }));
1196
+ }, fieldProps), options.length ? /*#__PURE__*/React$1.createElement(ChipsGroup, {
1197
+ direction: "horizontal",
1198
+ gap: "1m",
1199
+ wrap: "wrap"
1200
+ }, options.map(option => /*#__PURE__*/React$1.createElement(Chips, Object.assign({
1201
+ className: clsx(meta.active && 'form-chips_state_focus', meta.error && meta.touched && `form-chips_state_${errorKey}`),
1202
+ key: option.value,
1203
+ label: option.label,
1204
+ isDisabled: option.isDisabled,
1205
+ value: option.value,
1206
+ isActive: activeOptionsList.some(activeOption => activeOption.value === option.value),
1207
+ onClick: () => onChangeSomeInput(input.value, option.value)
1208
+ }, updatedInputProps)))) : /*#__PURE__*/React$1.createElement(Text, {
1209
+ size: emptyMessageTextSize,
1210
+ textColor: emptyMessageTextColor
1211
+ }, emptyMessage));
853
1212
  });
854
1213
  }
855
1214
 
856
- const defaultDropzoneProps = {
857
- fill: 'surfacePrimary',
858
- borderColor: 'surfaceBorderTertiary',
859
- borderColorHover: 'surfaceBorderQuaternary',
860
- hintTitle: 'Перетащите изображение или выберите файл с компьютера',
861
- hintTitleTextColor: 'surfaceTextPrimary',
862
- hintTitleTextSize: 'm',
863
- removeThumbText: 'удалить',
864
- removeThumbTextColor: 'errorTextPrimary',
865
- removeThumbTextHoverColor: 'errorTextPrimaryHover',
866
- removeThumbTextSize: 's',
867
- shape: 'rounded',
868
- showFilename: true,
869
- thumbBorderColor: 'surfaceBorderTertiary',
870
- thumbBorderColorHover: 'surfaceBorderQuaternary',
871
- thumbBorderWidth: 1,
872
- thumbNameTextColor: 'surfaceTextPrimary',
873
- thumbNameTextSize: 's',
874
- isPreviews: true
1215
+ const defaultChoiceProps = {
1216
+ appearance: 'defaultPrimary sizeM solid rounded',
1217
+ width: 'fill',
1218
+ errorBorderColor: 'errorBorderPrimary',
1219
+ requiredBorderColor: 'warningBorderPrimary'
875
1220
  };
876
1221
 
877
- const FileInputDropzone = /*#__PURE__*/React$1.memo(function FileInputDropzone(props) {
1222
+ const FormFieldChoice = /*#__PURE__*/React$1.memo(function FormFieldChoice(props) {
878
1223
  const {
879
- className,
880
- maxFiles,
881
- maxSize,
882
- size,
883
- fileErrorText,
884
- dropzoneProps = {},
885
- hintDescription,
886
- hintTitle,
887
- inputName,
888
- inputValue,
889
- showFilename,
890
- thumbColumn,
891
- isPreviews,
892
- onAddFiles,
893
- onDeleteFile
1224
+ name,
1225
+ initialValue,
1226
+ label,
1227
+ isDisabled,
1228
+ classNameGroupItem,
1229
+ fieldProps,
1230
+ inputProps,
1231
+ messageType,
1232
+ options,
1233
+ placeholder,
1234
+ showMessage,
1235
+ isCheckbox,
1236
+ isRequired,
1237
+ onChange
894
1238
  } = props;
895
-
896
- // TODO: delete react-final-form things out of here?
897
1239
  const {
898
1240
  change
899
1241
  } = useForm();
900
- const [fileError, setFileError] = useState('');
901
- const [fileIsLoading, setFileIsLoading] = useState(false);
902
- const filesList = useMemo(() => inputValue ? castArray(inputValue) : [], [inputValue]);
903
- const changeFormState = useCallback(newFiles => {
904
- // If max files in dropzone is 1 - return file as it self, else as array of files
905
- // ps: for old projects compatibility
906
- const toSave = dropzoneProps.maxFiles == 1 ? newFiles[0] : newFiles;
907
- change(inputName, toSave);
908
- return toSave;
909
- },
910
- // If "inputName" will be changes, then it should be a different field
911
- // eslint-disable-next-line react-hooks/exhaustive-deps
912
- [dropzoneProps, change]);
913
-
914
- //
915
- const convertFiledValueAndSaveAsFiles = useCallback(async currentFilesList => {
916
- setFileIsLoading(true);
917
- const newFiles = [];
918
- for (const fileItem of currentFilesList) {
919
- if (typeof fileItem === 'string') {
920
- const newFile = await convertToFile(fileItem, isPreviews);
921
- if (newFile) {
922
- newFiles.push(newFile);
923
- }
924
- } else {
925
- newFiles.push(fileItem);
926
- }
927
- }
928
- changeFormState(newFiles);
929
- setFileIsLoading(false);
930
- }, [isPreviews, changeFormState]);
931
-
932
- // Delete file from dropzone
933
- const removeFile = useCallback((event, index) => {
934
- event.stopPropagation();
935
- event.preventDefault();
936
- const newFiles = [...filesList];
937
- newFiles.splice(index, 1);
938
- if (onDeleteFile) {
939
- onDeleteFile(filesList[index], inputName);
1242
+ const setActiveSegment = useCallback((option, isChecked) => {
1243
+ change(name, isChecked && option.value);
1244
+ if (onChange) {
1245
+ onChange(option.value, name, isChecked);
940
1246
  }
941
- changeFormState(newFiles);
942
- },
943
- // If "inputName" will be changes, then it should be a different field
944
- // eslint-disable-next-line react-hooks/exhaustive-deps
945
- [filesList, changeFormState, onDeleteFile]);
946
-
947
- // Create dropzone options
948
- const {
949
- getInputProps,
950
- getRootProps
951
- } = useDropzone({
952
- maxFiles: maxFiles || 5,
953
- maxSize: maxSize || 10485760,
954
- // 10mb
955
- // accept: { 'image/*': [] },
956
- ...dropzoneProps,
957
- getFilesFromEvent: async event => {
958
- const result = await fromEvent(event);
959
- const newFiles = result.filter(item => item instanceof File);
960
- // Add exists and new files to accepted(or rejected)
961
- return [...filesList, ...newFiles];
962
- },
963
- onDropAccepted: acceptedFiles => {
964
- // If dropped files has accepted and we need a previews
965
- if (isPreviews) {
966
- // Add preview to every file
967
- acceptedFiles.forEach(file => {
968
- if (!file.error) {
969
- file.preview = URL.createObjectURL(file);
970
- }
971
- });
1247
+ }, [change, onChange]);
1248
+ return /*#__PURE__*/React$1.createElement(Field, {
1249
+ initialValue: initialValue,
1250
+ name: name
1251
+ }, function Render({
1252
+ input,
1253
+ meta
1254
+ }) {
1255
+ /** Note:
1256
+ * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
1257
+ * React Hooks cannot be called inside a callback.
1258
+ * React Hooks must be called in a React function component or a
1259
+ * custom React Hook function.
1260
+ */
1261
+ const activeOption = useMemo(() => {
1262
+ const emptyOption = {
1263
+ value: null,
1264
+ label: null
1265
+ };
1266
+ if (input.value) {
1267
+ const currentOption = options.find(option => option.value === input.value);
1268
+ return currentOption || emptyOption;
972
1269
  }
973
- // Save to form data (including empty when files are not valid)
974
- const filesToSave = changeFormState(acceptedFiles);
975
- setFileError('');
976
-
977
- // Save DataURL for all files
978
- const readerPromisesList = acceptedFiles.map(file => {
979
- return new Promise(resolve => setFileDataURL(file, resolve));
980
- });
981
- // Save files to form values
982
- Promise.all(readerPromisesList).then(() => {
983
- if (onAddFiles) {
984
- onAddFiles(filesToSave, inputName);
985
- }
986
- });
987
- },
988
- onDropRejected: rejectedFiles => {
989
- // If dropped files has rejected
990
- if (rejectedFiles.length) {
991
- let fileErrorMessage = 'Ошибка при добавлении файла';
992
- const firstFileErrorItem = rejectedFiles[0].errors[0];
993
- if (firstFileErrorItem) {
994
- if (firstFileErrorItem.code === ErrorCode.TooManyFiles) {
995
- fileErrorMessage = `Максимальное количество файлов: ${maxFiles}`;
996
- } else {
997
- fileErrorMessage = firstFileErrorItem.message;
998
- }
999
- }
1000
- // Show error
1001
- setFileError(fileErrorMessage);
1002
- } else {
1003
- // Else clean error
1004
- setFileError('');
1005
- }
1006
- }
1007
- });
1008
- useEffect(() => {
1009
- const currentFilesList = castArray(inputValue);
1010
- const isNeedToConvert = currentFilesList.some(fileItem => typeof fileItem === 'string');
1011
- if (isNeedToConvert) {
1012
- // First time convert value to Files and save to local and form state
1013
- convertFiledValueAndSaveAsFiles(currentFilesList);
1014
- }
1015
-
1016
- // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
1017
- return () => {
1018
- filesList.forEach(file => {
1019
- if (file?.preview) {
1020
- URL.revokeObjectURL(file.preview);
1021
- }
1022
- });
1023
- };
1024
- // eslint-disable-next-line react-hooks/exhaustive-deps
1025
- }, [inputValue]);
1026
- const propsGenerator = useDevicePropsGenerator(props);
1027
- const {
1028
- fillClass,
1029
- fillHoverClass,
1030
- borderColorClass,
1031
- borderColorHoverClass,
1032
- borderTypeClass,
1033
- borderWidthClass,
1034
- errorMessageTextColor,
1035
- errorMessageTextSize,
1036
- errorMessageTextWeight,
1037
- hintDescriptionTextColor,
1038
- hintDescriptionTextSize,
1039
- hintDescriptionTextWeight,
1040
- hintDescriptionTextWrap,
1041
- hintTitleTextColor,
1042
- hintTitleTextSize,
1043
- hintTitleTextWeight,
1044
- hintTitleTextWrap,
1045
- removeThumbAppearance,
1046
- removeThumbShape,
1047
- removeThumbText,
1048
- removeThumbTextWeight,
1049
- shapeClass,
1050
- thumbBorderColorClass,
1051
- thumbBorderColorHoverClass,
1052
- thumbBorderTypeClass,
1053
- thumbBorderWidthClass,
1054
- thumbDirectionClass,
1055
- thumbNameTextColor,
1056
- thumbNameTextSize,
1057
- thumbNameTextWeight,
1058
- thumbNameTextWrap
1059
- } = propsGenerator;
1060
- return /*#__PURE__*/React$1.createElement(React$1.Fragment, null, /*#__PURE__*/React$1.createElement("div", getRootProps({
1061
- className: `form-dropzone__dropzone dropzone ${className} form-dropzone__dropzone_size_${size} ${shapeClass}`
1062
- }), /*#__PURE__*/React$1.createElement("input", Object.assign({}, getInputProps(), {
1063
- name: inputName
1064
- })), /*#__PURE__*/React$1.createElement("div", {
1065
- className: clsx('form-dropzone__dropzone-wrapper', thumbColumn && `form-dropzone__dropzone-wrapper_column_${thumbColumn}`, fillClass, fillHoverClass, borderWidthClass, borderColorClass, borderColorHoverClass, borderTypeClass)
1066
- }, filesList.map((file, index) => /*#__PURE__*/React$1.createElement("aside", {
1067
- className: clsx('form-dropzone__thumb', fillClass, thumbDirectionClass, thumbBorderWidthClass, thumbBorderColorClass, thumbBorderColorHoverClass, thumbBorderTypeClass),
1068
- key: file.id || `${file.name}_${index}`
1069
- }, isPreviews && !file.error && /*#__PURE__*/React$1.createElement("div", {
1070
- className: "form-dropzone__thumb-image"
1071
- }, /*#__PURE__*/React$1.createElement("img", {
1072
- className: "form-dropzone__thumb-image-inner",
1073
- src: file.preview || file.image,
1074
- onLoad: () => {
1075
- // Revoke data uri after image is loaded
1076
- URL.revokeObjectURL(file.preview);
1077
- }
1078
- })), file.error && /*#__PURE__*/React$1.createElement("div", null, /*#__PURE__*/React$1.createElement(Text, {
1079
- size: thumbNameTextSize,
1080
- textColor: thumbNameTextColor,
1081
- textWeight: thumbNameTextWeight,
1082
- textWrap: thumbNameTextWrap
1083
- }, fileErrorText || file.error)), showFilename && /*#__PURE__*/React$1.createElement("div", {
1084
- className: "form-dropzone__thumb-name"
1085
- }, /*#__PURE__*/React$1.createElement(Text, {
1086
- className: "form-dropzone__thumb-name-inner",
1087
- size: thumbNameTextSize,
1088
- textColor: thumbNameTextColor,
1089
- textWeight: thumbNameTextWeight,
1090
- textWrap: thumbNameTextWrap
1091
- }, file.name)), fileIsLoading && /*#__PURE__*/React$1.createElement("div", {
1092
- className: "form-dropzone__thumb-loader"
1093
- }, /*#__PURE__*/React$1.createElement(Loader, {
1094
- width: "fill",
1095
- height: "fill",
1096
- fill: "surfacePrimary",
1097
- itemFill: "surfaceItemAccent",
1098
- set: "simple"
1099
- })), /*#__PURE__*/React$1.createElement("div", {
1100
- className: clsx('form-dropzone__thumb-remove')
1101
- }, /*#__PURE__*/React$1.createElement(Button, {
1102
- className: "form-dropzone__thumb-remove-text",
1103
- appearance: removeThumbAppearance,
1104
- label: removeThumbText || 'Удалить',
1105
- labelTextWeight: removeThumbTextWeight,
1106
- shape: removeThumbShape,
1107
- onClick: event => removeFile(event, index)
1108
- })))), !filesList.length ? /*#__PURE__*/React$1.createElement("div", {
1109
- className: "form-dropzone__hint"
1110
- }, /*#__PURE__*/React$1.createElement(Text, {
1111
- className: "form-dropzone__hint-title",
1112
- size: hintTitleTextSize,
1113
- textColor: hintTitleTextColor,
1114
- textWeight: hintTitleTextWeight,
1115
- textWrap: hintTitleTextWrap
1116
- }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React$1.createElement(Text, {
1117
- className: "form-dropzone__hint-text",
1118
- size: hintDescriptionTextSize,
1119
- textColor: hintDescriptionTextColor,
1120
- textWeight: hintDescriptionTextWeight,
1121
- textWrap: hintDescriptionTextWrap
1122
- }, hintDescription)) : /*#__PURE__*/React$1.createElement("div", {
1123
- className: "form-dropzone__hint form-dropzone__hint_type_add-more"
1124
- }, /*#__PURE__*/React$1.createElement(Text, {
1125
- className: "form-dropzone__hint-title",
1126
- size: hintTitleTextSize,
1127
- textColor: hintTitleTextColor,
1128
- textWeight: hintTitleTextWeight,
1129
- textWrap: hintTitleTextWrap
1130
- }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React$1.createElement(Text, {
1131
- className: "form-dropzone__hint-text",
1132
- size: hintDescriptionTextSize,
1133
- textColor: hintDescriptionTextColor,
1134
- textWeight: hintDescriptionTextWeight,
1135
- textWrap: hintDescriptionTextWrap
1136
- }, hintDescription)))), fileError && /*#__PURE__*/React$1.createElement("div", {
1137
- className: "form-field__message"
1138
- }, /*#__PURE__*/React$1.createElement(Text, {
1139
- className: "form-field__message-item form-field__message-item_type_message",
1140
- size: errorMessageTextSize,
1141
- textColor: errorMessageTextColor,
1142
- textWeight: errorMessageTextWeight
1143
- }, fileError)));
1144
- });
1145
- async function getFileByURL(url) {
1146
- try {
1147
- const response = await axios({
1148
- url: url,
1149
- responseType: 'blob'
1270
+ return emptyOption;
1271
+ }, [input.value]);
1272
+ const {
1273
+ isErrorState,
1274
+ isValidState,
1275
+ errorKey,
1276
+ errorMessage
1277
+ } = useFieldValidationState({
1278
+ fieldProps: fieldProps,
1279
+ input: input,
1280
+ meta: meta
1150
1281
  });
1151
- const blobObject = response.data;
1152
- const dirtyFilename = response.headers['content-disposition']?.split('filename=')[1];
1153
- // Remove double quotes
1154
- let filename = dirtyFilename?.substring(1).slice(0, -1);
1155
- if (!filename) {
1156
- filename = url.split('/').at(-1);
1157
- // const typeParts = blobObject.type.split('/')
1158
- // const fileType = typeParts[typeParts.length - 1]
1159
- // filename = `${new Date().getTime()}.${fileType}`
1160
- }
1161
- return new File([blobObject], filename, {
1162
- type: blobObject.type
1282
+ const updatedInputProps = useValidationAppearanceInputProps({
1283
+ inputProps: inputProps,
1284
+ validationStateKey: isErrorState ? errorKey : 'success'
1163
1285
  });
1164
- } catch (error) {
1165
- console.log('error: ', error);
1166
- return null;
1167
- }
1168
- }
1169
- async function convertToFile(inputValue, isPreviews) {
1170
- let newFile = null;
1171
-
1172
- // Download image by url and save as File instance
1173
- const isURL = typeof inputValue === 'string' && inputValue.includes('/');
1174
- if (inputValue.image || isURL) {
1175
- newFile = await getFileByURL(inputValue.image || inputValue);
1176
- if (newFile) {
1177
- setFileDataURL(newFile);
1178
- }
1179
- }
1180
-
1181
- // Convert dataURL to File instance
1182
- if (inputValue.dataURL) {
1183
- newFile = createFileFromDataURL(inputValue.name || inputValue.path, inputValue.dataURL);
1184
- newFile.dataURL = inputValue.dataURL;
1185
- }
1186
-
1187
- // Save new File to state
1188
- if (newFile) {
1189
- newFile.id = inputValue.id;
1190
- if (isPreviews) {
1191
- newFile.preview = URL.createObjectURL(newFile);
1192
- }
1193
- }
1194
- return newFile;
1195
- }
1196
- function setFileDataURL(file, resolve) {
1197
- resolve = resolve || (() => {});
1198
- // Init reader and save his file
1199
- const reader = new FileReader();
1200
- reader._readedFile = file;
1286
+ return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
1287
+ className: clsx('form-field_type_choice', 'form__item_type_choice', classNameGroupItem),
1288
+ label: label,
1289
+ errorKey: errorKey,
1290
+ errorMessage: errorMessage,
1291
+ isErrorState: isErrorState,
1292
+ metaError: meta.error,
1293
+ isDisabled: isDisabled,
1294
+ fieldClassName: "form-choice",
1295
+ inputName: input.name,
1296
+ inputValue: input.value || [],
1297
+ messageType: messageType,
1298
+ metaActive: meta.active,
1299
+ showMessage: showMessage,
1300
+ isRequired: isRequired,
1301
+ isValidState: isValidState
1302
+ }, fieldProps), /*#__PURE__*/React$1.createElement(Choice, Object.assign({
1303
+ className: clsx(meta.active && 'form-choice_state_focus', meta.error && meta.touched && `form-choice_state_${errorKey}`),
1304
+ name: input.name,
1305
+ isDisabled: isDisabled,
1306
+ active: activeOption,
1307
+ inputValue: input.value || [],
1308
+ options: options,
1309
+ placeholder: placeholder,
1310
+ isCheckbox: isCheckbox,
1311
+ isRequired: isRequired,
1312
+ setActiveSegment: setActiveSegment
1313
+ }, updatedInputProps)));
1314
+ });
1315
+ });
1201
1316
 
1202
- // Set handlers
1203
- reader.onabort = () => resolve();
1204
- reader.onerror = () => resolve();
1205
- reader.onload = event => {
1206
- event.target._readedFile.dataURL = reader.result;
1207
- resolve();
1208
- };
1209
- // Run reader
1210
- if (file instanceof File) {
1211
- reader.readAsDataURL(file);
1212
- } else {
1213
- resolve();
1214
- }
1215
- }
1317
+ const defaultCodeProps = {
1318
+ appearance: 'defaultPrimary sizeL solid rounded'
1319
+ };
1216
1320
 
1217
- const FileInput = /*#__PURE__*/React$1.memo(function FileInput(props) {
1321
+ const FormFieldCode = /*#__PURE__*/React$1.memo(function FormFieldCode(props) {
1218
1322
  const {
1219
- className,
1220
1323
  name,
1221
- width,
1222
- maxFiles,
1223
- maxSize,
1224
- label,
1225
- fileErrorText,
1324
+ initialValue,
1325
+ isDisabled,
1226
1326
  classNameGroupItem,
1227
- dropzoneProps,
1228
- fieldProps,
1229
- hintDescription,
1230
- hintTitle,
1231
- showFilename,
1327
+ fieldProps = {},
1328
+ inputProps = {},
1232
1329
  showMessage,
1233
- isPreviews,
1234
- isRequired,
1235
- onAddFiles,
1236
- onDeleteFile
1330
+ isRequired
1237
1331
  } = props;
1238
- const propsGenerator = useDevicePropsGenerator(props);
1239
- const {
1240
- size,
1241
- fill,
1242
- fillHover,
1243
- labelTextColor,
1244
- borderColorHover,
1245
- borderType,
1246
- borderWidth,
1247
- errorMessageTextColor,
1248
- errorMessageTextSize,
1249
- errorMessageTextWeight,
1250
- hintDescriptionTextColor,
1251
- hintDescriptionTextSize,
1252
- hintDescriptionTextWeight,
1253
- hintDescriptionTextWrap,
1254
- hintTitleTextColor,
1255
- hintTitleTextSize,
1256
- hintTitleTextWeight,
1257
- hintTitleTextWrap,
1258
- removeThumbAppearance,
1259
- removeThumbText,
1260
- removeThumbTextWeight,
1261
- removeThumbShape,
1262
- shape,
1263
- thumbBorderColor,
1264
- thumbBorderColorHover,
1265
- thumbBorderType,
1266
- thumbBorderWidth,
1267
- thumbColumn = 1,
1268
- thumbDirection = 'vertical',
1269
- thumbNameTextColor,
1270
- thumbNameTextSize,
1271
- thumbNameTextWeight,
1272
- thumbNameTextWrap
1273
- } = propsGenerator;
1274
1332
  return /*#__PURE__*/React$1.createElement(Field, {
1275
- name: name
1333
+ name: name,
1334
+ initialValue: initialValue
1276
1335
  }, function Render({
1277
1336
  input,
1278
1337
  meta
@@ -1285,125 +1344,57 @@ const FileInput = /*#__PURE__*/React$1.memo(function FileInput(props) {
1285
1344
  */
1286
1345
 
1287
1346
  const {
1288
- errorKey,
1289
- errorMessage,
1290
1347
  isErrorState,
1291
- isValidState
1292
- } = useFieldValidationState({
1348
+ isValidState,
1349
+ errorKey} = useFieldValidationState({
1293
1350
  fieldProps: fieldProps,
1294
1351
  input: input,
1295
1352
  meta: meta
1296
1353
  });
1297
1354
  const updatedInputProps = useValidationAppearanceInputProps({
1298
- inputProps: props,
1355
+ inputProps: inputProps,
1299
1356
  validationStateKey: isErrorState ? errorKey : 'success'
1300
1357
  });
1301
-
1302
- /** TODO:
1303
- * REFACTOR PROPERTIES
1304
- */
1305
1358
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
1306
- className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
1307
- width: width,
1308
- label: label,
1309
- labelTextColor: labelTextColor,
1310
- errorKey: errorKey,
1311
- errorMessage: errorMessage,
1312
- isErrorState: isErrorState,
1313
- metaError: meta.error,
1314
- fieldClassName: "form-dropzone",
1359
+ className: clsx('form-field_type_code', 'form__item_type_code', classNameGroupItem),
1360
+ fieldClassName: 'form-code',
1315
1361
  inputName: input.name,
1316
1362
  inputValue: input.value,
1317
1363
  metaActive: meta.active,
1318
- metaTouched: meta.touched,
1319
1364
  showMessage: showMessage,
1320
1365
  isRequired: isRequired,
1321
1366
  isValidState: isValidState
1322
- }, fieldProps), /*#__PURE__*/React$1.createElement(FileInputDropzone, {
1323
- className: className,
1324
- maxFiles: maxFiles,
1325
- maxSize: maxSize,
1326
- size: size,
1327
- fill: fill,
1328
- fillHover: fillHover,
1329
- borderColor: updatedInputProps.borderColor,
1330
- borderColorHover: borderColorHover,
1331
- borderType: borderType,
1332
- borderWidth: borderWidth,
1333
- errorMessageTextColor: errorMessageTextColor,
1334
- errorMessageTextSize: errorMessageTextSize,
1335
- errorMessageWeight: errorMessageTextWeight,
1336
- fileErrorText: fileErrorText,
1337
- metaError: meta.error,
1338
- dropzoneProps: dropzoneProps,
1339
- hintDescription: hintDescription,
1340
- hintDescriptionTextColor: hintDescriptionTextColor,
1341
- hintDescriptionTextSize: hintDescriptionTextSize,
1342
- hintDescriptionTextWeight: hintDescriptionTextWeight,
1343
- hintDescriptionTextWrap: hintDescriptionTextWrap,
1344
- hintTitle: hintTitle,
1345
- hintTitleTextColor: hintTitleTextColor,
1346
- hintTitleTextSize: hintTitleTextSize,
1347
- hintTitleTextWeight: hintTitleTextWeight,
1348
- hintTitleTextWrap: hintTitleTextWrap,
1349
- inputName: input.name,
1350
- inputValue: input.value,
1351
- metaTouched: meta.touched,
1352
- removeThumbAppearance: removeThumbAppearance,
1353
- removeThumbText: removeThumbText,
1354
- removeThumbTextWeight: removeThumbTextWeight,
1355
- removeThumbShape: removeThumbShape,
1356
- shape: shape,
1357
- showFilename: showFilename,
1358
- thumbBorderColor: thumbBorderColor,
1359
- thumbBorderColorHover: thumbBorderColorHover,
1360
- thumbBorderType: thumbBorderType,
1361
- thumbBorderWidth: thumbBorderWidth,
1362
- thumbColumn: thumbColumn,
1363
- thumbDirection: thumbDirection,
1364
- thumbNameTextColor: thumbNameTextColor,
1365
- thumbNameTextSize: thumbNameTextSize,
1366
- thumbNameTextWeight: thumbNameTextWeight,
1367
- thumbNameTextWrap: thumbNameTextWrap,
1368
- isPreviews: isPreviews,
1369
- onAddFiles: onAddFiles,
1370
- onDeleteFile: onDeleteFile
1371
- }));
1367
+ }, fieldProps), /*#__PURE__*/React$1.createElement(Code, Object.assign({
1368
+ name: input.name,
1369
+ isDisabled: isDisabled,
1370
+ autoComplete: "nope",
1371
+ value: input.value,
1372
+ onBlur: input.onBlur,
1373
+ onChange: input.onChange,
1374
+ onFocus: input.onFocus
1375
+ }, updatedInputProps)));
1372
1376
  });
1373
1377
  });
1374
1378
 
1375
- const defaultGroupProps = {
1376
- width: 'fill',
1377
- labelTextColor: 'surfaceTextPrimary',
1378
- labelTextSize: 'h5',
1379
- labelTextWeight: 500
1380
- };
1381
-
1382
- const Group = /*#__PURE__*/React$1.memo(function Group(props) {
1379
+ const FormFieldCustom = /*#__PURE__*/React$1.memo(function FormFieldCustom(props) {
1383
1380
  const {
1384
- className,
1381
+ Component,
1382
+ isDisabled,
1383
+ isRequired,
1385
1384
  name,
1386
- label,
1387
- labelTextColor,
1388
- labelTextSize,
1389
- labelTextWeight,
1390
- message,
1391
- column,
1392
- dataTour,
1393
- title,
1394
- titleTextSize,
1395
- titleTextColor,
1396
- titleTextWeight,
1397
- messageTextColor = 'surfaceTextTertiary',
1398
- messageTextSize = 's',
1399
- messageTextWeight,
1400
- showGroupMessage,
1401
- before,
1402
- after,
1403
- isHidden,
1404
- children
1385
+ initialValue,
1386
+ fieldProps = {},
1387
+ classNameGroupItem,
1388
+ showMessage,
1389
+ clearIcon,
1390
+ clearIconFill,
1391
+ clearIconFillHover,
1392
+ clearIconShape,
1393
+ clearIconSize,
1394
+ onClickClearIcon
1405
1395
  } = props;
1406
1396
  return /*#__PURE__*/React$1.createElement(Field, {
1397
+ initialValue: initialValue,
1407
1398
  name: name
1408
1399
  }, function Render({
1409
1400
  input,
@@ -1415,111 +1406,80 @@ const Group = /*#__PURE__*/React$1.memo(function Group(props) {
1415
1406
  * React Hooks must be called in a React function component or a
1416
1407
  * custom React Hook function.
1417
1408
  */
1409
+
1418
1410
  const {
1419
1411
  isErrorState,
1412
+ isValidState,
1420
1413
  errorKey,
1421
1414
  errorMessage
1422
1415
  } = useFieldValidationState({
1423
- fieldProps: props,
1424
- // or fieldProps?
1416
+ fieldProps: fieldProps,
1425
1417
  input: input,
1426
1418
  meta: meta
1427
1419
  });
1428
- const updatedProps = useValidationAppearanceInputProps({
1429
- inputProps: props,
1430
- validationStateKey: isErrorState ? errorKey : 'success'
1420
+ const updatedInputProps = useValidationAppearanceInputProps({
1421
+ validationStateKey: isErrorState ? errorKey : 'success',
1422
+ // For "Custom" field we pass all props. Can contain some special props, we don't known.
1423
+ inputProps: props
1431
1424
  });
1432
- return /*#__PURE__*/React$1.createElement("div", {
1433
- className: clsx('form__group', className, isHidden && 'form__group_hidden', column && `form__group_column_${column}`),
1434
- "data-tour": dataTour
1435
- }, /*#__PURE__*/React$1.createElement("div", {
1436
- className: "form__group-wrapper"
1437
- }, before, title && /*#__PURE__*/React$1.createElement("div", {
1438
- className: "form__group-title"
1439
- }, /*#__PURE__*/React$1.createElement(Title, {
1440
- size: titleTextSize,
1441
- textColor: titleTextColor,
1442
- textWeight: titleTextWeight
1443
- }, title)), label && /*#__PURE__*/React$1.createElement("div", {
1444
- className: "form__group-label"
1445
- }, /*#__PURE__*/React$1.createElement(Text, {
1446
- size: labelTextSize,
1447
- textColor: labelTextColor,
1448
- textWeight: labelTextWeight
1449
- }, label)), /*#__PURE__*/React$1.createElement("div", {
1450
- className: "form__group-items"
1451
- }, children), after), showGroupMessage && /*#__PURE__*/React$1.createElement(React$1.Fragment, null, isErrorState && errorMessage && /*#__PURE__*/React$1.createElement(Text, {
1452
- className: `form__group-message form__group-message_type-${errorKey}`,
1453
- id: `${name}-error`,
1454
- size: updatedProps.messageTextSize,
1455
- textColor: updatedProps.messageTextColor,
1456
- textWeight: updatedProps.messageTextWeight
1457
- }, errorMessage), Boolean(message) && (!isErrorState || !errorMessage) && /*#__PURE__*/React$1.createElement(Text, {
1458
- className: "form__group-message",
1459
- size: messageTextSize,
1460
- textColor: messageTextColor,
1461
- textWeight: messageTextWeight
1462
- }, message), !isErrorState && !message && /*#__PURE__*/React$1.createElement(Text, {
1463
- className: "form__group-message",
1464
- size: messageTextSize
1465
- }, '\u00A0')));
1425
+ return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
1426
+ className: clsx('form-field_type_custom', 'form__item_type_custom', classNameGroupItem),
1427
+ errorKey: errorKey,
1428
+ errorMessage: errorMessage,
1429
+ fieldClassName: 'form-custom',
1430
+ inputName: input.name,
1431
+ inputValue: input.value,
1432
+ isDisabled: isDisabled,
1433
+ isErrorState: isErrorState,
1434
+ isRequired: isRequired,
1435
+ isValidState: isValidState,
1436
+ metaActive: meta.active,
1437
+ metaError: meta.error,
1438
+ showMessage: showMessage
1439
+ }, fieldProps), /*#__PURE__*/React$1.createElement(Component, Object.assign({}, updatedInputProps, {
1440
+ input: input,
1441
+ isDisabled: isDisabled,
1442
+ meta: meta
1443
+ })), clearIcon && /*#__PURE__*/React$1.createElement(Icon, {
1444
+ className: "form-field__icon",
1445
+ iconFill: clearIconFill,
1446
+ iconFillHover: clearIconFillHover,
1447
+ imageSrc: clearIcon,
1448
+ shape: clearIconShape,
1449
+ size: clearIconSize,
1450
+ SvgImage: clearIcon,
1451
+ onClick: onClickClearIcon
1452
+ }));
1466
1453
  });
1467
1454
  });
1468
1455
 
1469
- const defaultInputProps = {
1470
- appearance: 'sizeM defaultSecondary',
1471
- width: 'fill',
1472
- errorBorderColor: 'errorBorderSecondary',
1473
- requiredBorderColor: 'warningBorderSecondary',
1474
- shape: 'rounded'
1456
+ const defaultDatepickerProps = {
1457
+ appearance: 'surfacePrimary sizeS',
1458
+ dateFormat: 'dd/MM/yyyy - HH:mm',
1459
+ readOnly: false,
1460
+ selectsRange: false,
1461
+ showTimeSelect: true,
1462
+ timeCaption: 'Время',
1463
+ timeFormat: 'p',
1464
+ timeIntervals: 60,
1465
+ isClearable: true,
1466
+ isStartDefaultNull: true
1475
1467
  };
1476
1468
 
1477
- const InputField = /*#__PURE__*/React$1.memo(function InputField(props) {
1469
+ function FormFieldDatePicker(props) {
1478
1470
  const {
1479
1471
  name,
1480
- initialValue,
1481
1472
  isDisabled,
1482
1473
  classNameGroupItem,
1483
- // dataTestId,
1484
- // iconBorder,
1485
- // iconBorderHover,
1486
- clearIcon,
1487
- clearIconFill,
1488
- clearIconFillHover,
1489
- clearIconShape,
1490
- clearIconSize,
1474
+ datePickerProps,
1491
1475
  fieldProps = {},
1492
- iconFill,
1493
- iconFillHover,
1494
- iconRevealableHide,
1495
- iconRevealableShow,
1496
- iconShape,
1497
- iconSize,
1498
1476
  inputProps = {},
1499
- parse,
1500
1477
  showMessage,
1501
- isPassword,
1502
1478
  isRequired,
1503
- isRevealable,
1504
- onChange,
1505
- onClickClearIcon
1479
+ onChange
1506
1480
  } = props;
1507
- const [isRevealed, setIsRevealed] = useState(false);
1508
- const inputType = useMemo(() => {
1509
- if (isPassword) {
1510
- return isRevealed ? 'text' : 'password';
1511
- } else {
1512
- return 'text';
1513
- }
1514
- }, [isRevealed, isPassword]);
1515
- const onClickIconReveal = useCallback(event => {
1516
- event.preventDefault();
1517
- setIsRevealed(prev => !prev);
1518
- }, []);
1519
1481
  return /*#__PURE__*/React$1.createElement(Field, {
1520
- name: name,
1521
- initialValue: initialValue,
1522
- parse: parse
1482
+ name: name
1523
1483
  }, function Render({
1524
1484
  input,
1525
1485
  meta
@@ -1531,12 +1491,22 @@ const InputField = /*#__PURE__*/React$1.memo(function InputField(props) {
1531
1491
  * custom React Hook function.
1532
1492
  */
1533
1493
 
1534
- const onChangeField = useCallback(event => {
1535
- input.onChange(event);
1494
+ const onChangeField = useCallback((startDate, endDate) => {
1495
+ if (!datePickerProps.selectsRange) {
1496
+ // When we need to save single date, value is date
1497
+ // TODO: make object with one date? need to check all forms with FormFieldDatePicker
1498
+ input.onChange(startDate);
1499
+ } else {
1500
+ // When we need to save range, value is object with two date
1501
+ input.onChange({
1502
+ endDate,
1503
+ startDate
1504
+ });
1505
+ }
1536
1506
  if (onChange) {
1537
- onChange(event.target.value, input.name);
1507
+ onChange(startDate, endDate);
1538
1508
  }
1539
- }, [onChange, input.onChange]);
1509
+ }, [input.onChange, onChange]);
1540
1510
  const {
1541
1511
  errorKey,
1542
1512
  errorMessage,
@@ -1551,200 +1521,87 @@ const InputField = /*#__PURE__*/React$1.memo(function InputField(props) {
1551
1521
  inputProps: inputProps,
1552
1522
  validationStateKey: isErrorState ? errorKey : 'success'
1553
1523
  });
1554
- const isIconRevealableString = typeof iconRevealableHide === 'string' && typeof iconRevealableShow === 'string';
1555
1524
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
1556
- className: clsx('form-field_type_input', 'form__item_type_input', classNameGroupItem),
1525
+ className: clsx('form-field_type_datepicker', 'form__item_type_datepicker', classNameGroupItem),
1557
1526
  errorKey: errorKey,
1558
1527
  errorMessage: errorMessage,
1559
1528
  isErrorState: isErrorState,
1560
1529
  metaError: meta.error,
1561
1530
  isDisabled: isDisabled,
1562
- fieldClassName: isRevealable ? 'form-password' : 'form-input',
1531
+ fieldClassName: "form-datepicker",
1563
1532
  inputName: input.name,
1564
1533
  inputValue: input.value || '',
1565
1534
  metaActive: meta.active,
1566
1535
  showMessage: showMessage,
1567
1536
  isRequired: isRequired,
1568
1537
  isValidState: isValidState
1569
- }, fieldProps), /*#__PURE__*/React$1.createElement(Input, Object.assign({
1570
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1571
- type: inputType,
1538
+ }, fieldProps), /*#__PURE__*/React$1.createElement(DatePickerInput, {
1572
1539
  name: input.name,
1573
1540
  isDisabled: isDisabled,
1574
- autoComplete: "nope",
1575
- dataTestId: `${input.name}FieldInput`,
1576
- value: input.value || '',
1541
+ datePickerProps: datePickerProps,
1542
+ endValue: datePickerProps.selectsRange ? input.value.endDate : null,
1543
+ inputProps: updatedInputProps,
1544
+ value: datePickerProps.selectsRange ? input.value.startDate : input.value,
1577
1545
  onBlur: input.onBlur,
1578
1546
  onChange: onChangeField,
1579
1547
  onFocus: input.onFocus
1580
- }, updatedInputProps)), isRevealable && /*#__PURE__*/React$1.createElement(Icon, {
1581
- className: "form-field__icon",
1582
- size: iconSize,
1583
- iconFill: iconFill,
1584
- iconFillHover: iconFillHover,
1585
- imageSrc: isRevealed && isIconRevealableString ? iconRevealableHide : iconRevealableShow,
1586
- shape: iconShape,
1587
- SvgImage: isRevealed && !isIconRevealableString ? iconRevealableHide : iconRevealableShow,
1588
- onClick: onClickIconReveal
1589
- }), clearIcon && /*#__PURE__*/React$1.createElement(Icon, {
1590
- className: "form-field__icon",
1591
- size: clearIconSize,
1592
- iconFill: clearIconFill,
1593
- iconFillHover: clearIconFillHover,
1594
- imageSrc: typeof clearIcon === 'string' && clearIcon,
1595
- shape: clearIconShape,
1596
- SvgImage: typeof clearIcon !== 'string' && clearIcon,
1597
- onClick: onClickClearIcon
1598
1548
  }));
1599
1549
  });
1600
- });
1601
-
1602
- const defaultRadioProps = {
1603
- fieldProps: {
1604
- width: 'fill',
1605
- size: 'm',
1606
- labelTextColor: 'surfaceTextPrimary',
1607
- labelTextSize: 's',
1608
- labelTextWeight: 'normal',
1609
- textColor: 'surfaceTextPrimary',
1610
- helpText: 'Supporting text',
1611
- helpTextColor: 'surfaceTextPrimary',
1612
- helpTextSize: 's',
1613
- helpTextWeight: 'normal',
1614
- showMessage: true
1615
- },
1616
- inputProps: {
1617
- width: 'fill',
1618
- size: 'm',
1619
- labelTextColor: 'surfaceTextPrimary',
1620
- labelTextSize: 's',
1621
- descTextColor: 'surfaceTextPrimary',
1622
- descTextSize: 's'
1623
- }
1624
- };
1625
-
1626
- function RadioGroupInput(props) {
1627
- const {
1628
- input,
1629
- value,
1630
- onChange
1631
- } = props;
1632
- const onChangeField = useCallback(event => onChange(event.target.value), [onChange]);
1633
- return /*#__PURE__*/React.createElement(Input, Object.assign({
1634
- name: input.name,
1635
- autoComplete: "nope",
1636
- value: value,
1637
- onBlur: input.onBlur,
1638
- onChange: onChangeField,
1639
- onFocus: input.onFocus
1640
- }, props));
1641
- }
1642
-
1643
- function RadioGroupItem(props) {
1644
- const {
1645
- input,
1646
- inputProps,
1647
- option,
1648
- onChange
1649
- } = props;
1650
- const onChangeField = useCallback(event => {
1651
- if (event.target.checked) {
1652
- onChange(option.value);
1653
- }
1654
- }, [onChange]);
1655
- return /*#__PURE__*/React.createElement(Radio, Object.assign({
1656
- className: "form-radio__item",
1657
- type: "radio",
1658
- name: input.name,
1659
- label: option.label,
1660
- checked: option.value === input.value,
1661
- value: option.value,
1662
- onBlur: input.onBlur,
1663
- onChange: onChangeField,
1664
- onFocus: input.onFocus
1665
- }, inputProps));
1666
1550
  }
1667
1551
 
1668
- function RadioGroupList(props) {
1669
- const {
1670
- editableProps,
1671
- input,
1672
- inputProps,
1673
- options,
1674
- onChange
1675
- } = props;
1676
- const [editableValue, setEditableValue] = useState(() => {
1677
- const isRadioValue = options.find(option => option.value === input.value);
1678
- if (!isRadioValue) {
1679
- return input.value;
1680
- }
1681
- return '';
1682
- });
1683
- useEffect(() => {
1684
- // When a new value from outside enters the form
1685
- if (input.value) {
1686
- // Check value for radio type
1687
- const isRadioValue = options.find(option => option.value === input.value && !option.editable);
1688
- // If new value not in radio list - set to editable input
1689
- setEditableValue(isRadioValue ? '' : input.value);
1690
- } else {
1691
- // If new value is empty - clear editable input
1692
- setEditableValue('');
1693
- }
1694
- }, [input.value]);
1695
-
1696
- // Callback for value changes
1697
- const onChangeSomeInput = useCallback(value => {
1698
- // Save to form values
1699
- input.onChange(value);
1700
- if (onChange) {
1701
- // Pass to custom event
1702
- onChange(value, input.name);
1703
- }
1704
- }, [input, onChange]);
1705
-
1706
- // Handle for radio inputs
1707
- const onChangeRadio = useCallback(value => {
1708
- setEditableValue('');
1709
- onChangeSomeInput(value);
1710
- }, [onChangeSomeInput]);
1711
-
1712
- // Handle for text input
1713
- const onChangeEditable = useCallback(value => {
1714
- setEditableValue(value);
1715
- onChangeSomeInput(value);
1716
- }, [onChangeSomeInput]);
1717
- return /*#__PURE__*/React$1.createElement(React$1.Fragment, null, options.map(option => option.editable ? /*#__PURE__*/React$1.createElement(RadioGroupInput, {
1718
- key: option.label,
1719
- editableProps: editableProps,
1720
- input: input,
1721
- inputProps: inputProps,
1722
- option: option,
1723
- value: editableValue,
1724
- onChange: onChangeEditable
1725
- }) : /*#__PURE__*/React$1.createElement(RadioGroupItem, {
1726
- key: option.value,
1727
- input: input,
1728
- inputProps: inputProps,
1729
- option: option,
1730
- onChange: onChangeRadio
1731
- })));
1732
- }
1552
+ const defaultInputProps = {
1553
+ appearance: 'sizeM defaultSecondary solid rounded',
1554
+ width: 'fill',
1555
+ errorBorderColor: 'errorBorderSecondary',
1556
+ requiredBorderColor: 'warningBorderSecondary'
1557
+ };
1733
1558
 
1734
- const RadioGroup = /*#__PURE__*/React$1.memo(function RadioGroup(props) {
1559
+ const FormFieldInput = /*#__PURE__*/React$1.memo(function FormFieldInput(props) {
1735
1560
  const {
1736
1561
  name,
1562
+ initialValue,
1737
1563
  isDisabled,
1738
- editableProps = {},
1564
+ classNameGroupItem,
1565
+ // dataTestId,
1566
+ // iconBorder,
1567
+ // iconBorderHover,
1568
+ clearIcon,
1569
+ clearIconFill,
1570
+ clearIconFillHover,
1571
+ clearIconShape,
1572
+ clearIconSize,
1739
1573
  fieldProps = {},
1574
+ iconFill,
1575
+ iconFillHover,
1576
+ iconRevealableHide,
1577
+ iconRevealableShow,
1578
+ iconShape,
1579
+ iconSize,
1740
1580
  inputProps = {},
1741
- options = [],
1581
+ parse,
1742
1582
  showMessage,
1583
+ isPassword,
1743
1584
  isRequired,
1744
- onChange
1585
+ isRevealable,
1586
+ onChange,
1587
+ onClickClearIcon
1745
1588
  } = props;
1589
+ const [isRevealed, setIsRevealed] = useState(false);
1590
+ const inputType = useMemo(() => {
1591
+ if (isPassword) {
1592
+ return isRevealed ? 'text' : 'password';
1593
+ } else {
1594
+ return 'text';
1595
+ }
1596
+ }, [isRevealed, isPassword]);
1597
+ const onClickIconReveal = useCallback(event => {
1598
+ event.preventDefault();
1599
+ setIsRevealed(prev => !prev);
1600
+ }, []);
1746
1601
  return /*#__PURE__*/React$1.createElement(Field, {
1747
- name: name
1602
+ name: name,
1603
+ initialValue: initialValue,
1604
+ parse: parse
1748
1605
  }, function Render({
1749
1606
  input,
1750
1607
  meta
@@ -1756,6 +1613,12 @@ const RadioGroup = /*#__PURE__*/React$1.memo(function RadioGroup(props) {
1756
1613
  * custom React Hook function.
1757
1614
  */
1758
1615
 
1616
+ const onChangeField = useCallback(event => {
1617
+ input.onChange(event);
1618
+ if (onChange) {
1619
+ onChange(event.target.value, input.name);
1620
+ }
1621
+ }, [onChange, input.onChange]);
1759
1622
  const {
1760
1623
  errorKey,
1761
1624
  errorMessage,
@@ -1770,40 +1633,62 @@ const RadioGroup = /*#__PURE__*/React$1.memo(function RadioGroup(props) {
1770
1633
  inputProps: inputProps,
1771
1634
  validationStateKey: isErrorState ? errorKey : 'success'
1772
1635
  });
1636
+ const isIconRevealableString = typeof iconRevealableHide === 'string' && typeof iconRevealableShow === 'string';
1773
1637
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
1774
- className: clsx('form-field_type_radio', 'form__item_type_radio"', classNameGroupItem),
1638
+ className: clsx('form-field_type_input', 'form__item_type_input', classNameGroupItem),
1775
1639
  errorKey: errorKey,
1776
1640
  errorMessage: errorMessage,
1777
1641
  isErrorState: isErrorState,
1778
1642
  metaError: meta.error,
1779
1643
  isDisabled: isDisabled,
1780
- fieldClassName: 'form-radio',
1644
+ fieldClassName: isRevealable ? 'form-password' : 'form-input',
1781
1645
  inputName: input.name,
1782
1646
  inputValue: input.value || '',
1783
1647
  metaActive: meta.active,
1784
1648
  showMessage: showMessage,
1785
1649
  isRequired: isRequired,
1786
1650
  isValidState: isValidState
1787
- }, fieldProps), /*#__PURE__*/React$1.createElement(RadioGroupList, {
1651
+ }, fieldProps), /*#__PURE__*/React$1.createElement(Input, Object.assign({
1652
+ dataTestId: `${input.name}FieldInput`,
1653
+ className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1654
+ type: inputType,
1655
+ name: input.name,
1788
1656
  isDisabled: isDisabled,
1789
- editableProps: editableProps,
1790
- input: input,
1791
- inputProps: updatedInputProps,
1792
- options: options,
1793
- onChange: onChange
1657
+ autoComplete: "nope",
1658
+ value: input.value || '',
1659
+ onBlur: input.onBlur,
1660
+ onChange: onChangeField,
1661
+ onFocus: input.onFocus
1662
+ }, updatedInputProps)), isRevealable && /*#__PURE__*/React$1.createElement(Icon, {
1663
+ className: "form-field__icon",
1664
+ size: iconSize,
1665
+ iconFill: iconFill,
1666
+ iconFillHover: iconFillHover,
1667
+ imageSrc: isRevealed && isIconRevealableString ? iconRevealableHide : iconRevealableShow,
1668
+ shape: iconShape,
1669
+ SvgImage: isRevealed && !isIconRevealableString ? iconRevealableHide : iconRevealableShow,
1670
+ onClick: onClickIconReveal
1671
+ }), clearIcon && /*#__PURE__*/React$1.createElement(Icon, {
1672
+ className: "form-field__icon",
1673
+ size: clearIconSize,
1674
+ iconFill: clearIconFill,
1675
+ iconFillHover: clearIconFillHover,
1676
+ imageSrc: typeof clearIcon === 'string' && clearIcon,
1677
+ shape: clearIconShape,
1678
+ SvgImage: typeof clearIcon !== 'string' && clearIcon,
1679
+ onClick: onClickClearIcon
1794
1680
  }));
1795
1681
  });
1796
1682
  });
1797
1683
 
1798
1684
  const defaultSegmentedProps = {
1799
- appearance: 'sizeM surfacePrimary',
1685
+ appearance: 'defaultPrimary sizeM solid rounded',
1800
1686
  width: 'fill',
1801
1687
  errorLabelTextColor: 'errorTextPrimary',
1802
- requiredLabelTextColor: 'warningTextPrimary',
1803
- shape: 'rounded'
1688
+ requiredLabelTextColor: 'warningTextPrimary'
1804
1689
  };
1805
1690
 
1806
- function SegmentedField(props) {
1691
+ function FormFieldSegmented(props) {
1807
1692
  const {
1808
1693
  name,
1809
1694
  isDisabled,
@@ -1881,36 +1766,7 @@ function SegmentedField(props) {
1881
1766
  }
1882
1767
 
1883
1768
  const defaultSelectProps = {
1884
- elevation: 8,
1885
- isClearable: true,
1886
- isSearchable: true,
1887
- badgeAppearance: 'accent',
1888
- badgeSize: 'm',
1889
- badgeTextSize: 'm',
1890
- // clearIcon: icon24.Clear,
1891
- clearIconFill: 'surfaceItemPrimary',
1892
- closeMenuOnSelect: true,
1893
- // optionSelected: <Icon iconFill="surfaceItemAccent" SvgImage={icon24.Check} />,
1894
-
1895
- dividerDirection: 'horizontal',
1896
- dividerFill: 'surfaceTertiary',
1897
- dividerSize: 'xxs',
1898
- // dropdownIcon: icon24.ChevronDownSmall,
1899
- dropdownIconFill: 'surfaceItemPrimary',
1900
- // error
1901
- errorInputBorderColor: 'errorBorderPrimary',
1902
- headingFill: 'surfaceSecondary',
1903
- loadingMessage: /*#__PURE__*/React$1.createElement(Loader, {
1904
- width: "fill",
1905
- height: "fill",
1906
- fill: "surfacePrimary",
1907
- position: "absolute",
1908
- left: "0px",
1909
- right: "0px",
1910
- zIndex: "1",
1911
- itemFill: "surfaceItemAccent",
1912
- set: "simple"
1913
- })
1769
+ appearance: 'defaultPrimary sizeM'
1914
1770
  };
1915
1771
 
1916
1772
  function getDefaultValue(options, selectValue) {
@@ -1931,7 +1787,7 @@ function getDefaultValue(options, selectValue) {
1931
1787
  });
1932
1788
  return result;
1933
1789
  }
1934
- const SelectField = /*#__PURE__*/React$1.memo(function SelectField(props) {
1790
+ const FormFieldSelect = /*#__PURE__*/React$1.memo(function FormFieldSelect(props) {
1935
1791
  const {
1936
1792
  isDisabled,
1937
1793
  isRequired,
@@ -2014,10 +1870,10 @@ const SelectField = /*#__PURE__*/React$1.memo(function SelectField(props) {
2014
1870
  isValidState: isValidState
2015
1871
  }, fieldProps), /*#__PURE__*/React$1.createElement(Select, Object.assign({
2016
1872
  className: "form-select-item",
1873
+ ref: selectRef,
2017
1874
  isDisabled: isDisabled,
2018
1875
  instanceId: `id_${input.name}`,
2019
1876
  options: options,
2020
- ref: selectRef,
2021
1877
  value: selectedOptions,
2022
1878
  onChange: onChangeValue,
2023
1879
  onInputChange: onInputChange
@@ -2026,32 +1882,10 @@ const SelectField = /*#__PURE__*/React$1.memo(function SelectField(props) {
2026
1882
  });
2027
1883
 
2028
1884
  const defaultSwitchProps = {
2029
- fieldProps: {
2030
- width: 'fill',
2031
- size: 'xl',
2032
- labelTextColor: 'surfaceTextPrimary',
2033
- labelTextSize: 's',
2034
- labelTextWeight: 'normal',
2035
- textColor: 'surfaceTextPrimary',
2036
- helpText: 'Supporting text',
2037
- helpTextColor: 'surfaceTextPrimary',
2038
- helpTextSize: 's',
2039
- helpTextWeight: 'normal',
2040
- showMessage: true
2041
- },
2042
- inputProps: {
2043
- size: 'm',
2044
- fill: 'surfaceSecondary',
2045
- title: 'Switch',
2046
- titleTextColor: 'surfaceTextPrimary',
2047
- titleTextSize: 's',
2048
- desc: 'Description',
2049
- descTextColor: 'surfaceTextPrimary',
2050
- descTextSize: 'xs'
2051
- }
1885
+ appearance: 'defaultPrimary sizeL solid rounded'
2052
1886
  };
2053
1887
 
2054
- const SwitchField = /*#__PURE__*/React$1.memo(function SwitchField(props) {
1888
+ const FormFieldSwitch = /*#__PURE__*/React$1.memo(function FormFieldSwitch(props) {
2055
1889
  const {
2056
1890
  name,
2057
1891
  isDisabled,
@@ -2125,14 +1959,12 @@ const SwitchField = /*#__PURE__*/React$1.memo(function SwitchField(props) {
2125
1959
  });
2126
1960
 
2127
1961
  const defaultTextareaProps = {
2128
- appearance: 'sizeM defaultSecondary',
2129
- width: 'fill',
1962
+ appearance: 'defaultPrimary sizeM solid rounded',
2130
1963
  errorBorderColor: 'errorBorderSecondary',
2131
- requiredBorderColor: 'warningBorderSecondary',
2132
- shape: 'rounded'
1964
+ requiredBorderColor: 'warningBorderSecondary'
2133
1965
  };
2134
1966
 
2135
- const TextareaField = /*#__PURE__*/React$1.memo(function TextareaField(props) {
1967
+ const FormFieldTextarea = /*#__PURE__*/React$1.memo(function FormFieldTextarea(props) {
2136
1968
  const {
2137
1969
  name,
2138
1970
  isDisabled,
@@ -2195,7 +2027,7 @@ const TextareaField = /*#__PURE__*/React$1.memo(function TextareaField(props) {
2195
2027
  });
2196
2028
  });
2197
2029
 
2198
- const MaskedInputField = /*#__PURE__*/React$1.memo(function MaskedInputField(props) {
2030
+ const FormFieldMaskedInput = /*#__PURE__*/React$1.memo(function FormFieldMaskedInput(props) {
2199
2031
  const {
2200
2032
  name,
2201
2033
  initialValue,
@@ -2292,51 +2124,144 @@ const MaskedInputField = /*#__PURE__*/React$1.memo(function MaskedInputField(pro
2292
2124
  });
2293
2125
  });
2294
2126
 
2295
- const defaultChipsProps = {
2296
- appearance: 'surfacePrimary',
2297
- width: 'fill',
2298
- errorBorderColor: 'errorBorderSecondary',
2299
- requiredBorderColor: 'warningBorderSecondary'
2127
+ const defaultRadioProps = {
2128
+ appearance: 'defaultPrimary sizeM solid circular'
2300
2129
  };
2301
2130
 
2302
- function ChipsField(props) {
2131
+ function RadioGroupInput(props) {
2132
+ const {
2133
+ input,
2134
+ value,
2135
+ onChange
2136
+ } = props;
2137
+ const onChangeField = useCallback(event => onChange(event.target.value), [onChange]);
2138
+ return /*#__PURE__*/React.createElement(Input, Object.assign({
2139
+ name: input.name,
2140
+ autoComplete: "nope",
2141
+ value: value,
2142
+ onBlur: input.onBlur,
2143
+ onChange: onChangeField,
2144
+ onFocus: input.onFocus
2145
+ }, props));
2146
+ }
2147
+
2148
+ function RadioGroupItem(props) {
2149
+ const {
2150
+ input,
2151
+ inputProps,
2152
+ option,
2153
+ onChange
2154
+ } = props;
2155
+ const onChangeField = useCallback(event => {
2156
+ if (event.target.checked) {
2157
+ onChange(option.value);
2158
+ }
2159
+ }, [onChange]);
2160
+ return /*#__PURE__*/React.createElement(Radio, Object.assign({
2161
+ className: "form-radio__item",
2162
+ type: "radio",
2163
+ name: input.name,
2164
+ label: option.label,
2165
+ checked: option.value === input.value,
2166
+ value: option.value,
2167
+ onBlur: input.onBlur,
2168
+ onChange: onChangeField,
2169
+ onFocus: input.onFocus
2170
+ }, inputProps));
2171
+ }
2172
+
2173
+ function RadioGroupList(props) {
2174
+ const {
2175
+ editableProps,
2176
+ input,
2177
+ inputProps,
2178
+ options,
2179
+ onChange
2180
+ } = props;
2181
+ const [editableValue, setEditableValue] = useState(() => {
2182
+ const isRadioValue = options.find(option => option.value === input.value);
2183
+ if (!isRadioValue) {
2184
+ return input.value;
2185
+ }
2186
+ return '';
2187
+ });
2188
+ useEffect(() => {
2189
+ // When a new value from outside enters the form
2190
+ if (input.value) {
2191
+ // Check value for radio type
2192
+ const isRadioValue = options.find(option => option.value === input.value && !option.editable);
2193
+ // If new value not in radio list - set to editable input
2194
+ setEditableValue(isRadioValue ? '' : input.value);
2195
+ } else {
2196
+ // If new value is empty - clear editable input
2197
+ setEditableValue('');
2198
+ }
2199
+ }, [input.value]);
2200
+
2201
+ // Callback for value changes
2202
+ const onChangeSomeInput = useCallback(value => {
2203
+ // Save to form values
2204
+ input.onChange(value);
2205
+ if (onChange) {
2206
+ // Pass to custom event
2207
+ onChange(value, input.name);
2208
+ }
2209
+ }, [input, onChange]);
2210
+
2211
+ // Handle for radio inputs
2212
+ const onChangeRadio = useCallback(value => {
2213
+ setEditableValue('');
2214
+ onChangeSomeInput(value);
2215
+ }, [onChangeSomeInput]);
2216
+
2217
+ // Handle for text input
2218
+ const onChangeEditable = useCallback(value => {
2219
+ setEditableValue(value);
2220
+ onChangeSomeInput(value);
2221
+ }, [onChangeSomeInput]);
2222
+ return /*#__PURE__*/React$1.createElement(React$1.Fragment, null, options.map(option => option.editable ? /*#__PURE__*/React$1.createElement(RadioGroupInput, {
2223
+ key: option.label,
2224
+ editableProps: editableProps,
2225
+ input: input,
2226
+ inputProps: inputProps,
2227
+ option: option,
2228
+ value: editableValue,
2229
+ onChange: onChangeEditable
2230
+ }) : /*#__PURE__*/React$1.createElement(RadioGroupItem, {
2231
+ key: option.value,
2232
+ input: input,
2233
+ inputProps: inputProps,
2234
+ option: option,
2235
+ onChange: onChangeRadio
2236
+ })));
2237
+ }
2238
+
2239
+ const RadioGroup = /*#__PURE__*/React$1.memo(function RadioGroup(props) {
2303
2240
  const {
2304
2241
  name,
2305
- initialValue,
2306
2242
  isDisabled,
2243
+ editableProps = {},
2244
+ fieldProps = {},
2245
+ inputProps = {},
2246
+ options = [],
2307
2247
  classNameGroupItem,
2308
- emptyMessage,
2309
- emptyMessageTextColor,
2310
- emptyMessageTextSize,
2311
- fieldProps,
2312
- inputProps,
2313
- options,
2314
2248
  showMessage,
2315
2249
  isRequired,
2316
2250
  onChange
2317
2251
  } = props;
2318
- const {
2319
- change
2320
- } = useForm();
2321
-
2322
- // Callback for value changes
2323
- const onChangeSomeInput = useCallback((inputValue, newOptionValue) => {
2324
- const updatedValues = inputValue.includes(newOptionValue) ? inputValue.filter(selectedValue => selectedValue !== newOptionValue) : [...inputValue, newOptionValue];
2325
- change(name, updatedValues);
2326
- onChange && onChange(updatedValues);
2327
- }, [change, name, onChange]);
2328
- useEffect(() => {
2329
- initialValue && change(name, initialValue);
2330
- // update the form value only when the initialValue changes, so use disable eslint to ignore the warning
2331
- // eslint-disable-next-line react-hooks/exhaustive-deps
2332
- }, [initialValue]);
2333
2252
  return /*#__PURE__*/React$1.createElement(Field, {
2334
- name: name,
2335
- initialValue: initialValue
2253
+ name: name
2336
2254
  }, function Render({
2337
2255
  input,
2338
2256
  meta
2339
2257
  }) {
2258
+ /** Note:
2259
+ * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
2260
+ * React Hooks cannot be called inside a callback.
2261
+ * React Hooks must be called in a React function component or a
2262
+ * custom React Hook function.
2263
+ */
2264
+
2340
2265
  const {
2341
2266
  errorKey,
2342
2267
  errorMessage,
@@ -2351,49 +2276,30 @@ function ChipsField(props) {
2351
2276
  inputProps: inputProps,
2352
2277
  validationStateKey: isErrorState ? errorKey : 'success'
2353
2278
  });
2354
- const activeOptionsList = useMemo(() => {
2355
- const emptyOptionsList = [{
2356
- label: null,
2357
- value: null
2358
- }];
2359
- if (input?.value) {
2360
- const currentOptions = options.filter(option => input.value?.includes(option.value));
2361
- return currentOptions || emptyOptionsList;
2362
- }
2363
- return emptyOptionsList;
2364
- }, [input.value]);
2365
2279
  return /*#__PURE__*/React$1.createElement(FieldWrapper, Object.assign({
2366
- className: clsx('form-field_type_chips', 'form__item_type_chips', classNameGroupItem),
2280
+ className: clsx('form-field_type_radio', 'form__item_type_radio"', classNameGroupItem),
2367
2281
  errorKey: errorKey,
2368
2282
  errorMessage: errorMessage,
2369
2283
  isErrorState: isErrorState,
2370
2284
  metaError: meta.error,
2371
2285
  isDisabled: isDisabled,
2372
- fieldClassName: "form-chips",
2286
+ fieldClassName: 'form-radio',
2373
2287
  inputName: input.name,
2374
- inputValue: input.value,
2288
+ inputValue: input.value || '',
2375
2289
  metaActive: meta.active,
2376
2290
  showMessage: showMessage,
2377
2291
  isRequired: isRequired,
2378
2292
  isValidState: isValidState
2379
- }, fieldProps), options.length ? /*#__PURE__*/React$1.createElement(ChipsGroup, {
2380
- direction: "horizontal",
2381
- gap: "1m",
2382
- wrap: "wrap"
2383
- }, options.map(option => /*#__PURE__*/React$1.createElement(Chips, Object.assign({
2384
- className: clsx(meta.active && 'form-chips_state_focus', meta.error && meta.touched && `form-chips_state_${errorKey}`),
2385
- key: option.value,
2386
- label: option.label,
2387
- isDisabled: option.isDisabled,
2388
- value: option.value,
2389
- isActive: activeOptionsList.some(activeOption => activeOption.value === option.value),
2390
- onClick: () => onChangeSomeInput(input.value, option.value)
2391
- }, updatedInputProps)))) : /*#__PURE__*/React$1.createElement(Text, {
2392
- size: emptyMessageTextSize,
2393
- textColor: emptyMessageTextColor
2394
- }, emptyMessage));
2293
+ }, fieldProps), /*#__PURE__*/React$1.createElement(RadioGroupList, {
2294
+ isDisabled: isDisabled,
2295
+ editableProps: editableProps,
2296
+ input: input,
2297
+ inputProps: updatedInputProps,
2298
+ options: options,
2299
+ onChange: onChange
2300
+ }));
2395
2301
  });
2396
- }
2302
+ });
2397
2303
 
2398
2304
  const formTypes = {
2399
2305
  code: 'code',
@@ -2417,43 +2323,43 @@ function generateField(field, config, props) {
2417
2323
  switch (field.type) {
2418
2324
  case formTypes.checkbox:
2419
2325
  {
2420
- return /*#__PURE__*/React$1.createElement(CheckboxField, Object.assign({
2326
+ return /*#__PURE__*/React$1.createElement(FormFieldCheckbox, Object.assign({
2421
2327
  key: config.key
2422
2328
  }, field, props));
2423
2329
  }
2424
2330
  case formTypes.choice:
2425
2331
  {
2426
- return /*#__PURE__*/React$1.createElement(ChoiceField, Object.assign({
2332
+ return /*#__PURE__*/React$1.createElement(FormFieldChoice, Object.assign({
2427
2333
  key: config.key
2428
2334
  }, field, props));
2429
2335
  }
2430
2336
  case formTypes.chips:
2431
2337
  {
2432
- return /*#__PURE__*/React$1.createElement(ChipsField, Object.assign({
2338
+ return /*#__PURE__*/React$1.createElement(FormFieldChips, Object.assign({
2433
2339
  key: config.key
2434
2340
  }, field, props));
2435
2341
  }
2436
2342
  case formTypes.code:
2437
2343
  {
2438
- return /*#__PURE__*/React$1.createElement(CodeField, Object.assign({
2344
+ return /*#__PURE__*/React$1.createElement(FormFieldCode, Object.assign({
2439
2345
  key: config.key
2440
2346
  }, field, props));
2441
2347
  }
2442
2348
  case formTypes.switch:
2443
2349
  {
2444
- return /*#__PURE__*/React$1.createElement(SwitchField, Object.assign({
2350
+ return /*#__PURE__*/React$1.createElement(FormFieldSwitch, Object.assign({
2445
2351
  key: config.key
2446
2352
  }, field, props));
2447
2353
  }
2448
2354
  case formTypes.segmented:
2449
2355
  {
2450
- return /*#__PURE__*/React$1.createElement(SegmentedField, Object.assign({
2356
+ return /*#__PURE__*/React$1.createElement(FormFieldSegmented, Object.assign({
2451
2357
  key: config.key
2452
2358
  }, field, props));
2453
2359
  }
2454
2360
  case formTypes.datePicker:
2455
2361
  {
2456
- return /*#__PURE__*/React$1.createElement(DatePickerField, Object.assign({
2362
+ return /*#__PURE__*/React$1.createElement(FormFieldDatePicker, Object.assign({
2457
2363
  key: config.key
2458
2364
  }, field, props));
2459
2365
  }
@@ -2471,37 +2377,37 @@ function generateField(field, config, props) {
2471
2377
  }
2472
2378
  case formTypes.select:
2473
2379
  {
2474
- return /*#__PURE__*/React$1.createElement(SelectField, Object.assign({
2380
+ return /*#__PURE__*/React$1.createElement(FormFieldSelect, Object.assign({
2475
2381
  key: config.key
2476
2382
  }, field, props));
2477
2383
  }
2478
2384
  case formTypes.text:
2479
2385
  {
2480
- return /*#__PURE__*/React$1.createElement(InputField, Object.assign({
2386
+ return /*#__PURE__*/React$1.createElement(FormFieldInput, Object.assign({
2481
2387
  key: config.key
2482
2388
  }, field, props));
2483
2389
  }
2484
2390
  case formTypes.textarea:
2485
2391
  {
2486
- return /*#__PURE__*/React$1.createElement(TextareaField, Object.assign({
2392
+ return /*#__PURE__*/React$1.createElement(FormFieldTextarea, Object.assign({
2487
2393
  key: config.key
2488
2394
  }, field, props));
2489
2395
  }
2490
2396
  case formTypes.maskedInput:
2491
2397
  {
2492
- return /*#__PURE__*/React$1.createElement(MaskedInputField, Object.assign({
2398
+ return /*#__PURE__*/React$1.createElement(FormFieldMaskedInput, Object.assign({
2493
2399
  key: config.key
2494
2400
  }, field, props));
2495
2401
  }
2496
2402
  case formTypes.custom:
2497
2403
  {
2498
- return /*#__PURE__*/React$1.createElement(CustomField, Object.assign({
2404
+ return /*#__PURE__*/React$1.createElement(FormFieldCustom, Object.assign({
2499
2405
  key: config.key
2500
2406
  }, field, props));
2501
2407
  }
2502
2408
  case formTypes.group:
2503
2409
  {
2504
- return /*#__PURE__*/React$1.createElement(Group, Object.assign({
2410
+ return /*#__PURE__*/React$1.createElement(FormBlockGroup, Object.assign({
2505
2411
  key: config.key
2506
2412
  }, field, props), Object.entries(field.group).map(([key, value]) => {
2507
2413
  const groupProps = {
@@ -2781,7 +2687,7 @@ const FinalForm = /*#__PURE__*/React$1.forwardRef(function FinalForm(props, ref)
2781
2687
  values: true
2782
2688
  },
2783
2689
  onChange: onChangeFormValues
2784
- }), Boolean(Object.keys(config).length) && /*#__PURE__*/React$1.createElement(React$1.Fragment, null, renderFieldsWrapper(/*#__PURE__*/React$1.createElement(Group$1, {
2690
+ }), Boolean(Object.keys(config).length) && /*#__PURE__*/React$1.createElement(React$1.Fragment, null, renderFieldsWrapper(/*#__PURE__*/React$1.createElement(Group, {
2785
2691
  className: "form__wrapper",
2786
2692
  direction: "vertical",
2787
2693
  gap: fieldsGap || groupGap,
@@ -2797,7 +2703,7 @@ const FinalForm = /*#__PURE__*/React$1.forwardRef(function FinalForm(props, ref)
2797
2703
  text: loaderText,
2798
2704
  itemFill: loaderItemFill,
2799
2705
  shape: loaderShape
2800
- }))))), (primaryButtonLabel || primaryButton || secondaryButtonLabel || secondaryButton || tertiaryButton || tertiaryButtonLabel) && /*#__PURE__*/React$1.createElement(Group$1, {
2706
+ }))))), (primaryButtonLabel || primaryButton || secondaryButtonLabel || secondaryButton || tertiaryButton || tertiaryButtonLabel) && /*#__PURE__*/React$1.createElement(Group, {
2801
2707
  className: "form__button",
2802
2708
  direction: buttonDirection,
2803
2709
  justifyContent: buttonJustifyContent,
@@ -3078,4 +2984,4 @@ const getErrorsForFinalForm = error => {
3078
2984
  return formErrors;
3079
2985
  };
3080
2986
 
3081
- export { CheckboxField, ChipsField, ChoiceField, CodeField, CustomField, DEFAULT_MESSAGES_FIELDS, DatePickerField, FieldWrapper, FieldWrapperBase, FileInput, FinalForm, Group, InputField, MaskedInputField, RadioGroup, SegmentedField, SelectField, SwitchField, TextareaField, addRequiredFieldsParamToSchema, dateValidation, defaultCheckboxProps, defaultChipsProps, defaultChoiceProps, defaultCodeProps, defaultDatepickerProps, defaultDropzoneProps, defaultFieldProps, defaultGroupProps, defaultInputProps, defaultRadioProps, defaultSegmentedProps, defaultSelectProps, defaultSwitchProps, defaultTextareaProps, emailValidation, focusOnError, focusOnErrorDecorator, formTypes, generateField, getErrorsForFinalForm, parseNumericField, phoneValidation, sendFormDataToServer, setErrorsMutator, useYupValidationSchema };
2987
+ export { DEFAULT_MESSAGES_FIELDS, FieldWrapper, FieldWrapperBase, FileInput, FinalForm, FormBlockGroup, FormFieldCheckbox, FormFieldChips, FormFieldChoice, FormFieldCode, FormFieldCustom, FormFieldDatePicker, FormFieldInput, FormFieldMaskedInput, FormFieldSegmented, FormFieldSelect, FormFieldSwitch, FormFieldTextarea, RadioGroup, addRequiredFieldsParamToSchema, dateValidation, defaultCheckboxProps, defaultChipsProps, defaultChoiceProps, defaultCodeProps, defaultDatepickerProps, defaultDropzoneProps, defaultFieldProps, defaultFieldSizeM, defaultFieldSizeXL, defaultGroupProps, defaultInputProps, defaultRadioProps, defaultSegmentedProps, defaultSelectProps, defaultSwitchProps, defaultTextareaProps, emailValidation, focusOnError, focusOnErrorDecorator, formTypes, generateField, getErrorsForFinalForm, parseNumericField, phoneValidation, sendFormDataToServer, setErrorsMutator, useYupValidationSchema };