@mainframework/dropzone 1.0.28 → 1.1.1
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.
- package/README.md +13 -6
- package/dist/index.d.ts +2 -66
- package/dist/index.js +554 -402
- package/dist/index.js.map +1 -1
- package/dist/shared/components/FileSelector/FileSelector.d.ts +6 -0
- package/dist/shared/components/FileSelector/index.d.ts +1 -0
- package/dist/shared/hooks/useFileSelector.d.ts +20 -0
- package/dist/shared/types/types.d.ts +46 -0
- package/dist/shared/utils/dragAndDrop.d.ts +2 -0
- package/dist/shared/utils/mergeStyles.d.ts +2 -0
- package/dist/shared/utils/processUploadedFiles.d.ts +23 -0
- package/package.json +27 -22
package/dist/index.js
CHANGED
|
@@ -1,155 +1,195 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useRef, useId, useState } from 'react';
|
|
2
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useRef, memo, useId, useCallback, useState, useEffect, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
//Use this to quickly get the file extensions
|
|
6
6
|
//Devs can pass their own custom type mappings to override these defaults
|
|
7
|
+
|
|
7
8
|
const defaultTypeExtensions = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
|
9
|
+
"image/png": ".png",
|
|
10
|
+
"image/jpeg": ".jpeg",
|
|
11
|
+
"image/svg+xml": ".svg",
|
|
12
|
+
"application/pdf": ".pdf",
|
|
13
|
+
"application/msword": ".doc",
|
|
14
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx"
|
|
15
15
|
};
|
|
16
|
+
|
|
16
17
|
//This is the attribute that should be present in all svg files
|
|
17
|
-
const xmlns =
|
|
18
|
+
const xmlns = '<svg xmlns="http://www.w3.org/2000/svg"';
|
|
18
19
|
const maximumUploadCount = 30;
|
|
19
20
|
const maximumFileSize = 5e6; //5 mb's
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
const formatFileSize = bytes => {
|
|
23
|
+
if (bytes >= 1e9) return `${Math.round(bytes / 1e9)} Gigabytes`;
|
|
24
|
+
if (bytes >= 1e6) return `${Math.round(bytes / 1e6)} Megabytes`;
|
|
25
|
+
if (bytes >= 1e3) return `${Math.round(bytes / 1e3)} Kilobytes`;
|
|
26
|
+
return `${bytes} Bytes`;
|
|
27
|
+
};
|
|
28
|
+
const buildAcceptString = acceptedTypes => {
|
|
29
|
+
const seen = new Set();
|
|
30
|
+
|
|
31
|
+
// Prefer extensions (input accept supports extensions and MIME types)
|
|
32
|
+
for (const ext of Object.values(acceptedTypes)) {
|
|
33
|
+
const trimmed = ext.trim();
|
|
34
|
+
if (!trimmed) continue;
|
|
35
|
+
if (!trimmed.startsWith(".")) {
|
|
36
|
+
const withDot = `.${trimmed}`;
|
|
37
|
+
if (!seen.has(withDot)) seen.add(withDot);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!seen.has(trimmed)) seen.add(trimmed);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Add MIME keys too (helps some pickers)
|
|
44
|
+
for (const mime of Object.keys(acceptedTypes)) {
|
|
45
|
+
const trimmed = mime.trim();
|
|
46
|
+
if (!trimmed) continue;
|
|
47
|
+
if (!seen.has(trimmed)) seen.add(trimmed);
|
|
48
|
+
}
|
|
49
|
+
return Array.from(seen).join(", ");
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// TYPE DEFINITIONS
|
|
53
|
+
|
|
21
54
|
// HELPER: Extract file ID (filename without extension)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
* "
|
|
26
|
-
* "
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* Extracts filename without extension, handling multiple dots correctly.
|
|
58
|
+
* "my.photo.final.png" -> "my.photo.final"
|
|
59
|
+
* "README.md" -> "README"
|
|
60
|
+
* "no-extension" -> "no-extension"
|
|
27
61
|
*/
|
|
28
|
-
const getFileId =
|
|
29
|
-
|
|
30
|
-
|
|
62
|
+
const getFileId = fileName => {
|
|
63
|
+
const lastDotIndex = fileName.lastIndexOf(".");
|
|
64
|
+
return lastDotIndex > 0 ? fileName.slice(0, lastDotIndex) : fileName;
|
|
31
65
|
};
|
|
66
|
+
|
|
32
67
|
// BLOB URL REGISTRY - WeakMap for automatic GC cleanup
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
*
|
|
68
|
+
|
|
69
|
+
/*
|
|
70
|
+
* WeakMap prevents memory leaks by allowing GC to reclaim File objects.
|
|
71
|
+
* No manual cleanup needed when Files are no longer referenced.
|
|
36
72
|
*/
|
|
37
73
|
const blobUrlRegistry = new WeakMap();
|
|
38
|
-
const createUrlString =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return url;
|
|
74
|
+
const createUrlString = file => {
|
|
75
|
+
const existing = blobUrlRegistry.get(file);
|
|
76
|
+
if (existing) return existing;
|
|
77
|
+
const url = URL.createObjectURL(file);
|
|
78
|
+
blobUrlRegistry.set(file, url);
|
|
79
|
+
return url;
|
|
45
80
|
};
|
|
46
|
-
const clearBlobFromMemory =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
blobUrlRegistry.delete(file);
|
|
81
|
+
const clearBlobFromMemory = file => {
|
|
82
|
+
const url = blobUrlRegistry.get(file);
|
|
83
|
+
if (!url) return;
|
|
84
|
+
URL.revokeObjectURL(url);
|
|
85
|
+
blobUrlRegistry.delete(file);
|
|
52
86
|
};
|
|
87
|
+
|
|
53
88
|
// VALIDATION FUNCTIONS
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
* Checks if file type is in accepted types map.
|
|
92
|
+
* Uses Object.hasOwn for better performance than Boolean() conversion.
|
|
57
93
|
*/
|
|
58
|
-
const isValidFileType = (file, acceptedTypes = defaultTypeExtensions) =>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
94
|
+
const isValidFileType = (file, acceptedTypes = defaultTypeExtensions) => {
|
|
95
|
+
if (Object.hasOwn(acceptedTypes, file.type)) return true;
|
|
96
|
+
const ext = "." + file.name.split(".").pop()?.toLowerCase();
|
|
97
|
+
return Object.values(acceptedTypes).some(e => e.toLowerCase() === ext);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* Returns true if ANY file exceeds the maximum size limit.
|
|
102
|
+
* Optimized with for-loop to avoid callback allocations in hot path.
|
|
62
103
|
*/
|
|
104
|
+
|
|
63
105
|
const checkFilesMaximumSize = (files, max = maximumFileSize) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return false;
|
|
106
|
+
let i = 0;
|
|
107
|
+
while (i < files.length) {
|
|
108
|
+
if (files[i].size > max) return true;
|
|
109
|
+
i++;
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
71
112
|
};
|
|
113
|
+
|
|
72
114
|
// DOCUMENT CREATION
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
*
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* Creates document data object with file metadata.
|
|
118
|
+
* Returns null if file type is not in allowableTypes to prevent invalid state.
|
|
76
119
|
*/
|
|
77
120
|
const createDocumentData = (file, allowableTypes = defaultTypeExtensions) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
121
|
+
const type = allowableTypes[file.type];
|
|
122
|
+
if (!type) return null;
|
|
123
|
+
return {
|
|
124
|
+
id: getFileId(file.name),
|
|
125
|
+
type,
|
|
126
|
+
file,
|
|
127
|
+
url: createUrlString(file)
|
|
128
|
+
};
|
|
87
129
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
*
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* Optimized SVG xmlns check - only reads first 2KB initially.
|
|
133
|
+
* Avoids toLowerCase() allocation and uses safer regex for replacement.
|
|
91
134
|
*/
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
const svgXmlnsAttributeCheck = async (file, allowableTypes = defaultTypeExtensions) => {
|
|
136
|
+
if (file.type !== "image/svg+xml") {
|
|
137
|
+
return createDocumentData(file, allowableTypes);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// OPTIMIZATION: Only read first 2KB to check for xmlns
|
|
141
|
+
const chunk = file.slice(0, 2048);
|
|
142
|
+
const text = await chunk.text();
|
|
143
|
+
|
|
144
|
+
// No toLowerCase() needed - xmlns attribute is case-sensitive in XML
|
|
145
|
+
if (/<svg\b[^>]*\bxmlns\s*=/i.test(text)) {
|
|
146
|
+
return createDocumentData(file, allowableTypes);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Missing the xmlns attribute, add it
|
|
150
|
+
// Need full file content for modification
|
|
151
|
+
const fullText = await file.text();
|
|
152
|
+
|
|
153
|
+
// SAFER: Use regex with word boundary instead of simple string replace
|
|
154
|
+
// Handles <svg> or <SVG> without space and various attribute orders
|
|
155
|
+
const svgWithXmlns = fullText.replace(/<svg\b/i, xmlns);
|
|
156
|
+
clearBlobFromMemory(file);
|
|
157
|
+
return createDocumentData(new File([svgWithXmlns], file.name, {
|
|
158
|
+
type: file.type
|
|
159
|
+
}), allowableTypes);
|
|
112
160
|
};
|
|
161
|
+
|
|
113
162
|
// FILE RENAMING
|
|
114
|
-
/*
|
|
115
|
-
* Renames a file or blob. Optimized to avoid unnecessary File creation
|
|
116
|
-
* if name already matches.
|
|
117
|
-
*/
|
|
118
|
-
const renameFile = (file, name) => file instanceof File && file.name === name ? file : new File([file], name, { type: file.type });
|
|
119
|
-
/*
|
|
120
|
-
* Checks if file needs renaming based on ID comparison.
|
|
121
|
-
* - Handles Blobs (no name) by converting to File
|
|
122
|
-
* - Avoids repeated string operations
|
|
123
|
-
* - Case-sensitive comparison
|
|
124
|
-
*/
|
|
125
|
-
const checkFile = (id, file) => {
|
|
126
|
-
// No ID provided, return as-is
|
|
127
|
-
if (!id)
|
|
128
|
-
return file;
|
|
129
|
-
// Handle Blob (not a File subclass)
|
|
130
|
-
if (!(file instanceof File)) {
|
|
131
|
-
return renameFile(file, id);
|
|
132
|
-
}
|
|
133
|
-
// It's a File - check if renaming is needed
|
|
134
|
-
const currentId = getFileId(file.name);
|
|
135
|
-
return id === currentId ? file : renameFile(file, id);
|
|
136
|
-
};
|
|
137
163
|
|
|
138
|
-
|
|
164
|
+
/*
|
|
165
|
+
* Checks if file needs renaming based on ID comparison.
|
|
166
|
+
* - Handles Blobs (no name) by converting to File
|
|
167
|
+
* - Avoids repeated string operations
|
|
168
|
+
* - Case-sensitive comparison
|
|
169
|
+
*/
|
|
170
|
+
const renameFile = (id, file) => {
|
|
171
|
+
// No ID provided, return as-is
|
|
172
|
+
if (!id) return file;
|
|
139
173
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const stableCallback = useRef((...args) => refCallback.current(...args)).current;
|
|
150
|
-
return stableCallback;
|
|
174
|
+
//It's a blob
|
|
175
|
+
if (!(file instanceof File)) {
|
|
176
|
+
return rename(id, file);
|
|
177
|
+
}
|
|
178
|
+
const currentId = getFileId(file.name);
|
|
179
|
+
if (id === currentId) return file;
|
|
180
|
+
const lastDot = file.name.lastIndexOf(".");
|
|
181
|
+
const ext = lastDot === -1 ? defaultTypeExtensions[file.type] ?? "" : file.name.slice(lastDot);
|
|
182
|
+
return rename(`${id}${ext}`, file);
|
|
151
183
|
};
|
|
152
184
|
|
|
185
|
+
/*
|
|
186
|
+
* Renames a file or blob. Optimized to avoid unnecessary File creation
|
|
187
|
+
* if name already matches.
|
|
188
|
+
*/
|
|
189
|
+
const rename = (id, file) => file instanceof File && file.name === id ? file : new File([file], id, {
|
|
190
|
+
type: file.type
|
|
191
|
+
});
|
|
192
|
+
|
|
153
193
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
154
194
|
|
|
155
195
|
/**
|
|
@@ -499,15 +539,27 @@ const createConfigUtils = config => ({
|
|
|
499
539
|
cache: createLruCache(config.cacheSize),
|
|
500
540
|
parseClassName: createParseClassName(config),
|
|
501
541
|
sortModifiers: createSortModifiers(config),
|
|
542
|
+
postfixLookupClassGroupIds: createPostfixLookupClassGroupIds(config),
|
|
502
543
|
...createClassGroupUtils(config)
|
|
503
544
|
});
|
|
545
|
+
const createPostfixLookupClassGroupIds = config => {
|
|
546
|
+
const lookup = Object.create(null);
|
|
547
|
+
const classGroupIds = config.postfixLookupClassGroups;
|
|
548
|
+
if (classGroupIds) {
|
|
549
|
+
for (let i = 0; i < classGroupIds.length; i++) {
|
|
550
|
+
lookup[classGroupIds[i]] = true;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return lookup;
|
|
554
|
+
};
|
|
504
555
|
const SPLIT_CLASSES_REGEX = /\s+/;
|
|
505
556
|
const mergeClassList = (classList, configUtils) => {
|
|
506
557
|
const {
|
|
507
558
|
parseClassName,
|
|
508
559
|
getClassGroupId,
|
|
509
560
|
getConflictingClassGroupIds,
|
|
510
|
-
sortModifiers
|
|
561
|
+
sortModifiers,
|
|
562
|
+
postfixLookupClassGroupIds
|
|
511
563
|
} = configUtils;
|
|
512
564
|
/**
|
|
513
565
|
* Set of classGroupIds in following format:
|
|
@@ -533,7 +585,18 @@ const mergeClassList = (classList, configUtils) => {
|
|
|
533
585
|
continue;
|
|
534
586
|
}
|
|
535
587
|
let hasPostfixModifier = !!maybePostfixModifierPosition;
|
|
536
|
-
let classGroupId
|
|
588
|
+
let classGroupId;
|
|
589
|
+
if (hasPostfixModifier) {
|
|
590
|
+
const baseClassNameWithoutPostfix = baseClassName.substring(0, maybePostfixModifierPosition);
|
|
591
|
+
classGroupId = getClassGroupId(baseClassNameWithoutPostfix);
|
|
592
|
+
const classGroupIdWithPostfix = classGroupId && postfixLookupClassGroupIds[classGroupId] ? getClassGroupId(baseClassName) : undefined;
|
|
593
|
+
if (classGroupIdWithPostfix && classGroupIdWithPostfix !== classGroupId) {
|
|
594
|
+
classGroupId = classGroupIdWithPostfix;
|
|
595
|
+
hasPostfixModifier = false;
|
|
596
|
+
}
|
|
597
|
+
} else {
|
|
598
|
+
classGroupId = getClassGroupId(baseClassName);
|
|
599
|
+
}
|
|
537
600
|
if (!classGroupId) {
|
|
538
601
|
if (!hasPostfixModifier) {
|
|
539
602
|
// Not a Tailwind class
|
|
@@ -664,6 +727,7 @@ const isNever = () => false;
|
|
|
664
727
|
const isShadow = value => shadowRegex.test(value);
|
|
665
728
|
const isImage = value => imageRegex.test(value);
|
|
666
729
|
const isAnyNonArbitrary = value => !isArbitraryValue(value) && !isArbitraryVariable(value);
|
|
730
|
+
const isNamedContainerQuery = value => value.startsWith('@container') && (value[10] === '/' && value[11] !== undefined || value[11] === 's' && value[16] !== undefined && value.startsWith('-size/', 10) || value[11] === 'n' && value[18] !== undefined && value.startsWith('-normal/', 10));
|
|
667
731
|
const isArbitrarySize = value => getIsArbitraryValue(value, isLabelSize, isNever);
|
|
668
732
|
const isArbitraryValue = value => arbitraryValueRegex.test(value);
|
|
669
733
|
const isArbitraryLength = value => getIsArbitraryValue(value, isLabelLength, isLengthOnly);
|
|
@@ -835,6 +899,18 @@ const getDefaultConfig = () => {
|
|
|
835
899
|
* @deprecated since Tailwind CSS v4.0.0
|
|
836
900
|
*/
|
|
837
901
|
container: ['container'],
|
|
902
|
+
/**
|
|
903
|
+
* Container Type
|
|
904
|
+
* @see https://tailwindcss.com/docs/responsive-design#container-queries
|
|
905
|
+
*/
|
|
906
|
+
'container-type': [{
|
|
907
|
+
'@container': ['', 'normal', 'size', isArbitraryVariable, isArbitraryValue]
|
|
908
|
+
}],
|
|
909
|
+
/**
|
|
910
|
+
* Container Name
|
|
911
|
+
* @see https://tailwindcss.com/docs/responsive-design#named-containers
|
|
912
|
+
*/
|
|
913
|
+
'container-named': [isNamedContainerQuery],
|
|
838
914
|
/**
|
|
839
915
|
* Columns
|
|
840
916
|
* @see https://tailwindcss.com/docs/columns
|
|
@@ -1763,6 +1839,13 @@ const getDefaultConfig = () => {
|
|
|
1763
1839
|
indent: [{
|
|
1764
1840
|
indent: scaleUnambiguousSpacing()
|
|
1765
1841
|
}],
|
|
1842
|
+
/**
|
|
1843
|
+
* Tab Size
|
|
1844
|
+
* @see https://tailwindcss.com/docs/tab-size
|
|
1845
|
+
*/
|
|
1846
|
+
'tab-size': [{
|
|
1847
|
+
tab: [isInteger, isArbitraryVariable, isArbitraryValue]
|
|
1848
|
+
}],
|
|
1766
1849
|
/**
|
|
1767
1850
|
* Vertical Alignment
|
|
1768
1851
|
* @see https://tailwindcss.com/docs/vertical-align
|
|
@@ -2970,6 +3053,13 @@ const getDefaultConfig = () => {
|
|
|
2970
3053
|
* @see https://tailwindcss.com/docs/translate
|
|
2971
3054
|
*/
|
|
2972
3055
|
'translate-none': ['translate-none'],
|
|
3056
|
+
/**
|
|
3057
|
+
* Zoom
|
|
3058
|
+
* @see https://tailwindcss.com/docs/zoom
|
|
3059
|
+
*/
|
|
3060
|
+
zoom: [{
|
|
3061
|
+
zoom: [isInteger, isArbitraryVariable, isArbitraryValue]
|
|
3062
|
+
}],
|
|
2973
3063
|
// ---------------------
|
|
2974
3064
|
// --- Interactivity ---
|
|
2975
3065
|
// ---------------------
|
|
@@ -3036,6 +3126,34 @@ const getDefaultConfig = () => {
|
|
|
3036
3126
|
'scroll-behavior': [{
|
|
3037
3127
|
scroll: ['auto', 'smooth']
|
|
3038
3128
|
}],
|
|
3129
|
+
/**
|
|
3130
|
+
* Scrollbar Thumb Color
|
|
3131
|
+
* @see https://tailwindcss.com/docs/scrollbar-color
|
|
3132
|
+
*/
|
|
3133
|
+
'scrollbar-thumb-color': [{
|
|
3134
|
+
'scrollbar-thumb': scaleColor()
|
|
3135
|
+
}],
|
|
3136
|
+
/**
|
|
3137
|
+
* Scrollbar Track Color
|
|
3138
|
+
* @see https://tailwindcss.com/docs/scrollbar-color
|
|
3139
|
+
*/
|
|
3140
|
+
'scrollbar-track-color': [{
|
|
3141
|
+
'scrollbar-track': scaleColor()
|
|
3142
|
+
}],
|
|
3143
|
+
/**
|
|
3144
|
+
* Scrollbar Gutter
|
|
3145
|
+
* @see https://tailwindcss.com/docs/scrollbar-gutter
|
|
3146
|
+
*/
|
|
3147
|
+
'scrollbar-gutter': [{
|
|
3148
|
+
'scrollbar-gutter': ['auto', 'stable', 'both']
|
|
3149
|
+
}],
|
|
3150
|
+
/**
|
|
3151
|
+
* Scrollbar Width
|
|
3152
|
+
* @see https://tailwindcss.com/docs/scrollbar-width
|
|
3153
|
+
*/
|
|
3154
|
+
'scrollbar-w': [{
|
|
3155
|
+
scrollbar: ['auto', 'thin', 'none']
|
|
3156
|
+
}],
|
|
3039
3157
|
/**
|
|
3040
3158
|
* Scroll Margin
|
|
3041
3159
|
* @see https://tailwindcss.com/docs/scroll-margin
|
|
@@ -3294,6 +3412,7 @@ const getDefaultConfig = () => {
|
|
|
3294
3412
|
}]
|
|
3295
3413
|
},
|
|
3296
3414
|
conflictingClassGroups: {
|
|
3415
|
+
'container-named': ['container-type'],
|
|
3297
3416
|
overflow: ['overflow-x', 'overflow-y'],
|
|
3298
3417
|
overscroll: ['overscroll-x', 'overscroll-y'],
|
|
3299
3418
|
inset: ['inset-x', 'inset-y', 'inset-bs', 'inset-be', 'start', 'end', 'top', 'right', 'bottom', 'left'],
|
|
@@ -3346,6 +3465,7 @@ const getDefaultConfig = () => {
|
|
|
3346
3465
|
conflictingClassGroupModifiers: {
|
|
3347
3466
|
'font-size': ['leading']
|
|
3348
3467
|
},
|
|
3468
|
+
postfixLookupClassGroups: ['container-type'],
|
|
3349
3469
|
orderSensitiveModifiers: ['*', '**', 'after', 'backdrop', 'before', 'details-content', 'file', 'first-letter', 'first-line', 'marker', 'placeholder', 'selection']
|
|
3350
3470
|
};
|
|
3351
3471
|
};
|
|
@@ -3354,15 +3474,14 @@ const twMerge = /*#__PURE__*/createTailwindMerge(getDefaultConfig);
|
|
|
3354
3474
|
const mergeStyles = (...inputs) => twMerge(clsx(inputs));
|
|
3355
3475
|
|
|
3356
3476
|
function styleInject(css, ref) {
|
|
3357
|
-
if (
|
|
3477
|
+
if (ref === void 0) ref = {};
|
|
3358
3478
|
var insertAt = ref.insertAt;
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3479
|
+
if (typeof document === 'undefined') {
|
|
3480
|
+
return;
|
|
3481
|
+
}
|
|
3362
3482
|
var head = document.head || document.getElementsByTagName('head')[0];
|
|
3363
3483
|
var style = document.createElement('style');
|
|
3364
3484
|
style.type = 'text/css';
|
|
3365
|
-
|
|
3366
3485
|
if (insertAt === 'top') {
|
|
3367
3486
|
if (head.firstChild) {
|
|
3368
3487
|
head.insertBefore(style, head.firstChild);
|
|
@@ -3372,7 +3491,6 @@ function styleInject(css, ref) {
|
|
|
3372
3491
|
} else {
|
|
3373
3492
|
head.appendChild(style);
|
|
3374
3493
|
}
|
|
3375
|
-
|
|
3376
3494
|
if (style.styleSheet) {
|
|
3377
3495
|
style.styleSheet.cssText = css;
|
|
3378
3496
|
} else {
|
|
@@ -3380,18 +3498,18 @@ function styleInject(css, ref) {
|
|
|
3380
3498
|
}
|
|
3381
3499
|
}
|
|
3382
3500
|
|
|
3383
|
-
var css_248z = "/*! tailwindcss v4.2
|
|
3501
|
+
var css_248z = "/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){.file-selector-scope *,.file-selector-scope ::backdrop,.file-selector-scope :after,.file-selector-scope :before{--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{.file-selector-scope,.file-selector-scope :host{--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-zinc-600:oklch(44.2% .017 285.786);--spacing:.25rem;--font-weight-bold:700;--radius-md:.375rem}}@layer base,components;@layer utilities{.file-selector-scope .flex{display:flex}.file-selector-scope .h-full{height:100%}.file-selector-scope .min-h-0{min-height:0}.file-selector-scope .min-h-\\[120px\\]{min-height:120px}.file-selector-scope .w-full{width:100%}.file-selector-scope .flex-1{flex:1}.file-selector-scope .cursor-pointer{cursor:pointer}.file-selector-scope .flex-col{flex-direction:column}.file-selector-scope .rounded-md{border-radius:var(--radius-md)}.file-selector-scope .border{border-style:var(--tw-border-style);border-width:1px}.file-selector-scope .border-2{border-style:var(--tw-border-style);border-width:2px}.file-selector-scope .border-dashed{--tw-border-style:dashed;border-style:dashed}.file-selector-scope .border-gray-300{border-color:var(--color-gray-300)}.file-selector-scope .border-gray-500{border-color:var(--color-gray-500)}.file-selector-scope .border-zinc-600{border-color:var(--color-zinc-600)}.file-selector-scope .bg-inherit{background-color:inherit}.file-selector-scope .p-4{padding:calc(var(--spacing)*4)}.file-selector-scope .px-4{padding-inline:calc(var(--spacing)*4)}.file-selector-scope .py-2{padding-block:calc(var(--spacing)*2)}.file-selector-scope .text-center{text-align:center}.file-selector-scope .font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.file-selector-scope .text-gray-600{color:var(--color-gray-600)}.file-selector-scope .text-inherit{color:inherit}.file-selector-scope .shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}@media (hover:hover){.file-selector-scope .hover\\:border-gray-400:hover{border-color:var(--color-gray-400)}}}.file-selector-scope .hiddenInput{display:none}@property --tw-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:\"*\";inherits:false}@property --tw-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\"*\";inherits:false}@property --tw-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\"*\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\"*\";inherits:false}@property --tw-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\"*\";inherits:false}@property --tw-inset-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\"*\";inherits:false}@property --tw-ring-offset-width{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\"*\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}";
|
|
3384
3502
|
styleInject(css_248z);
|
|
3385
3503
|
|
|
3386
|
-
const withDragDefaults =
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3504
|
+
const withDragDefaults = handler => {
|
|
3505
|
+
return e => {
|
|
3506
|
+
e.preventDefault();
|
|
3507
|
+
e.stopPropagation();
|
|
3508
|
+
handler(e);
|
|
3509
|
+
};
|
|
3392
3510
|
};
|
|
3393
3511
|
|
|
3394
|
-
const defaultAccept =
|
|
3512
|
+
const defaultAccept = buildAcceptString(defaultTypeExtensions);
|
|
3395
3513
|
const SCOPE_CLASS = "file-selector-scope";
|
|
3396
3514
|
const defaultInputClassName = "hiddenInput";
|
|
3397
3515
|
const defaultClickableAreaClassName = "dropzone border-dashed border-2 border-gray-500 p-4 rounded-md text-center cursor-pointer bg-inherit hover:border-gray-400 text-inherit font-bold py-2 px-4";
|
|
@@ -3399,284 +3517,318 @@ const defaultDropZoneWrapperClassName = "flex flex-col min-h-[120px] border bord
|
|
|
3399
3517
|
const defaultMessageParagraphClassName = "text-center text-gray-600";
|
|
3400
3518
|
const defaultMessageParagraph = "Drag 'n' drop some files here, or click to select files";
|
|
3401
3519
|
const defaultAriaLabel = "File upload drop zone";
|
|
3402
|
-
const defaultAriaDescribedBy = undefined;
|
|
3403
3520
|
const defaultAriaLabelButton = "Choose files to upload";
|
|
3404
|
-
const
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3521
|
+
const FileSelector = ({
|
|
3522
|
+
inputId,
|
|
3523
|
+
accept = defaultAccept,
|
|
3524
|
+
messageParagraph = defaultMessageParagraph,
|
|
3525
|
+
inputClassName,
|
|
3526
|
+
clickableAreaClassName,
|
|
3527
|
+
dropZoneWrapperClassName,
|
|
3528
|
+
messageParagraphClassName,
|
|
3529
|
+
ariaLabel = defaultAriaLabel,
|
|
3530
|
+
ariaDescribedBy,
|
|
3531
|
+
ariaLabelButton = defaultAriaLabelButton,
|
|
3532
|
+
onChange,
|
|
3533
|
+
onDragOver,
|
|
3534
|
+
onDrop,
|
|
3535
|
+
onDragEnter,
|
|
3536
|
+
onDragLeave
|
|
3537
|
+
}) => {
|
|
3538
|
+
const fileInputRef = useRef(null);
|
|
3539
|
+
const messageId = useId();
|
|
3540
|
+
|
|
3541
|
+
//Note, eslint doesn't like that I'm wrapping the anonymous function in withDragDefaults. Ignore for now
|
|
3542
|
+
|
|
3543
|
+
const internalOnClick = withDragDefaults(() => {
|
|
3544
|
+
fileInputRef.current?.click();
|
|
3545
|
+
});
|
|
3546
|
+
const internalOnDrop = withDragDefaults(e => {
|
|
3547
|
+
onDrop(e);
|
|
3548
|
+
});
|
|
3549
|
+
const internalOnDragOver = withDragDefaults(e_0 => {
|
|
3550
|
+
onDragOver(e_0);
|
|
3551
|
+
});
|
|
3552
|
+
const internalOnDragEnter = withDragDefaults(e_1 => {
|
|
3553
|
+
onDragEnter(e_1);
|
|
3554
|
+
});
|
|
3555
|
+
const internalOnDragLeave = withDragDefaults(e_2 => {
|
|
3556
|
+
onDragLeave(e_2);
|
|
3557
|
+
});
|
|
3558
|
+
const inputClasses = mergeStyles(defaultInputClassName, inputClassName);
|
|
3559
|
+
const resolvedClickableAreaClassName = mergeStyles(clickableAreaClassName ?? defaultClickableAreaClassName, "w-full h-full flex-1 min-h-0");
|
|
3560
|
+
const resolvedDropZoneWrapperClassName = mergeStyles(dropZoneWrapperClassName ?? defaultDropZoneWrapperClassName);
|
|
3561
|
+
const resolvedMessageParagraphClassName = mergeStyles(messageParagraphClassName ?? defaultMessageParagraphClassName);
|
|
3562
|
+
const resolvedInputId = inputId ?? messageId;
|
|
3563
|
+
return /*#__PURE__*/jsxs("div", {
|
|
3564
|
+
role: "group",
|
|
3565
|
+
"aria-label": ariaLabel,
|
|
3566
|
+
"aria-describedby": ariaDescribedBy,
|
|
3567
|
+
className: mergeStyles(SCOPE_CLASS, resolvedDropZoneWrapperClassName),
|
|
3568
|
+
draggable: false,
|
|
3569
|
+
children: [/*#__PURE__*/jsx("button", {
|
|
3570
|
+
type: "button",
|
|
3571
|
+
className: resolvedClickableAreaClassName,
|
|
3572
|
+
onClick: internalOnClick,
|
|
3573
|
+
onDragOver: internalOnDragOver,
|
|
3574
|
+
onDrop: internalOnDrop,
|
|
3575
|
+
onDragEnter: internalOnDragEnter,
|
|
3576
|
+
onDragLeave: internalOnDragLeave,
|
|
3577
|
+
draggable: false,
|
|
3578
|
+
"aria-label": ariaLabelButton,
|
|
3579
|
+
"aria-controls": resolvedInputId,
|
|
3580
|
+
children: /*#__PURE__*/jsx("p", {
|
|
3581
|
+
id: messageId,
|
|
3582
|
+
className: resolvedMessageParagraphClassName,
|
|
3583
|
+
children: messageParagraph
|
|
3584
|
+
})
|
|
3585
|
+
}), /*#__PURE__*/jsx("input", {
|
|
3586
|
+
ref: fileInputRef,
|
|
3587
|
+
id: resolvedInputId,
|
|
3588
|
+
type: "file",
|
|
3589
|
+
className: inputClasses,
|
|
3590
|
+
onChange: onChange,
|
|
3591
|
+
accept: accept,
|
|
3592
|
+
multiple: true,
|
|
3593
|
+
"aria-hidden": "true",
|
|
3594
|
+
tabIndex: -1
|
|
3595
|
+
})]
|
|
3596
|
+
});
|
|
3435
3597
|
};
|
|
3436
|
-
const FileSelector = memo(FileSelectorComponent);
|
|
3437
3598
|
FileSelector.displayName = "FileSelector";
|
|
3438
3599
|
|
|
3439
|
-
const
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3600
|
+
const defaultBorder = "border-gray-500";
|
|
3601
|
+
const defaultAlternateBorder = "border-zinc-600";
|
|
3602
|
+
const useFileSelector = ({
|
|
3603
|
+
maximumUploadCount: maximumUploadCount$1 = maximumUploadCount,
|
|
3604
|
+
maximumFileSize: maximumFileSize$1 = maximumFileSize,
|
|
3605
|
+
acceptedTypes = defaultTypeExtensions
|
|
3606
|
+
} = {}) => {
|
|
3607
|
+
const [, setUpdateTrigger] = useState(0);
|
|
3608
|
+
const [validFiles, SetValidFiles] = useState([]);
|
|
3609
|
+
const [invalidFiles, SetInvalidFiles] = useState([]);
|
|
3610
|
+
const dragDepthRef = useRef(0);
|
|
3611
|
+
const callIdRef = useRef(0);
|
|
3612
|
+
const borderClassRef = useRef(defaultAlternateBorder);
|
|
3613
|
+
const maxUploadErrorRef = useRef({
|
|
3614
|
+
status: false,
|
|
3615
|
+
message: ""
|
|
3616
|
+
});
|
|
3617
|
+
const maxFileSizeErrorRef = useRef({
|
|
3618
|
+
status: false,
|
|
3619
|
+
message: ""
|
|
3620
|
+
});
|
|
3621
|
+
const setMaximumUploadsExceeded = (status = false, fileCount, maximumUploads) => {
|
|
3622
|
+
maxUploadErrorRef.current.status = status;
|
|
3623
|
+
maxUploadErrorRef.current.message = status ? `You have attempted to upload ${fileCount} files. The maximum allowable uploads for this feature is ${maximumUploads}` : "";
|
|
3624
|
+
setUpdateTrigger(state => state + 1);
|
|
3625
|
+
};
|
|
3626
|
+
const setMaximumFileSizeExceeded = (status_0 = false) => {
|
|
3627
|
+
maxFileSizeErrorRef.current.status = status_0;
|
|
3628
|
+
maxFileSizeErrorRef.current.message = status_0 ? `You have attempted to upload a file(s) that exceeds the maximum size of ${formatFileSize(maximumFileSize$1)}` : "";
|
|
3629
|
+
setUpdateTrigger(state_0 => state_0 + 1);
|
|
3630
|
+
};
|
|
3631
|
+
const clearBlobs = () => {
|
|
3632
|
+
let i = 0;
|
|
3633
|
+
while (i < validFiles.length) {
|
|
3634
|
+
const file = validFiles[i].file;
|
|
3635
|
+
if (file instanceof File) {
|
|
3636
|
+
clearBlobFromMemory(file);
|
|
3637
|
+
}
|
|
3638
|
+
i++;
|
|
3462
3639
|
}
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
}
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
if (file instanceof File) {
|
|
3500
|
-
clearBlobFromMemory(file);
|
|
3501
|
-
}
|
|
3502
|
-
i++;
|
|
3503
|
-
}
|
|
3504
|
-
}, [validFiles]);
|
|
3505
|
-
const clearCache = useCustomCallback(() => {
|
|
3506
|
-
//Clear any blobs held in memory
|
|
3507
|
-
clearBlobs();
|
|
3508
|
-
SetInvalidFiles([]);
|
|
3509
|
-
SetValidFiles([]);
|
|
3510
|
-
}, [clearBlobs]);
|
|
3511
|
-
useEffect(() => {
|
|
3512
|
-
return () => {
|
|
3513
|
-
clearCache();
|
|
3514
|
-
};
|
|
3515
|
-
}, [clearCache]);
|
|
3516
|
-
const onCancel = useCustomCallback(() => {
|
|
3517
|
-
clearCache();
|
|
3518
|
-
}, [clearCache]);
|
|
3519
|
-
const getValidFileStreams = useCallback(() => (validFiles.length ? validFiles.map(({ file }) => file) : []), [validFiles]);
|
|
3520
|
-
//Main Engine to deal with files
|
|
3521
|
-
const processFiles = useCustomCallback((files) => {
|
|
3522
|
-
const maxFileSizeCheck = checkFilesMaximumSize(files, maximumFileSize$1) && !maxFileSizeErrorRef.current.status;
|
|
3523
|
-
const maxUploadCountCheck = typeof maximumUploadCount$1 !== "undefined"
|
|
3524
|
-
? !maxUploadErrorRef.current.status && files.length > maximumUploadCount$1
|
|
3525
|
-
: false;
|
|
3526
|
-
if (maxFileSizeCheck || maxUploadCountCheck) {
|
|
3527
|
-
if (maxFileSizeCheck)
|
|
3528
|
-
setMaximumFileSizeExceeded(true);
|
|
3529
|
-
if (maxUploadCountCheck)
|
|
3530
|
-
setMaximumUploadsExceeded(true, files.length, maximumUploadCount$1);
|
|
3531
|
-
onCancel();
|
|
3532
|
-
}
|
|
3533
|
-
else {
|
|
3534
|
-
const valid = [];
|
|
3535
|
-
const invalid = [];
|
|
3536
|
-
let i = 0;
|
|
3537
|
-
while (i < files.length) {
|
|
3538
|
-
const file = files[i];
|
|
3539
|
-
if (isValidFileType(file, acceptedTypes)) {
|
|
3540
|
-
valid.push(SvgXmlnsAttributeCheck(file, acceptedTypes));
|
|
3541
|
-
}
|
|
3542
|
-
else {
|
|
3543
|
-
invalid.push(file);
|
|
3544
|
-
}
|
|
3545
|
-
i++;
|
|
3546
|
-
}
|
|
3547
|
-
if (valid.length > 0) {
|
|
3548
|
-
Promise.all(valid)
|
|
3549
|
-
.then((results) => {
|
|
3550
|
-
const filteredResults = [];
|
|
3551
|
-
let j = 0;
|
|
3552
|
-
while (j < results.length) {
|
|
3553
|
-
const result = results[j];
|
|
3554
|
-
if (result !== null) {
|
|
3555
|
-
filteredResults.push(result);
|
|
3556
|
-
}
|
|
3557
|
-
j++;
|
|
3558
|
-
}
|
|
3559
|
-
SetValidFiles(filteredResults);
|
|
3560
|
-
})
|
|
3561
|
-
.catch((error) => {
|
|
3562
|
-
console.error("File processing error:", error);
|
|
3563
|
-
// Optionally expose error state to engineers
|
|
3564
|
-
SetInvalidFiles(invalid.concat(files)); // Treat all as invalid on error
|
|
3565
|
-
});
|
|
3566
|
-
}
|
|
3567
|
-
if (invalid.length > 0) {
|
|
3568
|
-
SetInvalidFiles(invalid);
|
|
3569
|
-
}
|
|
3640
|
+
};
|
|
3641
|
+
const clearCache = () => {
|
|
3642
|
+
clearBlobs();
|
|
3643
|
+
SetInvalidFiles([]);
|
|
3644
|
+
SetValidFiles([]);
|
|
3645
|
+
setMaximumUploadsExceeded(false);
|
|
3646
|
+
setMaximumFileSizeExceeded(false);
|
|
3647
|
+
};
|
|
3648
|
+
const onCancel = () => {
|
|
3649
|
+
clearCache();
|
|
3650
|
+
};
|
|
3651
|
+
const getValidFileStreams = () => validFiles.length ? validFiles.map(({
|
|
3652
|
+
file: file_0
|
|
3653
|
+
}) => file_0) : [];
|
|
3654
|
+
const processFiles = files => {
|
|
3655
|
+
const callId = ++callIdRef.current;
|
|
3656
|
+
const maxFileSizeCheck = checkFilesMaximumSize(files, maximumFileSize$1);
|
|
3657
|
+
if (maxFileSizeCheck) {
|
|
3658
|
+
if (!maxFileSizeErrorRef.current.status) {
|
|
3659
|
+
setMaximumFileSizeExceeded(true);
|
|
3660
|
+
}
|
|
3661
|
+
SetValidFiles([]);
|
|
3662
|
+
SetInvalidFiles([]);
|
|
3663
|
+
} else {
|
|
3664
|
+
const valid = [];
|
|
3665
|
+
const invalid = [];
|
|
3666
|
+
let i_0 = 0;
|
|
3667
|
+
while (i_0 < files.length) {
|
|
3668
|
+
const file_1 = files[i_0];
|
|
3669
|
+
if (isValidFileType(file_1, acceptedTypes)) {
|
|
3670
|
+
valid.push({
|
|
3671
|
+
file: file_1,
|
|
3672
|
+
promise: svgXmlnsAttributeCheck(file_1, acceptedTypes)
|
|
3673
|
+
});
|
|
3674
|
+
} else {
|
|
3675
|
+
invalid.push(file_1);
|
|
3570
3676
|
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
if (file instanceof File) {
|
|
3586
|
-
clearBlobFromMemory(file);
|
|
3587
|
-
}
|
|
3588
|
-
}
|
|
3589
|
-
else {
|
|
3590
|
-
updatedValidFiles.push(validFiles[i]);
|
|
3677
|
+
i_0++;
|
|
3678
|
+
}
|
|
3679
|
+
if (valid.length > 0) {
|
|
3680
|
+
Promise.all(valid.map(v => v.promise)).then(results => {
|
|
3681
|
+
if (callId !== callIdRef.current) return;
|
|
3682
|
+
const filteredResults = [];
|
|
3683
|
+
const nullFiles = [];
|
|
3684
|
+
let j = 0;
|
|
3685
|
+
while (j < results.length) {
|
|
3686
|
+
const result = results[j];
|
|
3687
|
+
if (result !== null) {
|
|
3688
|
+
filteredResults.push(result);
|
|
3689
|
+
} else {
|
|
3690
|
+
nullFiles.push(valid[j].file);
|
|
3591
3691
|
}
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
if (
|
|
3599
|
-
|
|
3600
|
-
|
|
3692
|
+
j++;
|
|
3693
|
+
}
|
|
3694
|
+
if (nullFiles.length > 0) {
|
|
3695
|
+
SetInvalidFiles(state_1 => state_1.concat(nullFiles));
|
|
3696
|
+
}
|
|
3697
|
+
SetValidFiles(current => {
|
|
3698
|
+
if (current.length + filteredResults.length > maximumUploadCount$1) {
|
|
3699
|
+
setMaximumUploadsExceeded(true, current.length + filteredResults.length, maximumUploadCount$1);
|
|
3700
|
+
return current;
|
|
3601
3701
|
}
|
|
3602
|
-
return
|
|
3702
|
+
return current.concat(filteredResults);
|
|
3703
|
+
});
|
|
3704
|
+
}).catch(() => {
|
|
3705
|
+
SetInvalidFiles(state_2 => state_2.concat(valid.map(v_0 => v_0.file)));
|
|
3603
3706
|
});
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
const
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
const createFileSelectorComponent = (handlers) => {
|
|
3638
|
-
const handlerProps = {
|
|
3639
|
-
onChange: handlers.onInputChange,
|
|
3640
|
-
onDragOver: handlers.onDragOver,
|
|
3641
|
-
onDrop: handlers.onDrop,
|
|
3642
|
-
onDragEnter: handlers.onDragEnter,
|
|
3643
|
-
onDragLeave: handlers.onDragLeave,
|
|
3707
|
+
}
|
|
3708
|
+
if (invalid.length > 0) {
|
|
3709
|
+
SetInvalidFiles(state_3 => state_3.concat(invalid));
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
};
|
|
3713
|
+
const onRemoveFile = index => {
|
|
3714
|
+
const updatedValidFiles = [];
|
|
3715
|
+
let i_1 = 0;
|
|
3716
|
+
while (i_1 < validFiles.length) {
|
|
3717
|
+
if (i_1 === index) {
|
|
3718
|
+
const file_2 = validFiles[i_1].file;
|
|
3719
|
+
if (file_2 instanceof File) {
|
|
3720
|
+
clearBlobFromMemory(file_2);
|
|
3721
|
+
}
|
|
3722
|
+
} else {
|
|
3723
|
+
updatedValidFiles.push(validFiles[i_1]);
|
|
3724
|
+
}
|
|
3725
|
+
i_1++;
|
|
3726
|
+
}
|
|
3727
|
+
SetValidFiles(updatedValidFiles);
|
|
3728
|
+
};
|
|
3729
|
+
const onIdChange = (index_0, id, files_0) => {
|
|
3730
|
+
const updatedValidFiles_0 = files_0.map((fileData, i_2) => {
|
|
3731
|
+
if (i_2 === index_0) {
|
|
3732
|
+
if (fileData.file instanceof File) clearBlobFromMemory(fileData.file);
|
|
3733
|
+
const renamedFile = renameFile(id, fileData.file);
|
|
3734
|
+
const newUrl = renamedFile instanceof File ? createUrlString(renamedFile) : fileData.url;
|
|
3735
|
+
return {
|
|
3736
|
+
...fileData,
|
|
3737
|
+
file: renamedFile,
|
|
3738
|
+
id,
|
|
3739
|
+
url: newUrl
|
|
3644
3740
|
};
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
const
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3741
|
+
}
|
|
3742
|
+
return fileData;
|
|
3743
|
+
});
|
|
3744
|
+
SetValidFiles(updatedValidFiles_0);
|
|
3745
|
+
};
|
|
3746
|
+
const onInputChange = event => {
|
|
3747
|
+
const files_1 = Array.from(event.target.files || []);
|
|
3748
|
+
processFiles(files_1);
|
|
3749
|
+
event.target.value = "";
|
|
3750
|
+
};
|
|
3751
|
+
const onDrop = e => {
|
|
3752
|
+
e.preventDefault();
|
|
3753
|
+
dragDepthRef.current = 0;
|
|
3754
|
+
const {
|
|
3755
|
+
classList
|
|
3756
|
+
} = e.currentTarget;
|
|
3757
|
+
classList.remove(defaultBorder);
|
|
3758
|
+
classList.add(borderClassRef.current);
|
|
3759
|
+
processFiles(Array.from(e.dataTransfer.files));
|
|
3760
|
+
};
|
|
3761
|
+
const onDragOver = e_0 => {
|
|
3762
|
+
e_0.preventDefault();
|
|
3763
|
+
e_0.dataTransfer.dropEffect = "copy";
|
|
3764
|
+
};
|
|
3765
|
+
const onDragEnter = e_1 => {
|
|
3766
|
+
e_1.preventDefault();
|
|
3767
|
+
dragDepthRef.current++;
|
|
3768
|
+
const {
|
|
3769
|
+
classList: classList_0
|
|
3770
|
+
} = e_1.currentTarget;
|
|
3771
|
+
classList_0.remove(borderClassRef.current);
|
|
3772
|
+
classList_0.add(defaultBorder);
|
|
3773
|
+
};
|
|
3774
|
+
const onDragLeave = e_2 => {
|
|
3775
|
+
e_2.preventDefault();
|
|
3776
|
+
dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
|
|
3777
|
+
if (dragDepthRef.current > 0) return;
|
|
3778
|
+
const {
|
|
3779
|
+
classList: classList_1
|
|
3780
|
+
} = e_2.currentTarget;
|
|
3781
|
+
classList_1.remove(defaultBorder);
|
|
3782
|
+
classList_1.add(borderClassRef.current);
|
|
3783
|
+
};
|
|
3784
|
+
const acceptRef = useRef(buildAcceptString(acceptedTypes));
|
|
3785
|
+
const BoundFileSelector = ({
|
|
3786
|
+
inputId,
|
|
3787
|
+
messageParagraph,
|
|
3788
|
+
inputClassName,
|
|
3789
|
+
clickableAreaClassName,
|
|
3790
|
+
dropZoneWrapperClassName,
|
|
3791
|
+
messageParagraphClassName,
|
|
3792
|
+
ariaLabel,
|
|
3793
|
+
ariaDescribedBy,
|
|
3794
|
+
ariaLabelButton
|
|
3795
|
+
}) => {
|
|
3796
|
+
borderClassRef.current = clickableAreaClassName ?? defaultAlternateBorder;
|
|
3797
|
+
return /*#__PURE__*/jsx(FileSelector, {
|
|
3798
|
+
inputId: inputId,
|
|
3799
|
+
messageParagraph: messageParagraph,
|
|
3800
|
+
inputClassName: inputClassName,
|
|
3801
|
+
clickableAreaClassName: clickableAreaClassName,
|
|
3802
|
+
dropZoneWrapperClassName: dropZoneWrapperClassName,
|
|
3803
|
+
messageParagraphClassName: messageParagraphClassName,
|
|
3804
|
+
ariaLabel: ariaLabel,
|
|
3805
|
+
ariaDescribedBy: ariaDescribedBy,
|
|
3806
|
+
ariaLabelButton: ariaLabelButton,
|
|
3807
|
+
onChange: onInputChange,
|
|
3808
|
+
onDragOver: onDragOver,
|
|
3809
|
+
onDrop: onDrop,
|
|
3810
|
+
onDragEnter: onDragEnter,
|
|
3811
|
+
onDragLeave: onDragLeave,
|
|
3812
|
+
accept: acceptRef.current
|
|
3813
|
+
});
|
|
3814
|
+
};
|
|
3815
|
+
BoundFileSelector.displayName = "FileSelectorWrapper";
|
|
3816
|
+
return {
|
|
3817
|
+
validFiles,
|
|
3818
|
+
invalidFiles,
|
|
3819
|
+
clearCache,
|
|
3820
|
+
getValidFileStreams,
|
|
3821
|
+
onCancel,
|
|
3822
|
+
onIdChange,
|
|
3823
|
+
onRemoveFile,
|
|
3824
|
+
clearBlobs,
|
|
3825
|
+
clearBlob: clearBlobFromMemory,
|
|
3826
|
+
maxUploadError: maxUploadErrorRef.current,
|
|
3827
|
+
maxFileSizeError: maxFileSizeErrorRef.current,
|
|
3828
|
+
setMaximumFileSizeExceeded,
|
|
3829
|
+
setMaximumUploadsExceeded,
|
|
3830
|
+
FileSelector: BoundFileSelector
|
|
3831
|
+
};
|
|
3680
3832
|
};
|
|
3681
3833
|
|
|
3682
3834
|
export { useFileSelector };
|