@itcase/forms 1.1.40 → 1.1.43

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,16 +1,22 @@
1
1
  import { isPossiblePhoneNumber } from 'libphonenumber-js';
2
- import React, { useMemo, useEffect, useState, useCallback } from 'react';
2
+ import React, { useMemo, useEffect, useCallback, useState } 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 { useDevicePropsGenerator } from '@itcase/ui/hooks/useDevicePropsGenerator';
7
+ import { Checkbox } from '@itcase/ui/components/Checkbox';
8
8
  import camelCase from 'lodash/camelCase';
9
9
  import snakeCase from 'lodash/snakeCase';
10
10
  import { Divider } from '@itcase/ui/components/Divider';
11
11
  import { Text } from '@itcase/ui/components/Text';
12
12
  import { useDeviceTargetClass } from '@itcase/ui/hooks/useDeviceTargetClass';
13
13
  import { useStyles } from '@itcase/ui/hooks/useStyles';
14
+ import { ChipsGroup, Chips } from '@itcase/ui/components/Chips';
15
+ import { Choice } from '@itcase/ui/components/Choice';
16
+ import { Code } from '@itcase/ui/components/Code';
17
+ import { Icon } from '@itcase/ui/components/Icon';
18
+ import { DatePickerInput } from '@itcase/ui/components/DatePicker';
19
+ import { useDevicePropsGenerator } from '@itcase/ui/hooks/useDevicePropsGenerator';
14
20
  import axios from 'axios';
15
21
  import { fromEvent } from 'file-selector';
16
22
  import castArray from 'lodash/castArray';
@@ -19,20 +25,14 @@ import { createFileFromDataURL } from '@itcase/common';
19
25
  import { Button } from '@itcase/ui/components/Button';
20
26
  import { Loader } from '@itcase/ui/components/Loader';
21
27
  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';
28
28
  import { Input } from '@itcase/ui/components/Input';
29
- import { icons24 } from '@itcase/icons/default';
29
+ import { useIMask } from 'react-imask';
30
+ import { InputPassword } from '@itcase/ui/components/InputPassword';
31
+ import { Radio } from '@itcase/ui/components/Radio';
30
32
  import { Segmented } from '@itcase/ui/components/Segmented';
31
33
  import { Select } from '@itcase/ui/components/Select';
32
34
  import { Switch } from '@itcase/ui/components/Switch';
33
35
  import { Textarea } from '@itcase/ui/components/Textarea';
34
- import { useIMask } from 'react-imask';
35
- import { Radio } from '@itcase/ui/components/Radio';
36
36
  import { Group } from '@itcase/ui/components/Group';
37
37
  import { Notification } from '@itcase/ui/components/Notification';
38
38
  import createDecorator from 'final-form-focus';
@@ -117,6 +117,16 @@ function useYupValidationSchema(schema, language) {
117
117
  return validate;
118
118
  }
119
119
 
120
+ const defaultCheckboxProps = {
121
+ appearance: 'defaultPrimary sizeL solid',
122
+ width: 'fill',
123
+ // useValidationAppearanceInputProps
124
+ // Error
125
+ errorAppearance: 'errorPrimary sizeL solid',
126
+ // Required
127
+ requiredAppearance: 'requirePrimary sizeL solid'
128
+ };
129
+
120
130
  // Whether to display an error message based on "fieldProps" and meta-objects
121
131
  function useFieldValidationState(props) {
122
132
  const {
@@ -430,428 +440,477 @@ function FieldWrapper(props) {
430
440
  return /*#__PURE__*/React.createElement(FieldWrapperBase, props);
431
441
  }
432
442
 
433
- const defaultDropzoneProps = {
434
- fill: 'surfaceSecondary',
435
- fillHover: 'surfaceTertiary',
436
- // borderColor: 'surfaceBorderTertiary',
437
- // borderColorHover: 'surfaceBorderQuaternary',
438
- hintTitle: 'Перетащите изображение или выберите файл с компьютера',
439
- hintTitleTextColor: 'surfaceTextPrimary',
440
- hintTitleTextSize: 'm',
441
- removeThumbText: 'удалить',
442
- removeThumbTextColor: 'errorTextPrimary',
443
- removeThumbTextHoverColor: 'errorTextPrimaryHover',
444
- removeThumbTextSize: 's',
445
- shape: 'rounded',
446
- showFilename: true,
447
- thumbBorderColor: 'surfaceBorderTertiary',
448
- thumbBorderColorHover: 'surfaceBorderQuaternary',
449
- thumbBorderWidth: 1,
450
- thumbNameTextColor: 'surfaceTextPrimary',
451
- thumbNameTextSize: 's',
452
- isPreviews: true
443
+ const FormFieldCheckbox = /*#__PURE__*/React.memo(function FormFieldCheckbox(props) {
444
+ const {
445
+ name,
446
+ initialValue,
447
+ isDisabled,
448
+ classNameGroupItem,
449
+ fieldProps = {},
450
+ inputProps = {},
451
+ showMessage,
452
+ isRequired,
453
+ onChange
454
+ } = props;
455
+ return /*#__PURE__*/React.createElement(Field, {
456
+ type: "checkbox",
457
+ name: name,
458
+ initialValue: initialValue
459
+ }, function Render({
460
+ input,
461
+ meta
462
+ }) {
463
+ /** Note:
464
+ * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
465
+ * React Hooks cannot be called inside a callback.
466
+ * React Hooks must be called in a React function component or a
467
+ * custom React Hook function.
468
+ */
469
+
470
+ const onChangeField = useCallback(event => {
471
+ input.onChange(event);
472
+ if (onChange) {
473
+ onChange(event.target.checked, input.name);
474
+ }
475
+ }, [onChange, input.onChange]);
476
+ const {
477
+ errorKey,
478
+ errorMessage,
479
+ isErrorState,
480
+ successKey,
481
+ isValidState
482
+ } = useFieldValidationState({
483
+ fieldProps: fieldProps,
484
+ input: input,
485
+ meta: meta
486
+ });
487
+ const updatedInputProps = useValidationAppearanceInputProps({
488
+ inputProps: inputProps,
489
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
490
+ });
491
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
492
+ className: clsx('form-field-checkbox', 'form__item_checkbox', classNameGroupItem),
493
+ errorKey: errorKey,
494
+ errorMessage: errorMessage,
495
+ isErrorState: isErrorState,
496
+ metaError: meta.error,
497
+ isDisabled: isDisabled,
498
+ fieldClassName: "form-checkbox",
499
+ inputName: input.name,
500
+ inputValue: input.checked,
501
+ metaActive: meta.active,
502
+ showMessage: showMessage,
503
+ tag: "label",
504
+ isRequired: isRequired,
505
+ isValidState: isValidState
506
+ }, fieldProps), /*#__PURE__*/React.createElement(Checkbox, Object.assign({
507
+ type: "checkbox",
508
+ name: input.name,
509
+ isDisabled: isDisabled,
510
+ autoComplete: "nope",
511
+ checked: input.checked,
512
+ isActive: input.checked,
513
+ onBlur: input.onBlur,
514
+ onChange: onChangeField,
515
+ onFocus: input.onFocus
516
+ }, updatedInputProps)));
517
+ });
518
+ });
519
+
520
+ const defaultChipsProps = {
521
+ appearance: 'surfacePrimary sizeM rounded',
522
+ width: 'fill',
523
+ // useValidationAppearanceInputProps
524
+ // Error
525
+ errorAppearance: 'errorPrimary sizeM solid rounded',
526
+ // Required
527
+ requiredAppearance: 'requirePrimary sizeM solid rounded'
528
+ // Success
529
+ // successAppearance: 'successPrimary sizeM solid rounded',
453
530
  };
454
531
 
