@uploadcare/file-uploader 1.15.0-alpha.2 → 1.15.0-alpha.20

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.
Files changed (293) hide show
  1. package/abstract/ActivityBlock.d.ts +5 -5
  2. package/abstract/ActivityBlock.d.ts.map +1 -1
  3. package/abstract/Block.d.ts +3 -9
  4. package/abstract/Block.d.ts.map +1 -1
  5. package/abstract/Block.js +1 -1
  6. package/abstract/CTX.d.ts +6 -6
  7. package/abstract/CTX.d.ts.map +1 -1
  8. package/abstract/LocaleManager.d.ts +3 -3
  9. package/abstract/LocaleManager.d.ts.map +1 -1
  10. package/abstract/ModalManager.d.ts +26 -17
  11. package/abstract/ModalManager.d.ts.map +1 -1
  12. package/abstract/ModalManager.js +32 -18
  13. package/abstract/SecureUploadsManager.d.ts +2 -2
  14. package/abstract/SecureUploadsManager.d.ts.map +1 -1
  15. package/abstract/SolutionBlock.d.ts +2 -2
  16. package/abstract/SolutionBlock.d.ts.map +1 -1
  17. package/abstract/TypedCollection.d.ts +44 -44
  18. package/abstract/TypedCollection.d.ts.map +1 -1
  19. package/abstract/TypedCollection.js +53 -33
  20. package/abstract/TypedData.d.ts +71 -25
  21. package/abstract/TypedData.d.ts.map +1 -1
  22. package/abstract/TypedData.js +74 -17
  23. package/abstract/UploaderBlock.d.ts +10 -10
  24. package/abstract/UploaderBlock.d.ts.map +1 -1
  25. package/abstract/UploaderBlock.js +23 -11
  26. package/abstract/UploaderPublicApi.d.ts +24 -23
  27. package/abstract/UploaderPublicApi.d.ts.map +1 -1
  28. package/abstract/UploaderPublicApi.js +21 -10
  29. package/abstract/ValidationManager.d.ts +125 -6
  30. package/abstract/ValidationManager.d.ts.map +1 -1
  31. package/abstract/ValidationManager.js +1 -1
  32. package/abstract/a11y.d.ts +2 -2
  33. package/abstract/a11y.d.ts.map +1 -1
  34. package/abstract/buildOutputCollectionState.d.ts +1 -1
  35. package/abstract/buildOutputCollectionState.d.ts.map +1 -1
  36. package/abstract/defineComponents.d.ts.map +1 -1
  37. package/abstract/l10nProcessor.d.ts.map +1 -1
  38. package/abstract/loadFileUploaderFrom.d.ts +1 -1
  39. package/abstract/loadFileUploaderFrom.d.ts.map +1 -1
  40. package/abstract/localeRegistry.d.ts.map +1 -1
  41. package/abstract/sharedConfigKey.d.ts.map +1 -1
  42. package/abstract/uploadEntrySchema.d.ts +123 -63
  43. package/abstract/uploadEntrySchema.d.ts.map +1 -1
  44. package/abstract/uploadEntrySchema.js +66 -81
  45. package/blocks/CameraSource/CameraSource.d.ts +9 -9
  46. package/blocks/CameraSource/CameraSource.d.ts.map +1 -1
  47. package/blocks/CameraSource/calcCameraModes.d.ts +1 -1
  48. package/blocks/CameraSource/constants.d.ts.map +1 -1
  49. package/blocks/CloudImageEditor/src/CloudImageEditorBlock.d.ts.map +1 -1
  50. package/blocks/CloudImageEditor/src/CropFrame.d.ts +1 -1
  51. package/blocks/CloudImageEditor/src/EditorFilterControl.js +1 -1
  52. package/blocks/CloudImageEditor/src/EditorImageCropper.d.ts +3 -3
  53. package/blocks/CloudImageEditor/src/EditorImageCropper.js +1 -1
  54. package/blocks/CloudImageEditor/src/EditorImageFader.d.ts +1 -1
  55. package/blocks/CloudImageEditor/src/EditorImageFader.d.ts.map +1 -1
  56. package/blocks/CloudImageEditor/src/EditorImageFader.js +1 -1
  57. package/blocks/CloudImageEditor/src/EditorSlider.d.ts +1 -1
  58. package/blocks/CloudImageEditor/src/EditorSlider.d.ts.map +1 -1
  59. package/blocks/CloudImageEditor/src/EditorToolbar.d.ts +1 -1
  60. package/blocks/CloudImageEditor/src/EditorToolbar.js +1 -1
  61. package/blocks/CloudImageEditor/src/crop-utils.d.ts +14 -14
  62. package/blocks/CloudImageEditor/src/crop-utils.d.ts.map +1 -1
  63. package/blocks/CloudImageEditor/src/cropper-constants.d.ts.map +1 -1
  64. package/blocks/CloudImageEditor/src/lib/applyFocusVisiblePolyfill.d.ts +1 -1
  65. package/blocks/CloudImageEditor/src/lib/applyFocusVisiblePolyfill.d.ts.map +1 -1
  66. package/blocks/CloudImageEditor/src/lib/parseCropPreset.d.ts +1 -1
  67. package/blocks/CloudImageEditor/src/lib/transformationUtils.d.ts +3 -3
  68. package/blocks/CloudImageEditor/src/lib/transformationUtils.d.ts.map +1 -1
  69. package/blocks/CloudImageEditor/src/state.d.ts +4 -4
  70. package/blocks/CloudImageEditor/src/svg-sprite.d.ts.map +1 -1
  71. package/blocks/CloudImageEditor/src/types.d.ts +8 -58
  72. package/blocks/CloudImageEditor/src/types.d.ts.map +1 -1
  73. package/blocks/CloudImageEditorActivity/CloudImageEditorActivity.d.ts +5 -2
  74. package/blocks/CloudImageEditorActivity/CloudImageEditorActivity.d.ts.map +1 -1
  75. package/blocks/CloudImageEditorActivity/CloudImageEditorActivity.js +7 -3
  76. package/blocks/Config/Config.d.ts +3 -12
  77. package/blocks/Config/Config.d.ts.map +1 -1
  78. package/blocks/Config/assertions.d.ts +1 -1
  79. package/blocks/Config/initialConfig.d.ts +1 -1
  80. package/blocks/Config/initialConfig.d.ts.map +1 -1
  81. package/blocks/Config/initialConfig.js +4 -4
  82. package/blocks/Config/normalizeConfigValue.d.ts +2 -1
  83. package/blocks/Config/normalizeConfigValue.d.ts.map +1 -1
  84. package/blocks/Config/normalizeConfigValue.js +18 -109
  85. package/blocks/Config/side-effects.d.ts.map +1 -1
  86. package/blocks/Config/validatorsType.d.ts +37 -0
  87. package/blocks/Config/validatorsType.d.ts.map +1 -0
  88. package/blocks/Config/validatorsType.js +134 -0
  89. package/blocks/DropArea/DropArea.d.ts +3 -2
  90. package/blocks/DropArea/DropArea.d.ts.map +1 -1
  91. package/blocks/DropArea/DropArea.js +20 -2
  92. package/blocks/DropArea/addDropzone.d.ts.map +1 -1
  93. package/blocks/DropArea/drop-area.css +4 -2
  94. package/blocks/DropArea/getDropItems.d.ts +2 -2
  95. package/blocks/DropArea/getDropItems.d.ts.map +1 -1
  96. package/blocks/ExternalSource/ExternalSource.d.ts +3 -3
  97. package/blocks/ExternalSource/ExternalSource.d.ts.map +1 -1
  98. package/blocks/ExternalSource/ExternalSource.js +0 -1
  99. package/blocks/ExternalSource/MessageBridge.d.ts +3 -3
  100. package/blocks/ExternalSource/MessageBridge.d.ts.map +1 -1
  101. package/blocks/ExternalSource/query-string.d.ts.map +1 -1
  102. package/blocks/ExternalSource/types.d.ts +64 -64
  103. package/blocks/ExternalSource/types.d.ts.map +1 -1
  104. package/blocks/FileItem/FileItem.d.ts +13 -40
  105. package/blocks/FileItem/FileItem.d.ts.map +1 -1
  106. package/blocks/FileItem/FileItem.js +126 -179
  107. package/blocks/FileItem/FileItemConfig.d.ts +28 -0
  108. package/blocks/FileItem/FileItemConfig.d.ts.map +1 -0
  109. package/blocks/FileItem/FileItemConfig.js +74 -0
  110. package/blocks/FileItem/file-item.css +39 -0
  111. package/blocks/Img/ImgBase.d.ts +3 -3
  112. package/blocks/Img/ImgBase.d.ts.map +1 -1
  113. package/blocks/Img/ImgBase.js +9 -9
  114. package/blocks/Img/ImgConfig.d.ts.map +1 -1
  115. package/blocks/Img/configurations.d.ts.map +1 -1
  116. package/blocks/Modal/Modal.d.ts +21 -2
  117. package/blocks/Modal/Modal.d.ts.map +1 -1
  118. package/blocks/Modal/Modal.js +37 -18
  119. package/blocks/ProgressBar/ProgressBar.d.ts +6 -1
  120. package/blocks/ProgressBar/ProgressBar.d.ts.map +1 -1
  121. package/blocks/ProgressBar/ProgressBar.js +41 -44
  122. package/blocks/ProgressBar/progress-bar.css +9 -6
  123. package/blocks/Range/Range.d.ts.map +1 -1
  124. package/blocks/SimpleBtn/SimpleBtn.d.ts +2 -2
  125. package/blocks/SimpleBtn/SimpleBtn.d.ts.map +1 -1
  126. package/blocks/SimpleBtn/SimpleBtn.js +1 -1
  127. package/blocks/SourceBtn/SourceBtn.d.ts +2 -5
  128. package/blocks/SourceBtn/SourceBtn.d.ts.map +1 -1
  129. package/blocks/SourceBtn/SourceBtn.js +5 -5
  130. package/blocks/SourceList/SourceList.js +2 -2
  131. package/blocks/Spinner/Spinner.d.ts.map +1 -1
  132. package/blocks/Thumb/Thumb.d.ts +51 -0
  133. package/blocks/Thumb/Thumb.d.ts.map +1 -0
  134. package/blocks/Thumb/Thumb.js +220 -0
  135. package/blocks/Thumb/thumb.css +4 -0
  136. package/blocks/UploadCtxProvider/EventEmitter.d.ts +20 -20
  137. package/blocks/UploadCtxProvider/EventEmitter.d.ts.map +1 -1
  138. package/blocks/UploadCtxProvider/UploadCtxProvider.d.ts +4 -4
  139. package/blocks/UploadCtxProvider/UploadCtxProvider.d.ts.map +1 -1
  140. package/blocks/UploadList/UploadList.d.ts +4 -2
  141. package/blocks/UploadList/UploadList.d.ts.map +1 -1
  142. package/blocks/UploadList/UploadList.js +3 -1
  143. package/blocks/svg-backgrounds/svg-backgrounds.d.ts +3 -3
  144. package/blocks/svg-backgrounds/svg-backgrounds.d.ts.map +1 -1
  145. package/blocks/themes/uc-basic/common.css +1 -1
  146. package/blocks/themes/uc-basic/index.css +1 -0
  147. package/blocks/themes/uc-basic/svg-sprite.d.ts.map +1 -1
  148. package/blocks/utils/UploadSource.d.ts.map +1 -1
  149. package/blocks/utils/debounce.d.ts +3 -1
  150. package/blocks/utils/debounce.d.ts.map +1 -1
  151. package/blocks/{CloudImageEditor/src/lib → utils}/preloadImage.js +1 -1
  152. package/blocks/utils/resizeImage.d.ts +1 -1
  153. package/blocks/utils/resizeImage.d.ts.map +1 -1
  154. package/blocks/utils/throttle.d.ts +3 -1
  155. package/blocks/utils/throttle.d.ts.map +1 -1
  156. package/blocks/utils/userAgent.d.ts +1 -1
  157. package/blocks/utils/userAgent.d.ts.map +1 -1
  158. package/env.d.ts.map +1 -1
  159. package/index.d.ts +2 -0
  160. package/index.js +2 -0
  161. package/index.ssr.d.ts +59 -0
  162. package/index.ssr.d.ts.map +1 -1
  163. package/index.ssr.js +79 -13
  164. package/locales/file-uploader/ar.d.ts +1 -0
  165. package/locales/file-uploader/ar.js +1 -0
  166. package/locales/file-uploader/az.d.ts +1 -0
  167. package/locales/file-uploader/az.js +1 -0
  168. package/locales/file-uploader/ca.d.ts +1 -0
  169. package/locales/file-uploader/ca.js +1 -0
  170. package/locales/file-uploader/cs.d.ts +1 -0
  171. package/locales/file-uploader/cs.js +1 -0
  172. package/locales/file-uploader/da.d.ts +1 -0
  173. package/locales/file-uploader/da.js +1 -0
  174. package/locales/file-uploader/de.d.ts +1 -0
  175. package/locales/file-uploader/de.js +1 -0
  176. package/locales/file-uploader/el.d.ts +1 -0
  177. package/locales/file-uploader/el.js +1 -0
  178. package/locales/file-uploader/en.d.ts +1 -0
  179. package/locales/file-uploader/en.js +1 -0
  180. package/locales/file-uploader/es.d.ts +1 -0
  181. package/locales/file-uploader/es.js +1 -0
  182. package/locales/file-uploader/et.d.ts +1 -0
  183. package/locales/file-uploader/et.js +1 -0
  184. package/locales/file-uploader/fi.d.ts +1 -0
  185. package/locales/file-uploader/fi.js +1 -0
  186. package/locales/file-uploader/fr.d.ts +1 -0
  187. package/locales/file-uploader/fr.js +1 -0
  188. package/locales/file-uploader/he.d.ts +1 -0
  189. package/locales/file-uploader/he.js +1 -0
  190. package/locales/file-uploader/hy.d.ts +1 -0
  191. package/locales/file-uploader/hy.js +1 -0
  192. package/locales/file-uploader/is.d.ts +1 -0
  193. package/locales/file-uploader/is.js +1 -0
  194. package/locales/file-uploader/it.d.ts +1 -0
  195. package/locales/file-uploader/it.js +1 -0
  196. package/locales/file-uploader/ja.d.ts +1 -0
  197. package/locales/file-uploader/ja.js +1 -0
  198. package/locales/file-uploader/ka.d.ts +1 -0
  199. package/locales/file-uploader/ka.js +1 -0
  200. package/locales/file-uploader/kk.d.ts +1 -0
  201. package/locales/file-uploader/kk.js +1 -0
  202. package/locales/file-uploader/ko.d.ts +1 -0
  203. package/locales/file-uploader/ko.js +1 -0
  204. package/locales/file-uploader/lv.d.ts +1 -0
  205. package/locales/file-uploader/lv.js +1 -0
  206. package/locales/file-uploader/nb.d.ts +1 -0
  207. package/locales/file-uploader/nb.js +1 -0
  208. package/locales/file-uploader/nl.d.ts +1 -0
  209. package/locales/file-uploader/nl.js +1 -0
  210. package/locales/file-uploader/pl.d.ts +1 -0
  211. package/locales/file-uploader/pl.js +1 -0
  212. package/locales/file-uploader/pt.d.ts +1 -0
  213. package/locales/file-uploader/pt.js +1 -0
  214. package/locales/file-uploader/ro.d.ts +1 -0
  215. package/locales/file-uploader/ro.js +1 -0
  216. package/locales/file-uploader/ru.d.ts +1 -0
  217. package/locales/file-uploader/ru.js +1 -0
  218. package/locales/file-uploader/sk.d.ts +1 -0
  219. package/locales/file-uploader/sk.js +1 -0
  220. package/locales/file-uploader/sr.d.ts +1 -0
  221. package/locales/file-uploader/sr.js +1 -0
  222. package/locales/file-uploader/sv.d.ts +1 -0
  223. package/locales/file-uploader/sv.js +1 -0
  224. package/locales/file-uploader/tr.d.ts +1 -0
  225. package/locales/file-uploader/tr.js +1 -0
  226. package/locales/file-uploader/uk.d.ts +1 -0
  227. package/locales/file-uploader/uk.js +1 -0
  228. package/locales/file-uploader/vi.d.ts +1 -0
  229. package/locales/file-uploader/vi.js +1 -0
  230. package/locales/file-uploader/zh-TW.d.ts +1 -0
  231. package/locales/file-uploader/zh-TW.js +1 -0
  232. package/locales/file-uploader/zh.d.ts +1 -0
  233. package/locales/file-uploader/zh.js +1 -0
  234. package/package.json +6 -5
  235. package/solutions/file-uploader/inline/FileUploaderInline.d.ts +2 -2
  236. package/solutions/file-uploader/inline/FileUploaderInline.d.ts.map +1 -1
  237. package/solutions/file-uploader/minimal/FileUploaderMinimal.d.ts +21 -2
  238. package/solutions/file-uploader/minimal/FileUploaderMinimal.d.ts.map +1 -1
  239. package/solutions/file-uploader/minimal/FileUploaderMinimal.js +102 -23
  240. package/solutions/file-uploader/minimal/index.css +11 -28
  241. package/solutions/file-uploader/minimal/index.d.ts +1 -16
  242. package/solutions/file-uploader/minimal/index.js +1 -18
  243. package/solutions/file-uploader/regular/FileUploaderRegular.d.ts +3 -5
  244. package/solutions/file-uploader/regular/FileUploaderRegular.d.ts.map +1 -1
  245. package/solutions/file-uploader/regular/FileUploaderRegular.js +1 -15
  246. package/types/exported.d.ts +4 -3
  247. package/types/jsx.d.ts +1 -1
  248. package/utils/browser-info.d.ts +13 -0
  249. package/utils/browser-info.d.ts.map +1 -0
  250. package/utils/browser-info.js +22 -0
  251. package/utils/browser-info.test.d.ts +2 -0
  252. package/utils/browser-info.test.d.ts.map +1 -0
  253. package/utils/browser-info.test.js +109 -0
  254. package/utils/cdn-utils.d.ts +3 -3
  255. package/utils/cdn-utils.d.ts.map +1 -1
  256. package/utils/fileTypes.d.ts +5 -1
  257. package/utils/fileTypes.d.ts.map +1 -1
  258. package/utils/fileTypes.js +18 -2
  259. package/utils/getPluralForm.d.ts.map +1 -1
  260. package/utils/isSecureTokenExpired.d.ts +1 -1
  261. package/utils/memoize.d.ts.map +1 -1
  262. package/utils/mixinClass.d.ts +3 -1
  263. package/utils/mixinClass.d.ts.map +1 -1
  264. package/utils/prettyBytes.d.ts.map +1 -1
  265. package/utils/template-utils.d.ts +1 -1
  266. package/utils/template-utils.d.ts.map +1 -1
  267. package/utils/toKebabCase.d.ts.map +1 -1
  268. package/utils/transparentPixelSrc.d.ts.map +1 -1
  269. package/utils/uniqueArray.d.ts.map +1 -1
  270. package/utils/validators/collection/validateCollectionUploadError.d.ts +1 -1
  271. package/utils/validators/collection/validateMultiple.d.ts +1 -1
  272. package/utils/validators/file/validateFileType.d.ts +1 -1
  273. package/utils/validators/file/validateIsImage.d.ts +1 -1
  274. package/utils/validators/file/validateMaxSizeLimit.d.ts +1 -1
  275. package/utils/validators/file/validateUploadError.d.ts +1 -1
  276. package/utils/waitForAttribute.d.ts +1 -1
  277. package/utils/waitForAttribute.d.ts.map +1 -1
  278. package/web/file-uploader.iife.min.js +4 -4
  279. package/web/file-uploader.min.js +4 -4
  280. package/web/uc-basic.min.css +1 -1
  281. package/web/uc-cloud-image-editor.min.js +4 -4
  282. package/web/uc-file-uploader-inline.min.css +1 -1
  283. package/web/uc-file-uploader-inline.min.js +4 -4
  284. package/web/uc-file-uploader-minimal.min.css +1 -1
  285. package/web/uc-file-uploader-minimal.min.js +4 -4
  286. package/web/uc-file-uploader-regular.min.css +1 -1
  287. package/web/uc-file-uploader-regular.min.js +4 -4
  288. package/web/uc-img.min.js +1 -1
  289. package/blocks/utils/supportCapture.d.ts +0 -2
  290. package/blocks/utils/supportCapture.d.ts.map +0 -1
  291. package/blocks/utils/supportCapture.js +0 -3
  292. /package/blocks/{CloudImageEditor/src/lib → utils}/preloadImage.d.ts +0 -0
  293. /package/blocks/{CloudImageEditor/src/lib → utils}/preloadImage.d.ts.map +0 -0
