@itcase/forms 1.1.39 → 1.1.42

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,423 +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
- 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
472
547
  } = props;
473
-
474
- // TODO: delete react-final-form things out of here?
475
548
  const {
476
549
  change
477
550
  } = useForm();
478
- const [fileError, setFileError] = useState('');
479
- const [fileIsLoading, setFileIsLoading] = useState(false);
480
- const filesList = useMemo(() => inputValue ? castArray(inputValue) : [], [inputValue]);
481
- const changeFormState = useCallback(newFiles => {
482
- // If max files in dropzone is 1 - return file as it self, else as array of files
483
- // ps: for old projects compatibility
484
- const toSave = dropzoneProps.maxFiles == 1 ? newFiles[0] : newFiles;
485
- change(inputName, toSave);
486
- return toSave;
487
- },
488
- // If "inputName" will be changes, then it should be a different field
489
- // eslint-disable-next-line react-hooks/exhaustive-deps
490
- [dropzoneProps, change]);
491
551
 
492
- //
493
- const convertFiledValueAndSaveAsFiles = useCallback(async currentFilesList => {
494
- setFileIsLoading(true);
495
- const newFiles = [];
496
- for (const fileItem of currentFilesList) {
497
- if (typeof fileItem === 'string') {
498
- const newFile = await convertToFile(fileItem, isPreviews);
499
- if (newFile) {
500
- newFiles.push(newFile);
501
- }
502
- } else {
503
- 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;
504
593
  }
505
- }
506
- changeFormState(newFiles);
507
- setFileIsLoading(false);
508
- }, [isPreviews, changeFormState]);
509
-
510
- // Delete file from dropzone
511
- const removeFile = useCallback((event, index) => {
512
- event.stopPropagation();
513
- event.preventDefault();
514
- const newFiles = [...filesList];
515
- newFiles.splice(index, 1);
516
- if (onDeleteFile) {
517
- onDeleteFile(filesList[index], inputName);
518
- }
519
- changeFormState(newFiles);
520
- },
521
- // If "inputName" will be changes, then it should be a different field
522
- // eslint-disable-next-line react-hooks/exhaustive-deps
523
- [filesList, changeFormState, onDeleteFile]);
524
-
525
- // Create dropzone options
526
- const {
527
- getInputProps,
528
- getRootProps
529
- } = useDropzone({
530
- maxFiles: maxFiles || 5,
531
- maxSize: maxSize || 10485760,
532
- // 10mb
533
- // accept: { 'image/*': [] },
534
- ...dropzoneProps,
535
- getFilesFromEvent: async event => {
536
- const result = await fromEvent(event);
537
- const newFiles = result.filter(item => item instanceof File);
538
- // Add exists and new files to accepted(or rejected)
539
- return [...filesList, ...newFiles];
540
- },
541
- onDropAccepted: acceptedFiles => {
542
- // If dropped files has accepted and we need a previews
543
- if (isPreviews) {
544
- // Add preview to every file
545
- acceptedFiles.forEach(file => {
546
- if (!file.error) {
547
- file.preview = URL.createObjectURL(file);
548
- }
549
- });
550
- }
551
- // Save to form data (including empty when files are not valid)
552
- const filesToSave = changeFormState(acceptedFiles);
553
- setFileError('');
554
-
555
- // Save DataURL for all files
556
- const readerPromisesList = acceptedFiles.map(file => {
557
- return new Promise(resolve => setFileDataURL(file, resolve));
558
- });
559
- // Save files to form values
560
- Promise.all(readerPromisesList).then(() => {
561
- if (onAddFiles) {
562
- onAddFiles(filesToSave, inputName);
563
- }
564
- });
565
- },
566
- onDropRejected: rejectedFiles => {
567
- // If dropped files has rejected
568
- if (rejectedFiles.length) {
569
- let fileErrorMessage = 'Ошибка при добавлении файла';
570
- const firstFileErrorItem = rejectedFiles[0].errors[0];
571
- if (firstFileErrorItem) {
572
- if (firstFileErrorItem.code === ErrorCode.TooManyFiles) {
573
- fileErrorMessage = `Максимальное количество файлов: ${maxFiles}`;
574
- } else {
575
- fileErrorMessage = firstFileErrorItem.message;
576
- }
577
- }
578
- // Show error
579
- setFileError(fileErrorMessage);
580
- } else {
581
- // Else clean error
582
- setFileError('');
583
- }
584
- }
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));
585
626
  });