455
- const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(props) {
532
+ function FormFieldChips(props) {
456
533
  const {
457
- className,
458
- maxFiles,
459
- maxSize,
460
- size,
461
- fileErrorText,
462
- dropzoneProps = {},
463
- hintDescription,
464
- hintTitle,
465
- inputName,
466
- inputValue,
467
- showFilename,
468
- thumbColumn,
469
- isPreviews,
470
- onAddFiles,
471
- onClickPreview,
472
- onDeleteFile
534
+ name,
535
+ initialValue,
536
+ isDisabled,
537
+ classNameGroupItem,
538
+ emptyMessage,
539
+ emptyMessageTextColor,
540
+ emptyMessageTextSize,
541
+ fieldProps,
542
+ inputProps,
543
+ options,
544
+ showMessage,
545
+ isRequired,
546
+ onChange
473
547
  } = props;
474
-
475
- // TODO: delete react-final-form things out of here?
476
548
  const {
477
549
  change
478
550
  } = useForm();
479
- const [fileError, setFileError] = useState('');
480
- const [fileIsLoading, setFileIsLoading] = useState(false);
481
- const filesList = useMemo(() => inputValue ? castArray(inputValue) : [], [inputValue]);
482
- const changeFormState = useCallback(newFiles => {
483
- // If max files in dropzone is 1 - return file as it self, else as array of files
484
- // ps: for old projects compatibility
485
- const toSave = dropzoneProps.maxFiles == 1 ? newFiles[0] : newFiles;
486
- change(inputName, toSave);
487
- return toSave;
488
- },
489
- // If "inputName" will be changes, then it should be a different field
490
- // eslint-disable-next-line react-hooks/exhaustive-deps
491
- [dropzoneProps, change]);
492
551
 
493
- //
494
- const convertFiledValueAndSaveAsFiles = useCallback(async currentFilesList => {
495
- setFileIsLoading(true);
496
- const newFiles = [];
497
- for (const fileItem of currentFilesList) {
498
- if (typeof fileItem === 'string') {
499
- const newFile = await convertToFile(fileItem, isPreviews);
500
- if (newFile) {
501
- newFiles.push(newFile);
502
- }
503
- } else {
504
- newFiles.push(fileItem);
552
+ // Callback for value changes
553
+ const onChangeSomeInput = useCallback((inputValue, newOptionValue) => {
554
+ const updatedValues = inputValue.includes(newOptionValue) ? inputValue.filter(selectedValue => selectedValue !== newOptionValue) : [...inputValue, newOptionValue];
555
+ change(name, updatedValues);
556
+ onChange && onChange(updatedValues);
557
+ }, [change, name, onChange]);
558
+ useEffect(() => {
559
+ initialValue && change(name, initialValue);
560
+ // update the form value only when the initialValue changes, so use disable eslint to ignore the warning
561
+ // eslint-disable-next-line react-hooks/exhaustive-deps
562
+ }, [initialValue]);
563
+ return /*#__PURE__*/React.createElement(Field, {
564
+ name: name,
565
+ initialValue: initialValue
566
+ }, function Render({
567
+ input,
568
+ meta
569
+ }) {
570
+ const {
571
+ errorKey,
572
+ errorMessage,
573
+ isErrorState,
574
+ successKey,
575
+ isValidState
576
+ } = useFieldValidationState({
577
+ fieldProps: fieldProps,
578
+ input: input,
579
+ meta: meta
580
+ });
581
+ const updatedInputProps = useValidationAppearanceInputProps({
582
+ inputProps: inputProps,
583
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
584
+ });
585
+ const activeOptionsList = useMemo(() => {
586
+ const emptyOptionsList = [{
587
+ label: null,
588
+ value: null
589
+ }];
590
+ if (input?.value) {
591
+ const currentOptions = options.filter(option => input.value?.includes(option.value));
592
+ return currentOptions || emptyOptionsList;
505
593
  }
506
- }
507
- changeFormState(newFiles);
508
- setFileIsLoading(false);
509
- }, [isPreviews, changeFormState]);
510
-
511
- // Delete file from dropzone
512
- const removeFile = useCallback((event, index) => {
513
- event.stopPropagation();
514
- event.preventDefault();
515
- const newFiles = [...filesList];
516
- newFiles.splice(index, 1);
517
- if (onDeleteFile) {
518
- onDeleteFile(filesList[index], inputName);
519
- }
520
- changeFormState(newFiles);
521
- },
522
- // If "inputName" will be changes, then it should be a different field
523
- // eslint-disable-next-line react-hooks/exhaustive-deps
524
- [filesList, changeFormState, onDeleteFile]);
525
-
526
- // Create dropzone options
527
- const {
528
- getInputProps,
529
- getRootProps
530
- } = useDropzone({
531
- maxFiles: maxFiles || 5,
532
- maxSize: maxSize || 10485760,
533
- // 10mb
534
- // accept: { 'image/*': [] },
535
- ...dropzoneProps,
536
- getFilesFromEvent: async event => {
537
- const result = await fromEvent(event);
538
- const newFiles = result.filter(item => item instanceof File);
539
- // Add exists and new files to accepted(or rejected)
540
- return [...filesList, ...newFiles];
541
- },
542
- onDropAccepted: acceptedFiles => {
543
- // If dropped files has accepted and we need a previews
544
- if (isPreviews) {
545
- // Add preview to every file
546
- acceptedFiles.forEach(file => {
547
- if (!file.error) {
548
- file.preview = URL.createObjectURL(file);
549
- }
550
- });
551
- }
552
- // Save to form data (including empty when files are not valid)
553
- const filesToSave = changeFormState(acceptedFiles);
554
- setFileError('');
555
-
556
- // Save DataURL for all files
557
- const readerPromisesList = acceptedFiles.map(file => {
558
- return new Promise(resolve => setFileDataURL(file, resolve));
559
- });
560
- // Save files to form values
561
- Promise.all(readerPromisesList).then(() => {
562
- if (onAddFiles) {
563
- onAddFiles(filesToSave, inputName);
564
- }
565
- });
566
- },
567
- onDropRejected: rejectedFiles => {
568
- // If dropped files has rejected
569
- if (rejectedFiles.length) {
570
- let fileErrorMessage = 'Ошибка при добавлении файла';
571
- const firstFileErrorItem = rejectedFiles[0].errors[0];
572
- if (firstFileErrorItem) {
573
- if (firstFileErrorItem.code === ErrorCode.TooManyFiles) {
574
- fileErrorMessage = `Максимальное количество файлов: ${maxFiles}`;
575
- } else {
576
- fileErrorMessage = firstFileErrorItem.message;
577
- }
578
- }
579
- // Show error
580
- setFileError(fileErrorMessage);
581
- } else {
582
- // Else clean error
583
- setFileError('');
584
- }
585
- }
594
+ return emptyOptionsList;
595
+ }, [input.value]);
596
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
597
+ className: clsx('form-field_chips', 'form__item_chips', classNameGroupItem),
598
+ errorKey: errorKey,
599
+ errorMessage: errorMessage,
600
+ isErrorState: isErrorState,
601
+ metaError: meta.error,
602
+ isDisabled: isDisabled,
603
+ fieldClassName: "form-chips",
604
+ inputName: input.name,
605
+ inputValue: input.value,
606
+ metaActive: meta.active,
607
+ showMessage: showMessage,
608
+ isRequired: isRequired,
609
+ isValidState: isValidState
610
+ }, fieldProps), options.length ? /*#__PURE__*/React.createElement(ChipsGroup, {
611
+ direction: "horizontal",
612
+ gap: "1m",
613
+ wrap: "wrap"
614
+ }, options.map(option => /*#__PURE__*/React.createElement(Chips, Object.assign({
615
+ className: clsx(meta.active && 'form-chips_state_focus', meta.error && meta.touched && `form-chips_state_${errorKey}`),
616
+ key: option.value,
617
+ label: option.label,
618
+ isDisabled: option.isDisabled,
619
+ value: option.value,
620
+ isActive: activeOptionsList.some(activeOption => activeOption.value === option.value),
621
+ onClick: () => onChangeSomeInput(input.value, option.value)
622
+ }, updatedInputProps)))) : /*#__PURE__*/React.createElement(Text, {
623
+ size: emptyMessageTextSize,
624
+ textColor: emptyMessageTextColor
625
+ }, emptyMessage));
586
626
  });
587
- useEffect(() => {
588
- const currentFilesList = castArray(inputValue);
589
- const isNeedToConvert = currentFilesList.some(fileItem => typeof fileItem === 'string');
590
- if (isNeedToConvert) {
591
- // First time convert value to Files and save to local and form state
592
- convertFiledValueAndSaveAsFiles(currentFilesList);
593
- }
594
-
595
- // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
596
- return () => {
597
- filesList.forEach(file => {
598
- if (file?.preview) {
599
- URL.revokeObjectURL(file.preview);
600
- }
601
- });
602
- };
603
- // eslint-disable-next-line react-hooks/exhaustive-deps
604
- }, [inputValue]);
605
- const propsGenerator = useDevicePropsGenerator(props);
606
- const {
607
- fillClass,
608
- fillHoverClass,
609
- borderColorClass,
610
- borderColorHoverClass,
611
- borderTypeClass,
612
- borderWidthClass,
613
- errorMessageTextColor,
614
- errorMessageTextSize,
615
- errorMessageTextWeight,
616
- hintDescriptionTextColor,
617
- hintDescriptionTextSize,
618
- hintDescriptionTextWeight,
619
- hintDescriptionTextWrap,
620
- hintTitleTextColor,
621
- hintTitleTextSize,
622
- hintTitleTextWeight,
623
- hintTitleTextWrap,
624
- removeThumbAppearance,
625
- removeThumbShape,
626
- removeThumbText,
627
- removeThumbTextWeight,
628
- shapeClass,
629
- thumbBorderColorClass,
630
- thumbBorderColorHoverClass,
631
- thumbBorderTypeClass,
632
- thumbBorderWidthClass,
633
- thumbDirectionClass,
634
- thumbNameTextColor,
635
- thumbNameTextSize,
636
- thumbNameTextWeight,
637
- thumbNameTextWrap
638
- } = propsGenerator;
639
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", getRootProps({
640
- // className: `form-dropzone__dropzone dropzone ${className} form-dropzone__dropzone_size_${size} ${shapeClass}`,
641
- className: `form-dropzone__dropzone dropzone`
642
- }), /*#__PURE__*/React.createElement("input", Object.assign({}, getInputProps(), {
643
- name: inputName
644
- })), /*#__PURE__*/React.createElement("div", {
645
- className: clsx('form-dropzone__dropzone-wrapper', thumbColumn && `form-dropzone__dropzone-wrapper_column_${thumbColumn}`, fillClass && `fill_${fillClass}`, fillHoverClass && `fill_hover_${fillHoverClass}`, borderWidthClass && `border-width_${borderWidthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderColorHoverClass && `border-color_hover_${borderColorHoverClass}`, borderTypeClass && `border_type_${borderTypeClass}`, shapeClass && `shape_${shapeClass}`)
646
- }, filesList.map((file, index) => /*#__PURE__*/React.createElement("aside", {
647
- className: clsx('form-dropzone__thumb', fillClass, thumbDirectionClass, thumbBorderWidthClass, thumbBorderColorClass, thumbBorderColorHoverClass, thumbBorderTypeClass),
648
- key: file.id || `${file.name}_${index}`
649
- }, isPreviews && !file.error && /*#__PURE__*/React.createElement("div", {
650
- className: "form-dropzone__thumb-image"
651
- }, /*#__PURE__*/React.createElement("img", {
652
- className: "form-dropzone__thumb-image-inner",
653
- src: file.preview || file.image,
654
- onClick: event => {
655
- onClickPreview && onClickPreview(file, event);
656
- },
657
- onLoad: () => {
658
- // Revoke data uri after image is loaded
659
- URL.revokeObjectURL(file.preview);
660
- }
661
- })), file.error && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Text, {
662
- size: thumbNameTextSize,
663
- textColor: thumbNameTextColor,
664
- textWeight: thumbNameTextWeight,
665
- textWrap: thumbNameTextWrap
666
- }, fileErrorText || file.error)), showFilename && /*#__PURE__*/React.createElement("div", {
667
- className: "form-dropzone__thumb-name"
668
- }, /*#__PURE__*/React.createElement(Text, {
669
- className: "form-dropzone__thumb-name-inner",
670
- size: thumbNameTextSize,
671
- textColor: thumbNameTextColor,
672
- textWeight: thumbNameTextWeight,
673
- textWrap: thumbNameTextWrap
674
- }, file.name)), fileIsLoading && /*#__PURE__*/React.createElement("div", {
675
- className: "form-dropzone__thumb-loader"
676
- }, /*#__PURE__*/React.createElement(Loader, {
677
- width: "fill",
678
- height: "fill"
679
- })), /*#__PURE__*/React.createElement("div", {
680
- className: clsx('form-dropzone__thumb-remove')
681
- }, /*#__PURE__*/React.createElement(Button, {
682
- className: "form-dropzone__thumb-remove-text",
683
- appearance: removeThumbAppearance,
684
- label: removeThumbText || 'Удалить',
685
- labelTextWeight: removeThumbTextWeight,
686
- shape: removeThumbShape,
687
- onClick: event => removeFile(event, index)
688
- })))), !filesList.length ? /*#__PURE__*/React.createElement("div", {
689
- className: "form-dropzone__hint"
690
- }, /*#__PURE__*/React.createElement(Text, {
691
- className: "form-dropzone__hint-title",
692
- size: hintTitleTextSize,
693
- textColor: hintTitleTextColor,
694
- textWeight: hintTitleTextWeight,
695
- textWrap: hintTitleTextWrap
696
- }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React.createElement(Text, {
697
- className: "form-dropzone__hint-text",
698
- size: hintDescriptionTextSize,
699
- textColor: hintDescriptionTextColor,
700
- textWeight: hintDescriptionTextWeight,
701
- textWrap: hintDescriptionTextWrap
702
- }, hintDescription)) : /*#__PURE__*/React.createElement("div", {
703
- className: "form-dropzone__hint form-dropzone__hint_type_add-more"
704
- }, /*#__PURE__*/React.createElement(Text, {
705
- className: "form-dropzone__hint-title",
706
- size: hintTitleTextSize,
707
- textColor: hintTitleTextColor,
708
- textWeight: hintTitleTextWeight,
709
- textWrap: hintTitleTextWrap
710
- }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React.createElement(Text, {
711
- className: "form-dropzone__hint-text",
712
- size: hintDescriptionTextSize,
713
- textColor: hintDescriptionTextColor,
714
- textWeight: hintDescriptionTextWeight,
715
- textWrap: hintDescriptionTextWrap
716
- }, hintDescription)))), fileError && /*#__PURE__*/React.createElement("div", {
717
- className: "form-field__message"
718
- }, /*#__PURE__*/React.createElement(Text, {
719
- className: "form-field__message-item form-field__message-item_type_message",
720
- size: errorMessageTextSize,
721
- textColor: errorMessageTextColor,
722
- textWeight: errorMessageTextWeight
723
- }, fileError)));
724
- });
725
- async function getFileByURL(url) {
726
- try {
727
- const response = await axios({
728
- url: url,
729
- responseType: 'blob'
730
- });
731
- const blobObject = response.data;
732
- const dirtyFilename = response.headers['content-disposition']?.split('filename=')[1];
733
- // Remove double quotes
734
- let filename = dirtyFilename?.substring(1).slice(0, -1);
735
- if (!filename) {
736
- filename = url.split('/').at(-1);
737
- // const typeParts = blobObject.type.split('/')
738
- // const fileType = typeParts[typeParts.length - 1]
739
- // filename = `${new Date().getTime()}.${fileType}`
740
- }
741
- return new File([blobObject], filename, {
742
- type: blobObject.type
743
- });
744
- } catch (error) {
745
- console.log('error: ', error);
746
- return null;
747
- }
748
627
  }
749
- async function convertToFile(inputValue, isPreviews) {
750
- let newFile = null;
751
628
 
752
- // Download image by url and save as File instance
753
- const isURL = typeof inputValue === 'string' && inputValue.includes('/');
754
- if (inputValue.image || isURL) {
755
- newFile = await getFileByURL(inputValue.image || inputValue);
756
- if (newFile) {
757
- setFileDataURL(newFile);
758
- }
759
- }
760
-
761
- // Convert dataURL to File instance
762
- if (inputValue.dataURL) {
763
- newFile = createFileFromDataURL(inputValue.name || inputValue.path, inputValue.dataURL);
764
- newFile.dataURL = inputValue.dataURL;
765
- }
629
+ const defaultChoiceProps = {
630
+ appearance: 'defaultPrimary sizeM solid rounded',
631
+ width: 'fill',
632
+ // useValidationAppearanceInputProps
633
+ // Error
634
+ errorAppearance: 'errorPrimary sizeM solid rounded',
635
+ // Required
636
+ requiredAppearance: 'requirePrimary sizeM solid rounded'
637
+ };
766
638
 
767
- // Save new File to state
768
- if (newFile) {
769
- newFile.id = inputValue.id;
770
- if (isPreviews) {
771
- newFile.preview = URL.createObjectURL(newFile);
639
+ const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props) {
640
+ const {
641
+ name,
642
+ initialValue,
643
+ label,
644
+ messageType,
645
+ isDisabled,
646
+ classNameGroupItem,
647
+ fieldProps,
648
+ inputProps,
649
+ options,
650
+ placeholder,
651
+ showMessage,
652
+ isCheckbox,
653
+ isRequired,
654
+ onChange
655
+ } = props;
656
+ const {
657
+ change
658
+ } = useForm();
659
+ const setActiveSegment = useCallback((option, isChecked) => {
660
+ change(name, isChecked && option.value);
661
+ if (onChange) {
662
+ onChange(option.value, name, isChecked);
772
663
  }
773
- }
774
- return newFile;
775
- }
776
- function setFileDataURL(file, resolve) {
777
- resolve = resolve || (() => {});
778
- // Init reader and save his file
779
- const reader = new FileReader();
780
- reader._readedFile = file;
664
+ }, [change, onChange]);
665
+ return /*#__PURE__*/React.createElement(Field, {
666
+ initialValue: initialValue,
667
+ name: name
668
+ }, function Render({
669
+ input,
670
+ meta
671
+ }) {
672
+ /** Note:
673
+ * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
674
+ * React Hooks cannot be called inside a callback.
675
+ * React Hooks must be called in a React function component or a
676
+ * custom React Hook function.
677
+ */
678
+ const activeOption = useMemo(() => {
679
+ const emptyOption = {
680
+ value: null,
681
+ label: null
682
+ };
683
+ if (input.value) {
684
+ const currentOption = options.find(option => option.value === input.value);
685
+ return currentOption || emptyOption;
686
+ }
687
+ return emptyOption;
688
+ }, [input.value]);
689
+ const {
690
+ errorKey,
691
+ errorMessage,
692
+ isErrorState,
693
+ successKey,
694
+ isValidState
695
+ } = useFieldValidationState({
696
+ fieldProps: fieldProps,
697
+ input: input,
698
+ meta: meta
699
+ });
700
+ const updatedInputProps = useValidationAppearanceInputProps({
701
+ inputProps: inputProps,
702
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
703
+ });
704
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
705
+ className: clsx('form-field_choice', 'form__item_choice', classNameGroupItem),
706
+ label: label,
707
+ messageType: messageType,
708
+ errorKey: errorKey,
709
+ errorMessage: errorMessage,
710
+ isErrorState: isErrorState,
711
+ metaError: meta.error,
712
+ isDisabled: isDisabled,
713
+ fieldClassName: "form-choice",
714
+ inputName: input.name,
715
+ inputValue: input.value || [],
716
+ metaActive: meta.active,
717
+ showMessage: showMessage,
718
+ isRequired: isRequired,
719
+ isValidState: isValidState
720
+ }, fieldProps), /*#__PURE__*/React.createElement(Choice, Object.assign({
721
+ className: clsx(meta.active && 'form-choice_state_focus', meta.error && meta.touched && `form-choice_state_${errorKey}`),
722
+ name: input.name,
723
+ isDisabled: isDisabled,
724
+ active: activeOption,
725
+ inputValue: input.value || [],
726
+ options: options,
727
+ placeholder: placeholder,
728
+ setActiveSegment: setActiveSegment,
729
+ isCheckbox: isCheckbox,
730
+ isRequired: isRequired
731
+ }, updatedInputProps)));
732
+ });
733
+ });
781
734
 
782
- // Set handlers
783
- reader.onabort = () => resolve();
784
- reader.onerror = () => resolve();
785
- reader.onload = event => {
786
- event.target._readedFile.dataURL = reader.result;
787
- resolve();
788
- };
789
- // Run reader
790
- if (file instanceof File) {
791
- reader.readAsDataURL(file);
792
- } else {
793
- resolve();
794
- }
795
- }
735
+ const defaultCodeProps = {
736
+ appearance: 'defaultPrimary sizeL solid rounded',
737
+ // useValidationAppearanceInputProps
738
+ // Error
739
+ errorAppearance: 'errorPrimary sizeM solid rounded',
740
+ // Required
741
+ requiredAppearance: 'requirePrimary sizeM solid rounded'
742
+ };
796
743
 
797
- const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
744
+ const FormFieldCode = /*#__PURE__*/React.memo(function FormFieldCode(props) {
798
745
  const {
799
- className,
800
746
  name,
801
- width,
802
- maxFiles,
803
- maxSize,
747
+ initialValue,
804
748
  label,
805
- fileErrorText,
749
+ messageType,
750
+ isDisabled,
806
751
  classNameGroupItem,
807
- dropzoneProps,
808
- fieldProps,
809
- hintDescription,
810
- hintTitle,
811
- showFilename,
752
+ fieldProps = {},
753
+ inputProps = {},
812
754
  showMessage,
813
- isPreviews,
814
- isRequired,
815
- onAddFiles,
816
- onClickPreview,
817
- onDeleteFile
755
+ isRequired
818
756
  } = props;
819
- const propsGenerator = useDevicePropsGenerator(props);
757
+ return /*#__PURE__*/React.createElement(Field, {
758
+ name: name,
759
+ initialValue: initialValue
760
+ }, function Render({
761
+ input,
762
+ meta
763
+ }) {
764
+ /** Note:
765
+ * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
766
+ * React Hooks cannot be called inside a callback.
767
+ * React Hooks must be called in a React function component or a
768
+ * custom React Hook function.
769
+ */
770
+
771
+ const {
772
+ errorKey,
773
+ errorMessage,
774
+ isErrorState,
775
+ successKey,
776
+ isValidState
777
+ } = useFieldValidationState({
778
+ fieldProps: fieldProps,
779
+ input: input,
780
+ meta: meta
781
+ });
782
+ const updatedInputProps = useValidationAppearanceInputProps({
783
+ inputProps: inputProps,
784
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
785
+ });
786
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
787
+ className: clsx('form-field-code', 'form__item_code', classNameGroupItem),
788
+ label: label,
789
+ messageType: messageType,
790
+ errorKey: errorKey,
791
+ errorMessage: errorMessage,
792
+ isErrorState: isErrorState,
793
+ fieldClassName: 'form-code',
794
+ inputName: input.name,
795
+ inputValue: input.value,
796
+ metaActive: meta.active,
797
+ showMessage: showMessage,
798
+ isRequired: isRequired,
799
+ isValidState: isValidState
800
+ }, fieldProps), /*#__PURE__*/React.createElement(Code, Object.assign({
801
+ name: input.name,
802
+ initialValue: input.value,
803
+ isDisabled: isDisabled,
804
+ autoComplete: "nope",
805
+ onBlur: input.onBlur,
806
+ onChange: input.onChange,
807
+ onFocus: input.onFocus
808
+ }, updatedInputProps)));
809
+ });
810
+ });
811
+
812
+ const FormFieldCustom = /*#__PURE__*/React.memo(function FormFieldCustom(props) {
820
813
  const {
821
- size,
822
- fill,
823
- fillHover,
824
- labelTextColor,
825
- borderColorHover,
826
- borderType,
827
- borderWidth,
828
- errorMessageTextColor,
829
- errorMessageTextSize,
830
- errorMessageTextWeight,
831
- hintDescriptionTextColor,
832
- hintDescriptionTextSize,
833
- hintDescriptionTextWeight,
834
- hintDescriptionTextWrap,
835
- hintTitleTextColor,
836
- hintTitleTextSize,
837
- hintTitleTextWeight,
838
- hintTitleTextWrap,
839
- removeThumbAppearance,
840
- removeThumbShape,
841
- removeThumbText,
842
- removeThumbTextWeight,
843
- shape,
844
- thumbBorderColor,
845
- thumbBorderColorHover,
846
- thumbBorderType,
847
- thumbBorderWidth,
848
- thumbColumn = 1,
849
- thumbDirection = 'vertical',
850
- thumbNameTextColor,
851
- thumbNameTextSize,
852
- thumbNameTextWeight,
853
- thumbNameTextWrap
854
- } = propsGenerator;
814
+ Component,
815
+ isDisabled,
816
+ isRequired,
817
+ name,
818
+ initialValue,
819
+ fieldProps = {},
820
+ classNameGroupItem,
821
+ showMessage,
822
+ clearIcon,
823
+ clearIconFill,
824
+ clearIconFillHover,
825
+ clearIconShape,
826
+ clearIconSize,
827
+ onClickClearIcon
828
+ } = props;
829
+ return /*#__PURE__*/React.createElement(Field, {
830
+ initialValue: initialValue,
831
+ name: name
832
+ }, function Render({
833
+ input,
834
+ meta
835
+ }) {
836
+ /** Note:
837
+ * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
838
+ * React Hooks cannot be called inside a callback.
839
+ * React Hooks must be called in a React function component or a
840
+ * custom React Hook function.
841
+ */
842
+
843
+ const {
844
+ isErrorState,
845
+ isValidState,
846
+ errorKey,
847
+ errorMessage
848
+ } = useFieldValidationState({
849
+ fieldProps: fieldProps,
850
+ input: input,
851
+ meta: meta
852
+ });
853
+ const updatedInputProps = useValidationAppearanceInputProps({
854
+ validationStateKey: isErrorState ? errorKey : 'success',
855
+ // For "Custom" field we pass all props. Can contain some special props, we don't known.
856
+ inputProps: props
857
+ });
858
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
859
+ className: clsx('form-field_custom', 'form__item_custom', classNameGroupItem),
860
+ errorKey: errorKey,
861
+ errorMessage: errorMessage,
862
+ fieldClassName: 'form-custom',
863
+ inputName: input.name,
864
+ inputValue: input.value,
865
+ isDisabled: isDisabled,
866
+ isErrorState: isErrorState,
867
+ isRequired: isRequired,
868
+ isValidState: isValidState,
869
+ metaActive: meta.active,
870
+ metaError: meta.error,
871
+ showMessage: showMessage
872
+ }, fieldProps), /*#__PURE__*/React.createElement(Component, Object.assign({}, updatedInputProps, {
873
+ input: input,
874
+ isDisabled: isDisabled,
875
+ meta: meta
876
+ })), clearIcon && /*#__PURE__*/React.createElement(Icon, {
877
+ className: "form-field__icon",
878
+ iconFill: clearIconFill,
879
+ iconFillHover: clearIconFillHover,
880
+ imageSrc: clearIcon,
881
+ shape: clearIconShape,
882
+ size: clearIconSize,
883
+ SvgImage: clearIcon,
884
+ onClick: onClickClearIcon
885
+ }));
886
+ });
887
+ });
888
+
889
+ const defaultDatepickerProps = {
890
+ appearance: 'surfacePrimary sizeS',
891
+ dateFormat: 'dd/MM/yyyy - HH:mm',
892
+ readOnly: false,
893
+ selectsRange: false,
894
+ showTimeSelect: true,
895
+ timeCaption: 'Время',
896
+ timeFormat: 'p',
897
+ timeIntervals: 60,
898
+ isClearable: true,
899
+ isStartDefaultNull: true
900
+ };
901
+
902
+ function FormFieldDatePicker(props) {
903
+ const {
904
+ name,
905
+ isDisabled,
906
+ classNameGroupItem,
907
+ datePickerProps,
908
+ fieldProps = {},
909
+ inputProps = {},
910
+ showMessage,
911
+ isRequired,
912
+ onChange
913
+ } = props;
855
914
  return /*#__PURE__*/React.createElement(Field, {
856
915
  name: name
857
916
  }, function Render({
@@ -865,10 +924,27 @@ const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
865
924
  * custom React Hook function.
866
925
  */
867
926
 
927
+ const onChangeField = useCallback((startDate, endDate) => {
928
+ if (!datePickerProps.selectsRange) {
929
+ // When we need to save single date, value is date
930
+ // TODO: make object with one date? need to check all forms with FormFieldDatePicker
931
+ input.onChange(startDate);
932
+ } else {
933
+ // When we need to save range, value is object with two date
934
+ input.onChange({
935
+ endDate,
936
+ startDate
937
+ });
938
+ }
939
+ if (onChange) {
940
+ onChange(startDate, endDate);
941
+ }
942
+ }, [input.onChange, onChange]);
868
943
  const {
869
944
  errorKey,
870
945
  errorMessage,
871
946
  isErrorState,
947
+ successKey,
872
948
  isValidState
873
949
  } = useFieldValidationState({
874
950
  fieldProps: fieldProps,
@@ -876,423 +952,460 @@ const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
876
952
  meta: meta
877
953
  });
878
954
  const updatedInputProps = useValidationAppearanceInputProps({
879
- inputProps: props,
880
- validationStateKey: isErrorState ? errorKey : 'success'
955
+ inputProps: inputProps,
956
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
881
957
  });
882
-
883
- /** TODO:
884
- * REFACTOR PROPERTIES
885
- */
886
958
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
887
- className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
888
- width: width,
889
- label: label,
890
- labelTextColor: labelTextColor,
959
+ className: clsx('form-field_datepicker', 'form__item_datepicker', classNameGroupItem),
891
960
  errorKey: errorKey,
892
961
  errorMessage: errorMessage,
893
962
  isErrorState: isErrorState,
894
963
  metaError: meta.error,
895
- fieldClassName: "form-dropzone",
964
+ isDisabled: isDisabled,
965
+ fieldClassName: "form-datepicker",
896
966
  inputName: input.name,
897
- inputValue: input.value,
967
+ inputValue: input.value || '',
898
968
  metaActive: meta.active,
899
- metaTouched: meta.touched,
900
969
  showMessage: showMessage,
901
970
  isRequired: isRequired,
902
971
  isValidState: isValidState
903
- }, fieldProps), /*#__PURE__*/React.createElement(FileInputDropzone, {
904
- className: className,
905
- maxFiles: maxFiles,
906
- maxSize: maxSize,
907
- size: size,
908
- fill: fill,
909
- fillHover: fillHover,
910
- borderColor: updatedInputProps.borderColor,
911
- borderColorHover: borderColorHover,
912
- borderType: borderType,
913
- borderWidth: borderWidth,
914
- errorMessageTextColor: errorMessageTextColor,
915
- errorMessageTextSize: errorMessageTextSize,
916
- errorMessageWeight: errorMessageTextWeight,
917
- fileErrorText: fileErrorText,
918
- metaError: meta.error,
919
- dropzoneProps: dropzoneProps,
920
- hintDescription: hintDescription,
921
- hintDescriptionTextColor: hintDescriptionTextColor,
922
- hintDescriptionTextSize: hintDescriptionTextSize,
923
- hintDescriptionTextWeight: hintDescriptionTextWeight,
924
- hintDescriptionTextWrap: hintDescriptionTextWrap,
925
- hintTitle: hintTitle,
926
- hintTitleTextColor: hintTitleTextColor,
927
- hintTitleTextSize: hintTitleTextSize,
928
- hintTitleTextWeight: hintTitleTextWeight,
929
- hintTitleTextWrap: hintTitleTextWrap,
930
- inputName: input.name,
931
- inputValue: input.value,
932
- metaTouched: meta.touched,
933
- removeThumbAppearance: removeThumbAppearance,
934
- removeThumbShape: removeThumbShape,
935
- removeThumbText: removeThumbText,
936
- removeThumbTextWeight: removeThumbTextWeight,
937
- shape: shape,
938
- showFilename: showFilename,
939
- thumbBorderColor: thumbBorderColor,
940
- thumbBorderColorHover: thumbBorderColorHover,
941
- thumbBorderType: thumbBorderType,
942
- thumbBorderWidth: thumbBorderWidth,
943
- thumbColumn: thumbColumn,
944
- thumbDirection: thumbDirection,
945
- thumbNameTextColor: thumbNameTextColor,
946
- thumbNameTextSize: thumbNameTextSize,
947
- thumbNameTextWeight: thumbNameTextWeight,
948
- thumbNameTextWrap: thumbNameTextWrap,
949
- isPreviews: isPreviews,
950
- onAddFiles: onAddFiles,
951
- onClickPreview: onClickPreview,
952
- onDeleteFile: onDeleteFile
972
+ }, fieldProps), /*#__PURE__*/React.createElement(DatePickerInput, {
973
+ name: input.name,
974
+ isDisabled: isDisabled,
975
+ datePickerProps: datePickerProps,
976
+ endValue: datePickerProps.selectsRange ? input.value.endDate : null,
977
+ inputProps: updatedInputProps,
978
+ value: datePickerProps.selectsRange ? input.value.startDate : input.value,
979
+ onBlur: input.onBlur,
980
+ onChange: onChangeField,
981
+ onFocus: input.onFocus
953
982
  }));
954
983
  });
955
- });
984
+ }
956
985
 
957
- const defaultGroupProps = {
958
- width: 'fill',
959
- labelTextSize: 's',
960
- messageTextColor: 'surfaceTextPrimary',
961
- messageTextSize: 's',
962
- errorMessageTextSize: 's',
963
- errorMessageTextColor: 'errorTextSecondary',
964
- helpTextSize: 's',
965
- requiredMessageTextColor: 'warningTextSecondary',
966
- requiredMessageTextSize: 's'
986
+ const defaultDropzoneProps = {
987
+ fill: 'surfaceSecondary',
988
+ fillHover: 'surfaceTertiary',
989
+ // borderColor: 'surfaceBorderTertiary',
990
+ // borderColorHover: 'surfaceBorderQuaternary',
991
+ hintTitle: 'Перетащите изображение или выберите файл с компьютера',
992
+ hintTitleTextColor: 'surfaceTextPrimary',
993
+ hintTitleTextSize: 'm',
994
+ removeThumbText: 'удалить',
995
+ removeThumbTextColor: 'errorTextPrimary',
996
+ removeThumbTextHoverColor: 'errorTextPrimaryHover',
997
+ removeThumbTextSize: 's',
998
+ shape: 'rounded',
999
+ showFilename: true,
1000
+ thumbBorderColor: 'surfaceBorderTertiary',
1001
+ thumbBorderColorHover: 'surfaceBorderQuaternary',
1002
+ thumbBorderWidth: 1,
1003
+ thumbNameTextColor: 'surfaceTextPrimary',
1004
+ thumbNameTextSize: 's',
1005
+ isPreviews: true
967
1006
  };
968
1007
 
969
- const FormBlockGroup = /*#__PURE__*/React.memo(function Group(props) {
1008
+ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(props) {
970
1009
  const {
971
- dataTour,
972
1010
  className,
973
- name,
974
- title,
975
- titleTextColor,
976
- titleTextSize,
977
- titleTextWeight,
978
- label,
979
- labelTextColor,
980
- labelTextSize,
981
- labelTextWeight,
982
- message,
983
- messageTextColor,
984
- messageTextSize,
985
- messageTextWeight,
986
- column,
987
- showGroupMessage,
988
- before,
989
- after,
990
- isHidden,
991
- children
992
- } = props;
993
-
994
- // @ts-expect-error
995
- const {
996
- styles: styles
997
- } = useStyles(props);
998
- return /*#__PURE__*/React.createElement(Field, {
999
- name: name
1000
- }, function Render({
1001
- input,
1002
- meta
1003
- }) {
1004
- /** Note:
1005
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
1006
- * React Hooks cannot be called inside a callback.
1007
- * React Hooks must be called in a React function component or a
1008
- * custom React Hook function.
1009
- */
1010
- const {
1011
- errorKey,
1012
- errorMessage,
1013
- isErrorState
1014
- } = useFieldValidationState({
1015
- fieldProps: props,
1016
- // or fieldProps?
1017
- input: input,
1018
- meta: meta
1019
- });
1020
- const updatedProps = useValidationAppearanceInputProps({
1021
- inputProps: props,
1022
- validationStateKey: isErrorState ? errorKey : 'success'
1023
- });
1024
- return /*#__PURE__*/React.createElement("div", {
1025
- className: clsx('form__group', className, isHidden && 'form__group_hidden', column && `form__group_column_${column}`),
1026
- "data-tour": dataTour,
1027
- style: styles
1028
- }, /*#__PURE__*/React.createElement("div", {
1029
- className: "form__group-wrapper"
1030
- }, before, title && /*#__PURE__*/React.createElement("div", {
1031
- className: "form__group-title"
1032
- }, /*#__PURE__*/React.createElement(Title, {
1033
- size: titleTextSize,
1034
- textColor: titleTextColor,
1035
- textWeight: titleTextWeight
1036
- }, title)), label && /*#__PURE__*/React.createElement("div", {
1037
- className: "form__group-label"
1038
- }, /*#__PURE__*/React.createElement(Text, {
1039
- size: labelTextSize,
1040
- textColor: labelTextColor,
1041
- textWeight: labelTextWeight
1042
- }, label)), /*#__PURE__*/React.createElement("div", {
1043
- className: "form__group-items"
1044
- }, children), after), showGroupMessage && /*#__PURE__*/React.createElement(React.Fragment, null, isErrorState && errorMessage && /*#__PURE__*/React.createElement(Text, {
1045
- id: `${name}-error`,
1046
- className: `form__group-message form__group-message_type-${errorKey}`,
1047
- size: updatedProps.messageTextSize,
1048
- textColor: updatedProps.messageTextColor,
1049
- textWeight: updatedProps.messageTextWeight
1050
- }, errorMessage), Boolean(message) && (!isErrorState || !errorMessage) && /*#__PURE__*/React.createElement(Text, {
1051
- className: "form__group-message",
1052
- size: messageTextSize,
1053
- textColor: messageTextColor,
1054
- textWeight: messageTextWeight
1055
- }, message), !isErrorState && !message && /*#__PURE__*/React.createElement(Text, {
1056
- className: "form__group-message",
1057
- size: messageTextSize
1058
- }, '\u00A0')));
1059
- });
1060
- });
1011
+ maxFiles,
1012
+ maxSize,
1013
+ size,
1014
+ fileErrorText,
1015
+ dropzoneProps = {},
1016
+ hintDescription,
1017
+ hintTitle,
1018
+ inputName,
1019
+ inputValue,
1020
+ showFilename,
1021
+ thumbColumn,
1022
+ isPreviews,
1023
+ onAddFiles,
1024
+ onClickPreview,
1025
+ onDeleteFile
1026
+ } = props;
1061
1027
 
1062
- const defaultCheckboxProps = {
1063
- appearance: 'defaultPrimary sizeL solid',
1064
- width: 'fill',
1065
- // useValidationAppearanceInputProps
1066
- // Error
1067
- errorAppearance: 'errorPrimary sizeL solid',
1068
- // Required
1069
- requiredAppearance: 'requirePrimary sizeL solid'
1070
- };
1028
+ // TODO: delete react-final-form things out of here?
1029
+ const {
1030
+ change
1031
+ } = useForm();
1032
+ const [fileError, setFileError] = useState('');
1033
+ const [fileIsLoading, setFileIsLoading] = useState(false);
1034
+ const filesList = useMemo(() => inputValue ? castArray(inputValue) : [], [inputValue]);
1035
+ const changeFormState = useCallback(newFiles => {
1036
+ // If max files in dropzone is 1 - return file as it self, else as array of files
1037
+ // ps: for old projects compatibility
1038
+ const toSave = dropzoneProps.maxFiles == 1 ? newFiles[0] : newFiles;
1039
+ change(inputName, toSave);
1040
+ return toSave;
1041
+ },
1042
+ // If "inputName" will be changes, then it should be a different field
1043
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1044
+ [dropzoneProps, change]);
1071
1045
 
1072
- const FormFieldCheckbox = /*#__PURE__*/React.memo(function FormFieldCheckbox(props) {
1046
+ //
1047
+ const convertFiledValueAndSaveAsFiles = useCallback(async currentFilesList => {
1048
+ setFileIsLoading(true);
1049
+ const newFiles = [];
1050
+ for (const fileItem of currentFilesList) {
1051
+ if (typeof fileItem === 'string') {
1052
+ const newFile = await convertToFile(fileItem, isPreviews);
1053
+ if (newFile) {
1054
+ newFiles.push(newFile);
1055
+ }
1056
+ } else {
1057
+ newFiles.push(fileItem);
1058
+ }
1059
+ }
1060
+ changeFormState(newFiles);
1061
+ setFileIsLoading(false);
1062
+ }, [isPreviews, changeFormState]);
1063
+
1064
+ // Delete file from dropzone
1065
+ const removeFile = useCallback((event, index) => {
1066
+ event.stopPropagation();
1067
+ event.preventDefault();
1068
+ const newFiles = [...filesList];
1069
+ newFiles.splice(index, 1);
1070
+ if (onDeleteFile) {
1071
+ onDeleteFile(filesList[index], inputName);
1072
+ }
1073
+ changeFormState(newFiles);
1074
+ },
1075
+ // If "inputName" will be changes, then it should be a different field
1076
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1077
+ [filesList, changeFormState, onDeleteFile]);
1078
+
1079
+ // Create dropzone options
1073
1080
  const {
1074
- name,
1075
- initialValue,
1076
- isDisabled,
1077
- classNameGroupItem,
1078
- fieldProps = {},
1079
- inputProps = {},
1080
- showMessage,
1081
- isRequired,
1082
- onChange
1083
- } = props;
1084
- return /*#__PURE__*/React.createElement(Field, {
1085
- type: "checkbox",
1086
- name: name,
1087
- initialValue: initialValue
1088
- }, function Render({
1089
- input,
1090
- meta
1091
- }) {
1092
- /** Note:
1093
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
1094
- * React Hooks cannot be called inside a callback.
1095
- * React Hooks must be called in a React function component or a
1096
- * custom React Hook function.
1097
- */
1081
+ getInputProps,
1082
+ getRootProps
1083
+ } = useDropzone({
1084
+ maxFiles: maxFiles || 5,
1085
+ maxSize: maxSize || 10485760,
1086
+ // 10mb
1087
+ // accept: { 'image/*': [] },
1088
+ ...dropzoneProps,
1089
+ getFilesFromEvent: async event => {
1090
+ const result = await fromEvent(event);
1091
+ const newFiles = result.filter(item => item instanceof File);
1092
+ // Add exists and new files to accepted(or rejected)
1093
+ return [...filesList, ...newFiles];
1094
+ },
1095
+ onDropAccepted: acceptedFiles => {
1096
+ // If dropped files has accepted and we need a previews
1097
+ if (isPreviews) {
1098
+ // Add preview to every file
1099
+ acceptedFiles.forEach(file => {
1100
+ if (!file.error) {
1101
+ file.preview = URL.createObjectURL(file);
1102
+ }
1103
+ });
1104
+ }
1105
+ // Save to form data (including empty when files are not valid)
1106
+ const filesToSave = changeFormState(acceptedFiles);
1107
+ setFileError('');
1098
1108
 
1099
- const onChangeField = useCallback(event => {
1100
- input.onChange(event);
1101
- if (onChange) {
1102
- onChange(event.target.checked, input.name);
1109
+ // Save DataURL for all files
1110
+ const readerPromisesList = acceptedFiles.map(file => {
1111
+ return new Promise(resolve => setFileDataURL(file, resolve));
1112
+ });
1113
+ // Save files to form values
1114
+ Promise.all(readerPromisesList).then(() => {
1115
+ if (onAddFiles) {
1116
+ onAddFiles(filesToSave, inputName);
1117
+ }
1118
+ });
1119
+ },
1120
+ onDropRejected: rejectedFiles => {
1121
+ // If dropped files has rejected
1122
+ if (rejectedFiles.length) {
1123
+ let fileErrorMessage = 'Ошибка при добавлении файла';
1124
+ const firstFileErrorItem = rejectedFiles[0].errors[0];
1125
+ if (firstFileErrorItem) {
1126
+ if (firstFileErrorItem.code === ErrorCode.TooManyFiles) {
1127
+ fileErrorMessage = `Максимальное количество файлов: ${maxFiles}`;
1128
+ } else {
1129
+ fileErrorMessage = firstFileErrorItem.message;
1130
+ }
1131
+ }
1132
+ // Show error
1133
+ setFileError(fileErrorMessage);
1134
+ } else {
1135
+ // Else clean error
1136
+ setFileError('');
1103
1137
  }
1104
- }, [onChange, input.onChange]);
1105
- const {
1106
- errorKey,
1107
- errorMessage,
1108
- isErrorState,
1109
- successKey,
1110
- isValidState
1111
- } = useFieldValidationState({
1112
- fieldProps: fieldProps,
1113
- input: input,
1114
- meta: meta
1138
+ }
1139
+ });
1140
+ useEffect(() => {
1141
+ const currentFilesList = castArray(inputValue);
1142
+ const isNeedToConvert = currentFilesList.some(fileItem => typeof fileItem === 'string');
1143
+ if (isNeedToConvert) {
1144
+ // First time convert value to Files and save to local and form state
1145
+ convertFiledValueAndSaveAsFiles(currentFilesList);
1146
+ }
1147
+
1148
+ // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
1149
+ return () => {
1150
+ filesList.forEach(file => {
1151
+ if (file?.preview) {
1152
+ URL.revokeObjectURL(file.preview);
1153
+ }
1154
+ });
1155
+ };
1156
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1157
+ }, [inputValue]);
1158
+ const propsGenerator = useDevicePropsGenerator(props);
1159
+ const {
1160
+ fillClass,
1161
+ fillHoverClass,
1162
+ borderColorClass,
1163
+ borderColorHoverClass,
1164
+ borderTypeClass,
1165
+ borderWidthClass,
1166
+ errorMessageTextColor,
1167
+ errorMessageTextSize,
1168
+ errorMessageTextWeight,
1169
+ hintDescriptionTextColor,
1170
+ hintDescriptionTextSize,
1171
+ hintDescriptionTextWeight,
1172
+ hintDescriptionTextWrap,
1173
+ hintTitleTextColor,
1174
+ hintTitleTextSize,
1175
+ hintTitleTextWeight,
1176
+ hintTitleTextWrap,
1177
+ removeThumbAppearance,
1178
+ removeThumbShape,
1179
+ removeThumbText,
1180
+ removeThumbTextWeight,
1181
+ shapeClass,
1182
+ thumbBorderColorClass,
1183
+ thumbBorderColorHoverClass,
1184
+ thumbBorderTypeClass,
1185
+ thumbBorderWidthClass,
1186
+ thumbDirectionClass,
1187
+ thumbNameTextColor,
1188
+ thumbNameTextSize,
1189
+ thumbNameTextWeight,
1190
+ thumbNameTextWrap
1191
+ } = propsGenerator;
1192
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", getRootProps({
1193
+ // className: `form-dropzone__dropzone dropzone ${className} form-dropzone__dropzone_size_${size} ${shapeClass}`,
1194
+ className: `form-dropzone__dropzone dropzone`
1195
+ }), /*#__PURE__*/React.createElement("input", Object.assign({}, getInputProps(), {
1196
+ name: inputName
1197
+ })), /*#__PURE__*/React.createElement("div", {
1198
+ className: clsx('form-dropzone__dropzone-wrapper', thumbColumn && `form-dropzone__dropzone-wrapper_column_${thumbColumn}`, fillClass && `fill_${fillClass}`, fillHoverClass && `fill_hover_${fillHoverClass}`, borderWidthClass && `border-width_${borderWidthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderColorHoverClass && `border-color_hover_${borderColorHoverClass}`, borderTypeClass && `border_type_${borderTypeClass}`, shapeClass && `shape_${shapeClass}`)
1199
+ }, filesList.map((file, index) => /*#__PURE__*/React.createElement("aside", {
1200
+ className: clsx('form-dropzone__thumb', fillClass, thumbDirectionClass, thumbBorderWidthClass, thumbBorderColorClass, thumbBorderColorHoverClass, thumbBorderTypeClass),
1201
+ key: file.id || `${file.name}_${index}`
1202
+ }, isPreviews && !file.error && /*#__PURE__*/React.createElement("div", {
1203
+ className: "form-dropzone__thumb-image"
1204
+ }, /*#__PURE__*/React.createElement("img", {
1205
+ className: "form-dropzone__thumb-image-inner",
1206
+ src: file.preview || file.image,
1207
+ onClick: event => {
1208
+ onClickPreview && onClickPreview(file, event);
1209
+ },
1210
+ onLoad: () => {
1211
+ // Revoke data uri after image is loaded
1212
+ URL.revokeObjectURL(file.preview);
1213
+ }
1214
+ })), file.error && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Text, {
1215
+ size: thumbNameTextSize,
1216
+ textColor: thumbNameTextColor,
1217
+ textWeight: thumbNameTextWeight,
1218
+ textWrap: thumbNameTextWrap
1219
+ }, fileErrorText || file.error)), showFilename && /*#__PURE__*/React.createElement("div", {
1220
+ className: "form-dropzone__thumb-name"
1221
+ }, /*#__PURE__*/React.createElement(Text, {
1222
+ className: "form-dropzone__thumb-name-inner",
1223
+ size: thumbNameTextSize,
1224
+ textColor: thumbNameTextColor,
1225
+ textWeight: thumbNameTextWeight,
1226
+ textWrap: thumbNameTextWrap
1227
+ }, file.name)), fileIsLoading && /*#__PURE__*/React.createElement("div", {
1228
+ className: "form-dropzone__thumb-loader"
1229
+ }, /*#__PURE__*/React.createElement(Loader, {
1230
+ width: "fill",
1231
+ height: "fill"
1232
+ })), /*#__PURE__*/React.createElement("div", {
1233
+ className: clsx('form-dropzone__thumb-remove')
1234
+ }, /*#__PURE__*/React.createElement(Button, {
1235
+ className: "form-dropzone__thumb-remove-text",
1236
+ appearance: removeThumbAppearance,
1237
+ label: removeThumbText || 'Удалить',
1238
+ labelTextWeight: removeThumbTextWeight,
1239
+ shape: removeThumbShape,
1240
+ onClick: event => removeFile(event, index)
1241
+ })))), !filesList.length ? /*#__PURE__*/React.createElement("div", {
1242
+ className: "form-dropzone__hint"
1243
+ }, /*#__PURE__*/React.createElement(Text, {
1244
+ className: "form-dropzone__hint-title",
1245
+ size: hintTitleTextSize,
1246
+ textColor: hintTitleTextColor,
1247
+ textWeight: hintTitleTextWeight,
1248
+ textWrap: hintTitleTextWrap
1249
+ }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React.createElement(Text, {
1250
+ className: "form-dropzone__hint-text",
1251
+ size: hintDescriptionTextSize,
1252
+ textColor: hintDescriptionTextColor,
1253
+ textWeight: hintDescriptionTextWeight,
1254
+ textWrap: hintDescriptionTextWrap
1255
+ }, hintDescription)) : /*#__PURE__*/React.createElement("div", {
1256
+ className: "form-dropzone__hint form-dropzone__hint_type_add-more"
1257
+ }, /*#__PURE__*/React.createElement(Text, {
1258
+ className: "form-dropzone__hint-title",
1259
+ size: hintTitleTextSize,
1260
+ textColor: hintTitleTextColor,
1261
+ textWeight: hintTitleTextWeight,
1262
+ textWrap: hintTitleTextWrap
1263
+ }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React.createElement(Text, {
1264
+ className: "form-dropzone__hint-text",
1265
+ size: hintDescriptionTextSize,
1266
+ textColor: hintDescriptionTextColor,
1267
+ textWeight: hintDescriptionTextWeight,
1268
+ textWrap: hintDescriptionTextWrap
1269
+ }, hintDescription)))), fileError && /*#__PURE__*/React.createElement("div", {
1270
+ className: "form-field__message"
1271
+ }, /*#__PURE__*/React.createElement(Text, {
1272
+ className: "form-field__message-item form-field__message-item_type_message",
1273
+ size: errorMessageTextSize,
1274
+ textColor: errorMessageTextColor,
1275
+ textWeight: errorMessageTextWeight
1276
+ }, fileError)));
1277
+ });
1278
+ async function getFileByURL(url) {
1279
+ try {
1280
+ const response = await axios({
1281
+ url: url,
1282
+ responseType: 'blob'
1115
1283
  });
1116
- const updatedInputProps = useValidationAppearanceInputProps({
1117
- inputProps: inputProps,
1118
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1284
+ const blobObject = response.data;
1285
+ const dirtyFilename = response.headers['content-disposition']?.split('filename=')[1];
1286
+ // Remove double quotes
1287
+ let filename = dirtyFilename?.substring(1).slice(0, -1);
1288
+ if (!filename) {
1289
+ filename = url.split('/').at(-1);
1290
+ // const typeParts = blobObject.type.split('/')
1291
+ // const fileType = typeParts[typeParts.length - 1]
1292
+ // filename = `${new Date().getTime()}.${fileType}`
1293
+ }
1294
+ return new File([blobObject], filename, {
1295
+ type: blobObject.type
1119
1296
  });
1120
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1121
- className: clsx('form-field-checkbox', 'form__item_checkbox', classNameGroupItem),
1122
- errorKey: errorKey,
1123
- errorMessage: errorMessage,
1124
- isErrorState: isErrorState,
1125
- metaError: meta.error,
1126
- isDisabled: isDisabled,
1127
- fieldClassName: "form-checkbox",
1128
- inputName: input.name,
1129
- inputValue: input.checked,
1130
- metaActive: meta.active,
1131
- showMessage: showMessage,
1132
- tag: "label",
1133
- isRequired: isRequired,
1134
- isValidState: isValidState
1135
- }, fieldProps), /*#__PURE__*/React.createElement(Checkbox, Object.assign({
1136
- type: "checkbox",
1137
- name: input.name,
1138
- isDisabled: isDisabled,
1139
- autoComplete: "nope",
1140
- checked: input.checked,
1141
- isActive: input.checked,
1142
- onBlur: input.onBlur,
1143
- onChange: onChangeField,
1144
- onFocus: input.onFocus
1145
- }, updatedInputProps)));
1146
- });
1147
- });
1297
+ } catch (error) {
1298
+ console.log('error: ', error);
1299
+ return null;
1300
+ }
1301
+ }
1302
+ async function convertToFile(inputValue, isPreviews) {
1303
+ let newFile = null;
1148
1304
 
1149
- const defaultChipsProps = {
1150
- appearance: 'surfacePrimary sizeM rounded',
1151
- width: 'fill',
1152
- // useValidationAppearanceInputProps
1153
- // Error
1154
- errorAppearance: 'errorPrimary sizeM solid rounded',
1155
- // Required
1156
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1157
- // Success
1158
- // successAppearance: 'successPrimary sizeM solid rounded',
1159
- };
1305
+ // Download image by url and save as File instance
1306
+ const isURL = typeof inputValue === 'string' && inputValue.includes('/');
1307
+ if (inputValue.image || isURL) {
1308
+ newFile = await getFileByURL(inputValue.image || inputValue);
1309
+ if (newFile) {
1310
+ setFileDataURL(newFile);
1311
+ }
1312
+ }
1160
1313
 
1161
- function FormFieldChips(props) {
1162
- const {
1163
- name,
1164
- initialValue,
1165
- isDisabled,
1166
- classNameGroupItem,
1167
- emptyMessage,
1168
- emptyMessageTextColor,
1169
- emptyMessageTextSize,
1170
- fieldProps,
1171
- inputProps,
1172
- options,
1173
- showMessage,
1174
- isRequired,
1175
- onChange
1176
- } = props;
1177
- const {
1178
- change
1179
- } = useForm();
1314
+ // Convert dataURL to File instance
1315
+ if (inputValue.dataURL) {
1316
+ newFile = createFileFromDataURL(inputValue.name || inputValue.path, inputValue.dataURL);
1317
+ newFile.dataURL = inputValue.dataURL;
1318
+ }
1180
1319
 
1181
- // Callback for value changes
1182
- const onChangeSomeInput = useCallback((inputValue, newOptionValue) => {
1183
- const updatedValues = inputValue.includes(newOptionValue) ? inputValue.filter(selectedValue => selectedValue !== newOptionValue) : [...inputValue, newOptionValue];
1184
- change(name, updatedValues);
1185
- onChange && onChange(updatedValues);
1186
- }, [change, name, onChange]);
1187
- useEffect(() => {
1188
- initialValue && change(name, initialValue);
1189
- // update the form value only when the initialValue changes, so use disable eslint to ignore the warning
1190
- // eslint-disable-next-line react-hooks/exhaustive-deps
1191
- }, [initialValue]);
1192
- return /*#__PURE__*/React.createElement(Field, {
1193
- name: name,
1194
- initialValue: initialValue
1195
- }, function Render({
1196
- input,
1197
- meta
1198
- }) {
1199
- const {
1200
- errorKey,
1201
- errorMessage,
1202
- isErrorState,
1203
- successKey,
1204
- isValidState
1205
- } = useFieldValidationState({
1206
- fieldProps: fieldProps,
1207
- input: input,
1208
- meta: meta
1209
- });
1210
- const updatedInputProps = useValidationAppearanceInputProps({
1211
- inputProps: inputProps,
1212
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1213
- });
1214
- const activeOptionsList = useMemo(() => {
1215
- const emptyOptionsList = [{
1216
- label: null,
1217
- value: null
1218
- }];
1219
- if (input?.value) {
1220
- const currentOptions = options.filter(option => input.value?.includes(option.value));
1221
- return currentOptions || emptyOptionsList;
1222
- }
1223
- return emptyOptionsList;
1224
- }, [input.value]);
1225
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1226
- className: clsx('form-field_chips', 'form__item_chips', classNameGroupItem),
1227
- errorKey: errorKey,
1228
- errorMessage: errorMessage,
1229
- isErrorState: isErrorState,
1230
- metaError: meta.error,
1231
- isDisabled: isDisabled,
1232
- fieldClassName: "form-chips",
1233
- inputName: input.name,
1234
- inputValue: input.value,
1235
- metaActive: meta.active,
1236
- showMessage: showMessage,
1237
- isRequired: isRequired,
1238
- isValidState: isValidState
1239
- }, fieldProps), options.length ? /*#__PURE__*/React.createElement(ChipsGroup, {
1240
- direction: "horizontal",
1241
- gap: "1m",
1242
- wrap: "wrap"
1243
- }, options.map(option => /*#__PURE__*/React.createElement(Chips, Object.assign({
1244
- className: clsx(meta.active && 'form-chips_state_focus', meta.error && meta.touched && `form-chips_state_${errorKey}`),
1245
- key: option.value,
1246
- label: option.label,
1247
- isDisabled: option.isDisabled,
1248
- value: option.value,
1249
- isActive: activeOptionsList.some(activeOption => activeOption.value === option.value),
1250
- onClick: () => onChangeSomeInput(input.value, option.value)
1251
- }, updatedInputProps)))) : /*#__PURE__*/React.createElement(Text, {
1252
- size: emptyMessageTextSize,
1253
- textColor: emptyMessageTextColor
1254
- }, emptyMessage));
1255
- });
1320
+ // Save new File to state
1321
+ if (newFile) {
1322
+ newFile.id = inputValue.id;
1323
+ if (isPreviews) {
1324
+ newFile.preview = URL.createObjectURL(newFile);
1325
+ }
1326
+ }
1327
+ return newFile;
1256
1328
  }
