@itcase/forms 1.1.24 → 1.1.27

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