586
- useEffect(() => {
587
- const currentFilesList = castArray(inputValue);
588
- const isNeedToConvert = currentFilesList.some(fileItem => typeof fileItem === 'string');
589
- if (isNeedToConvert) {
590
- // First time convert value to Files and save to local and form state
591
- convertFiledValueAndSaveAsFiles(currentFilesList);
592
- }
627
+ }
593
628
 
594
- // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
595
- return () => {
596
- filesList.forEach(file => {
597
- if (file?.preview) {
598
- URL.revokeObjectURL(file.preview);
599
- }
600
- });
601
- };
602
- // eslint-disable-next-line react-hooks/exhaustive-deps
603
- }, [inputValue]);
604
- const propsGenerator = useDevicePropsGenerator(props);
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
+ };
638
+
639
+ const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props) {
605
640
  const {
606
- fillClass,
607
- fillHoverClass,
608
- borderColorClass,
609
- borderColorHoverClass,
610
- borderTypeClass,
611
- borderWidthClass,
612
- errorMessageTextColor,
613
- errorMessageTextSize,
614
- errorMessageTextWeight,
615
- hintDescriptionTextColor,
616
- hintDescriptionTextSize,
617
- hintDescriptionTextWeight,
618
- hintDescriptionTextWrap,
619
- hintTitleTextColor,
620
- hintTitleTextSize,
621
- hintTitleTextWeight,
622
- hintTitleTextWrap,
623
- removeThumbAppearance,
624
- removeThumbShape,
625
- removeThumbText,
626
- removeThumbTextWeight,
627
- shapeClass,
628
- thumbBorderColorClass,
629
- thumbBorderColorHoverClass,
630
- thumbBorderTypeClass,
631
- thumbBorderWidthClass,
632
- thumbDirectionClass,
633
- thumbNameTextColor,
634
- thumbNameTextSize,
635
- thumbNameTextWeight,
636
- thumbNameTextWrap
637
- } = propsGenerator;
638
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", getRootProps({
639
- // className: `form-dropzone__dropzone dropzone ${className} form-dropzone__dropzone_size_${size} ${shapeClass}`,
640
- className: `form-dropzone__dropzone dropzone`
641
- }), /*#__PURE__*/React.createElement("input", Object.assign({}, getInputProps(), {
642
- name: inputName
643
- })), /*#__PURE__*/React.createElement("div", {
644
- 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}`)
645
- }, filesList.map((file, index) => /*#__PURE__*/React.createElement("aside", {
646
- className: clsx('form-dropzone__thumb', fillClass, thumbDirectionClass, thumbBorderWidthClass, thumbBorderColorClass, thumbBorderColorHoverClass, thumbBorderTypeClass),
647
- key: file.id || `${file.name}_${index}`
648
- }, isPreviews && !file.error && /*#__PURE__*/React.createElement("div", {
649
- className: "form-dropzone__thumb-image"
650
- }, /*#__PURE__*/React.createElement("img", {
651
- className: "form-dropzone__thumb-image-inner",
652
- src: file.preview || file.image,
653
- onLoad: () => {
654
- // Revoke data uri after image is loaded
655
- URL.revokeObjectURL(file.preview);
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);
656
663
  }
657
- })), file.error && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Text, {
658
- size: thumbNameTextSize,
659
- textColor: thumbNameTextColor,
660
- textWeight: thumbNameTextWeight,
661
- textWrap: thumbNameTextWrap
662
- }, fileErrorText || file.error)), showFilename && /*#__PURE__*/React.createElement("div", {
663
- className: "form-dropzone__thumb-name"
664
- }, /*#__PURE__*/React.createElement(Text, {
665
- className: "form-dropzone__thumb-name-inner",
666
- size: thumbNameTextSize,
667
- textColor: thumbNameTextColor,
668
- textWeight: thumbNameTextWeight,
669
- textWrap: thumbNameTextWrap
670
- }, file.name)), fileIsLoading && /*#__PURE__*/React.createElement("div", {
671
- className: "form-dropzone__thumb-loader"
672
- }, /*#__PURE__*/React.createElement(Loader, {
673
- width: "fill",
674
- height: "fill"
675
- })), /*#__PURE__*/React.createElement("div", {
676
- className: clsx('form-dropzone__thumb-remove')
677
- }, /*#__PURE__*/React.createElement(Button, {
678
- className: "form-dropzone__thumb-remove-text",
679
- appearance: removeThumbAppearance,
680
- label: removeThumbText || 'Удалить',
681
- labelTextWeight: removeThumbTextWeight,
682
- shape: removeThumbShape,
683
- onClick: event => removeFile(event, index)
684
- })))), !filesList.length ? /*#__PURE__*/React.createElement("div", {
685
- className: "form-dropzone__hint"
686
- }, /*#__PURE__*/React.createElement(Text, {
687
- className: "form-dropzone__hint-title",
688
- size: hintTitleTextSize,
689
- textColor: hintTitleTextColor,
690
- textWeight: hintTitleTextWeight,
691
- textWrap: hintTitleTextWrap
692
- }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React.createElement(Text, {
693
- className: "form-dropzone__hint-text",
694
- size: hintDescriptionTextSize,
695
- textColor: hintDescriptionTextColor,
696
- textWeight: hintDescriptionTextWeight,
697
- textWrap: hintDescriptionTextWrap
698
- }, hintDescription)) : /*#__PURE__*/React.createElement("div", {
699
- className: "form-dropzone__hint form-dropzone__hint_type_add-more"
700
- }, /*#__PURE__*/React.createElement(Text, {
701
- className: "form-dropzone__hint-title",
702
- size: hintTitleTextSize,
703
- textColor: hintTitleTextColor,
704
- textWeight: hintTitleTextWeight,
705
- textWrap: hintTitleTextWrap
706
- }, hintTitle || 'Select a file or drag in form'), hintDescription && /*#__PURE__*/React.createElement(Text, {
707
- className: "form-dropzone__hint-text",
708
- size: hintDescriptionTextSize,
709
- textColor: hintDescriptionTextColor,
710
- textWeight: hintDescriptionTextWeight,
711
- textWrap: hintDescriptionTextWrap
712
- }, hintDescription)))), fileError && /*#__PURE__*/React.createElement("div", {
713
- className: "form-field__message"
714
- }, /*#__PURE__*/React.createElement(Text, {
715
- className: "form-field__message-item form-field__message-item_type_message",
716
- size: errorMessageTextSize,
717
- textColor: errorMessageTextColor,
718
- textWeight: errorMessageTextWeight
719
- }, fileError)));
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
+ });
720
733
  });
721
- async function getFileByURL(url) {
722
- try {
723
- const response = await axios({
724
- url: url,
725
- responseType: 'blob'
734
+
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
+ };
743
+
744
+ const FormFieldCode = /*#__PURE__*/React.memo(function FormFieldCode(props) {
745
+ const {
746
+ name,
747
+ initialValue,
748
+ label,
749
+ messageType,
750
+ isDisabled,
751
+ classNameGroupItem,
752
+ fieldProps = {},
753
+ inputProps = {},
754
+ showMessage,
755
+ isRequired
756
+ } = 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
726
781
  });
727
- const blobObject = response.data;
728
- const dirtyFilename = response.headers['content-disposition']?.split('filename=')[1];
729
- // Remove double quotes
730
- let filename = dirtyFilename?.substring(1).slice(0, -1);
731
- if (!filename) {
732
- filename = url.split('/').at(-1);
733
- // const typeParts = blobObject.type.split('/')
734
- // const fileType = typeParts[typeParts.length - 1]
735
- // filename = `${new Date().getTime()}.${fileType}`
736
- }
737
- return new File([blobObject], filename, {
738
- type: blobObject.type
782
+ const updatedInputProps = useValidationAppearanceInputProps({
783
+ inputProps: inputProps,
784
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
739
785
  });
740
- } catch (error) {
741
- console.log('error: ', error);
742
- return null;
743
- }
744
- }
745
- async function convertToFile(inputValue, isPreviews) {
746
- let newFile = null;
747
-
748
- // Download image by url and save as File instance
749
- const isURL = typeof inputValue === 'string' && inputValue.includes('/');
750
- if (inputValue.image || isURL) {
751
- newFile = await getFileByURL(inputValue.image || inputValue);
752
- if (newFile) {
753
- setFileDataURL(newFile);
754
- }
755
- }
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
+ });
756
811
 
757
- // Convert dataURL to File instance
758
- if (inputValue.dataURL) {
759
- newFile = createFileFromDataURL(inputValue.name || inputValue.path, inputValue.dataURL);
760
- newFile.dataURL = inputValue.dataURL;
761
- }
812
+ const FormFieldCustom = /*#__PURE__*/React.memo(function FormFieldCustom(props) {
813
+ const {
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
+ */
762
842
 
763
- // Save new File to state
764
- if (newFile) {
765
- newFile.id = inputValue.id;
766
- if (isPreviews) {
767
- newFile.preview = URL.createObjectURL(newFile);
768
- }
769
- }
770
- return newFile;
771
- }
772
- function setFileDataURL(file, resolve) {
773
- resolve = resolve || (() => {});
774
- // Init reader and save his file
775
- const reader = new FileReader();
776
- reader._readedFile = file;
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
+ });
777
888
 
778
- // Set handlers
779
- reader.onabort = () => resolve();
780
- reader.onerror = () => resolve();
781
- reader.onload = event => {
782
- event.target._readedFile.dataURL = reader.result;
783
- resolve();
784
- };
785
- // Run reader
786
- if (file instanceof File) {
787
- reader.readAsDataURL(file);
788
- } else {
789
- resolve();
790
- }
791
- }
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
+ };
792
901
 
793
- const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
902
+ function FormFieldDatePicker(props) {
794
903
  const {
795
- className,
796
904
  name,
797
- width,
798
- maxFiles,
799
- maxSize,
800
- label,
801
- fileErrorText,
905
+ isDisabled,
802
906
  classNameGroupItem,
803
- dropzoneProps,
804
- fieldProps,
805
- hintDescription,
806
- hintTitle,
807
- showFilename,
907
+ datePickerProps,
908
+ fieldProps = {},
909
+ inputProps = {},
808
910
  showMessage,
809
- isPreviews,
810
911
  isRequired,
811
- onAddFiles,
812
- onDeleteFile
912
+ onChange
813
913
  } = props;
814
- const propsGenerator = useDevicePropsGenerator(props);
815
- const {
816
- size,
817
- fill,
818
- fillHover,
819
- labelTextColor,
820
- borderColorHover,
821
- borderType,
822
- borderWidth,
823
- errorMessageTextColor,
824
- errorMessageTextSize,
825
- errorMessageTextWeight,
826
- hintDescriptionTextColor,
827
- hintDescriptionTextSize,
828
- hintDescriptionTextWeight,
829
- hintDescriptionTextWrap,
830
- hintTitleTextColor,
831
- hintTitleTextSize,
832
- hintTitleTextWeight,
833
- hintTitleTextWrap,
834
- removeThumbAppearance,
835
- removeThumbShape,
836
- removeThumbText,
837
- removeThumbTextWeight,
838
- shape,
839
- thumbBorderColor,
840
- thumbBorderColorHover,
841
- thumbBorderType,
842
- thumbBorderWidth,
843
- thumbColumn = 1,
844
- thumbDirection = 'vertical',
845
- thumbNameTextColor,
846
- thumbNameTextSize,
847
- thumbNameTextWeight,
848
- thumbNameTextWrap
849
- } = propsGenerator;
850
914
  return /*#__PURE__*/React.createElement(Field, {
851
915
  name: name
852
916
  }, function Render({
@@ -860,10 +924,27 @@ const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
860
924
  * custom React Hook function.
861
925
  */
862
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]);
863
943
  const {
864
944
  errorKey,
865
945
  errorMessage,
866
946
  isErrorState,
947
+ successKey,
867
948
  isValidState
868
949
  } = useFieldValidationState({
869
950
  fieldProps: fieldProps,
@@ -871,422 +952,460 @@ const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
871
952
  meta: meta
872
953
  });
873
954
  const updatedInputProps = useValidationAppearanceInputProps({
874
- inputProps: props,
875
- validationStateKey: isErrorState ? errorKey : 'success'
955
+ inputProps: inputProps,
956
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
876
957
  });
877
-
878
- /** TODO:
879
- * REFACTOR PROPERTIES
880
- */
881
958
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
882
- className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
883
- width: width,
884
- label: label,
885
- labelTextColor: labelTextColor,
959
+ className: clsx('form-field_datepicker', 'form__item_datepicker', classNameGroupItem),
886
960
  errorKey: errorKey,
887
961
  errorMessage: errorMessage,
888
962
  isErrorState: isErrorState,
889
963
  metaError: meta.error,
890
- fieldClassName: "form-dropzone",
964
+ isDisabled: isDisabled,
965
+ fieldClassName: "form-datepicker",
891
966
  inputName: input.name,
892
- inputValue: input.value,
967
+ inputValue: input.value || '',
893
968
  metaActive: meta.active,
894
- metaTouched: meta.touched,
895
969
  showMessage: showMessage,
896
970
  isRequired: isRequired,
897
971
  isValidState: isValidState
898
- }, fieldProps), /*#__PURE__*/React.createElement(FileInputDropzone, {
899
- className: className,
900
- maxFiles: maxFiles,
901
- maxSize: maxSize,
902
- size: size,
903
- fill: fill,
904
- fillHover: fillHover,
905
- borderColor: updatedInputProps.borderColor,
906
- borderColorHover: borderColorHover,
907
- borderType: borderType,
908
- borderWidth: borderWidth,
909
- errorMessageTextColor: errorMessageTextColor,
910
- errorMessageTextSize: errorMessageTextSize,
911
- errorMessageWeight: errorMessageTextWeight,
912
- fileErrorText: fileErrorText,
913
- metaError: meta.error,
914
- dropzoneProps: dropzoneProps,
915
- hintDescription: hintDescription,
916
- hintDescriptionTextColor: hintDescriptionTextColor,
917
- hintDescriptionTextSize: hintDescriptionTextSize,
918
- hintDescriptionTextWeight: hintDescriptionTextWeight,
919
- hintDescriptionTextWrap: hintDescriptionTextWrap,
920
- hintTitle: hintTitle,
921
- hintTitleTextColor: hintTitleTextColor,
922
- hintTitleTextSize: hintTitleTextSize,
923
- hintTitleTextWeight: hintTitleTextWeight,
924
- hintTitleTextWrap: hintTitleTextWrap,
925
- inputName: input.name,
926
- inputValue: input.value,
927
- metaTouched: meta.touched,
928
- removeThumbAppearance: removeThumbAppearance,
929
- removeThumbShape: removeThumbShape,
930
- removeThumbText: removeThumbText,
931
- removeThumbTextWeight: removeThumbTextWeight,
932
- shape: shape,
933
- showFilename: showFilename,
934
- thumbBorderColor: thumbBorderColor,
935
- thumbBorderColorHover: thumbBorderColorHover,
936
- thumbBorderType: thumbBorderType,
937
- thumbBorderWidth: thumbBorderWidth,
938
- thumbColumn: thumbColumn,
939
- thumbDirection: thumbDirection,
940
- thumbNameTextColor: thumbNameTextColor,
941
- thumbNameTextSize: thumbNameTextSize,
942
- thumbNameTextWeight: thumbNameTextWeight,
943
- thumbNameTextWrap: thumbNameTextWrap,
944
- isPreviews: isPreviews,
945
- onAddFiles: onAddFiles,
946
- 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
947
982
  }));
948
983
  });
949
- });
984
+ }
950
985
 
951
- const defaultGroupProps = {
952
- width: 'fill',
953
- labelTextSize: 's',
954
- messageTextColor: 'surfaceTextPrimary',
955
- messageTextSize: 's',
956
- errorMessageTextSize: 's',
957
- errorMessageTextColor: 'errorTextSecondary',
958
- helpTextSize: 's',
959
- requiredMessageTextColor: 'warningTextSecondary',
960
- 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
961
1006
  };
962
1007
 
963
- const FormBlockGroup = /*#__PURE__*/React.memo(function Group(props) {
1008
+ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(props) {
964
1009
  const {
965
- dataTour,
966
1010
  className,
967
- name,
968
- title,
969
- titleTextColor,
970
- titleTextSize,
971
- titleTextWeight,
972
- label,
973
- labelTextColor,
974
- labelTextSize,
975
- labelTextWeight,
976
- message,
977
- messageTextColor,
978
- messageTextSize,
979
- messageTextWeight,
980
- column,
981
- showGroupMessage,
982
- before,
983
- after,
984
- isHidden,
985
- children
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
986
1026
  } = props;
987
1027
 
988
- // @ts-expect-error
1028
+ // TODO: delete react-final-form things out of here?
989
1029
  const {
990
- styles: styles
991
- } = useStyles(props);
992
- return /*#__PURE__*/React.createElement(Field, {
993
- name: name
994
- }, function Render({
995
- input,
996
- meta
997
- }) {
998
- /** Note:
999
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
1000
- * React Hooks cannot be called inside a callback.
1001
- * React Hooks must be called in a React function component or a
1002
- * custom React Hook function.
1003
- */
1004
- const {
1005
- errorKey,
1006
- errorMessage,
1007
- isErrorState
1008
- } = useFieldValidationState({
1009
- fieldProps: props,
1010
- // or fieldProps?
1011
- input: input,
1012
- meta: meta
1013
- });
1014
- const updatedProps = useValidationAppearanceInputProps({
1015
- inputProps: props,
1016
- validationStateKey: isErrorState ? errorKey : 'success'
1017
- });
1018
- return /*#__PURE__*/React.createElement("div", {
1019
- className: clsx('form__group', className, isHidden && 'form__group_hidden', column && `form__group_column_${column}`),
1020
- "data-tour": dataTour,
1021
- style: styles
1022
- }, /*#__PURE__*/React.createElement("div", {
1023
- className: "form__group-wrapper"
1024
- }, before, title && /*#__PURE__*/React.createElement("div", {
1025
- className: "form__group-title"
1026
- }, /*#__PURE__*/React.createElement(Title, {
1027
- size: titleTextSize,
1028
- textColor: titleTextColor,
1029
- textWeight: titleTextWeight
1030
- }, title)), label && /*#__PURE__*/React.createElement("div", {
1031
- className: "form__group-label"
1032
- }, /*#__PURE__*/React.createElement(Text, {
1033
- size: labelTextSize,
1034
- textColor: labelTextColor,
1035
- textWeight: labelTextWeight
1036
- }, label)), /*#__PURE__*/React.createElement("div", {
1037
- className: "form__group-items"
1038
- }, children), after), showGroupMessage && /*#__PURE__*/React.createElement(React.Fragment, null, isErrorState && errorMessage && /*#__PURE__*/React.createElement(Text, {
1039
- id: `${name}-error`,
1040
- className: `form__group-message form__group-message_type-${errorKey}`,
1041
- size: updatedProps.messageTextSize,
1042
- textColor: updatedProps.messageTextColor,
1043
- textWeight: updatedProps.messageTextWeight
1044
- }, errorMessage), Boolean(message) && (!isErrorState || !errorMessage) && /*#__PURE__*/React.createElement(Text, {
1045
- className: "form__group-message",
1046
- size: messageTextSize,
1047
- textColor: messageTextColor,
1048
- textWeight: messageTextWeight
1049
- }, message), !isErrorState && !message && /*#__PURE__*/React.createElement(Text, {
1050
- className: "form__group-message",
1051
- size: messageTextSize
1052
- }, '\u00A0')));
1053
- });
1054
- });
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]);
1045
+
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]);
1055
1063
 
1056
- const defaultCheckboxProps = {
1057
- appearance: 'defaultPrimary sizeL solid',
1058
- width: 'fill',
1059
- // useValidationAppearanceInputProps
1060
- // Error
1061
- errorAppearance: 'errorPrimary sizeL solid',
1062
- // Required
1063
- requiredAppearance: 'requirePrimary sizeL solid'
1064
- };
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]);
1065
1078
 
1066
- const FormFieldCheckbox = /*#__PURE__*/React.memo(function FormFieldCheckbox(props) {
1079
+ // Create dropzone options
1067
1080
  const {
1068
- name,
1069
- initialValue,
1070
- isDisabled,
1071
- classNameGroupItem,
1072
- fieldProps = {},
1073
- inputProps = {},
1074
- showMessage,
1075
- isRequired,
1076
- onChange
1077
- } = props;
1078
- return /*#__PURE__*/React.createElement(Field, {
1079
- type: "checkbox",
1080
- name: name,
1081
- initialValue: initialValue
1082
- }, function Render({
1083
- input,
1084
- meta
1085
- }) {
1086
- /** Note:
1087
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
1088
- * React Hooks cannot be called inside a callback.
1089
- * React Hooks must be called in a React function component or a
1090
- * custom React Hook function.
1091
- */
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('');
1092
1108
 
1093
- const onChangeField = useCallback(event => {
1094
- input.onChange(event);
1095
- if (onChange) {
1096
- 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('');
1097
1137
  }
1098
- }, [onChange, input.onChange]);
1099
- const {
1100
- errorKey,
1101
- errorMessage,
1102
- isErrorState,
1103
- successKey,
1104
- isValidState
1105
- } = useFieldValidationState({
1106
- fieldProps: fieldProps,
1107
- input: input,
1108
- 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'
1109
1283
  });
1110
- const updatedInputProps = useValidationAppearanceInputProps({
1111
- inputProps: inputProps,
1112
- 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
1113
1296
  });
1114
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1115
- className: clsx('form-field-checkbox', 'form__item_checkbox', classNameGroupItem),
1116
- errorKey: errorKey,
1117
- errorMessage: errorMessage,
1118
- isErrorState: isErrorState,
1119
- metaError: meta.error,
1120
- isDisabled: isDisabled,
1121
- fieldClassName: "form-checkbox",
1122
- inputName: input.name,
1123
- inputValue: input.checked,
1124
- metaActive: meta.active,
1125
- showMessage: showMessage,
1126
- tag: "label",
1127
- isRequired: isRequired,
1128
- isValidState: isValidState
1129
- }, fieldProps), /*#__PURE__*/React.createElement(Checkbox, Object.assign({
1130
- type: "checkbox",
1131
- name: input.name,
1132
- isDisabled: isDisabled,
1133
- autoComplete: "nope",
1134
- checked: input.checked,
1135
- isActive: input.checked,
1136
- onBlur: input.onBlur,
1137
- onChange: onChangeField,
1138
- onFocus: input.onFocus
1139
- }, updatedInputProps)));
1140
- });
1141
- });
1297
+ } catch (error) {
1298
+ console.log('error: ', error);
1299
+ return null;
1300
+ }
1301
+ }
1302
+ async function convertToFile(inputValue, isPreviews) {
1303
+ let newFile = null;
1142
1304
 
1143
- const defaultChipsProps = {
1144
- appearance: 'surfacePrimary sizeM rounded',
1145
- width: 'fill',
1146
- // useValidationAppearanceInputProps
1147
- // Error
1148
- errorAppearance: 'errorPrimary sizeM solid rounded',
1149
- // Required
1150
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1151
- // Success
1152
- // successAppearance: 'successPrimary sizeM solid rounded',
1153
- };
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
+ }
1154
1313
 
1155
- function FormFieldChips(props) {
1156
- const {
1157
- name,
1158
- initialValue,
1159
- isDisabled,
1160
- classNameGroupItem,
1161
- emptyMessage,
1162
- emptyMessageTextColor,
1163
- emptyMessageTextSize,
1164
- fieldProps,
1165
- inputProps,
1166
- options,
1167
- showMessage,
1168
- isRequired,
1169
- onChange
1170
- } = props;
1171
- const {
1172
- change
1173
- } = 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
+ }
1174
1319
 
1175
- // Callback for value changes
1176
- const onChangeSomeInput = useCallback((inputValue, newOptionValue) => {
1177
- const updatedValues = inputValue.includes(newOptionValue) ? inputValue.filter(selectedValue => selectedValue !== newOptionValue) : [...inputValue, newOptionValue];
1178
- change(name, updatedValues);
1179
- onChange && onChange(updatedValues);
1180
- }, [change, name, onChange]);
1181
- useEffect(() => {
1182
- initialValue && change(name, initialValue);
1183
- // update the form value only when the initialValue changes, so use disable eslint to ignore the warning
1184
- // eslint-disable-next-line react-hooks/exhaustive-deps
1185
- }, [initialValue]);
1186
- return /*#__PURE__*/React.createElement(Field, {
1187
- name: name,
1188
- initialValue: initialValue
1189
- }, function Render({
1190
- input,
1191
- meta
1192
- }) {
1193
- const {
1194
- errorKey,
1195
- errorMessage,
1196
- isErrorState,
1197
- successKey,
1198
- isValidState
1199
- } = useFieldValidationState({
1200
- fieldProps: fieldProps,
1201
- input: input,
1202
- meta: meta
1203
- });
1204
- const updatedInputProps = useValidationAppearanceInputProps({
1205
- inputProps: inputProps,
1206
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1207
- });
1208
- const activeOptionsList = useMemo(() => {
1209
- const emptyOptionsList = [{
1210
- label: null,
1211
- value: null
1212
- }];
1213
- if (input?.value) {
1214
- const currentOptions = options.filter(option => input.value?.includes(option.value));
1215
- return currentOptions || emptyOptionsList;
1216
- }
1217
- return emptyOptionsList;
1218
- }, [input.value]);
1219
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1220
- className: clsx('form-field_chips', 'form__item_chips', classNameGroupItem),
1221
- errorKey: errorKey,
1222
- errorMessage: errorMessage,
1223
- isErrorState: isErrorState,
1224
- metaError: meta.error,
1225
- isDisabled: isDisabled,
1226
- fieldClassName: "form-chips",
1227
- inputName: input.name,
1228
- inputValue: input.value,
1229
- metaActive: meta.active,
1230
- showMessage: showMessage,
1231
- isRequired: isRequired,
1232
- isValidState: isValidState
1233
- }, fieldProps), options.length ? /*#__PURE__*/React.createElement(ChipsGroup, {
1234
- direction: "horizontal",
1235
- gap: "1m",
1236
- wrap: "wrap"
1237
- }, options.map(option => /*#__PURE__*/React.createElement(Chips, Object.assign({
1238
- className: clsx(meta.active && 'form-chips_state_focus', meta.error && meta.touched && `form-chips_state_${errorKey}`),
1239
- key: option.value,
1240
- label: option.label,
1241
- isDisabled: option.isDisabled,
1242
- value: option.value,
1243
- isActive: activeOptionsList.some(activeOption => activeOption.value === option.value),
1244
- onClick: () => onChangeSomeInput(input.value, option.value)
1245
- }, updatedInputProps)))) : /*#__PURE__*/React.createElement(Text, {
1246
- size: emptyMessageTextSize,
1247
- textColor: emptyMessageTextColor
1248
- }, emptyMessage));
1249
- });
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;
1250
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;
1251
1334
 
1252
- const defaultChoiceProps = {
1253
- appearance: 'defaultPrimary sizeM solid rounded',
1254
- width: 'fill',
1255
- // useValidationAppearanceInputProps
1256
- // Error
1257
- errorAppearance: 'errorPrimary sizeM solid rounded',
1258
- // Required
1259
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1260
- };
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
+ }
1261
1349
 
1262
- const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props) {
1350
+ const FormFieldFileInput = /*#__PURE__*/React.memo(function FormFieldFileInput(props) {
1263
1351
  const {
1352
+ className,
1264
1353
  name,
1265
- initialValue,
1354
+ width,
1355
+ maxFiles,
1356
+ maxSize,
1266
1357
  label,
1267
- messageType,
1268
- isDisabled,
1358
+ fileErrorText,
1269
1359
  classNameGroupItem,
1360
+ dropzoneProps,
1270
1361
  fieldProps,
1271
- inputProps,
1272
- options,
1273
- placeholder,
1362
+ hintDescription,
1363
+ hintTitle,
1364
+ showFilename,
1274
1365
  showMessage,
1275
- isCheckbox,
1366
+ isPreviews,
1276
1367
  isRequired,
1277
- onChange
1368
+ onAddFiles,
1369
+ onClickPreview,
1370
+ onDeleteFile
1278
1371
  } = props;
1372
+ const propsGenerator = useDevicePropsGenerator(props);
1279
1373
  const {
1280
- change
1281
- } = useForm();
1282
- const setActiveSegment = useCallback((option, isChecked) => {
1283
- change(name, isChecked && option.value);
1284
- if (onChange) {
1285
- onChange(option.value, name, isChecked);
1286
- }
1287
- }, [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;
1288
1408
  return /*#__PURE__*/React.createElement(Field, {
1289
- initialValue: initialValue,
1290
1409
  name: name
1291
1410
  }, function Render({
1292
1411
  input,
@@ -1298,22 +1417,11 @@ const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props)
1298
1417
  * React Hooks must be called in a React function component or a
1299
1418
  * custom React Hook function.
1300
1419
  */
1301
- const activeOption = useMemo(() => {
1302
- const emptyOption = {
1303
- value: null,
1304
- label: null
1305
- };
1306
- if (input.value) {
1307
- const currentOption = options.find(option => option.value === input.value);
1308
- return currentOption || emptyOption;
1309
- }
1310
- return emptyOption;
1311
- }, [input.value]);
1420
+
1312
1421
  const {
1313
1422
  errorKey,
1314
1423
  errorMessage,
1315
1424
  isErrorState,
1316
- successKey,
1317
1425
  isValidState
1318
1426
  } = useFieldValidationState({
1319
1427
  fieldProps: fieldProps,
@@ -1321,65 +1429,127 @@ const FormFieldChoice = /*#__PURE__*/React.memo(function FormFieldChoice(props)
1321
1429
  meta: meta
1322
1430
  });
1323
1431
  const updatedInputProps = useValidationAppearanceInputProps({
1324
- inputProps: inputProps,
1325
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1432
+ inputProps: props,
1433
+ validationStateKey: isErrorState ? errorKey : 'success'
1326
1434
  });
1435
+
1436
+ /** TODO:
1437
+ * REFACTOR PROPERTIES
1438
+ */
1327
1439
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1328
- className: clsx('form-field_choice', 'form__item_choice', classNameGroupItem),
1440
+ className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
1441
+ width: width,
1329
1442
  label: label,
1330
- messageType: messageType,
1443
+ labelTextColor: labelTextColor,
1331
1444
  errorKey: errorKey,
1332
1445
  errorMessage: errorMessage,
1333
1446
  isErrorState: isErrorState,
1334
1447
  metaError: meta.error,
1335
- isDisabled: isDisabled,
1336
- fieldClassName: "form-choice",
1448
+ fieldClassName: "form-dropzone",
1337
1449
  inputName: input.name,
1338
- inputValue: input.value || [],
1450
+ inputValue: input.value,
1339
1451
  metaActive: meta.active,
1452
+ metaTouched: meta.touched,
1340
1453
  showMessage: showMessage,
1341
1454
  isRequired: isRequired,
1342
1455
  isValidState: isValidState
1343
- }, fieldProps), /*#__PURE__*/React.createElement(Choice, Object.assign({
1344
- className: clsx(meta.active && 'form-choice_state_focus', meta.error && meta.touched && `form-choice_state_${errorKey}`),
1345
- name: input.name,
1346
- isDisabled: isDisabled,
1347
- active: activeOption,
1348
- inputValue: input.value || [],
1349
- options: options,
1350
- placeholder: placeholder,
1351
- setActiveSegment: setActiveSegment,
1352
- isCheckbox: isCheckbox,
1353
- isRequired: isRequired
1354
- }, 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
+ }));
1355
1507
  });
1356
1508
  });
1357
1509
 
1358
- const defaultCodeProps = {
1359
- appearance: 'defaultPrimary sizeL solid rounded',
1360
- // useValidationAppearanceInputProps
1361
- // Error
1362
- errorAppearance: 'errorPrimary sizeM solid rounded',
1363
- // Required
1364
- 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'
1365
1520
  };
1366
1521
 
1367
- const FormFieldCode = /*#__PURE__*/React.memo(function FormFieldCode(props) {
1522
+ const FormBlockGroup = /*#__PURE__*/React.memo(function Group(props) {
1368
1523
  const {
1524
+ dataTour,
1525
+ className,
1369
1526
  name,
1370
- initialValue,
1371
- messageType,
1527
+ title,
1528
+ titleTextColor,
1529
+ titleTextSize,
1530
+ titleTextWeight,
1372
1531
  label,
1373
- isDisabled,
1374
- classNameGroupItem,
1375
- fieldProps = {},
1376
- inputProps = {},
1377
- showMessage,
1378
- 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
1379
1545
  } = props;
1546
+
1547
+ // @ts-expect-error
1548
+ const {
1549
+ styles: styles
1550
+ } = useStyles(props);
1380
1551
  return /*#__PURE__*/React.createElement(Field, {
1381
- name: name,
1382
- initialValue: initialValue
1552
+ name: name
1383
1553
  }, function Render({
1384
1554
  input,
1385
1555
  meta
@@ -1390,68 +1560,93 @@ const FormFieldCode = /*#__PURE__*/React.memo(function FormFieldCode(props) {
1390
1560
  * React Hooks must be called in a React function component or a
1391
1561
  * custom React Hook function.
1392
1562
  */
1393
-
1394
1563
  const {
1395
1564
  errorKey,
1396
1565
  errorMessage,
1397
- isErrorState,
1398
- successKey,
1399
- isValidState
1566
+ isErrorState
1400
1567
  } = useFieldValidationState({
1401
- fieldProps: fieldProps,
1568
+ fieldProps: props,
1569
+ // or fieldProps?
1402
1570
  input: input,
1403
1571
  meta: meta
1404
1572
  });
1405
- const updatedInputProps = useValidationAppearanceInputProps({
1406
- inputProps: inputProps,
1407
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1573
+ const updatedProps = useValidationAppearanceInputProps({
1574
+ inputProps: props,
1575
+ validationStateKey: isErrorState ? errorKey : 'success'
1408
1576
  });
1409
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1410
- className: clsx('form-field-code', 'form__item_code', classNameGroupItem),
1411
- label: label,
1412
- messageType: messageType,
1413
- errorKey: errorKey,
1414
- errorMessage: errorMessage,
1415
- isErrorState: isErrorState,
1416
- fieldClassName: 'form-code',
1417
- inputName: input.name,
1418
- inputValue: input.value,
1419
- metaActive: meta.active,
1420
- showMessage: showMessage,
1421
- isRequired: isRequired,
1422
- isValidState: isValidState
1423
- }, fieldProps), /*#__PURE__*/React.createElement(Code, Object.assign({
1424
- name: input.name,
1425
- isDisabled: isDisabled,
1426
- autoComplete: "nope",
1427
- value: input.value,
1428
- onBlur: input.onBlur,
1429
- onChange: input.onChange,
1430
- onFocus: input.onFocus
1431
- }, 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')));
1432
1612
  });
1433
1613
  });
1434
1614
 
1435
- 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) {
1436
1628
  const {
1437
- Component,
1438
- isDisabled,
1439
- isRequired,
1440
1629
  name,
1441
1630
  initialValue,
1442
- fieldProps = {},
1443
1631
  classNameGroupItem,
1444
- showMessage,
1445
1632
  clearIcon,
1446
1633
  clearIconFill,
1447
1634
  clearIconFillHover,
1448
1635
  clearIconShape,
1449
1636
  clearIconSize,
1450
- onClickClearIcon
1637
+ fieldProps = {},
1638
+ inputProps = {},
1639
+ parse,
1640
+ showMessage,
1641
+ isDisabled,
1642
+ isRequired,
1643
+ onClickClearIcon,
1644
+ onChange
1451
1645
  } = props;
1452
1646
  return /*#__PURE__*/React.createElement(Field, {
1647
+ name: name,
1453
1648
  initialValue: initialValue,
1454
- name: name
1649
+ parse: parse
1455
1650
  }, function Render({
1456
1651
  input,
1457
1652
  meta
@@ -1463,79 +1658,87 @@ const FormFieldCustom = /*#__PURE__*/React.memo(function FormFieldCustom(props)
1463
1658
  * custom React Hook function.
1464
1659
  */
1465
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]);
1466
1667
  const {
1467
- isErrorState,
1468
- isValidState,
1469
1668
  errorKey,
1470
- errorMessage
1669
+ errorMessage,
1670
+ successKey,
1671
+ isErrorState,
1672
+ isValidState
1471
1673
  } = useFieldValidationState({
1472
1674
  fieldProps: fieldProps,
1473
1675
  input: input,
1474
1676
  meta: meta
1475
1677
  });
1476
1678
  const updatedInputProps = useValidationAppearanceInputProps({
1477
- validationStateKey: isErrorState ? errorKey : 'success',
1478
- // For "Custom" field we pass all props. Can contain some special props, we don't known.
1479
- inputProps: props
1679
+ inputProps: inputProps,
1680
+ validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1480
1681
  });
1481
1682
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1482
- className: clsx('form-field_custom', 'form__item_custom', classNameGroupItem),
1683
+ className: clsx('form-field_input', 'form__item_input', classNameGroupItem),
1483
1684
  errorKey: errorKey,
1484
1685
  errorMessage: errorMessage,
1485
- fieldClassName: 'form-custom',
1686
+ fieldClassName: "form-input",
1486
1687
  inputName: input.name,
1487
- inputValue: input.value,
1688
+ inputValue: input.value || '',
1689
+ metaActive: meta.active,
1690
+ metaError: meta.error,
1691
+ showMessage: showMessage,
1488
1692
  isDisabled: isDisabled,
1489
1693
  isErrorState: isErrorState,
1490
1694
  isRequired: isRequired,
1491
- isValidState: isValidState,
1492
- metaActive: meta.active,
1493
- metaError: meta.error,
1494
- showMessage: showMessage
1495
- }, fieldProps), /*#__PURE__*/React.createElement(Component, Object.assign({}, updatedInputProps, {
1496
- 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 || '',
1497
1703
  isDisabled: isDisabled,
1498
- meta: meta
1499
- })), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1704
+ onBlur: input.onBlur,
1705
+ onChange: onChangeField,
1706
+ onFocus: input.onFocus
1707
+ }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1500
1708
  className: "form-field__icon",
1709
+ size: clearIconSize,
1501
1710
  iconFill: clearIconFill,
1502
1711
  iconFillHover: clearIconFillHover,
1503
- imageSrc: clearIcon,
1712
+ imageSrc: typeof clearIcon === 'string' && clearIcon,
1504
1713
  shape: clearIconShape,
1505
- size: clearIconSize,
1506
- SvgImage: clearIcon,
1714
+ SvgImage: typeof clearIcon !== 'string' && clearIcon,
1507
1715
  onClick: onClickClearIcon
1508
1716
  }));
1509
1717
  });
1510
1718
  });
1511
1719
 
1512
- const defaultDatepickerProps = {
1513
- appearance: 'surfacePrimary sizeS',
1514
- dateFormat: 'dd/MM/yyyy - HH:mm',
1515
- readOnly: false,
1516
- selectsRange: false,
1517
- showTimeSelect: true,
1518
- timeCaption: 'Время',
1519
- timeFormat: 'p',
1520
- timeIntervals: 60,
1521
- isClearable: true,
1522
- isStartDefaultNull: true
1523
- };
1524
-
1525
- function FormFieldDatePicker(props) {
1720
+ const FormFieldMaskedInput = /*#__PURE__*/React.memo(function FormFieldMaskedInput(props) {
1526
1721
  const {
1527
1722
  name,
1528
- isDisabled,
1723
+ initialValue,
1529
1724
  classNameGroupItem,
1530
- datePickerProps,
1725
+ clearIcon,
1726
+ clearIconFill,
1727
+ clearIconFillHover,
1728
+ clearIconShape,
1729
+ clearIconSize,
1531
1730
  fieldProps = {},
1532
1731
  inputProps = {},
1732
+ optionsMask,
1533
1733
  showMessage,
1734
+ unmasked,
1735
+ isDisabled,
1534
1736
  isRequired,
1535
- onChange
1737
+ onClickClearIcon
1536
1738
  } = props;
1537
1739
  return /*#__PURE__*/React.createElement(Field, {
1538
- name: name
1740
+ name: name,
1741
+ initialValue: initialValue
1539
1742
  }, function Render({
1540
1743
  input,
1541
1744
  meta
@@ -1547,27 +1750,35 @@ function FormFieldDatePicker(props) {
1547
1750
  * custom React Hook function.
1548
1751
  */
1549
1752
 
1550
- const onChangeField = useCallback((startDate, endDate) => {
1551
- if (!datePickerProps.selectsRange) {
1552
- // When we need to save single date, value is date
1553
- // TODO: make object with one date? need to check all forms with FormFieldDatePicker
1554
- input.onChange(startDate);
1555
- } else {
1556
- // When we need to save range, value is object with two date
1557
- input.onChange({
1558
- endDate,
1559
- startDate
1560
- });
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
+ }
1561
1763
  }
1562
- if (onChange) {
1563
- onChange(startDate, endDate);
1764
+ });
1765
+ useEffect(() => {
1766
+ if (input.value !== unmaskedValue) {
1767
+ setUnmaskedValue(input.value.replace(unmasked, ''));
1564
1768
  }
1565
- }, [input.onChange, onChange]);
1769
+ }, [input.value]);
1770
+
1771
+ // useEffect(() => {
1772
+ // if (unmaskedValue !== input.value) {
1773
+ // input.onChange(unmaskedValue)
1774
+ // }
1775
+ // }, [unmaskedValue])
1776
+
1566
1777
  const {
1567
1778
  errorKey,
1568
1779
  errorMessage,
1569
- isErrorState,
1570
1780
  successKey,
1781
+ isErrorState,
1571
1782
  isValidState
1572
1783
  } = useFieldValidationState({
1573
1784
  fieldProps: fieldProps,
@@ -1579,36 +1790,40 @@ function FormFieldDatePicker(props) {
1579
1790
  validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1580
1791
  });
1581
1792
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1582
- className: clsx('form-field_datepicker', 'form__item_datepicker', classNameGroupItem),
1793
+ className: clsx('form-field-masked-input', 'form__item_masked-input', classNameGroupItem),
1583
1794
  errorKey: errorKey,
1584
1795
  errorMessage: errorMessage,
1585
- isErrorState: isErrorState,
1586
- metaError: meta.error,
1587
- isDisabled: isDisabled,
1588
- fieldClassName: "form-datepicker",
1796
+ fieldClassName: 'form-maskedInput',
1589
1797
  inputName: input.name,
1590
- inputValue: input.value || '',
1798
+ inputValue: input.value,
1591
1799
  metaActive: meta.active,
1800
+ metaError: meta.error,
1592
1801
  showMessage: showMessage,
1802
+ isDisabled: isDisabled,
1803
+ isErrorState: isErrorState,
1593
1804
  isRequired: isRequired,
1594
1805
  isValidState: isValidState
1595
- }, fieldProps), /*#__PURE__*/React.createElement(DatePickerInput, {
1596
- name: input.name,
1597
- isDisabled: isDisabled,
1598
- datePickerProps: datePickerProps,
1599
- endValue: datePickerProps.selectsRange ? input.value.endDate : null,
1600
- inputProps: updatedInputProps,
1601
- 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,
1602
1810
  onBlur: input.onBlur,
1603
- onChange: onChangeField,
1604
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
1605
1821
  }));
1606
1822
  });
1607
- }
1823
+ });
1608
1824
 
1609
- const defaultInputProps = {
1825
+ const defaultPasswordProps = {
1610
1826
  appearance: 'defaultPrimary sizeM solid rounded',
1611
- width: 'fill',
1612
1827
  // useValidationAppearanceInputProps
1613
1828
  // Error
1614
1829
  errorAppearance: 'errorPrimary sizeM solid rounded',
@@ -1618,27 +1833,18 @@ const defaultInputProps = {
1618
1833
  successAppearance: 'successPrimary sizeM solid rounded'
1619
1834
  };
1620
1835
 
1621
- const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1836
+ const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(props) {
1622
1837
  const {
1623
1838
  name,
1624
1839
  initialValue,
1625
- isDisabled,
1626
1840
  classNameGroupItem,
1627
- // dataTestId,
1628
- // iconBorder,
1629
- // iconBorderHover,
1630
- clearIcon,
1631
- clearIconFill,
1632
- clearIconFillHover,
1633
- clearIconShape,
1634
- clearIconSize,
1635
- fieldProps = {},
1636
- inputProps = {},
1841
+ fieldProps,
1842
+ inputProps,
1637
1843
  parse,
1638
1844
  showMessage,
1845
+ isDisabled,
1639
1846
  isRequired,
1640
- onChange,
1641
- onClickClearIcon
1847
+ onChange
1642
1848
  } = props;
1643
1849
  return /*#__PURE__*/React.createElement(Field, {
1644
1850
  name: name,
@@ -1664,8 +1870,8 @@ const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1664
1870
  const {
1665
1871
  errorKey,
1666
1872
  errorMessage,
1667
- isErrorState,
1668
1873
  successKey,
1874
+ isErrorState,
1669
1875
  isValidState
1670
1876
  } = useFieldValidationState({
1671
1877
  fieldProps: fieldProps,
@@ -1677,79 +1883,90 @@ const FormFieldInput = /*#__PURE__*/React.memo(function FormFieldInput(props) {
1677
1883
  validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1678
1884
  });
1679
1885
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1680
- className: clsx('form-field_input', 'form__item_input', classNameGroupItem),
1886
+ className: clsx('form-field_input-password', 'form__item_input-password', classNameGroupItem),
1681
1887
  errorKey: errorKey,
1682
1888
  errorMessage: errorMessage,
1683
- isErrorState: isErrorState,
1684
- metaError: meta.error,
1685
- isDisabled: isDisabled,
1686
- fieldClassName: "form-input",
1889
+ fieldClassName: "form-password",
1687
1890
  inputName: input.name,
1688
1891
  inputValue: input.value || '',
1689
1892
  metaActive: meta.active,
1893
+ metaError: meta.error,
1690
1894
  showMessage: showMessage,
1895
+ isDisabled: isDisabled,
1896
+ isErrorState: isErrorState,
1691
1897
  isRequired: isRequired,
1692
1898
  isValidState: isValidState
1693
- }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1694
- dataTestId: `${input.name}FieldInput`,
1695
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1696
- 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`,
1697
1902
  name: input.name,
1698
- isDisabled: isDisabled,
1699
1903
  autoComplete: "nope",
1700
1904
  value: input.value || '',
1905
+ isDisabled: isDisabled,
1701
1906
  onBlur: input.onBlur,
1702
1907
  onChange: onChangeField,
1703
1908
  onFocus: input.onFocus
1704
- }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
1705
- className: "form-field__icon",
1706
- size: clearIconSize,
1707
- iconFill: clearIconFill,
1708
- iconFillHover: clearIconFillHover,
1709
- imageSrc: typeof clearIcon === 'string' && clearIcon,
1710
- shape: clearIconShape,
1711
- SvgImage: typeof clearIcon !== 'string' && clearIcon,
1712
- onClick: onClickClearIcon
1713
- }));
1909
+ }, updatedInputProps)));
1714
1910
  });