1329
+ function setFileDataURL(file, resolve) {
1330
+ resolve = resolve || (() => {});
1331
+ // Init reader and save his file
1332
+ const reader = new FileReader();
1333
+ reader._readedFile = file;
1257
1334
 
1258
- const defaultChoiceProps = {
1259
- appearance: 'defaultPrimary sizeM solid rounded',
1260
- width: 'fill',
1261
- // useValidationAppearanceInputProps
1262
- // Error
1263
- errorAppearance: 'errorPrimary sizeM solid rounded',
1264
- // Required
1265
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1266
- };
1335
+ // Set handlers
1336
+ reader.onabort = () => resolve();
1337
+ reader.onerror = () => resolve();
1338
+ reader.onload = event => {
1339
+ event.target._readedFile.dataURL = reader.result;
1340
+ resolve();
1341
+ };
1342
+ // Run reader
1343
+ if (file instanceof File) {
1344
+ reader.readAsDataURL(file);
1345
+ } else {
1346
+ resolve();
1347
+ }
1348
+ }
1267
1349
 
1268
- const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props) {
1350
+ const FormFieldFileInput = /*#__PURE__*/React.memo(function FormFieldFileInput(props) {
1269
1351
  const {
1352
+ className,
1270
1353
  name,
1271
- initialValue,
1354
+ width,
1355
+ maxFiles,
1356
+ maxSize,
1272
1357
  label,
1273
- messageType,
1274
- isDisabled,
1358
+ fileErrorText,
1275
1359
  classNameGroupItem,
1360
+ dropzoneProps,
1276
1361
  fieldProps,
1277
- inputProps,
1278
- options,
1279
- placeholder,
1362
+ hintDescription,
1363
+ hintTitle,
1364
+ showFilename,
1280
1365
  showMessage,
1281
- isCheckbox,
1366
+ isPreviews,
1282
1367
  isRequired,
1283
- onChange
1368
+ onAddFiles,
1369
+ onClickPreview,
1370
+ onDeleteFile
1284
1371
  } = props;
1372
+ const propsGenerator = useDevicePropsGenerator(props);
1285
1373
  const {
1286
- change
1287
- } = useForm();
1288
- const setActiveSegment = useCallback((option, isChecked) => {
1289
- change(name, isChecked && option.value);
1290
- if (onChange) {
1291
- onChange(option.value, name, isChecked);
1292
- }
1293
- }, [change, onChange]);
1374
+ size,
1375
+ fill,
1376
+ fillHover,
1377
+ labelTextColor,
1378
+ borderColorHover,
1379
+ borderType,
1380
+ borderWidth,
1381
+ errorMessageTextColor,
1382
+ errorMessageTextSize,
1383
+ errorMessageTextWeight,
1384
+ hintDescriptionTextColor,
1385
+ hintDescriptionTextSize,
1386
+ hintDescriptionTextWeight,
1387
+ hintDescriptionTextWrap,
1388
+ hintTitleTextColor,
1389
+ hintTitleTextSize,
1390
+ hintTitleTextWeight,
1391
+ hintTitleTextWrap,
1392
+ removeThumbAppearance,
1393
+ removeThumbShape,
1394
+ removeThumbText,
1395
+ removeThumbTextWeight,
1396
+ shape,
1397
+ thumbBorderColor,
1398
+ thumbBorderColorHover,
1399
+ thumbBorderType,
1400
+ thumbBorderWidth,
1401
+ thumbColumn = 1,
1402
+ thumbDirection = 'vertical',
1403
+ thumbNameTextColor,
1404
+ thumbNameTextSize,
1405
+ thumbNameTextWeight,
1406
+ thumbNameTextWrap
1407
+ } = propsGenerator;
1294
1408
  return /*#__PURE__*/React.createElement(Field, {
1295
- initialValue: initialValue,
1296
1409
  name: name
1297
1410
  }, function Render({
1298
1411
  input,
@@ -1304,22 +1417,11 @@ const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props)
1304
1417
  * React Hooks must be called in a React function component or a
1305
1418
  * custom React Hook function.
1306
1419
  */
1307
- const activeOption = useMemo(() => {
1308
- const emptyOption = {
1309
- value: null,
1310
- label: null
1311
- };
1312
- if (input.value) {
1313
- const currentOption = options.find(option => option.value === input.value);
1314
- return currentOption || emptyOption;
1315
- }
1316
- return emptyOption;
1317
- }, [input.value]);
1420
+
1318
1421
  const {
1319
1422
  errorKey,
1320
1423
  errorMessage,
1321
1424
  isErrorState,
1322
- successKey,
1323
1425
  isValidState
1324
1426
  } = useFieldValidationState({
1325
1427
  fieldProps: fieldProps,
@@ -1327,65 +1429,127 @@ const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props)
1327
1429
  meta: meta
1328
1430
  });
1329
1431
  const updatedInputProps = useValidationAppearanceInputProps({
1330
- inputProps: inputProps,
1331
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1432
+ inputProps: props,
1433
+ validationStateKey: isErrorState ? errorKey : 'success'
1332
1434
  });
1435
+
1436
+ /** TODO:
1437
+ * REFACTOR PROPERTIES
1438
+ */
1333
1439
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1334
- className: clsx('form-field_choice', 'form__item_choice', classNameGroupItem),
1440
+ className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
1441
+ width: width,
1335
1442
  label: label,
1336
- messageType: messageType,
1443
+ labelTextColor: labelTextColor,
1337
1444
  errorKey: errorKey,
1338
1445
  errorMessage: errorMessage,
1339
1446
  isErrorState: isErrorState,
1340
1447
  metaError: meta.error,
1341
- isDisabled: isDisabled,
1342
- fieldClassName: "form-choice",
1448
+ fieldClassName: "form-dropzone",
1343
1449
  inputName: input.name,
1344
- inputValue: input.value || [],
1450
+ inputValue: input.value,
1345
1451
  metaActive: meta.active,
1452
+ metaTouched: meta.touched,
1346
1453
  showMessage: showMessage,
1347
1454
  isRequired: isRequired,
1348
1455
  isValidState: isValidState
1349
- }, fieldProps), /*#__PURE__*/React.createElement(Choice, Object.assign({
1350
- className: clsx(meta.active && 'form-choice_state_focus', meta.error && meta.touched && `form-choice_state_${errorKey}`),
1351
- name: input.name,
1352
- isDisabled: isDisabled,
1353
- active: activeOption,
1354
- inputValue: input.value || [],
1355
- options: options,
1356
- placeholder: placeholder,
1357
- setActiveSegment: setActiveSegment,
1358
- isCheckbox: isCheckbox,
1359
- isRequired: isRequired
1360
- }, updatedInputProps)));
1456
+ }, fieldProps), /*#__PURE__*/React.createElement(FileInputDropzone, {
1457
+ className: className,
1458
+ maxFiles: maxFiles,
1459
+ maxSize: maxSize,
1460
+ size: size,
1461
+ fill: fill,
1462
+ fillHover: fillHover,
1463
+ borderColor: updatedInputProps.borderColor,
1464
+ borderColorHover: borderColorHover,
1465
+ borderType: borderType,
1466
+ borderWidth: borderWidth,
1467
+ errorMessageTextColor: errorMessageTextColor,
1468
+ errorMessageTextSize: errorMessageTextSize,
1469
+ errorMessageWeight: errorMessageTextWeight,
1470
+ fileErrorText: fileErrorText,
1471
+ metaError: meta.error,
1472
+ dropzoneProps: dropzoneProps,
1473
+ hintDescription: hintDescription,
1474
+ hintDescriptionTextColor: hintDescriptionTextColor,
1475
+ hintDescriptionTextSize: hintDescriptionTextSize,
1476
+ hintDescriptionTextWeight: hintDescriptionTextWeight,
1477
+ hintDescriptionTextWrap: hintDescriptionTextWrap,
1478
+ hintTitle: hintTitle,
1479
+ hintTitleTextColor: hintTitleTextColor,
1480
+ hintTitleTextSize: hintTitleTextSize,
1481
+ hintTitleTextWeight: hintTitleTextWeight,
1482
+ hintTitleTextWrap: hintTitleTextWrap,
1483
+ inputName: input.name,
1484
+ inputValue: input.value,
1485
+ metaTouched: meta.touched,
1486
+ removeThumbAppearance: removeThumbAppearance,
1487
+ removeThumbShape: removeThumbShape,
1488
+ removeThumbText: removeThumbText,
1489
+ removeThumbTextWeight: removeThumbTextWeight,
1490
+ shape: shape,
1491
+ showFilename: showFilename,
1492
+ thumbBorderColor: thumbBorderColor,
1493
+ thumbBorderColorHover: thumbBorderColorHover,
1494
+ thumbBorderType: thumbBorderType,
1495
+ thumbBorderWidth: thumbBorderWidth,
1496
+ thumbColumn: thumbColumn,
1497
+ thumbDirection: thumbDirection,
1498
+ thumbNameTextColor: thumbNameTextColor,
1499
+ thumbNameTextSize: thumbNameTextSize,
1500
+ thumbNameTextWeight: thumbNameTextWeight,
1501
+ thumbNameTextWrap: thumbNameTextWrap,
1502
+ isPreviews: isPreviews,
1503
+ onAddFiles: onAddFiles,
1504
+ onClickPreview: onClickPreview,
1505
+ onDeleteFile: onDeleteFile
1506
+ }));
1361
1507
  });
