@itcase/forms 1.1.47 → 1.1.49

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.
@@ -1019,10 +1019,10 @@ const defaultDropzoneProps = {
1019
1019
 
1020
1020
  const FileInputDropzone = /*#__PURE__*/React__default.default.memo(function FileInputDropzone(props) {
1021
1021
  const {
1022
- className,
1022
+ // className, unused
1023
1023
  maxFiles,
1024
1024
  maxSize,
1025
- size,
1025
+ // size, unused
1026
1026
  fileErrorText,
1027
1027
  dropzoneProps = {},
1028
1028
  hintDescription,
@@ -1043,7 +1043,28 @@ const FileInputDropzone = /*#__PURE__*/React__default.default.memo(function File
1043
1043
  } = reactFinalForm.useForm();
1044
1044
  const [fileError, setFileError] = React.useState('');
1045
1045
  const [fileIsLoading, setFileIsLoading] = React.useState(false);
1046
- const filesList = React.useMemo(() => inputValue ? castArray__default.default(inputValue) : [], [inputValue]);
1046
+ const prevFilesListRef = React.useRef(null);
1047
+ const filesList = React.useMemo(() => {
1048
+ const newFilesList = inputValue ? castArray__default.default(inputValue) : [];
1049
+ if (prevFilesListRef.current === null) {
1050
+ prevFilesListRef.current = newFilesList;
1051
+ return newFilesList;
1052
+ }
1053
+ // keep track of previous state and revoke unused object urls
1054
+ prevFilesListRef.current.forEach(prevFile => {
1055
+ if (!prevFile.preview) {
1056
+ return;
1057
+ }
1058
+ const isFileDeleted = !newFilesList.some(newFile => {
1059
+ return newFile.preview === prevFile.preview;
1060
+ });
1061
+ if (isFileDeleted) {
1062
+ URL.revokeObjectURL(prevFile.preview);
1063
+ }
1064
+ });
1065
+ prevFilesListRef.current = newFilesList;
1066
+ return newFilesList;
1067
+ }, [inputValue]);
1047
1068
  const changeFormState = React.useCallback(newFiles => {
1048
1069
  // If max files in dropzone is 1 - return file as it self, else as array of files
1049
1070
  // ps: for old projects compatibility
@@ -1109,7 +1130,7 @@ const FileInputDropzone = /*#__PURE__*/React__default.default.memo(function File
1109
1130
  if (isPreviews) {
1110
1131
  // Add preview to every file
1111
1132
  acceptedFiles.forEach(file => {
1112
- if (!file.error) {
1133
+ if (!file.error && !file.preview) {
1113
1134
  file.preview = URL.createObjectURL(file);
1114
1135
  }
1115
1136
  });
@@ -1156,17 +1177,18 @@ const FileInputDropzone = /*#__PURE__*/React__default.default.memo(function File
1156
1177
  // First time convert value to Files and save to local and form state
1157
1178
  convertFiledValueAndSaveAsFiles(currentFilesList);
1158
1179
  }
1159
-
1180
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1181
+ }, [inputValue]);
1182
+ React.useEffect(() => {
1160
1183
  // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
1161
1184
  return () => {
1162
- filesList.forEach(file => {
1163
- if (file?.preview) {
1185
+ prevFilesListRef.current.forEach(file => {
1186
+ if (file.preview) {
1164
1187
  URL.revokeObjectURL(file.preview);
1165
1188
  }
1166
1189
  });
1167
1190
  };
1168
- // eslint-disable-next-line react-hooks/exhaustive-deps
1169
- }, [inputValue]);
1191
+ }, []);
1170
1192
  const propsGenerator = useDevicePropsGenerator.useDevicePropsGenerator(props);
1171
1193
  const {
1172
1194
  fillClass,
@@ -1218,10 +1240,6 @@ const FileInputDropzone = /*#__PURE__*/React__default.default.memo(function File
1218
1240
  src: file.preview || file.image,
1219
1241
  onClick: event => {
1220
1242
  onClickPreview && onClickPreview(file, event);
1221
- },
1222
- onLoad: () => {
1223
- // Revoke data uri after image is loaded
1224
- URL.revokeObjectURL(file.preview);
1225
1243
  }
1226
1244
  })), file.error && /*#__PURE__*/React__default.default.createElement("div", null, /*#__PURE__*/React__default.default.createElement(Text.Text, {
1227
1245
  size: thumbNameTextSize,
@@ -2777,6 +2795,7 @@ const FinalForm = /*#__PURE__*/React__default.default.forwardRef(function FinalF
2777
2795
  fieldsGap,
2778
2796
  formName,
2779
2797
  groupGap,
2798
+ heightClass,
2780
2799
  language,
2781
2800
  loader,
2782
2801
  loaderAppearance,
@@ -2821,6 +2840,7 @@ const FinalForm = /*#__PURE__*/React__default.default.forwardRef(function FinalF
2821
2840
  tertiaryButtonLabelTextColor,
2822
2841
  tertiaryButtonLabelTextWeight,
2823
2842
  tertiaryButtonSize,
2843
+ widthClass,
2824
2844
  before,
2825
2845
  after,
2826
2846
  isLoading,
@@ -2856,7 +2876,7 @@ const FinalForm = /*#__PURE__*/React__default.default.forwardRef(function FinalF
2856
2876
  submitError
2857
2877
  }) => {
2858
2878
  return /*#__PURE__*/React__default.default.createElement("form", {
2859
- className: clsx__default.default(className, 'form', type && `form_type_${type}`, titlePosition && `form_title-position_${titlePosition}`, buttonPosition && `form_button-position_${buttonPosition}`, directionClass && `direction_${directionClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, elevationClass && `elevation_${elevationClass}`),
2879
+ className: clsx__default.default(className, 'form', type && `form_type_${type}`, widthClass && `width_${widthClass}`, heightClass && `height_${heightClass}`, titlePosition && `form_title-position_${titlePosition}`, buttonPosition && `form_button-position_${buttonPosition}`, directionClass && `direction_${directionClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, elevationClass && `elevation_${elevationClass}`),
2860
2880
  name: formName
2861
2881
  // We no need set reference to html element, we need reference to "final-form" instance
2862
2882
  ,
@@ -1,5 +1,5 @@
1
1
  import { isPossiblePhoneNumber } from 'libphonenumber-js';
2
- import React, { useMemo, useEffect, useCallback, useState } from 'react';
2
+ import React, { useMemo, useEffect, useCallback, useState, useRef } from 'react';
3
3
  import { setIn, FORM_ERROR, getIn } from 'final-form';
4
4
  import { useForm, Field, Form, FormSpy } from 'react-final-form';
5
5
  export { Field, useForm, useFormState } from 'react-final-form';
@@ -1008,10 +1008,10 @@ const defaultDropzoneProps = {
1008
1008
 
1009
1009
  const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(props) {
1010
1010
  const {
1011
- className,
1011
+ // className, unused
1012
1012
  maxFiles,
1013
1013
  maxSize,
1014
- size,
1014
+ // size, unused
1015
1015
  fileErrorText,
1016
1016
  dropzoneProps = {},
1017
1017
  hintDescription,
@@ -1032,7 +1032,28 @@ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(pro
1032
1032
  } = useForm();
1033
1033
  const [fileError, setFileError] = useState('');
1034
1034
  const [fileIsLoading, setFileIsLoading] = useState(false);
1035
- const filesList = useMemo(() => inputValue ? castArray(inputValue) : [], [inputValue]);
1035
+ const prevFilesListRef = useRef(null);
1036
+ const filesList = useMemo(() => {
1037
+ const newFilesList = inputValue ? castArray(inputValue) : [];
1038
+ if (prevFilesListRef.current === null) {
1039
+ prevFilesListRef.current = newFilesList;
1040
+ return newFilesList;
1041
+ }
1042
+ // keep track of previous state and revoke unused object urls
1043
+ prevFilesListRef.current.forEach(prevFile => {
1044
+ if (!prevFile.preview) {
1045
+ return;
1046
+ }
1047
+ const isFileDeleted = !newFilesList.some(newFile => {
1048
+ return newFile.preview === prevFile.preview;
1049
+ });
1050
+ if (isFileDeleted) {
1051
+ URL.revokeObjectURL(prevFile.preview);
1052
+ }
1053
+ });
1054
+ prevFilesListRef.current = newFilesList;
1055
+ return newFilesList;
1056
+ }, [inputValue]);
1036
1057
  const changeFormState = useCallback(newFiles => {
1037
1058
  // If max files in dropzone is 1 - return file as it self, else as array of files
1038
1059
  // ps: for old projects compatibility
@@ -1098,7 +1119,7 @@ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(pro
1098
1119
  if (isPreviews) {
1099
1120
  // Add preview to every file
1100
1121
  acceptedFiles.forEach(file => {
1101
- if (!file.error) {
1122
+ if (!file.error && !file.preview) {
1102
1123
  file.preview = URL.createObjectURL(file);
1103
1124
  }
1104
1125
  });
@@ -1145,17 +1166,18 @@ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(pro
1145
1166
  // First time convert value to Files and save to local and form state
1146
1167
  convertFiledValueAndSaveAsFiles(currentFilesList);
1147
1168
  }
1148
-
1169
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1170
+ }, [inputValue]);
1171
+ useEffect(() => {
1149
1172
  // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
1150
1173
  return () => {
1151
- filesList.forEach(file => {
1152
- if (file?.preview) {
1174
+ prevFilesListRef.current.forEach(file => {
1175
+ if (file.preview) {
1153
1176
  URL.revokeObjectURL(file.preview);
1154
1177
  }
1155
1178
  });
1156
1179
  };
1157
- // eslint-disable-next-line react-hooks/exhaustive-deps
1158
- }, [inputValue]);
1180
+ }, []);
1159
1181
  const propsGenerator = useDevicePropsGenerator(props);
1160
1182
  const {
1161
1183
  fillClass,
@@ -1207,10 +1229,6 @@ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(pro
1207
1229
  src: file.preview || file.image,
1208
1230
  onClick: event => {
1209
1231
  onClickPreview && onClickPreview(file, event);
1210
- },
1211
- onLoad: () => {
1212
- // Revoke data uri after image is loaded
1213
- URL.revokeObjectURL(file.preview);
1214
1232
  }
1215
1233
  })), file.error && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Text, {
1216
1234
  size: thumbNameTextSize,
@@ -2766,6 +2784,7 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2766
2784
  fieldsGap,
2767
2785
  formName,
2768
2786
  groupGap,
2787
+ heightClass,
2769
2788
  language,
2770
2789
  loader,
2771
2790
  loaderAppearance,
@@ -2810,6 +2829,7 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2810
2829
  tertiaryButtonLabelTextColor,
2811
2830
  tertiaryButtonLabelTextWeight,
2812
2831
  tertiaryButtonSize,
2832
+ widthClass,
2813
2833
  before,
2814
2834
  after,
2815
2835
  isLoading,
@@ -2845,7 +2865,7 @@ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2845
2865
  submitError
2846
2866
  }) => {
2847
2867
  return /*#__PURE__*/React.createElement("form", {
2848
- className: clsx(className, 'form', type && `form_type_${type}`, titlePosition && `form_title-position_${titlePosition}`, buttonPosition && `form_button-position_${buttonPosition}`, directionClass && `direction_${directionClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, elevationClass && `elevation_${elevationClass}`),
2868
+ className: clsx(className, 'form', type && `form_type_${type}`, widthClass && `width_${widthClass}`, heightClass && `height_${heightClass}`, titlePosition && `form_title-position_${titlePosition}`, buttonPosition && `form_button-position_${buttonPosition}`, directionClass && `direction_${directionClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, elevationClass && `elevation_${elevationClass}`),
2849
2869
  name: formName
2850
2870
  // We no need set reference to html element, we need reference to "final-form" instance
2851
2871
  ,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itcase/forms",
3
- "version": "1.1.47",
3
+ "version": "1.1.49",
4
4
  "description": "Forms fields, inputs, etc.",
5
5
  "keywords": [],
6
6
  "license": "MIT",