1715
1911
  });
1716
1912
 
1717
- const defaultPasswordProps = {
1718
- appearance: 'sizeM defaultSecondary solid rounded',
1719
- // useValidationAppearanceInputProps
1720
- // Error
1721
- errorAppearance: 'errorPrimary sizeM solid rounded',
1722
- // Required
1723
- iconRevealableHide: icons24.View.HideValue,
1724
- iconRevealableShow: icons24.View.ShowValue,
1725
- requiredAppearance: 'requirePrimary sizeM solid rounded'
1913
+ const defaultRadioProps = {
1914
+ appearance: 'defaultPrimary sizeM solid circular'
1726
1915
  };
1727
1916
 
1728
- 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) {
1729
1956
  const {
1730
1957
  name,
1731
- initialValue,
1732
1958
  isDisabled,
1959
+ editableProps = {},
1960
+ fieldProps = {},
1961
+ inputProps = {},
1962
+ options = [],
1733
1963
  classNameGroupItem,
1734
- fieldProps,
1735
- inputProps,
1736
- parse,
1737
1964
  showMessage,
1738
1965
  isRequired,
1739
1966
  onChange
1740
1967
  } = props;
1741
- const [isRevealed, setIsRevealed] = useState(false);
1742
- const inputType = useMemo(() => {
1743
- return isRevealed ? 'text' : 'password';
1744
- }, [isRevealed]);
1745
- const onClickIconReveal = useCallback(event => {
1746
- event.preventDefault();
1747
- setIsRevealed(prev => !prev);
1748
- }, []);
1749
1968
  return /*#__PURE__*/React.createElement(Field, {
1750
- name: name,
1751
- initialValue: initialValue,
1752
- parse: parse
1969
+ name: name
1753
1970
  }, function Render({
1754
1971
  input,
1755
1972
  meta
@@ -1761,17 +1978,10 @@ const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(pro
1761
1978
  * custom React Hook function.
1762
1979
  */
1763
1980
 
1764
- const onChangeField = useCallback(event => {
1765
- input.onChange(event);
1766
- if (onChange) {
1767
- onChange(event.target.value, input.name);
1768
- }
1769
- }, [onChange, input.onChange]);
1770
1981
  const {
1771
1982
  errorKey,
1772
1983
  errorMessage,
1773
1984
  isErrorState,
1774
- successKey,
1775
1985
  isValidState
1776
1986
  } = useFieldValidationState({
1777
1987
  fieldProps: fieldProps,
@@ -1780,39 +1990,29 @@ const FormFieldPassword = /*#__PURE__*/React.memo(function FormFieldPassword(pro
1780
1990
  });
1781
1991
  const updatedInputProps = useValidationAppearanceInputProps({
1782
1992
  inputProps: inputProps,
1783
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
1993
+ validationStateKey: isErrorState ? errorKey : 'success'
1784
1994
  });
1785
1995
  return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1786
- className: clsx('form-field_input', 'form__item_input', classNameGroupItem),
1996
+ className: clsx('form-field_radio', 'form__item_radio', classNameGroupItem),
1787
1997
  errorKey: errorKey,
1788
1998
  errorMessage: errorMessage,
1789
1999
  isErrorState: isErrorState,
1790
2000
  metaError: meta.error,
1791
2001
  isDisabled: isDisabled,
1792
- fieldClassName: "form-password",
2002
+ fieldClassName: 'form-radio',
1793
2003
  inputName: input.name,
1794
2004
  inputValue: input.value || '',
1795
2005
  metaActive: meta.active,
1796
2006
  showMessage: showMessage,
1797
2007
  isRequired: isRequired,
1798
2008
  isValidState: isValidState
1799
- }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1800
- dataTestId: `${input.name}FieldInputPassword`,
1801
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
1802
- type: inputType,
1803
- name: input.name,
2009
+ }, fieldProps), /*#__PURE__*/React.createElement(FormFieldRadioGroupList, {
1804
2010
  isDisabled: isDisabled,
1805
- autoComplete: "nope",
1806
- value: input.value || '',
1807
- onBlur: input.onBlur,
1808
- onChange: onChangeField,
1809
- onFocus: input.onFocus
1810
- }, updatedInputProps)), /*#__PURE__*/React.createElement(Icon, {
1811
- className: "form-field__icon",
1812
- size: inputProps?.iconSize,
1813
- iconFill: inputProps?.iconFill,
1814
- SvgImage: isRevealed ? inputProps?.iconRevealableHide : inputProps?.iconRevealableShow,
1815
- onClick: onClickIconReveal
2011
+ editableProps: editableProps,
2012
+ input: input,
2013
+ inputProps: updatedInputProps,
2014
+ options: options,
2015
+ onChange: onChange
1816
2016
  }));
1817
2017
  });