1362
1508
  });
1363
1509
 
1364
- const defaultCodeProps = {
1365
- appearance: 'defaultPrimary sizeL solid rounded',
1366
- // useValidationAppearanceInputProps
1367
- // Error
1368
- errorAppearance: 'errorPrimary sizeM solid rounded',
1369
- // Required
1370
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1510
+ const defaultGroupProps = {
1511
+ width: 'fill',
1512
+ labelTextSize: 's',
1513
+ messageTextColor: 'surfaceTextPrimary',
1514
+ messageTextSize: 's',
1515
+ errorMessageTextSize: 's',
1516
+ errorMessageTextColor: 'errorTextSecondary',
1517
+ helpTextSize: 's',
1518
+ requiredMessageTextColor: 'warningTextSecondary',
1519
+ requiredMessageTextSize: 's'
1371
1520
  };
1372
1521
 
1373
- const FormFieldCode = /*#__PURE__*/React.memo(function FormFieldCode(props) {
1522
+ const FormBlockGroup = /*#__PURE__*/React.memo(function Group(props) {
1374
1523
  const {
1524
+ dataTour,
1525
+ className,
1375
1526
  name,
1376
- initialValue,
1527
+ title,
1528
+ titleTextColor,
1529
+ titleTextSize,
1530
+ titleTextWeight,
1377
1531
  label,
1378
- messageType,
1379
- isDisabled,
1380
- classNameGroupItem,
1381
- fieldProps = {},
1382
- inputProps = {},
1383
- showMessage,
1384
- isRequired
1532
+ labelTextColor,
1533
+ labelTextSize,
1534
+ labelTextWeight,
1535
+ message,
1536
+ messageTextColor,
1537
+ messageTextSize,
1538
+ messageTextWeight,
1539
+ column,
1540
+ showGroupMessage,
1541
+ before,
1542
+ after,
1543
+ isHidden,
1544
+ children
1385
1545
  } = props;
1546
+
1547
+ // @ts-expect-error
1548
+ const {
1549
+ styles: styles
1550
+ } = useStyles(props);
1386
1551
  return /*#__PURE__*/React.createElement(Field, {
1387
- name: name,
1388
- initialValue: initialValue
1552
+ name: name
1389
1553
  }, function Render({
1390
1554
  input,
1391
1555
  meta
@@ -1396,68 +1560,93 @@ const FormFieldCode = /*#__PURE__*/React.memo(function FormFieldCode(props) {
1396
1560
  * React Hooks must be called in a React function component or a
1397
1561
  * custom React Hook function.
1398
1562
  */
1399
-
1400
1563
  const {
1401
1564
  errorKey,
1402
1565
  errorMessage,
1403
- isErrorState,
1404
- successKey,
1405
- isValidState
1566
+ isErrorState
1406
1567
  } = useFieldValidationState({
1407
- fieldProps: fieldProps,
1568
+ fieldProps: props,
1569
+ // or fieldProps?
1408
1570
  input: input,
1409
1571
  meta: meta
1410
1572
  });
1411
- const updatedInputProps = useValidationAppearanceInputProps({
1412
- inputProps: inputProps,
1413
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1573
+ const updatedProps = useValidationAppearanceInputProps({
1574
+ inputProps: props,
1575
+ validationStateKey: isErrorState ? errorKey : 'success'
1414
1576
  });
1415
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1416
- className: clsx('form-field-code', 'form__item_code', classNameGroupItem),
1417
- label: label,
1418
- messageType: messageType,
1419
- errorKey: errorKey,
1420
- errorMessage: errorMessage,
1421
- isErrorState: isErrorState,
1422
- fieldClassName: 'form-code',
1423
- inputName: input.name,
1424
- inputValue: input.value,
1425
- metaActive: meta.active,
1426
- showMessage: showMessage,
1427
- isRequired: isRequired,
1428
- isValidState: isValidState
1429
- }, fieldProps), /*#__PURE__*/React.createElement(Code, Object.assign({
1430
- name: input.name,
1431
- initialValue: input.value,
1432
- isDisabled: isDisabled,
1433
- autoComplete: "nope",
1434
- onBlur: input.onBlur,
1435
- onChange: input.onChange,
1436
- onFocus: input.onFocus
1437
- }, updatedInputProps)));
1577
+ return /*#__PURE__*/React.createElement("div", {
1578
+ className: clsx('form__group', className, isHidden && 'form__group_hidden', column && `form__group_column_${column}`),
1579
+ "data-tour": dataTour,
1580
+ style: styles
1581
+ }, /*#__PURE__*/React.createElement("div", {
1582
+ className: "form__group-wrapper"
1583
+ }, before, title && /*#__PURE__*/React.createElement("div", {
1584
+ className: "form__group-title"
1585
+ }, /*#__PURE__*/React.createElement(Title, {
1586
+ size: titleTextSize,
1587
+ textColor: titleTextColor,
1588
+ textWeight: titleTextWeight
1589
+ }, title)), label && /*#__PURE__*/React.createElement("div", {
1590
+ className: "form__group-label"
1591
+ }, /*#__PURE__*/React.createElement(Text, {
1592
+ size: labelTextSize,
1593
+ textColor: labelTextColor,
1594
+ textWeight: labelTextWeight
1595
+ }, label)), /*#__PURE__*/React.createElement("div", {
1596
+ className: "form__group-items"
1597
+ }, children), after), showGroupMessage && /*#__PURE__*/React.createElement(React.Fragment, null, isErrorState && errorMessage && /*#__PURE__*/React.createElement(Text, {
1598
+ id: `${name}-error`,
1599
+ className: `form__group-message form__group-message_type-${errorKey}`,
1600
+ size: updatedProps.messageTextSize,
1601
+ textColor: updatedProps.messageTextColor,
1602
+ textWeight: updatedProps.messageTextWeight
1603
+ }, errorMessage), Boolean(message) && (!isErrorState || !errorMessage) && /*#__PURE__*/React.createElement(Text, {
1604
+ className: "form__group-message",
1605
+ size: messageTextSize,
1606
+ textColor: messageTextColor,
1607
+ textWeight: messageTextWeight
1608
+ }, message), !isErrorState && !message && /*#__PURE__*/React.createElement(Text, {
1609
+ className: "form__group-message",
1610
+ size: messageTextSize
1611
+ }, '\u00A0')));
1438
1612
  });
1439
1613
  });
1440
1614
 
1441
- const FormFieldCustom = /*#__PURE__*/React.memo(function FormFieldCustom(props) {
1615
+ const defaultInputProps = {
1616
+ appearance: 'defaultPrimary sizeM solid rounded',
1617
+ width: 'fill',
1618
+ // useValidationAppearanceInputProps
1619
+ // Error
1620
+ errorAppearance: 'errorPrimary sizeM solid rounded',
1621
+ // Required
1622
+ requiredAppearance: 'requirePrimary sizeM solid rounded',
1623
+ // Success
1624
+ successAppearance: 'successPrimary sizeM solid rounded'
1625
+ };
1626
+
1627
+ const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1442
1628
  const {
1443
- Component,
1444
- isDisabled,
1445
- isRequired,
1446
1629
  name,
1447
1630
  initialValue,
1448
- fieldProps = {},
1449
1631
  classNameGroupItem,
1450
- showMessage,
1451
1632
  clearIcon,
1452
1633
  clearIconFill,
1453
1634
  clearIconFillHover,
1454
1635
  clearIconShape,
1455
1636
  clearIconSize,
1456
- onClickClearIcon
1637
+ fieldProps = {},
1638
+ inputProps = {},
1639
+ parse,
1640
+ showMessage,
1641
+ isDisabled,
1642
+ isRequired,
1643
+ onClickClearIcon,
1644
+ onChange
1457
1645
  } = props;
1458
1646
  return /*#__PURE__*/React.createElement(Field, {
1647
+ name: name,
1459
1648
  initialValue: initialValue,
1460
- name: name
1649
+ parse: parse
1461
1650
  }, function Render({
1462
1651
  input,
1463
1652
  meta
@@ -1469,79 +1658,87 @@ const FormFieldCustom = /*#__PURE__*/React.memo(function FormFieldCustom(props)
1469
1658
  * custom React Hook function.
1470
1659
  */
1471
1660
 
1661
+ const onChangeField = useCallback(event => {
1662
+ input.onChange(event);
1663
+ if (onChange) {
1664
+ onChange(event.target.value, input.name);
1665
+ }
1666
+ }, [onChange, input.onChange]);
1472
1667
  const {
1473
- isErrorState,
1474
- isValidState,
1475
1668
  errorKey,
1476
- errorMessage
1669
+ errorMessage,
1670
+ successKey,
1671
+ isErrorState,
1672
+ isValidState
1477
1673
  } = useFieldValidationState({
1478
1674
  fieldProps: fieldProps,
1479
1675
  input: input,
1480
1676
  meta: meta
1481
1677
  });
1482
1678
  const updatedInputProps = useValidationAppearanceInputProps({
1483
- validationStateKey: isErrorState ? errorKey : 'success',
1484
- // For "Custom" field we pass all props. Can contain some special props, we don't known.
1485
- inputProps: props
1679
+ inputProps: inputProps,
1680
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1486
1681
  });
1487
1682
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1488
- className: clsx('form-field_custom', 'form__item_custom', classNameGroupItem),
1683
+ className: clsx('form-field_input', 'form__item_input', classNameGroupItem),
1489
1684
  errorKey: errorKey,
1490
1685
  errorMessage: errorMessage,
1491
- fieldClassName: 'form-custom',
1686
+ fieldClassName: "form-input",
1492
1687
  inputName: input.name,
1493
- inputValue: input.value,
1688
+ inputValue: input.value || '',
1689
+ metaActive: meta.active,
1690
+ metaError: meta.error,
1691
+ showMessage: showMessage,
1494
1692
  isDisabled: isDisabled,
1495
1693
  isErrorState: isErrorState,
1496
1694
  isRequired: isRequired,
1497
- isValidState: isValidState,
1498
- metaActive: meta.active,
1499
- metaError: meta.error,
1500
- showMessage: showMessage
1501
- }, fieldProps), /*#__PURE__*/React.createElement(Component, Object.assign({}, updatedInputProps, {
1502
- input: input,
1695
+ isValidState: isValidState
1696
+ }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1697
+ className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1698
+ dataTestId: `${input.name}FieldInput`,
1699
+ type: "text",
1700
+ name: input.name,
1701
+ autoComplete: "nope",
1702
+ value: input.value || '',
1503
1703
  isDisabled: isDisabled,
1504
- meta: meta
1505
- })), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1704
+ onBlur: input.onBlur,
1705
+ onChange: onChangeField,
1706
+ onFocus: input.onFocus
1707
+ }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1506
1708
  className: "form-field__icon",
1709
+ size: clearIconSize,
1507
1710
  iconFill: clearIconFill,
1508
1711
  iconFillHover: clearIconFillHover,
1509
- imageSrc: clearIcon,
1712
+ imageSrc: typeof clearIcon === 'string' && clearIcon,
1510
1713
  shape: clearIconShape,
1511
- size: clearIconSize,
1512
- SvgImage: clearIcon,
1714
+ SvgImage: typeof clearIcon !== 'string' && clearIcon,
1513
1715
  onClick: onClickClearIcon
1514
1716
  }));
1515
1717
  });
1516
1718
  });