@@ -1,15 +1,12 @@
1
1
  // @ts-check
2
- import { CancelError, uploadFile } from '@uploadcare/upload-client';
3
2
  import { shrinkFile } from '@uploadcare/image-shrink';
3
+ import { CancelError, UploadcareError, uploadFile } from '@uploadcare/upload-client';
4
4
  import { ActivityBlock } from '../../abstract/ActivityBlock.js';
5
- import { UploaderBlock } from '../../abstract/UploaderBlock.js';
6
- import { createCdnUrl, createCdnUrlModifiers, createOriginalUrl } from '../../utils/cdn-utils.js';
7
- import { fileCssBg } from '../svg-backgrounds/svg-backgrounds.js';
8
5
  import { debounce } from '../utils/debounce.js';
9
- import { generateThumb } from '../utils/resizeImage.js';
10
6
  import { parseShrink } from '../../utils/parseShrink.js';
11
7
  import { UploadSource } from '../utils/UploadSource.js';
12
8
  import { throttle } from '../utils/throttle.js';
9
+ import { FileItemConfig } from './FileItemConfig.js';
13
10
 
14
11
  const FileItemState = Object.freeze({
15
12
  FINISHED: Symbol('FINISHED'),
@@ -18,24 +15,10 @@ const FileItemState = Object.freeze({
18
15
  IDLE: Symbol('IDLE'),
19
16
  });
20
17
 
21
- export class FileItem extends UploaderBlock {
18
+ export class FileItem extends FileItemConfig {
22
19
  couldBeCtxOwner = true;
23
20
  pauseRender = true;
24
21
 
25
- /** @private */
26
- _entrySubs = new Set();
27
- /**
28
- * @private
29
- * @type {any} TODO: Add types for upload entry
30
- */
31
- _entry = null;
32
- /** @private */
33
- _isIntersecting = false;
34
- /** @private */
35
- _debouncedGenerateThumb = debounce(this._generateThumbnail.bind(this), 100);
36
- /** @private */
37
- _debouncedCalculateState = debounce(this._calculateState.bind(this), 100);
38
-
39
22
  /** @private */
40
23
  _renderedOnce = false;
41
24
 
@@ -57,16 +40,16 @@ export class FileItem extends UploaderBlock {
57
40
  isUploading: false,
58
41
  isFocused: false,
59
42
  isEditable: false,
60
- isFileName: false,
43
+ showFileNames: false,
61
44
  state: FileItemState.IDLE,
62
45
  ariaLabelStatusFile: '',
63
- onEdit: () => {
46
+ onEdit: this._withEntry((entry) => {
64
47
  this.$['*currentActivityParams'] = {
65
- internalId: this._entry.uid,
48
+ internalId: entry.uid,
66
49
  };
67
50
  this.modalManager.open(ActivityBlock.activities.CLOUD_IMG_EDIT);
68
51
  this.$['*currentActivity'] = ActivityBlock.activities.CLOUD_IMG_EDIT;
69
- },
52
+ }),
70
53
  onRemove: () => {
71
54
  this.uploadCollection.remove(this.$.uid);
72
55
  },
@@ -77,14 +60,8 @@ export class FileItem extends UploaderBlock {
77
60
  }
78
61
 
79
62
  _reset() {
80
- for (let sub of this._entrySubs) {
81
- sub.remove();
82
- }
83
-
84
- this._debouncedGenerateThumb.cancel();
63
+ super._reset();
85
64
  this._debouncedCalculateState.cancel();
86
- this._entrySubs = new Set();
87
- this._entry = null;
88
65
  }
89
66
 
90
67
  /**
@@ -93,6 +70,7 @@ export class FileItem extends UploaderBlock {
93
70
  */
94
71
  _observerCallback(entries) {
95
72
  let [entry] = entries;
73
+
96
74
  this._isIntersecting = entry.isIntersecting;
97
75
  this._thumbRect = entry.boundingClientRect;
98
76
 
@@ -100,19 +78,10 @@ export class FileItem extends UploaderBlock {
100
78
  this.render();
101
79
  this._renderedOnce = true;
102
80
  }
103
- if (entry.intersectionRatio === 0) {
104
- this._debouncedGenerateThumb.cancel();
105
- } else {
106
- this._debouncedGenerateThumb();
107
- }
108
81
  }
109
82
 
110
83
  /** @private */
111
- _calculateState() {
112
- if (!this._entry) {
113
- return;
114
- }
115
- let entry = this._entry;
84
+ _calculateState = this._withEntry((entry) => {
116
85
  let state = FileItemState.IDLE;
117
86
 
118
87
  if (entry.getValue('errors').length > 0) {
@@ -124,85 +93,40 @@ export class FileItem extends UploaderBlock {
124
93
  }
125
94
 
126
95
  this.$.state = state;
127
- }
96
+ });
128
97
 
129
98
  /** @private */
130
- async _generateThumbnail() {
131
- if (!this._entry) {
132
- return;
133
- }
134
- let entry = this._entry;
135
-
136
- if (entry.getValue('fileInfo') && entry.getValue('isImage')) {
137
- let size = Math.max(
138
- parseInt(String(this?._thumbRect?.height || 0)),
139
- parseInt(String(this?._thumbRect?.width || 0)),
140
- this.cfg.thumbSize,
141
- );
142
-
143
- let thumbUrl = await this.proxyUrl(
144
- createCdnUrl(
145
- createOriginalUrl(this.cfg.cdnCname, this._entry.getValue('uuid')),
146
- createCdnUrlModifiers(entry.getValue('cdnUrlModifiers'), `scale_crop/${size}x${size}/center`),
147
- ),
148
- );
149
- let currentThumbUrl = entry.getValue('thumbUrl');
150
- if (currentThumbUrl !== thumbUrl) {
151
- entry.setValue('thumbUrl', thumbUrl);
152
- currentThumbUrl?.startsWith('blob:') && URL.revokeObjectURL(currentThumbUrl);
153
- }
154
- return;
155
- }
156
-
157
- if (entry.getValue('thumbUrl')) {
158
- return;
159
- }
99
+ _debouncedCalculateState = debounce(this._calculateState.bind(this), 100);
160
100
 
161
- if (entry.getValue('file')?.type.includes('image')) {
162
- try {
163
- let thumbUrl = await generateThumb(entry.getValue('file'), this.cfg.thumbSize);
164
- entry.setValue('thumbUrl', thumbUrl);
165
- } catch (err) {
166
- let color = window.getComputedStyle(this).getPropertyValue('--uc-muted-foreground');
167
- entry.setValue('thumbUrl', fileCssBg(color));
101
+ _updateHint = this._withEntry(
102
+ throttle((entry) => {
103
+ const source = entry.getValue('source');
104
+ const externalUrl = entry.getValue('externalUrl');
105
+ const noErrors = entry.getValue('errors').length === 0;
106
+ const noProgress = this.$.progressValue === 0;
107
+ const isUploading = this.$.state === FileItemState.UPLOADING;
108
+ const isQueued = entry.getValue('isQueued');
109
+
110
+ if (!noErrors || !isUploading || !noProgress) {
111
+ this.$.hint = '';
112
+ return;
168
113
  }
169
- } else {
170
- let color = window.getComputedStyle(this).getPropertyValue('--uc-muted-foreground');
171
- entry.setValue('thumbUrl', fileCssBg(color));
172
- }
173
- }
174
114
 
175
- /**
176
- * @private
177
- * @param {string} prop
178
- * @param {(value: any) => void} handler
179
- */
180
- _subEntry(prop, handler) {
181
- let sub = this._entry.subscribe(
182
- prop,
183
- /** @param {any} value */ (value) => {
184
- if (this.isConnected) {
185
- handler(value);
186
- }
187
- },
188
- );
189
- this._entrySubs.add(sub);
190
- }
191
-
192
- _updateHint = throttle(() => {
193
- const showHint =
194
- this.$.state === FileItemState.UPLOADING &&
195
- this._entry.getValue('externalUrl') &&
196
- this._entry.getValue('source') !== UploadSource.URL &&
197
- this._entry.getValue('errors').length === 0 &&
198
- this.$.progressValue === 0;
115
+ if (isQueued) {
116
+ const hint = this.l10n('queued');
117
+ this.$.hint = hint;
118
+ return;
119
+ }
199
120
 
200
- const hint = showHint
201
- ? this.l10n('waiting-for', { source: this.l10n(`src-type-${this._entry.getValue('source')}`) })
202
- : '';
121
+ if (externalUrl && source && source !== UploadSource.URL) {
122
+ const hint = this.l10n('waiting-for', { source: this.l10n(`src-type-${source}`) });
123
+ this.$.hint = hint;
124
+ return;
125
+ }
203
126
 
204
- this.$.hint = hint;
205
- }, 100);
127
+ this.$.hint = '';
128
+ }, 100),
129
+ );
206
130
 
207
131
  /**
208
132
  * @private
@@ -211,7 +135,6 @@ export class FileItem extends UploaderBlock {
211
135
  _handleEntryId(id) {
212
136
  this._reset();
213
137
 
214
- /** @type {import('../../abstract/TypedData.js').TypedData} */
215
138
  let entry = this.uploadCollection?.read(id);
216
139
  this._entry = entry;
217
140
 
@@ -224,6 +147,10 @@ export class FileItem extends UploaderBlock {
224
147
  this._updateHint();
225
148
  });
226
149
 
150
+ this._subEntry('isQueued', () => {
151
+ this._updateHint();
152
+ });
153
+
227
154
  this._subEntry('fileName', (name) => {
228
155
  this.$.itemName = name || entry.getValue('externalUrl') || this.l10n('file-no-name');
229
156
  this._debouncedCalculateState();
@@ -233,21 +160,8 @@ export class FileItem extends UploaderBlock {
233
160
  this.$.itemName = entry.getValue('fileName') || externalUrl || this.l10n('file-no-name');
234
161
  });
235
162
 
236
- this._subEntry('fileInfo', (fileInfo) => {
163
+ this._subEntry('fileInfo', () => {
237
164
  this._debouncedCalculateState();
238
- if (fileInfo && this._isIntersecting) {
239
- this._debouncedGenerateThumb();
240
- }
241
- });
242
-
243
- this._subEntry('cdnUrlModifiers', () => {
244
- if (this._isIntersecting) {
245
- this._debouncedGenerateThumb();
246
- }
247
- });
248
-
249
- this._subEntry('thumbUrl', (thumbUrl) => {
250
- this.$.thumbUrl = thumbUrl ? `url(${thumbUrl})` : '';
251
165
  });
252
166
 
253
167
  this._subEntry('errors', () => this._debouncedCalculateState());
@@ -255,10 +169,17 @@ export class FileItem extends UploaderBlock {
255
169
  this._subEntry('fileSize', () => this._debouncedCalculateState());
256
170
  this._subEntry('mimeType', () => this._debouncedCalculateState());
257
171
  this._subEntry('isImage', () => this._debouncedCalculateState());
172
+ }
258
173
 
259
- if (this._isIntersecting) {
260
- this._debouncedGenerateThumb();
174
+ /** @param {boolean} value */
175
+ _updateShowFileNames(value) {
176
+ const isListMode = this.cfg.filesViewMode === 'list';
177
+ if (isListMode) {
178
+ this.$.showFileNames = true;
179
+ return;
261
180
  }
181
+
182
+ this.$.showFileNames = value;
262
183
  }
263
184
 
264
185
  initCallback() {
@@ -273,14 +194,17 @@ export class FileItem extends UploaderBlock {
273
194
  });
274
195
 
275
196
  this.subConfigValue('useCloudImageEditor', () => this._debouncedCalculateState());
276
- this.subConfigValue('displayUploadList', (mode) => {
277
- if (mode === 'grid') {
278
- this.subConfigValue('enableFileName', (value) => (this.$.isFileName = !value));
279
- }
197
+
198
+ this.subConfigValue('filesViewMode', (mode) => {
199
+ this._updateShowFileNames(this.cfg.gridShowFileNames);
280
200
 
281
201
  this.setAttribute('mode', mode);
282
202
  });
283
203
 
204
+ this.subConfigValue('gridShowFileNames', (value) => {
205
+ this._updateShowFileNames(value);
206
+ });
207
+
284
208
  this.onclick = () => {
285
209
  FileItem.activeInstances.forEach((inst) => {
286
210
  if (inst === this) {
@@ -295,7 +219,7 @@ export class FileItem extends UploaderBlock {
295
219
  '*uploadTrigger',
296
220
  /** @param {Set<string>} itemsToUpload */
297
221
  (itemsToUpload) => {
298
- if (!itemsToUpload.has(this._entry.uid)) {
222
+ if (this._entry && !itemsToUpload.has(this._entry.uid)) {
299
223
  return;
300
224
  }
301
225
  setTimeout(() => this.isConnected && this.upload());
@@ -304,33 +228,38 @@ export class FileItem extends UploaderBlock {
304
228
  FileItem.activeInstances.add(this);
305
229
  }
306
230
 
307
- /** @param {(typeof FileItemState)[keyof typeof FileItemState]} state */
308
- _handleState(state) {
309
- if (state === FileItemState.FAILED) {
310
- this.$.badgeIcon = 'badge-error';
311
- } else if (state === FileItemState.FINISHED) {
312
- this.$.badgeIcon = 'badge-success';
313
- }
314
-
315
- if (state === FileItemState.UPLOADING) {
316
- this.$.isFocused = false;
317
- }
231
+ _handleState = this._withEntry(
232
+ /** @param {(typeof FileItemState)[keyof typeof FileItemState]} state */
233
+ (entry, state) => {
234
+ if (state === FileItemState.FAILED) {
235
+ this.$.badgeIcon = 'badge-error';
236
+ } else if (state === FileItemState.FINISHED) {
237
+ this.$.badgeIcon = 'badge-success';
238
+ }
318
239
 
319
- this.set$({
320
- isFailed: state === FileItemState.FAILED,
321
- isUploading: state === FileItemState.UPLOADING,
322
- isFinished: state === FileItemState.FINISHED,
323
- progressVisible: state === FileItemState.UPLOADING,
324
- isEditable: this.cfg.useCloudImageEditor && this._entry?.getValue('isImage') && this._entry?.getValue('cdnUrl'),
325
- errorText: this._entry.getValue('errors')?.[0]?.message,
326
- ariaLabelStatusFile: this.l10n('a11y-file-item-status', {
327
- fileName: this._entry?.getValue('fileName'),
328
- status: this.l10n(state?.description?.toLocaleLowerCase() ?? '').toLocaleLowerCase(),
329
- }),
330
- });
240
+ if (state === FileItemState.UPLOADING) {
241
+ this.$.isFocused = false;
242
+ }
243
+ const fileName = entry.getValue('fileName');
244
+
245
+ this.set$({
246
+ isFailed: state === FileItemState.FAILED,
247
+ isUploading: state === FileItemState.UPLOADING,
248
+ isFinished: state === FileItemState.FINISHED,
249
+ progressVisible: state === FileItemState.UPLOADING,
250
+ isEditable: this.cfg.useCloudImageEditor && this._entry?.getValue('isImage') && this._entry?.getValue('cdnUrl'),
251
+ errorText: entry.getValue('errors')?.[0]?.message,
252
+ ariaLabelStatusFile:
253
+ fileName &&
254
+ this.l10n('a11y-file-item-status', {
255
+ fileName,
256
+ status: this.l10n(state?.description?.toLocaleLowerCase() ?? '').toLocaleLowerCase(),
257
+ }),
258
+ });
331
259
 
332
- this._updateHint();
333
- }
260
+ this._updateHint();
261
+ },
262
+ );
334
263
 
335
264
  destroyCallback() {
336
265
  super.destroyCallback();
@@ -353,7 +282,6 @@ export class FileItem extends UploaderBlock {
353
282
  disconnectedCallback() {
354
283
  super.disconnectedCallback();
355
284
 
356
- this._debouncedGenerateThumb.cancel();
357
285
  this._observer?.disconnect();
358
286
  }
359
287
 
@@ -369,9 +297,7 @@ export class FileItem extends UploaderBlock {
369
297
  return shrinkFile(file, this._settingsOfShrink());
370
298
  }
371
299
 
372
- async upload() {
373
- let entry = this._entry;
374
-
300
+ upload = this._withEntry(async (entry) => {
375
301
  if (!this.uploadCollection.read(entry.uid)) {
376
302
  return;
377
303
  }
@@ -385,26 +311,35 @@ export class FileItem extends UploaderBlock {
385
311
  }
386
312
 
387
313
  this._debouncedCalculateState();
388
- entry.setValue('isUploading', true);
389
- entry.setValue('errors', []);
314
+
315
+ entry.setMultipleValues({
316
+ isUploading: true,
317
+ errors: [],
318
+ isQueued: true,
319
+ });
390
320
 
391
321
  try {
392
322
  let abortController = new AbortController();
393
323
  entry.setValue('abortController', abortController);
394
324
 
395
325
  const uploadTask = async () => {
326
+ entry.setValue('isQueued', false);
327
+ /** @type {Blob | File | null} */
396
328
  let file = entry.getValue('file');
397
329
  if (file && this.cfg.imageShrink) {
398
- file = await this._processShrink(file).catch(() => file);
330
+ file = await this._processShrink(/** @type {File} */ (file)).catch(() => file);
399
331
  }
400
332
 
401
333
  const fileInput = file || entry.getValue('externalUrl') || entry.getValue('uuid');
334
+ if (!fileInput) {
335
+ throw new Error('No file input');
336
+ }
402
337
  const baseUploadClientOptions = await this.getUploadClientOptions();
403
338
  /** @type {import('@uploadcare/upload-client').FileFromOptions} */
404
339
  const uploadClientOptions = {
405
340
  ...baseUploadClientOptions,
406
- fileName: entry.getValue('fileName'),
407
- source: entry.getValue('source'),
341
+ fileName: entry.getValue('fileName') ?? undefined,
342
+ source: entry.getValue('source') ?? undefined,
408
343
  onProgress: (progress) => {
409
344
  if (progress.isComputable) {
410
345
  let percentage = progress.value * 100;
@@ -422,10 +357,11 @@ export class FileItem extends UploaderBlock {
422
357
  let fileInfo = await this.$['*uploadQueue'].add(uploadTask);
423
358
  entry.setMultipleValues({
424
359
  fileInfo,
360
+ isQueued: false,
425
361
  isUploading: false,
426
362
  fileName: fileInfo.originalFilename,
427
363
  fileSize: fileInfo.size,
428
- isImage: fileInfo.isImage,
364
+ isImage: fileInfo.isImage ?? false,
429
365
  mimeType: fileInfo.contentInfo?.mime?.mime ?? fileInfo.mimeType,
430
366
  uuid: fileInfo.uuid,
431
367
  cdnUrl: entry.getValue('cdnUrl') ?? fileInfo.cdnUrl,
@@ -443,30 +379,37 @@ export class FileItem extends UploaderBlock {
443
379
  isUploading: false,
444
380
  uploadProgress: 0,
445
381
  });
446
- } else {
382
+ } else if (cause instanceof UploadcareError) {
447
383
  entry.setMultipleValues({
448
384
  isUploading: false,
449
385
  uploadProgress: 0,
450
386
  uploadError: cause,
451
387
  });
388
+ } else {
389
+ console.error('Unknown upload error', cause);
390
+ entry.setMultipleValues({
391
+ isUploading: false,
392
+ uploadProgress: 0,
393
+ // TODO: Add translation?
394
+ uploadError: new Error('Something went wrong', {
395
+ cause,
396
+ }),
397
+ });
452
398
  }
453
399
 
454
400
  if (entry === this._entry) {
455
401
  this._debouncedCalculateState();
456
402
  }
457
403
  }
458
- }
404
+ });
459
405
  }
460
406
 
461
407
  FileItem.template = /* HTML */ `
462
408
  <div class="uc-inner" set="@finished: isFinished; @uploading: isUploading; @failed: isFailed; @focused: isFocused">
463
- <div class="uc-thumb" set="style.backgroundImage: thumbUrl">
464
- <div class="uc-badge">
465
- <uc-icon set="@name: badgeIcon"></uc-icon>
466
- </div>
467
- </div>
409
+ <uc-thumb set="uid:uid;badgeIcon:badgeIcon"></uc-thumb>
410
+
468
411
  <div aria-atomic="true" aria-live="polite" class="uc-file-name-wrapper" set="@aria-label:ariaLabelStatusFile;">
469
- <span class="uc-file-name" set="@hidden: isFileName">{{itemName}}</span>
412
+ <span class="uc-file-name" set="@hidden: !showFileNames">{{itemName}}</span>
470
413
  <span class="uc-file-error" set="@hidden: !errorText;">{{errorText}}</span>
471
414
  <span class="uc-file-hint" set="@hidden: !hint">{{hint}}</span>
472
415
  </div>
@@ -491,7 +434,11 @@ FileItem.template = /* HTML */ `
491
434
  <uc-icon name="upload"></uc-icon>
492
435
  </button>
493
436
  </div>
494
- <uc-progress-bar class="uc-progress-bar" set="value: progressValue; visible: progressVisible;"> </uc-progress-bar>
437
+ <uc-progress-bar
438
+ class="uc-progress-bar"
439
+ set="value: progressValue; visible: progressVisible; @hasFileName: showFileNames;"
440
+ >
441
+ </uc-progress-bar>
495
442
  </div>
496
443
  `;
497
444
  FileItem.activeInstances = new Set();
@@ -0,0 +1,28 @@
1
+ export class FileItemConfig extends UploaderBlock {
2
+ /** @protected */
3
+ protected _entrySubs: Set<any>;
4
+ /**
5
+ * @type {import('../../abstract/uploadEntrySchema.js').UploadEntryTypedData | null}
6
+ * @protected
7
+ */
8
+ protected _entry: import("../../abstract/uploadEntrySchema.js").UploadEntryTypedData | null;
9
+ /**
10
+ * @template {any[]} A
11
+ * @template {(entry: import('../../abstract/uploadEntrySchema.js').UploadEntryTypedData, ...args: A) => any} T
12
+ * @param {T} fn
13
+ * @returns {(...args: A) => ReturnType<T>}
14
+ * @protected
15
+ */
16
+ protected _withEntry<A extends any[], T extends (entry: import("../../abstract/uploadEntrySchema.js").UploadEntryTypedData, ...args: A) => any>(fn: T): (...args: A) => ReturnType<T>;
17
+ /**
18
+ * @template {import('../../abstract/uploadEntrySchema.js').UploadEntryKeys} K
19
+ * @param {K} prop_
20
+ * @param {(value: import('../../abstract/uploadEntrySchema.js').UploadEntryData[K]) => void} handler_
21
+ * @protected
22
+ */
23
+ protected _subEntry: (prop_: K, handler_: (value: import("../../abstract/uploadEntrySchema.js").UploadEntryData[K]) => void) => void;
24
+ /** @protected */
25
+ protected _reset(): void;
26
+ }
27
+ import { UploaderBlock } from '../../abstract/UploaderBlock.js';
28
+ //# sourceMappingURL=FileItemConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileItemConfig.d.ts","sourceRoot":"","sources":["FileItemConfig.js"],"names":[],"mappings":"AAIA;IACE,iBAAiB;IACjB,+BAAuB;IAEvB;;;OAGG;IACH,kBAHU,OAAO,qCAAqC,EAAE,oBAAoB,GAAG,IAAI,CAGrE;IAEd;;;;;;OAMG;IACH,qBANqB,CAAC,SAAR,GAAG,EAAG,EAC0F,CAAC,SAAlG,CAAE,KAAK,EAAE,OAAO,qCAAqC,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,GAAI,MAClG,CAAC,GACC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAezC;IAED;;;;;OAKG;IACH,sBAAa,OAJF,CAIO,EAAE,UAHT,CAAC,KAAK,EAAE,OAAO,qCAAqC,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,IAG5D,UAgBP;IAErB,iBAAiB;IACjB,yBAOC;CAMF;8BAvE6B,iCAAiC"}
@@ -0,0 +1,74 @@
1
+ //@ts-check
2
+
3
+ import { UploaderBlock } from '../../abstract/UploaderBlock.js';
4
+
5
+ export class FileItemConfig extends UploaderBlock {
6
+ /** @protected */
7
+ _entrySubs = new Set();
8
+
9
+ /**
10
+ * @type {import('../../abstract/uploadEntrySchema.js').UploadEntryTypedData | null}
11
+ * @protected
12
+ */
13
+ _entry = null;
14
+
15
+ /**
16
+ * @template {any[]} A
17
+ * @template {(entry: import('../../abstract/uploadEntrySchema.js').UploadEntryTypedData, ...args: A) => any} T
18
+ * @param {T} fn
19
+ * @returns {(...args: A) => ReturnType<T>}
20
+ * @protected
21
+ */
22
+ _withEntry(fn) {
23
+ const wrapperFn = /** @type {(...args: A) => ReturnType<T>} */ (
24
+ (...args) => {
25
+ const entry = this._entry;
26
+ if (!entry) {
27
+ console.warn('No entry found');
28
+ return;
29
+ }
30
+ return fn(entry, ...args);
31
+ }
32
+ );
33
+ return wrapperFn;
34
+ }
35
+
36
+ /**
37
+ * @template {import('../../abstract/uploadEntrySchema.js').UploadEntryKeys} K
38
+ * @param {K} prop_
39
+ * @param {(value: import('../../abstract/uploadEntrySchema.js').UploadEntryData[K]) => void} handler_
40
+ * @protected
41
+ */
42
+ _subEntry = (prop_, handler_) =>
43
+ this._withEntry(
44
+ /**
45
+ * @template {import('../../abstract/uploadEntrySchema.js').UploadEntryKeys} K
46
+ * @param {import('../../abstract/uploadEntrySchema.js').UploadEntryTypedData} entry
47
+ * @param {K} prop
48
+ * @param {(value: import('../../abstract/uploadEntrySchema.js').UploadEntryData[K]) => void} handler
49
+ */
50
+ (entry, prop, handler) => {
51
+ let sub = entry.subscribe(prop, (value) => {
52
+ if (this.isConnected) {
53
+ handler(value);
54
+ }
55
+ });
56
+ this._entrySubs.add(sub);
57
+ },
58
+ )(prop_, handler_);
59
+
60
+ /** @protected */
61
+ _reset() {
62
+ for (let sub of this._entrySubs) {
63
+ sub.remove();
64
+ }
65
+
66
+ this._entrySubs = new Set();
67
+ this._entry = null;
68
+ }
69
+
70
+ disconnectedCallback() {
71
+ super.disconnectedCallback();
72
+ this._entrySubs = new Set();
73
+ }
74
+ }
@@ -74,6 +74,7 @@ uc-file-item .uc-file-error {
74
74
  display: none;
75
75
  color: var(--uc-destructive-foreground);
76
76
  font-size: 0.85em;
77
+ z-index: 2;
77
78
  }
78
79
 
79
80
  uc-file-item button.uc-remove-btn,
@@ -193,6 +194,17 @@ uc-file-item[mode='grid'] .uc-file-error {
193
194
  padding: calc(var(--uc-padding) / 2) var(--uc-padding);
194
195
  }
195
196
 
197
+ uc-file-item[mode='grid'] .uc-file-hint {
198
+ position: absolute;
199
+ background-color: var(--uc-background);
200
+ border-radius: var(--uc-radius);
201
+ color: var(--uc-foreground);
202
+ bottom: calc(var(--uc-padding) * 2);
203
+ left: var(--uc-padding);
204
+ right: var(--uc-padding);
205
+ padding: calc(var(--uc-padding) / 2) var(--uc-padding);
206
+ }
207
+
196
208
  uc-file-item[mode='grid'] .uc-file-actions {
197
209
  position: absolute;
198
210
  top: var(--uc-padding);
@@ -202,3 +214,30 @@ uc-file-item[mode='grid'] .uc-file-actions {
202
214
  uc-file-item[mode='grid'] button {
203
215
  background-color: var(--uc-background);
204
216
  }
217
+
218
+ uc-file-item[mode='grid'] button:hover {
219
+ background-color: var(--uc-muted);
220
+ }
221
+
222
+ uc-file-item[mode='grid'] .uc-progress-bar {
223
+ width: initial;
224
+ height: 4px !important;
225
+ top: initial !important;
226
+ bottom: var(--uc-padding);
227
+ left: var(--uc-padding);
228
+ right: var(--uc-padding);
229
+ border-radius: var(--uc-radius);
230
+ z-index: 1;
231
+ transition:
232
+ background-color 0.3s,
233
+ opacity 0.3s;
234
+ background-color: var(--uc-background);
235
+ }
236
+
237
+ uc-file-item[mode='grid'] .uc-progress-bar :is(.uc-fake-progress, .uc-progress) {
238
+ background-color: var(--uc-primary);
239
+ }
240
+
241
+ uc-file-item[mode='grid'] .uc-progress-bar[hasfilename] {
242
+ bottom: calc(var(--uc-padding) + var(--uc-font-size));
243
+ }