1818
2018
  });
@@ -2031,12 +2231,8 @@ const FormFieldSelect = /*#__PURE__*/React.memo(function FormFieldSelect(props)
2031
2231
 
2032
2232
  const defaultSwitchProps = {
2033
2233
  appearance: 'defaultPrimary sizeL solid rounded',
2034
- // useValidationAppearanceInputProps
2035
- // Error
2036
2234
  errorAppearance: 'errorPrimary sizeL solid rounded',
2037
- // Success
2038
2235
  successAppearance: 'successPrimary sizeL solid rounded',
2039
- // Required
2040
2236
  requiredAppearance: 'requirePrimary sizeL solid rounded'
2041
2237
  };
2042
2238
 
@@ -2191,211 +2387,6 @@ const FormFieldTextarea = /*#__PURE__*/React.memo(function FormFieldTextarea(pro
2191
2387
  });
2192
2388
  });
2193
2389
 
2194
- const FormFieldMaskedInput = /*#__PURE__*/React.memo(function FormFieldMaskedInput(props) {
2195
- const {
2196
- name,
2197
- initialValue,
2198
- isDisabled,
2199
- classNameGroupItem,
2200
- clearIcon,
2201
- clearIconFill,
2202
- clearIconFillHover,
2203
- clearIconShape,
2204
- clearIconSize,
2205
- fieldProps = {},
2206
- inputProps = {},
2207
- optionsMask,
2208
- showMessage,
2209
- unmasked,
2210
- isRequired,
2211
- onClickClearIcon
2212
- } = props;
2213
- return /*#__PURE__*/React.createElement(Field, {
2214
- name: name,
2215
- initialValue: initialValue
2216
- }, function Render({
2217
- input,
2218
- meta
2219
- }) {
2220
- /** Note:
2221
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
2222
- * React Hooks cannot be called inside a callback.
2223
- * React Hooks must be called in a React function component or a
2224
- * custom React Hook function.
2225
- */
2226
-
2227
- const {
2228
- ref,
2229
- unmaskedValue,
2230
- value,
2231
- setUnmaskedValue
2232
- } = useIMask(optionsMask, {
2233
- onAccept: (newValue, event, element) => {
2234
- if (element) {
2235
- input.onChange(event._unmaskedValue);
2236
- }
2237
- }
2238
- });
2239
- useEffect(() => {
2240
- if (input.value !== unmaskedValue) {
2241
- setUnmaskedValue(input.value.replace(unmasked, ''));
2242
- }
2243
- }, [input.value]);
2244
- const {
2245
- errorKey,
2246
- errorMessage,
2247
- isErrorState,
2248
- successKey,
2249
- isValidState
2250
- } = useFieldValidationState({
2251
- fieldProps: fieldProps,
2252
- input: input,
2253
- meta: meta
2254
- });
2255
- const updatedInputProps = useValidationAppearanceInputProps({
2256
- inputProps: inputProps,
2257
- validationStateKey: isErrorState ? errorKey : isValidState ? successKey : null
2258
- });
2259
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2260
- className: clsx('form-field-masked-input', 'form__item_masked-input', classNameGroupItem),
2261
- errorKey: errorKey,
2262
- errorMessage: errorMessage,
2263
- isErrorState: isErrorState,
2264
- metaError: meta.error,
2265
- isDisabled: isDisabled,
2266
- fieldClassName: 'form-maskedInput',
2267
- inputName: input.name,
2268
- inputValue: input.value,
2269
- metaActive: meta.active,
2270
- showMessage: showMessage,
2271
- isRequired: isRequired,
2272
- isValidState: isValidState
2273
- }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
2274
- className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && `input_state_${errorKey}`),
2275
- ref: ref,
2276
- value: value,
2277
- onBlur: input.onBlur,
2278
- onFocus: input.onFocus
2279
- }, updatedInputProps)), clearIcon && /*#__PURE__*/React.createElement(Icon, {
2280
- className: "form-field__icon",
2281
- size: clearIconSize,
2282
- iconFill: clearIconFill,
2283
- iconFillHover: clearIconFillHover,
2284
- imageSrc: clearIcon,
2285
- shape: clearIconShape,
2286
- SvgImage: clearIcon,
2287
- onClick: onClickClearIcon
2288
- }));
2289
- });
2290
- });
2291
-
2292
- const defaultRadioProps = {
2293
- appearance: 'defaultPrimary sizeM solid circular'
2294
- };
2295
-
2296
- function RadioGroupList(props) {
2297
- const {
2298
- input,
2299
- inputProps,
2300
- options,
2301
- onChange
2302
- } = props;
2303
-
2304
- // Callback for value changes
2305
- const onChangeSomeInput = useCallback(value => {
2306
- // Save to form values
2307
- input.onChange(value);
2308
- if (onChange) {
2309
- // Pass to custom event
2310
- onChange(value, input.name);
2311
- }
2312
- }, [input, onChange]);
2313
-
2314
- // Handle for radio inputs
2315
- const onChangeRadio = useCallback(event => {
2316
- if (event.target.checked) {
2317
- onChangeSomeInput(event.target.value);
2318
- }
2319
- }, [onChange]);
2320
- return /*#__PURE__*/React.createElement(React.Fragment, null, options.map(option => /*#__PURE__*/React.createElement(Radio, Object.assign({
2321
- className: "form-radio__item",
2322
- key: option.value,
2323
- type: "radio",
2324
- name: input.name,
2325
- label: option.label,
2326
- checked: option.value === input.value,
2327
- value: option.value,
2328
- onBlur: input.onBlur,
2329
- onChange: onChangeRadio,
2330
- onFocus: input.onFocus
2331
- }, inputProps))));
2332
- }
2333
-
2334
- const RadioGroup = /*#__PURE__*/React.memo(function RadioGroup(props) {
2335
- const {
2336
- name,
2337
- isDisabled,
2338
- editableProps = {},
2339
- fieldProps = {},
2340
- inputProps = {},
2341
- options = [],
2342
- classNameGroupItem,
2343
- showMessage,
2344
- isRequired,
2345
- onChange
2346
- } = props;
2347
- return /*#__PURE__*/React.createElement(Field, {
2348
- name: name
2349
- }, function Render({
2350
- input,
2351
- meta
2352
- }) {
2353
- /** Note:
2354
- * Create "Render" function by "eslint-react-hooks/rules-of-hooks":
2355
- * React Hooks cannot be called inside a callback.
2356
- * React Hooks must be called in a React function component or a
2357
- * custom React Hook function.
2358
- */
2359
-
2360
- const {
2361
- errorKey,
2362
- errorMessage,
2363
- isErrorState,
2364
- isValidState
2365
- } = useFieldValidationState({
2366
- fieldProps: fieldProps,
2367
- input: input,
2368
- meta: meta
2369
- });
2370
- const updatedInputProps = useValidationAppearanceInputProps({
2371
- inputProps: inputProps,
2372
- validationStateKey: isErrorState ? errorKey : 'success'
2373
- });
2374
- return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
2375
- className: clsx('form-field_radio', 'form__item_radio', classNameGroupItem),
2376
- errorKey: errorKey,
2377
- errorMessage: errorMessage,
2378
- isErrorState: isErrorState,
2379
- metaError: meta.error,
2380
- isDisabled: isDisabled,
2381
- fieldClassName: 'form-radio',
2382
- inputName: input.name,
2383
- inputValue: input.value || '',
2384
- metaActive: meta.active,
2385
- showMessage: showMessage,
2386
- isRequired: isRequired,
2387
- isValidState: isValidState
2388
- }, fieldProps), /*#__PURE__*/React.createElement(RadioGroupList, {
2389
- isDisabled: isDisabled,
2390
- editableProps: editableProps,
2391
- input: input,
2392
- inputProps: updatedInputProps,
2393
- options: options,
2394
- onChange: onChange
2395
- }));
2396
- });
2397
- });
2398
-
2399
2390
  const formTypes = {
2400
2391
  password: 'password',
2401
2392
  code: 'code',
@@ -2467,13 +2458,13 @@ function generateField(field, config, props) {
2467
2458
  }
2468
2459
  case formTypes.fileInput:
2469
2460
  {
2470
- return /*#__PURE__*/React.createElement(FileInput, Object.assign({
2461
+ return /*#__PURE__*/React.createElement(FormFieldFileInput, Object.assign({
2471
2462
  key: config.key
2472
2463
  }, field, props));
2473
2464
  }
2474
2465
  case formTypes.radioGroup:
2475
2466
  {
2476
- return /*#__PURE__*/React.createElement(RadioGroup, Object.assign({
2467
+ return /*#__PURE__*/React.createElement(FormFieldRadioGroup, Object.assign({
2477
2468
  key: config.key
2478
2469
  }, field, props));
2479
2470
  }
@@ -3126,4 +3117,4 @@ const getErrorsForFinalForm = error => {
3126
3117
  return formErrors;
3127
3118
  };
3128
3119
 
3129
- 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 };