1517
1719
 
1518
- const defaultDatepickerProps = {
1519
- appearance: 'surfacePrimary sizeS',
1520
- dateFormat: 'dd/MM/yyyy - HH:mm',
1521
- readOnly: false,
1522
- selectsRange: false,
1523
- showTimeSelect: true,
1524
- timeCaption: 'Время',
1525
- timeFormat: 'p',
1526
- timeIntervals: 60,
1527
- isClearable: true,
1528
- isStartDefaultNull: true
1529
- };
1530
-
1531
- function FormFieldDatePicker(props) {
1720
+ const FormFieldMaskedInput = /*#__PURE__*/React.memo(function FormFieldMaskedInput(props) {
1532
1721
  const {
1533
1722
  name,
1534
- isDisabled,
1723
+ initialValue,
1535
1724
  classNameGroupItem,
1536
- datePickerProps,
1725
+ clearIcon,
1726
+ clearIconFill,
1727
+ clearIconFillHover,
1728
+ clearIconShape,
1729
+ clearIconSize,
1537
1730
  fieldProps = {},
1538
1731
  inputProps = {},
1732
+ optionsMask,
1539
1733
  showMessage,
1734
+ unmasked,
1735
+ isDisabled,
1540
1736
  isRequired,
1541
- onChange
1737
+ onClickClearIcon
1542
1738
  } = props;
1543
1739
  return /*#__PURE__*/React.createElement(Field, {
1544
- name: name
1740
+ name: name,
1741
+ initialValue: initialValue
1545
1742
  }, function Render({
1546
1743
  input,
1547
1744
  meta
@@ -1553,27 +1750,35 @@ function FormFieldDatePicker(props) {
1553
1750
  * custom React Hook function.
1554
1751
  */
1555
1752
 
1556
- const onChangeField = useCallback((startDate, endDate) => {
1557
- if (!datePickerProps.selectsRange) {
1558
- // When we need to save single date, value is date
1559
- // TODO: make object with one date? need to check all forms with FormFieldDatePicker
1560
- input.onChange(startDate);
1561
- } else {
1562
- // When we need to save range, value is object with two date
1563
- input.onChange({
1564
- endDate,
1565
- startDate
1566
- });
1753
+ const {
1754
+ ref,
1755
+ unmaskedValue,
1756
+ value,
1757
+ setUnmaskedValue
1758
+ } = useIMask(optionsMask, {
1759
+ onAccept: (newValue, event, element) => {
1760
+ if (element) {
1761
+ input.onChange(event._unmaskedValue);
1762
+ }
1567
1763
  }
1568
- if (onChange) {
1569
- onChange(startDate, endDate);
1764
+ });
1765
+ useEffect(() => {
1766
+ if (input.value !== unmaskedValue) {
1767
+ setUnmaskedValue(input.value.replace(unmasked, ''));
1570
1768
  }
1571
- }, [input.onChange, onChange]);
1769
+ }, [input.value]);
1770
+
1771
+ // useEffect(() => {
1772
+ // if (unmaskedValue !== input.value) {
1773
+ // input.onChange(unmaskedValue)
1774
+ // }
1775
+ // }, [unmaskedValue])
1776
+
1572
1777
  const {
1573
1778
  errorKey,
1574
1779
  errorMessage,
1575
- isErrorState,
1576
1780
  successKey,
1781
+ isErrorState,
1577
1782
  isValidState
1578
1783
  } = useFieldValidationState({
1579
1784
  fieldProps: fieldProps,
@@ -1585,36 +1790,40 @@ function FormFieldDatePicker(props) {
1585
1790
  validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1586
1791
  });
1587
1792
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1588
- className: clsx('form-field_datepicker', 'form__item_datepicker', classNameGroupItem),
1793
+ className: clsx('form-field-masked-input', 'form__item_masked-input', classNameGroupItem),
1589
1794
  errorKey: errorKey,
1590
1795
  errorMessage: errorMessage,
1591
- isErrorState: isErrorState,
1592
- metaError: meta.error,
1593
- isDisabled: isDisabled,
1594
- fieldClassName: "form-datepicker",
1796
+ fieldClassName: 'form-maskedInput',
1595
1797
  inputName: input.name,
1596
- inputValue: input.value || '',
1798
+ inputValue: input.value,
1597
1799
  metaActive: meta.active,
1800
+ metaError: meta.error,
1598
1801
  showMessage: showMessage,
1802
+ isDisabled: isDisabled,
1803
+ isErrorState: isErrorState,
1599
1804
  isRequired: isRequired,
1600
1805
  isValidState: isValidState
1601
- }, fieldProps), /*#__PURE__*/React.createElement(DatePickerInput, {
1602
- name: input.name,
1603
- isDisabled: isDisabled,
1604
- datePickerProps: datePickerProps,
1605
- endValue: datePickerProps.selectsRange ? input.value.endDate : null,
1606
- inputProps: updatedInputProps,
1607
- value: datePickerProps.selectsRange ? input.value.startDate : input.value,
1806
+ }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1807
+ className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1808
+ ref: ref,
1809
+ value: value,
1608
1810
  onBlur: input.onBlur,
1609
- onChange: onChangeField,
1610
1811
  onFocus: input.onFocus
1812
+ }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1813
+ className: "form-field__icon",
1814
+ size: clearIconSize,
1815
+ iconFill: clearIconFill,
1816
+ iconFillHover: clearIconFillHover,
1817
+ imageSrc: clearIcon,
1818
+ shape: clearIconShape,
1819
+ SvgImage: clearIcon,
1820
+ onClick: onClickClearIcon
1611
1821
  }));
1612
1822
  });
1613
- }
1823
+ });
1614
1824
 
1615
- const defaultInputProps = {
1825
+ const defaultPasswordProps = {
1616
1826
  appearance: 'defaultPrimary sizeM solid rounded',
1617
- width: 'fill',
1618
1827
  // useValidationAppearanceInputProps
1619
1828
  // Error
1620
1829
  errorAppearance: 'errorPrimary sizeM solid rounded',
@@ -1624,27 +1833,18 @@ const defaultInputProps = {
1624
1833
  successAppearance: 'successPrimary sizeM solid rounded'
1625
1834
  };
1626
1835
 
1627
- const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1836
+ const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(props) {
1628
1837
  const {
1629
1838
  name,
1630
1839
  initialValue,
1631
- isDisabled,
1632
1840
  classNameGroupItem,
1633
- // dataTestId,
1634
- // iconBorder,
1635
- // iconBorderHover,
1636
- clearIcon,
1637
- clearIconFill,
1638
- clearIconFillHover,
1639
- clearIconShape,
1640
- clearIconSize,
1641
- fieldProps = {},
1642
- inputProps = {},
1841
+ fieldProps,
1842
+ inputProps,
1643
1843
  parse,
1644
1844
  showMessage,
1845
+ isDisabled,
1645
1846
  isRequired,
1646
- onChange,
1647
- onClickClearIcon
1847
+ onChange
1648
1848
  } = props;
1649
1849
  return /*#__PURE__*/React.createElement(Field, {
1650
1850
  name: name,
@@ -1670,8 +1870,8 @@ const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1670
1870
  const {
1671
1871
  errorKey,
1672
1872
  errorMessage,
1673
- isErrorState,
1674
1873
  successKey,
1874
+ isErrorState,
1675
1875
  isValidState
1676
1876
  } = useFieldValidationState({
1677
1877
  fieldProps: fieldProps,
@@ -1683,79 +1883,90 @@ const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1683
1883
  validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1684
1884
  });
1685
1885
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1686
- className: clsx('form-field_input', 'form__item_input', classNameGroupItem),
1886
+ className: clsx('form-field_input-password', 'form__item_input-password', classNameGroupItem),
1687
1887
  errorKey: errorKey,
1688
1888
  errorMessage: errorMessage,
1689
- isErrorState: isErrorState,
1690
- metaError: meta.error,
1691
- isDisabled: isDisabled,
1692
- fieldClassName: "form-input",
1889
+ fieldClassName: "form-password",
1693
1890
  inputName: input.name,
1694
1891
  inputValue: input.value || '',
1695
1892
  metaActive: meta.active,
1893
+ metaError: meta.error,
1696
1894
  showMessage: showMessage,
1895
+ isDisabled: isDisabled,
1896
+ isErrorState: isErrorState,
1697
1897
  isRequired: isRequired,
1698
1898
  isValidState: isValidState
1699
- }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1700
- dataTestId: `${input.name}FieldInput`,
1701
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1702
- type: "text",
1899
+ }, fieldProps), /*#__PURE__*/React.createElement(InputPassword, Object.assign({
1900
+ className: clsx(meta.active && 'input-password_state_focus', meta.error && meta.touched && `input-password_state_${errorKey}`),
1901
+ dataTestId: `${input.name}FieldInputPassword`,
1703
1902
  name: input.name,
1704
- isDisabled: isDisabled,
1705
1903
  autoComplete: "nope",
1706
- value: input.value || '',
1707
- onBlur: input.onBlur,
1708
- onChange: onChangeField,
1709
- onFocus: input.onFocus
1710
- }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1711
- className: "form-field__icon",
1712
- size: clearIconSize,
1713
- iconFill: clearIconFill,
1714
- iconFillHover: clearIconFillHover,
1715
- imageSrc: typeof clearIcon === 'string' && clearIcon,
1716
- shape: clearIconShape,
1717
- SvgImage: typeof clearIcon !== 'string' && clearIcon,
1718
- onClick: onClickClearIcon
1719
- }));
1904
+ value: input.value || '',
1905
+ isDisabled: isDisabled,
1906
+ onBlur: input.onBlur,
1907
+ onChange: onChangeField,
1908
+ onFocus: input.onFocus
1909
+ }, updatedInputProps)));
1720
1910
  });
1721
1911
  });
1722
1912
 
1723
- const defaultPasswordProps = {
1724
- appearance: 'sizeM defaultSecondary solid rounded',
1725
- // useValidationAppearanceInputProps
1726
- // Error
1727
- errorAppearance: 'errorPrimary sizeM solid rounded',
1728
- // Required
1729
- iconRevealableHide: icons24.View.HideValue,
1730
- iconRevealableShow: icons24.View.ShowValue,
1731
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1913
+ const defaultRadioProps = {
1914
+ appearance: 'defaultPrimary sizeM solid circular'
1732
1915
  };
1733
1916
 
1734
- const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(props) {
1917
+ function FormFieldRadioGroupList(props) {
1918
+ const {
1919
+ input,
1920
+ inputProps,
1921
+ options,
1922
+ onChange
1923
+ } = props;
1924
+
1925
+ // Callback for value changes
1926
+ const onChangeSomeInput = useCallback(value => {
1927
+ // Save to form values
1928
+ input.onChange(value);
1929
+ if (onChange) {
1930
+ // Pass to custom event
1931
+ onChange(value, input.name);
1932
+ }
1933
+ }, [input, onChange]);
1934
+
1935
+ // Handle for radio inputs
1936
+ const onChangeRadio = useCallback(event => {
1937
+ if (event.target.checked) {
1938
+ onChangeSomeInput(event.target.value);
1939
+ }
1940
+ }, [onChange]);
1941
+ return /*#__PURE__*/React.createElement(React.Fragment, null, options.map(option => /*#__PURE__*/React.createElement(Radio, Object.assign({
1942
+ className: "form-radio__item",
1943
+ key: option.value,
1944
+ type: "radio",
1945
+ name: input.name,
1946
+ label: option.label,
1947
+ checked: option.value === input.value,
1948
+ value: option.value,
1949
+ onBlur: input.onBlur,
1950
+ onChange: onChangeRadio,
1951
+ onFocus: input.onFocus
1952
+ }, inputProps))));
1953
+ }
1954
+
1955
+ const FormFieldRadioGroup = /*#__PURE__*/React.memo(function FormFieldRadioGroup(props) {
1735
1956
  const {
1736
1957
  name,
1737
- initialValue,
1738
1958
  isDisabled,
1959
+ editableProps = {},
1960
+ fieldProps = {},
1961
+ inputProps = {},
1962
+ options = [],
1739
1963
  classNameGroupItem,
1740
- fieldProps,
1741
- inputProps,
1742
- parse,
1743
1964
  showMessage,
1744
1965
  isRequired,
1745
1966
  onChange
1746
1967
  } = props;
1747
- const [isRevealed, setIsRevealed] = useState(false);
1748
- const inputType = useMemo(() => {
1749
- return isRevealed ? 'text' : 'password';
1750
- }, [isRevealed]);
1751
- const onClickIconReveal = useCallback(event => {
1752
- event.preventDefault();
1753
- setIsRevealed(prev => !prev);
1754
- }, []);
1755
1968
  return /*#__PURE__*/React.createElement(Field, {
1756
- name: name,
1757
- initialValue: initialValue,
1758
- parse: parse
1969
+ name: name
1759
1970
  }, function Render({
1760
1971
  input,
1761
1972
  meta
@@ -1767,17 +1978,10 @@ const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(pro
1767
1978
  * custom React Hook function.
1768
1979
  */
1769
1980
 
1770
- const onChangeField = useCallback(event => {
1771
- input.onChange(event);
1772
- if (onChange) {
1773
- onChange(event.target.value, input.name);
1774
- }
1775
- }, [onChange, input.onChange]);
1776
1981
  const {
1777
1982
  errorKey,
1778
1983
  errorMessage,
1779
1984
  isErrorState,
1780
- successKey,
1781
1985
  isValidState
1782
1986
  } = useFieldValidationState({
1783
1987
  fieldProps: fieldProps,
@@ -1786,39 +1990,29 @@ const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(pro
1786
1990
  });
1787
1991
  const updatedInputProps = useValidationAppearanceInputProps({
1788
1992
  inputProps: inputProps,
1789
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1993
+ validationStateKey: isErrorState ? errorKey : 'success'
1790
1994
  });
1791
1995
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1792
- className: clsx('form-field_input', 'form__item_input', classNameGroupItem),
1996
+ className: clsx('form-field_radio', 'form__item_radio', classNameGroupItem),
1793
1997
  errorKey: errorKey,
1794
1998
  errorMessage: errorMessage,
1795
1999
  isErrorState: isErrorState,
1796
2000
  metaError: meta.error,
1797
2001
  isDisabled: isDisabled,
1798
- fieldClassName: "form-password",
2002
+ fieldClassName: 'form-radio',
1799
2003
  inputName: input.name,
1800
2004
  inputValue: input.value || '',
1801
2005
  metaActive: meta.active,
1802
2006
  showMessage: showMessage,
1803
2007
  isRequired: isRequired,
1804
2008
  isValidState: isValidState
1805
- }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1806
- dataTestId: `${input.name}FieldInputPassword`,
1807
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1808
- type: inputType,
1809
- name: input.name,
2009
+ }, fieldProps), /*#__PURE__*/React.createElement(FormFieldRadioGroupList, {
1810
2010
  isDisabled: isDisabled,
1811
- autoComplete: "nope",
1812
- value: input.value || '',
1813
- onBlur: input.onBlur,
1814
- onChange: onChangeField,
1815
- onFocus: input.onFocus
1816
- }, updatedInputProps)), /*#__PURE__*/React.createElement(Icon, {
1817
- className: "form-field__icon",
1818
- size: inputProps?.iconSize,
1819
- iconFill: inputProps?.iconFill,
1820
- SvgImage: isRevealed ? inputProps?.iconRevealableHide : inputProps?.iconRevealableShow,
1821
- onClick: onClickIconReveal
2011
+ editableProps: editableProps,
2012
+ input: input,
2013
+ inputProps: updatedInputProps,
2014
+ options: options,
2015
+ onChange: onChange
1822
2016
  }));
1823
2017
  });
1824
2018
  });
@@ -2005,220 +2199,57 @@ const FormFieldSelect = /*#__PURE__*/React.memo(function FormFieldSelect(props)
2005
2199
  meta: meta
2006
2200
  });
2007
2201
  const updatedSelectProps = useValidationAppearanceInputProps({
2008
- inputProps: selectProps,
2009
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
2010
- });
2011
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2012
- className: clsx('form-field_select', 'form__item_select', classNameGroupItem),
2013
- errorKey: errorKey,
2014
- errorMessage: errorMessage,
2015
- isErrorState: isErrorState,
2016
- metaError: meta.error,
2017
- isDisabled: isDisabled,
2018
- fieldClassName: 'form-select',
2019
- inputName: input.name,
2020
- inputValue: input.value,
2021
- metaActive: meta.active,
2022
- showMessage: showMessage,
2023
- isRequired: isRequired,
2024
- isValidState: isValidState
2025
- }, fieldProps), /*#__PURE__*/React.createElement(Select, Object.assign({
2026
- className: "form-select-item",
2027
- ref: selectRef,
2028
- isDisabled: isDisabled,
2029
- instanceId: `id_${input.name}`,
2030
- options: options,
2031
- value: selectedOptions,
2032
- onChange: onChangeValue,
2033
- onInputChange: onInputChange
2034
- }, updatedSelectProps)));
2035
- });
2036
- });
2037
-
2038
- const defaultSwitchProps = {
2039
- appearance: 'defaultPrimary sizeL solid rounded',
2040
- // useValidationAppearanceInputProps
2041
- // Error
2042
- errorAppearance: 'errorPrimary sizeL solid rounded',
2043
- // Success
2044
- successAppearance: 'successPrimary sizeL solid rounded',
2045
- // Required
2046
- requiredAppearance: 'requirePrimary sizeL solid rounded'
2047
- };
2048
-
2049
- const FormFieldSwitch = /*#__PURE__*/React.memo(function FormFieldSwitch(props) {
2050
- const {
2051
- name,
2052
- isDisabled,
2053
- classNameGroupItem,
2054
- fieldProps = {},
2055
- inputProps = {},
2056
- showMessage,
2057
- isRequired,
2058
- onChange
2059
- } = props;
2060
- return /*#__PURE__*/React.createElement(Field, {
2061
- type: "checkbox",
2062
- name: name
2063
- }, function Render({
2064
- input,
2065
- meta
2066
- }) {
2067
- /** Note:
2068
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
2069
- * React Hooks cannot be called inside a callback.
2070
- * React Hooks must be called in a React function component or a
2071
- * custom React Hook function.
2072
- */
2073
-
2074
- const onChangeField = useCallback(event => {
2075
- input.onChange(event);
2076
- if (onChange) {
2077
- onChange(event.target.checked, input.name);
2078
- }
2079
- }, [onChange, input.onChange]);
2080
- const {
2081
- errorKey,
2082
- errorMessage,
2083
- isErrorState,
2084
- successKey,
2085
- isValidState
2086
- } = useFieldValidationState({
2087
- fieldProps: fieldProps,
2088
- input: input,
2089
- meta: meta
2090
- });
2091
- const updatedInputProps = useValidationAppearanceInputProps({
2092
- inputProps: inputProps,
2093
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
2094
- });
2095
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2096
- className: clsx('form-field-switch', 'form__item_switch', classNameGroupItem),
2097
- errorKey: errorKey,
2098
- errorMessage: errorMessage,
2099
- isErrorState: isErrorState,
2100
- metaError: meta.error,
2101
- isDisabled: isDisabled,
2102
- fieldClassName: "form-switch",
2103
- inputName: input.name,
2104
- inputValue: input.checked,
2105
- metaActive: meta.active,
2106
- showMessage: showMessage,
2107
- tag: "label",
2108
- isRequired: isRequired,
2109
- isValidState: isValidState
2110
- }, fieldProps), /*#__PURE__*/React.createElement(Switch, Object.assign({
2111
- type: "checkbox",
2112
- name: input.name,
2113
- isDisabled: isDisabled,
2114
- autoComplete: "nope",
2115
- isActive: input.checked,
2116
- onBlur: input.onBlur,
2117
- onChange: onChangeField,
2118
- onFocus: input.onFocus
2119
- }, updatedInputProps)));
2120
- });
2121
- });
2122
-
2123
- const defaultTextareaProps = {
2124
- appearance: 'defaultPrimary sizeM solid rounded',
2125
- // useValidationAppearanceInputProps
2126
- // Error
2127
- errorAppearance: 'errorPrimary sizeM solid rounded',
2128
- // Success
2129
- successAppearance: 'successPrimary sizeM solid rounded',
2130
- // Required
2131
- requiredAppearance: 'requirePrimary sizeM solid rounded'
2132
- };
2133
-
2134
- const FormFieldTextarea = /*#__PURE__*/React.memo(function FormFieldTextarea(props) {
2135
- const {
2136
- name,
2137
- isDisabled,
2138
- classNameGroupItem,
2139
- fieldProps = {},
2140
- inputProps = {},
2141
- showMessage,
2142
- isRequired
2143
- } = props;
2144
- return /*#__PURE__*/React.createElement(Field, {
2145
- name: name
2146
- }, function Render({
2147
- input,
2148
- meta
2149
- }) {
2150
- /** Note:
2151
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
2152
- * React Hooks cannot be called inside a callback.
2153
- * React Hooks must be called in a React function component or a
2154
- * custom React Hook function.
2155
- */
2156
-
2157
- const {
2158
- errorKey,
2159
- errorMessage,
2160
- isErrorState,
2161
- successKey,
2162
- isValidState
2163
- } = useFieldValidationState({
2164
- fieldProps: fieldProps,
2165
- input: input,
2166
- meta: meta
2167
- });
2168
- const updatedInputProps = useValidationAppearanceInputProps({
2169
- inputProps: inputProps,
2202
+ inputProps: selectProps,
2170
2203
  validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
2171
2204
  });
2172
2205
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2173
- className: clsx('form-field_textarea', 'form__item_textarea', classNameGroupItem),
2206
+ className: clsx('form-field_select', 'form__item_select', classNameGroupItem),
2174
2207
  errorKey: errorKey,
2175
2208
  errorMessage: errorMessage,
2176
2209
  isErrorState: isErrorState,
2177
2210
  metaError: meta.error,
2178
2211
  isDisabled: isDisabled,
2179
- fieldClassName: 'form-textarea',
2212
+ fieldClassName: 'form-select',
2180
2213
  inputName: input.name,
2181
2214
  inputValue: input.value,
2182
2215
  metaActive: meta.active,
2183
2216
  showMessage: showMessage,
2184
2217
  isRequired: isRequired,
2185
2218
  isValidState: isValidState
2186
- }, fieldProps), /*#__PURE__*/React.createElement(Textarea, Object.assign({
2187
- dataTestId: `${input.name}FieldTextarea`,
2188
- className: clsx(meta.active && 'textarea_state_focus', meta.error && meta.touched && `textarea_state_${errorKey}`),
2189
- name: input.name,
2219
+ }, fieldProps), /*#__PURE__*/React.createElement(Select, Object.assign({
2220
+ className: "form-select-item",
2221
+ ref: selectRef,
2190
2222
  isDisabled: isDisabled,
2191
- autoComplete: "nope",
2192
- value: input.value || '',
2193
- onBlur: input.onBlur,
2194
- onChange: input.onChange,
2195
- onFocus: input.onFocus
2196
- }, updatedInputProps)));
2223
+ instanceId: `id_${input.name}`,
2224
+ options: options,
2225
+ value: selectedOptions,
2226
+ onChange: onChangeValue,
2227
+ onInputChange: onInputChange
2228
+ }, updatedSelectProps)));
2197
2229
  });
2198
2230
  });
2199
2231
 
2200
- const FormFieldMaskedInput = /*#__PURE__*/React.memo(function FormFieldMaskedInput(props) {
2232
+ const defaultSwitchProps = {
2233
+ appearance: 'defaultPrimary sizeL solid rounded',
2234
+ errorAppearance: 'errorPrimary sizeL solid rounded',
2235
+ successAppearance: 'successPrimary sizeL solid rounded',
2236
+ requiredAppearance: 'requirePrimary sizeL solid rounded'
2237
+ };
2238
+
2239
+ const FormFieldSwitch = /*#__PURE__*/React.memo(function FormFieldSwitch(props) {
2201
2240
  const {
2202
2241
  name,
2203
- initialValue,
2204
2242
  isDisabled,
2205
2243
  classNameGroupItem,
2206
- clearIcon,
2207
- clearIconFill,
2208
- clearIconFillHover,
2209
- clearIconShape,
2210
- clearIconSize,
2211
2244
  fieldProps = {},
2212
2245
  inputProps = {},
2213
- optionsMask,
2214
2246
  showMessage,
2215
- unmasked,
2216
2247
  isRequired,
2217
- onClickClearIcon
2248
+ onChange
2218
2249
  } = props;
2219
2250
  return /*#__PURE__*/React.createElement(Field, {
2220
- name: name,
2221
- initialValue: initialValue
2251
+ type: "checkbox",
2252
+ name: name
2222
2253
  }, function Render({
2223
2254
  input,
2224
2255
  meta
@@ -2230,28 +2261,12 @@ const FormFieldMaskedInput = /*#__PURE__*/React.memo(function FormFieldMaskedInp
2230
2261
  * custom React Hook function.
2231
2262
  */
2232
2263
 
2233
- const {
2234
- ref,
2235
- setUnmaskedValue,
2236
- unmaskedValue,
2237
- value
2238
- } = useIMask(optionsMask, {
2239
- onAccept: (newValue, event, element) => {
2240
- if (element) {
2241
- input.onChange(event._unmaskedValue);
2242
- }
2243
- }
2244
- });
2245
- useEffect(() => {
2246
- if (input.value !== unmaskedValue) {
2247
- setUnmaskedValue(input.value.replace(unmasked, ''));
2248
- }
2249
- }, [input.value]);
2250
- useEffect(() => {
2251
- if (unmaskedValue !== input.value) {
2252
- input.onChange(unmaskedValue);
2264
+ const onChangeField = useCallback(event => {
2265
+ input.onChange(event);
2266
+ if (onChange) {
2267
+ onChange(event.target.checked, input.name);
2253
2268
  }
2254
- }, [unmaskedValue]);
2269
+ }, [onChange, input.onChange]);
2255
2270
  const {
2256
2271
  errorKey,
2257
2272
  errorMessage,
@@ -2268,92 +2283,53 @@ const FormFieldMaskedInput = /*#__PURE__*/React.memo(function FormFieldMaskedInp
2268
2283
  validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
2269
2284
  });
2270
2285
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2271
- className: clsx('form-field-masked-input', 'form__item_masked-input', classNameGroupItem),
2286
+ className: clsx('form-field-switch', 'form__item_switch', classNameGroupItem),
2272
2287
  errorKey: errorKey,
2273
2288
  errorMessage: errorMessage,
2274
2289
  isErrorState: isErrorState,
2275
2290
  metaError: meta.error,
2276
2291
  isDisabled: isDisabled,
2277
- fieldClassName: 'form-maskedInput',
2292
+ fieldClassName: "form-switch",
2278
2293
  inputName: input.name,
2279
- inputValue: input.value,
2294
+ inputValue: input.checked,
2280
2295
  metaActive: meta.active,
2281
2296
  showMessage: showMessage,
2297
+ tag: "label",
2282
2298
  isRequired: isRequired,
2283
2299
  isValidState: isValidState
2284
- }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
2285
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
2286
- ref: ref,
2287
- value: value,
2300
+ }, fieldProps), /*#__PURE__*/React.createElement(Switch, Object.assign({
2301
+ type: "checkbox",
2302
+ name: input.name,
2303
+ isDisabled: isDisabled,
2304
+ autoComplete: "nope",
2305
+ isActive: input.checked,
2288
2306
  onBlur: input.onBlur,
2307
+ onChange: onChangeField,
2289
2308
  onFocus: input.onFocus
2290
- }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
2291
- className: "form-field__icon",
2292
- size: clearIconSize,
2293
- iconFill: clearIconFill,
2294
- iconFillHover: clearIconFillHover,
2295
- imageSrc: clearIcon,
2296
- shape: clearIconShape,
2297
- SvgImage: clearIcon,
2298
- onClick: onClickClearIcon
2299
- }));
2309
+ }, updatedInputProps)));
2300
2310
  });
2301
2311
  });
2302
2312
 
2303
- const defaultRadioProps = {
2304
- appearance: 'defaultPrimary sizeM solid circular'
2313
+ const defaultTextareaProps = {
2314
+ appearance: 'defaultPrimary sizeM solid rounded',
2315
+ // useValidationAppearanceInputProps
2316
+ // Error
2317
+ errorAppearance: 'errorPrimary sizeM solid rounded',
2318
+ // Success
2319
+ successAppearance: 'successPrimary sizeM solid rounded',
2320
+ // Required
2321
+ requiredAppearance: 'requirePrimary sizeM solid rounded'
2305
2322
  };
2306
2323
 
2307
- function RadioGroupList(props) {
2308
- const {
2309
- input,
2310
- inputProps,
2311
- options,
2312
- onChange
2313
- } = props;
2314
-
2315
- // Callback for value changes
2316
- const onChangeSomeInput = useCallback(value => {
2317
- // Save to form values
2318
- input.onChange(value);
2319
- if (onChange) {
2320
- // Pass to custom event
2321
- onChange(value, input.name);
2322
- }
2323
- }, [input, onChange]);
2324
-
2325
- // Handle for radio inputs
2326
- const onChangeRadio = useCallback(event => {
2327
- if (event.target.checked) {
2328
- onChangeSomeInput(event.target.value);
2329
- }
2330
- }, [onChange]);
2331
- return /*#__PURE__*/React.createElement(React.Fragment, null, options.map(option => /*#__PURE__*/React.createElement(Radio, Object.assign({
2332
- className: "form-radio__item",
2333
- key: option.value,
2334
- type: "radio",
2335
- name: input.name,
2336
- label: option.label,
2337
- checked: option.value === input.value,
2338
- value: option.value,
2339
- onBlur: input.onBlur,
2340
- onChange: onChangeRadio,
2341
- onFocus: input.onFocus
2342
- }, inputProps))));
2343
- }
2344
-
2345
- const RadioGroup = /*#__PURE__*/React.memo(function RadioGroup(props) {
2324
+ const FormFieldTextarea = /*#__PURE__*/React.memo(function FormFieldTextarea(props) {
2346
2325
  const {
2347
2326
  name,
2348
2327
  isDisabled,
2349
- editableProps = {},
2328
+ classNameGroupItem,
2350
2329
  fieldProps = {},
2351
2330
  inputProps = {},
2352
- options = [],
2353
- classNameGroupItem,
2354
2331
  showMessage,
2355
- isRequired,
2356
- onChange
2332
+ isRequired
2357
2333
  } = props;
2358
2334
  return /*#__PURE__*/React.createElement(Field, {
2359
2335
  name: name
@@ -2372,6 +2348,7 @@ const RadioGroup = /*#__PURE__*/React.memo(function RadioGroup(props) {
2372
2348
  errorKey,
2373
2349
  errorMessage,
2374
2350
  isErrorState,
2351
+ successKey,
2375
2352
  isValidState
2376
2353
  } = useFieldValidationState({
2377
2354
  fieldProps: fieldProps,
@@ -2380,30 +2357,33 @@ const RadioGroup = /*#__PURE__*/React.memo(function RadioGroup(props) {
2380
2357
  });
2381
2358
  const updatedInputProps = useValidationAppearanceInputProps({
2382
2359
  inputProps: inputProps,
2383
- validationStateKey: isErrorState ? errorKey : 'success'
2360
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
2384
2361
  });
2385
2362
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2386
- className: clsx('form-field_radio', 'form__item_radio', classNameGroupItem),
2363
+ className: clsx('form-field_textarea', 'form__item_textarea', classNameGroupItem),
2387
2364
  errorKey: errorKey,
2388
2365
  errorMessage: errorMessage,
2389
2366
  isErrorState: isErrorState,
2390
2367
  metaError: meta.error,
2391
2368
  isDisabled: isDisabled,
2392
- fieldClassName: 'form-radio',
2369
+ fieldClassName: 'form-textarea',
2393
2370
  inputName: input.name,
2394
- inputValue: input.value || '',
2371
+ inputValue: input.value,
2395
2372
  metaActive: meta.active,
2396
2373
  showMessage: showMessage,
2397
2374
  isRequired: isRequired,
2398
2375
  isValidState: isValidState
2399
- }, fieldProps), /*#__PURE__*/React.createElement(RadioGroupList, {
2376
+ }, fieldProps), /*#__PURE__*/React.createElement(Textarea, Object.assign({
2377
+ dataTestId: `${input.name}FieldTextarea`,
2378
+ className: clsx(meta.active && 'textarea_state_focus', meta.error && meta.touched && `textarea_state_${errorKey}`),
2379
+ name: input.name,
2400
2380
  isDisabled: isDisabled,
2401
- editableProps: editableProps,
2402
- input: input,
2403
- inputProps: updatedInputProps,
2404
- options: options,
2405
- onChange: onChange
2406
- }));
2381
+ autoComplete: "nope",
2382
+ value: input.value || '',
2383
+ onBlur: input.onBlur,
2384
+ onChange: input.onChange,
2385
+ onFocus: input.onFocus
2386
+ }, updatedInputProps)));
2407
2387
  });
2408
2388
  });
2409
2389
 
@@ -2478,13 +2458,13 @@ function generateField(field, config, props) {
2478
2458
  }
2479
2459
  case formTypes.fileInput:
2480
2460
  {
2481
- return /*#__PURE__*/React.createElement(FileInput, Object.assign({
2461
+ return /*#__PURE__*/React.createElement(FormFieldFileInput, Object.assign({
2482
2462
  key: config.key
2483
2463
  }, field, props));
2484
2464
  }
2485
2465
  case formTypes.radioGroup:
2486
2466
  {
2487
- return /*#__PURE__*/React.createElement(RadioGroup, Object.assign({
2467
+ return /*#__PURE__*/React.createElement(FormFieldRadioGroup, Object.assign({
2488
2468
  key: config.key
2489
2469
  }, field, props));
2490
2470
  }
@@ -2651,9 +2631,9 @@ const sendFormDataToServer = async (url, data) => {
2651
2631
 
2652
2632
  const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2653
2633
  const {
2634
+ className,
2654
2635
  dataTestId,
2655
2636
  dataTour,
2656
- className,
2657
2637
  type,
2658
2638
  initialValues,
2659
2639
  initialValuesEqual,
@@ -2669,8 +2649,36 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2669
2649
  descTextColor,
2670
2650
  descTextWeight,
2671
2651
  buttonGap,
2652
+ additionalProps = {},
2653
+ buttonDirection = 'vertical',
2654
+ buttonFill,
2655
+ buttonJustifyContent,
2656
+ buttonPadding,
2657
+ buttonPosition,
2658
+ dataTestIdButtons,
2672
2659
  dataTestIdPrimaryButton,
2660
+ dataTestIdSecondaryButton,
2661
+ dataTestIdTertiaryButton,
2662
+ dataTourButtons,
2673
2663
  dataTourPrimaryButton,
2664
+ dataTourSecondaryButton,
2665
+ dataTourTertiaryButton,
2666
+ disableFieldsAutoComplete = false,
2667
+ fieldsGap,
2668
+ formName,
2669
+ groupGap,
2670
+ language,
2671
+ loader,
2672
+ loaderAppearance,
2673
+ loaderFill = 'surfacePrimary',
2674
+ loaderItemFill = 'accentItemSecondary',
2675
+ loaderShape,
2676
+ loaderSize = 'l',
2677
+ loaderText,
2678
+ loaderType = 'simple',
2679
+ mutators,
2680
+ notificationCloseButton,
2681
+ notificationType,
2674
2682
  primaryButton,
2675
2683
  primaryButtonAppearance,
2676
2684
  primaryButtonFill,
@@ -2682,9 +2690,7 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2682
2690
  primaryButtonLabelTextColor,
2683
2691
  primaryButtonLabelTextWeight,
2684
2692
  primaryButtonSize,
2685
- dataTestIdSecondaryButton,
2686
- dataTourSecondaryButton,
2687
- onClickSecondaryButton,
2693
+ renderFieldsWrapper = wrapperChildren => wrapperChildren,
2688
2694
  secondaryButton,
2689
2695
  secondaryButtonAppearance,
2690
2696
  secondaryButtonFill,
@@ -2696,9 +2702,7 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2696
2702
  secondaryButtonLabelTextColor,
2697
2703
  secondaryButtonLabelTextWeight,
2698
2704
  secondaryButtonSize,
2699
- dataTestIdTertiaryButton,
2700
- dataTourTertiaryButton,
2701
- onClickTertiaryButton,
2705
+ shapeStrengthClass,
2702
2706
  tertiaryButton,
2703
2707
  tertiaryButtonFill,
2704
2708
  tertiaryButtonFillHover,
@@ -2707,35 +2711,11 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2707
2711
  tertiaryButtonLabelTextColor,
2708
2712
  tertiaryButtonLabelTextWeight,
2709
2713
  tertiaryButtonSize,
2710
- additionalProps = {},
2711
- buttonDirection = 'vertical',
2712
- buttonFill,
2713
- buttonJustifyContent,
2714
- buttonPadding,
2715
- buttonPosition,
2716
- dataTestIdButtons,
2717
- dataTourButtons,
2718
- disableFieldsAutoComplete = false,
2719
- fieldsGap,
2720
- formName,
2721
- groupGap,
2722
- language,
2723
- loader,
2724
- loaderAppearance = 'surfacePrimary sizeM',
2725
- loaderFill,
2726
- loaderItemFill,
2727
- loaderShape,
2728
- loaderSize,
2729
- loaderText,
2730
- loaderType = 'simple',
2731
- mutators,
2732
- notificationCloseButton,
2733
- notificationType,
2734
- renderFieldsWrapper = wrapperChildren => wrapperChildren,
2735
- shapeStrengthClass,
2736
2714
  before,
2737
2715
  after,
2738
2716
  isLoading,
2717
+ onClickSecondaryButton,
2718
+ onClickTertiaryButton,
2739
2719
  onChangeFormValues,
2740
2720
  onSubmit
2741
2721
  } = props;
@@ -2760,10 +2740,10 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2760
2740
  initialValues: initialValues,
2761
2741
  initialValuesEqual: initialValuesEqual,
2762
2742
  render: ({
2763
- submitError,
2764
2743
  form,
2765
2744
  handleSubmit,
2766
- modifiedSinceLastSubmit
2745
+ modifiedSinceLastSubmit,
2746
+ submitError
2767
2747
  }) => {
2768
2748
  return /*#__PURE__*/React.createElement("form", {
2769
2749
  className: clsx(className, 'form', type && `form_type_${type}`, buttonPosition && `form_button-position_${buttonPosition}`, directionClass && `direction_${directionClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, elevationClass && `elevation_${elevationClass}`),
@@ -2793,8 +2773,8 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2793
2773
  }, desc), submitError && !modifiedSinceLastSubmit && /*#__PURE__*/React.createElement("div", {
2794
2774
  className: clsx('notification', 'form-notification', notificationType ? `form-notification_${notificationType}` : 'form-notification_global')
2795
2775
  }, /*#__PURE__*/React.createElement(Notification, {
2796
- className: "form-notification__item",
2797
2776
  appearance: "errorPrimary",
2777
+ className: "form-notification__item",
2798
2778
  title: form.getState().submitError,
2799
2779
  titleTextSize: "h6",
2800
2780
  status: "error",
@@ -2812,28 +2792,28 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2812
2792
  }, Object.keys(config).map(key => generateField(config[key], {
2813
2793
  key
2814
2794
  }, additionalProps[config[key].name])), isLoading && (loader || /*#__PURE__*/React.createElement(Loader, {
2795
+ appearance: loaderAppearance,
2815
2796
  className: "form__loader",
2816
2797
  type: loaderType,
2817
- appearance: loaderAppearance,
2818
2798
  size: loaderSize,
2819
2799
  fill: loaderFill,
2820
2800
  text: loaderText,
2821
2801
  itemFill: loaderItemFill,
2822
2802
  shape: loaderShape
2823
2803
  }))))), (primaryButtonLabel || primaryButton || secondaryButtonLabel || secondaryButton || tertiaryButton || tertiaryButtonLabel) && /*#__PURE__*/React.createElement(Group, {
2804
+ className: "form__button",
2824
2805
  dataTestId: dataTestIdButtons,
2825
2806
  dataTour: dataTourButtons,
2826
- className: "form__button",
2827
2807
  direction: buttonDirection,
2828
2808
  justifyContent: buttonJustifyContent,
2829
2809
  fill: buttonFill,
2830
2810
  padding: buttonPadding,
2831
2811
  gap: buttonGap
2832
2812
  }, primaryButtonLabel ? /*#__PURE__*/React.createElement(Button, {
2813
+ appearance: primaryButtonAppearance,
2814
+ className: "form__button-item",
2833
2815
  dataTestId: dataTestIdPrimaryButton,
2834
2816
  dataTour: dataTourPrimaryButton,
2835
- className: "form__button-item",
2836
- appearance: primaryButtonAppearance,
2837
2817
  width: "fill",
2838
2818
  size: primaryButtonSize,
2839
2819
  fill: primaryButtonFill,
@@ -2842,13 +2822,13 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2842
2822
  labelTextColor: primaryButtonLabelTextColor,
2843
2823
  labelTextSize: primaryButtonLabelSize,
2844
2824
  labelTextWeight: primaryButtonLabelTextWeight,
2845
- isDisabled: primaryButtonIsDisabled,
2846
- loading: primaryButtonIsLoading
2825
+ loading: primaryButtonIsLoading,
2826
+ isDisabled: primaryButtonIsDisabled
2847
2827
  }) : primaryButton, secondaryButtonLabel ? /*#__PURE__*/React.createElement(Button, {
2828
+ appearance: secondaryButtonAppearance,
2829
+ className: "form__button-item",
2848
2830
  dataTestId: dataTestIdSecondaryButton,
2849
2831
  dataTour: dataTourSecondaryButton,
2850
- className: "form__button-item",
2851
- appearance: secondaryButtonAppearance,
2852
2832
  width: "fill",
2853
2833
  size: secondaryButtonSize,
2854
2834
  fill: secondaryButtonFill,
@@ -2857,13 +2837,13 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2857
2837
  labelTextColor: secondaryButtonLabelTextColor,
2858
2838
  labelTextSize: secondaryButtonLabelSize,
2859
2839
  labelTextWeight: secondaryButtonLabelTextWeight,
2860
- isDisabled: secondaryButtonIsDisabled,
2861
2840
  loading: secondaryButtonIsLoading,
2841
+ isDisabled: secondaryButtonIsDisabled,
2862
2842
  onClick: onClickSecondaryButton
2863
2843
  }) : secondaryButton, tertiaryButtonLabel ? /*#__PURE__*/React.createElement(Button, {
2844
+ className: "form__button-item",
2864
2845
  dataTestId: dataTestIdTertiaryButton,
2865
2846
  dataTour: dataTourTertiaryButton,
2866
- className: "form__button-item",
2867
2847
  width: "fill",
2868
2848
  size: tertiaryButtonSize,
2869
2849
  fill: tertiaryButtonFill,
@@ -2878,9 +2858,9 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2878
2858
  decorators: [focusOnErrorDecorator],
2879
2859
  mutators: mutators,
2880
2860
  subscription: {
2881
- submitError: true,
2882
2861
  modifiedSinceLastSubmit: true,
2883
2862
  pristine: true,
2863
+ submitError: true,
2884
2864
  submitting: true
2885
2865
  },
2886
2866
  validate: validate,
@@ -3137,4 +3117,4 @@ const getErrorsForFinalForm = error => {
3137
3117
  return formErrors;
3138
3118
  };
3139
3119
 
3140
- export { DEFAULT_MESSAGES_FIELDS, FieldWrapper, FieldWrapperBase, FileInput, FinalForm, FormBlockGroup, FormFieldCheckbox, FormFieldChips, FormFieldChoice, FormFieldCode, FormFieldCustom, FormFieldDatePicker, FormFieldInput, FormFieldMaskedInput, FormFieldPassword, FormFieldSegmented, FormFieldSelect, FormFieldSwitch, FormFieldTextarea, RadioGroup, addRequiredFieldsParamToSchema, dateValidation, defaultCheckboxProps, defaultChipsProps, defaultChoiceProps, defaultCodeProps, defaultDatepickerProps, defaultDropzoneProps, defaultFieldProps, defaultFieldSizeL, defaultFieldSizeM, defaultFieldSizeS, defaultFieldSizeXL, defaultGroupProps, defaultInputProps, defaultPasswordProps, defaultRadioProps, defaultSegmentedProps, defaultSelectProps, defaultSwitchProps, defaultTextareaProps, emailValidation, focusOnError, focusOnErrorDecorator, formTypes, generateField, getErrorsForFinalForm, parseNumericField, phoneValidation, sendFormDataToServer, setErrorsMutator, useYupValidationSchema };
3120
+ export { DEFAULT_MESSAGES_FIELDS, FieldWrapper, FieldWrapperBase, FinalForm, FormBlockGroup, FormFieldCheckbox, FormFieldChips, FormFieldChoice, FormFieldCode, FormFieldCustom, FormFieldDatePicker, FormFieldFileInput, FormFieldInput, FormFieldMaskedInput, FormFieldPassword, FormFieldRadioGroup, FormFieldSegmented, FormFieldSelect, FormFieldSwitch, FormFieldTextarea, addRequiredFieldsParamToSchema, dateValidation, defaultCheckboxProps, defaultChipsProps, defaultChoiceProps, defaultCodeProps, defaultDatepickerProps, defaultDropzoneProps, defaultFieldProps, defaultFieldSizeL, defaultFieldSizeM, defaultFieldSizeS, defaultFieldSizeXL, defaultGroupProps, defaultInputProps, defaultPasswordProps, defaultRadioProps, defaultSegmentedProps, defaultSelectProps, defaultSwitchProps, defaultTextareaProps, emailValidation, focusOnError, focusOnErrorDecorator, formTypes, generateField, getErrorsForFinalForm, parseNumericField, phoneValidation, sendFormDataToServer, setErrorsMutator, useYupValidationSchema };