ics-ui-kit 0.1.5 → 0.1.7
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/dist/components/file-upload/FileUpload.d.ts +1 -0
- package/dist/components/file-upload/FileUpload.stories.d.ts +1 -0
- package/dist/components/file-upload/components/file-upload-compact-input-zone/FileUploadCompactInputZone.d.ts +1 -1
- package/dist/components/file-upload/components/file-upload-input-zone/FileUploadInputZone.d.ts +1 -1
- package/dist/components/file-upload/components/file-upload-item/FileUploadItem.d.ts +2 -0
- package/dist/components/file-upload/components/file-upload-item/FileUploadItem.stories.d.ts +1 -0
- package/dist/components/file-upload/components/file-upload-item-compact/FileUploadItemCompact.d.ts +2 -0
- package/dist/components/file-upload/components/file-upload-item-compact/FileUploadItemCompact.stories.d.ts +1 -0
- package/dist/components/file-upload/file-upload-compact/FileUploadCompact.d.ts +1 -0
- package/dist/components/file-upload/file-upload-compact/FileUploadCompact.stories.d.ts +1 -0
- package/dist/components/file-upload.js +194 -185
- package/dist/components/file-upload.js.map +1 -1
- package/dist/components/resizable/components/ResizableCornerIcon.d.ts +3 -0
- package/dist/components/resizable/components/ResizableCornerIcon.stories.d.ts +7 -0
- package/dist/components/resizable/index.d.ts +1 -0
- package/dist/components/resizable.js +255 -232
- package/dist/components/resizable.js.map +1 -1
- package/dist/formatBytes-C4QXq5lC.js +9 -0
- package/dist/formatBytes-C4QXq5lC.js.map +1 -0
- package/dist/hooks/use-file-upload.js +1 -1
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils.js +4 -2
- package/dist/lib/utils.js.map +1 -1
- package/dist/styles-scoped.css +10 -2
- package/dist/styles.css +10 -2
- package/dist/theme.css +2 -0
- package/dist/useFileUpload-Bnl3P8mP.js +193 -0
- package/dist/useFileUpload-Bnl3P8mP.js.map +1 -0
- package/package.json +1 -1
- package/tailwind.preset.js +4 -3
- package/dist/useFileUpload-iDag0iqM.js +0 -197
- package/dist/useFileUpload-iDag0iqM.js.map +0 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const e = (t, o = 2) => {
|
|
2
|
+
if (t === 0) return "0 Bytes";
|
|
3
|
+
const B = 1024, s = o < 0 ? 0 : o, a = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], r = Math.floor(Math.log(t) / Math.log(B));
|
|
4
|
+
return `${Number.parseFloat((t / Math.pow(B, r)).toFixed(s))} ${a[r]}`;
|
|
5
|
+
};
|
|
6
|
+
export {
|
|
7
|
+
e as f
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=formatBytes-C4QXq5lC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatBytes-C4QXq5lC.js","sources":["../src/lib/utils/file/formatBytes.ts"],"sourcesContent":["// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n\tif (bytes === 0) return \"0 Bytes\";\n\n\tconst k = 1024;\n\tconst dm = decimals < 0 ? 0 : decimals;\n\tconst sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\n\treturn `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\n};\n"],"names":["formatBytes","bytes","decimals","k","dm","sizes","i"],"mappings":"AACO,MAAMA,IAAc,CAACC,GAAeC,IAAW,MAAc;AAC/D,MAAAD,MAAU,EAAU,QAAA;AAExB,QAAME,IAAI,MACJC,IAAKF,IAAW,IAAI,IAAIA,GACxBG,IAAQ,CAAC,SAAS,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI,GAEhEC,IAAI,KAAK,MAAM,KAAK,IAAIL,CAAK,IAAI,KAAK,IAAIE,CAAC,CAAC;AAElD,SAAO,GAAG,OAAO,YAAYF,IAAQ,KAAK,IAAIE,GAAGG,CAAC,GAAG,QAAQF,CAAE,CAAC,CAAC,IAAIC,EAAMC,CAAC,CAAC;AAC9E;"}
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { c as
|
|
1
|
+
import { c as i } from "../cn-dsXlqdJg.js";
|
|
2
|
+
import { f as c } from "../formatBytes-C4QXq5lC.js";
|
|
2
3
|
function n(r) {
|
|
3
4
|
if (r === 0 || r < 0)
|
|
4
5
|
return "";
|
|
@@ -19,7 +20,8 @@ function n(r) {
|
|
|
19
20
|
return String(r);
|
|
20
21
|
}
|
|
21
22
|
export {
|
|
22
|
-
|
|
23
|
+
i as cn,
|
|
24
|
+
c as formatBytes,
|
|
23
25
|
n as formatCounterValue
|
|
24
26
|
};
|
|
25
27
|
//# sourceMappingURL=utils.js.map
|
package/dist/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../src/lib/utils/formatCounterValue.ts"],"sourcesContent":["/**\n * Форматирует число для отображения в компоненте Counter согласно правилам:\n * - Максимум 4 символа, включая `+`\n * - 0 не отображается\n * - Без дробей\n *\n * @param value - Число для форматирования\n * @returns Отформатированная строка или пустая строка для 0\n *\n * @example\n * formatCounterValue(5) // \"5\"\n * formatCounterValue(42) // \"42\"\n * formatCounterValue(150) // \"99+\"\n * formatCounterValue(5000) // \"999+\"\n * formatCounterValue(50000) // \"10k+\"\n * formatCounterValue(2000000) // \"2М+\"\n * formatCounterValue(10000000) // \"10М+\"\n * formatCounterValue(99000000) // \"99М+\"\n * formatCounterValue(0) // \"\"\n */\nexport function formatCounterValue(value: number): string {\n\t// 0 не отображаем\n\tif (value === 0) {\n\t\treturn \"\";\n\t}\n\n\t// Отрицательные числа не поддерживаются\n\tif (value < 0) {\n\t\treturn \"\";\n\t}\n\n\t// 1-9: показать одну цифру\n\tif (value >= 1 && value <= 9) {\n\t\treturn String(value);\n\t}\n\n\t// 10-99: показать две цифры\n\tif (value >= 10 && value <= 99) {\n\t\treturn String(value);\n\t}\n\n\t// 100-999: показать \"99+\"\n\tif (value >= 100 && value <= 999) {\n\t\treturn \"99+\";\n\t}\n\n\t// 1 000-9 999: показать \"999+\"\n\tif (value >= 1000 && value <= 9999) {\n\t\treturn \"999+\";\n\t}\n\n\t// 10 000-999 999: показать \"10k+\", \"99k+\" и т.д.\n\tif (value >= 10000 && value <= 999999) {\n\t\tconst thousands = Math.floor(value / 1000);\n\t\t// Проверяем, что результат не превышает 4 символа\n\t\tif (thousands <= 99) {\n\t\t\treturn `${thousands}k+`;\n\t\t}\n\t\t// Если больше 99k, показываем 99k+\n\t\treturn \"99k+\";\n\t}\n\n\t// ≥ 1 000 000: показать \"1М+\", \"9М+\", \"10М+\", \"99М+\" и т.д.\n\tif (value >= 1000000) {\n\t\tconst millions = Math.floor(value / 1000000);\n\t\t// 1-9 млн и 10-98 млн\"\n\t\tif ((millions >= 1 && millions <= 9) || (millions >= 10 && millions <= 98)) {\n\t\t\treturn `${millions}М+`;\n\t\t}\n\t\t// 99 млн и выше: всегда \"99М+\"\n\t\treturn \"99М+\";\n\t}\n\n\t// Fallback (не должно произойти)\n\treturn String(value);\n}\n"],"names":["formatCounterValue","value","thousands","millions"],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../src/lib/utils/formatCounterValue.ts"],"sourcesContent":["/**\n * Форматирует число для отображения в компоненте Counter согласно правилам:\n * - Максимум 4 символа, включая `+`\n * - 0 не отображается\n * - Без дробей\n *\n * @param value - Число для форматирования\n * @returns Отформатированная строка или пустая строка для 0\n *\n * @example\n * formatCounterValue(5) // \"5\"\n * formatCounterValue(42) // \"42\"\n * formatCounterValue(150) // \"99+\"\n * formatCounterValue(5000) // \"999+\"\n * formatCounterValue(50000) // \"10k+\"\n * formatCounterValue(2000000) // \"2М+\"\n * formatCounterValue(10000000) // \"10М+\"\n * formatCounterValue(99000000) // \"99М+\"\n * formatCounterValue(0) // \"\"\n */\nexport function formatCounterValue(value: number): string {\n\t// 0 не отображаем\n\tif (value === 0) {\n\t\treturn \"\";\n\t}\n\n\t// Отрицательные числа не поддерживаются\n\tif (value < 0) {\n\t\treturn \"\";\n\t}\n\n\t// 1-9: показать одну цифру\n\tif (value >= 1 && value <= 9) {\n\t\treturn String(value);\n\t}\n\n\t// 10-99: показать две цифры\n\tif (value >= 10 && value <= 99) {\n\t\treturn String(value);\n\t}\n\n\t// 100-999: показать \"99+\"\n\tif (value >= 100 && value <= 999) {\n\t\treturn \"99+\";\n\t}\n\n\t// 1 000-9 999: показать \"999+\"\n\tif (value >= 1000 && value <= 9999) {\n\t\treturn \"999+\";\n\t}\n\n\t// 10 000-999 999: показать \"10k+\", \"99k+\" и т.д.\n\tif (value >= 10000 && value <= 999999) {\n\t\tconst thousands = Math.floor(value / 1000);\n\t\t// Проверяем, что результат не превышает 4 символа\n\t\tif (thousands <= 99) {\n\t\t\treturn `${thousands}k+`;\n\t\t}\n\t\t// Если больше 99k, показываем 99k+\n\t\treturn \"99k+\";\n\t}\n\n\t// ≥ 1 000 000: показать \"1М+\", \"9М+\", \"10М+\", \"99М+\" и т.д.\n\tif (value >= 1000000) {\n\t\tconst millions = Math.floor(value / 1000000);\n\t\t// 1-9 млн и 10-98 млн\"\n\t\tif ((millions >= 1 && millions <= 9) || (millions >= 10 && millions <= 98)) {\n\t\t\treturn `${millions}М+`;\n\t\t}\n\t\t// 99 млн и выше: всегда \"99М+\"\n\t\treturn \"99М+\";\n\t}\n\n\t// Fallback (не должно произойти)\n\treturn String(value);\n}\n"],"names":["formatCounterValue","value","thousands","millions"],"mappings":";;AAoBO,SAASA,EAAmBC,GAAuB;AAOzD,MALIA,MAAU,KAKVA,IAAQ;AACJ,WAAA;AASJ,MALAA,KAAS,KAAKA,KAAS,KAKvBA,KAAS,MAAMA,KAAS;AAC3B,WAAO,OAAOA,CAAK;AAIhB,MAAAA,KAAS,OAAOA,KAAS;AACrB,WAAA;AAIJ,MAAAA,KAAS,OAAQA,KAAS;AACtB,WAAA;AAIJ,MAAAA,KAAS,OAASA,KAAS,QAAQ;AACtC,UAAMC,IAAY,KAAK,MAAMD,IAAQ,GAAI;AAEzC,WAAIC,KAAa,KACT,GAAGA,CAAS,OAGb;AAAA,EAAA;AAIR,MAAID,KAAS,KAAS;AACrB,UAAME,IAAW,KAAK,MAAMF,IAAQ,GAAO;AAE3C,WAAKE,KAAY,KAAKA,KAAY,KAAOA,KAAY,MAAMA,KAAY,KAC/D,GAAGA,CAAQ,OAGZ;AAAA,EAAA;AAIR,SAAO,OAAOF,CAAK;AACpB;"}
|
package/dist/styles-scoped.css
CHANGED
|
@@ -181,6 +181,7 @@
|
|
|
181
181
|
|
|
182
182
|
--shadow-glass-sm: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 0 40px 30px -40px rgba(0, 0, 0, 0.16) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-secondary-border, #E4E4E7), 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
|
183
183
|
--shadow-glass-md: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-primary-border, #D4D4D8), 0 4px 24px 0 rgba(0, 0, 0, 0.12);
|
|
184
|
+
--shadow-glass-lg: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-secondary-border, #E4E4E7), 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
|
184
185
|
}
|
|
185
186
|
.dark {
|
|
186
187
|
/**
|
|
@@ -344,6 +345,7 @@
|
|
|
344
345
|
|
|
345
346
|
--shadow-glass-sm: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -40px 80px -40px rgba(255, 255, 255, 0.30) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 16px 0 rgba(0, 0, 0, 0.04);
|
|
346
347
|
--shadow-glass-md: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -20px 250px -100px rgba(255, 255, 255, 0.20) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 48px 0 rgba(0, 0, 0, 0.48);
|
|
348
|
+
--shadow-glass-lg: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -20px 250px -100px rgba(255, 255, 255, 0.20) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 16px 0 rgba(0, 0, 0, 0.04);
|
|
347
349
|
}
|
|
348
350
|
.backdrop-glass-clear {
|
|
349
351
|
backdrop-filter: var(--glass-clear);
|
|
@@ -1440,6 +1442,9 @@
|
|
|
1440
1442
|
.ui-kit .right-0 {
|
|
1441
1443
|
right: 0px;
|
|
1442
1444
|
}
|
|
1445
|
+
.ui-kit .right-0\.5 {
|
|
1446
|
+
right: 0.125rem;
|
|
1447
|
+
}
|
|
1443
1448
|
.ui-kit .right-1 {
|
|
1444
1449
|
right: 0.25rem;
|
|
1445
1450
|
}
|
|
@@ -3002,13 +3007,13 @@
|
|
|
3002
3007
|
background-color: hsl(var(--alpha-50));
|
|
3003
3008
|
}
|
|
3004
3009
|
.ui-kit .bg-alpha-60 {
|
|
3005
|
-
background-color: hsl(var(--alpha-
|
|
3010
|
+
background-color: hsl(var(--alpha-40));
|
|
3006
3011
|
}
|
|
3007
3012
|
.ui-kit .bg-alpha-high-20 {
|
|
3008
3013
|
background-color: hsl(var(--alpha-high-80));
|
|
3009
3014
|
}
|
|
3010
3015
|
.ui-kit .bg-alpha-high-60 {
|
|
3011
|
-
background-color: hsl(var(--alpha-high-
|
|
3016
|
+
background-color: hsl(var(--alpha-high-40));
|
|
3012
3017
|
}
|
|
3013
3018
|
.ui-kit .bg-alpha-high-80 {
|
|
3014
3019
|
background-color: hsl(var(--alpha-high-20));
|
|
@@ -6103,6 +6108,9 @@
|
|
|
6103
6108
|
visibility: visible;
|
|
6104
6109
|
}
|
|
6105
6110
|
}
|
|
6111
|
+
.ui-kit .\[\&\:\:-webkit-resizer\]\:appearance-none::-webkit-resizer {
|
|
6112
|
+
appearance: none;
|
|
6113
|
+
}
|
|
6106
6114
|
.ui-kit .\[\&\:\:-webkit-search-cancel-button\]\:hidden::-webkit-search-cancel-button {
|
|
6107
6115
|
display: none;
|
|
6108
6116
|
}
|
package/dist/styles.css
CHANGED
|
@@ -181,6 +181,7 @@
|
|
|
181
181
|
|
|
182
182
|
--shadow-glass-sm: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 0 40px 30px -40px rgba(0, 0, 0, 0.16) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-secondary-border, #E4E4E7), 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
|
183
183
|
--shadow-glass-md: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-primary-border, #D4D4D8), 0 4px 24px 0 rgba(0, 0, 0, 0.12);
|
|
184
|
+
--shadow-glass-lg: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-secondary-border, #E4E4E7), 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
|
184
185
|
}
|
|
185
186
|
.dark {
|
|
186
187
|
/**
|
|
@@ -344,6 +345,7 @@
|
|
|
344
345
|
|
|
345
346
|
--shadow-glass-sm: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -40px 80px -40px rgba(255, 255, 255, 0.30) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 16px 0 rgba(0, 0, 0, 0.04);
|
|
346
347
|
--shadow-glass-md: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -20px 250px -100px rgba(255, 255, 255, 0.20) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 48px 0 rgba(0, 0, 0, 0.48);
|
|
348
|
+
--shadow-glass-lg: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -20px 250px -100px rgba(255, 255, 255, 0.20) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 16px 0 rgba(0, 0, 0, 0.04);
|
|
347
349
|
}
|
|
348
350
|
.backdrop-glass-clear {
|
|
349
351
|
backdrop-filter: var(--glass-clear);
|
|
@@ -1425,6 +1427,9 @@ body {
|
|
|
1425
1427
|
.right-0 {
|
|
1426
1428
|
right: 0px;
|
|
1427
1429
|
}
|
|
1430
|
+
.right-0\.5 {
|
|
1431
|
+
right: 0.125rem;
|
|
1432
|
+
}
|
|
1428
1433
|
.right-1 {
|
|
1429
1434
|
right: 0.25rem;
|
|
1430
1435
|
}
|
|
@@ -2987,13 +2992,13 @@ body {
|
|
|
2987
2992
|
background-color: hsl(var(--alpha-50));
|
|
2988
2993
|
}
|
|
2989
2994
|
.bg-alpha-60 {
|
|
2990
|
-
background-color: hsl(var(--alpha-
|
|
2995
|
+
background-color: hsl(var(--alpha-40));
|
|
2991
2996
|
}
|
|
2992
2997
|
.bg-alpha-high-20 {
|
|
2993
2998
|
background-color: hsl(var(--alpha-high-80));
|
|
2994
2999
|
}
|
|
2995
3000
|
.bg-alpha-high-60 {
|
|
2996
|
-
background-color: hsl(var(--alpha-high-
|
|
3001
|
+
background-color: hsl(var(--alpha-high-40));
|
|
2997
3002
|
}
|
|
2998
3003
|
.bg-alpha-high-80 {
|
|
2999
3004
|
background-color: hsl(var(--alpha-high-20));
|
|
@@ -6092,6 +6097,9 @@ body {
|
|
|
6092
6097
|
visibility: visible;
|
|
6093
6098
|
}
|
|
6094
6099
|
}
|
|
6100
|
+
.\[\&\:\:-webkit-resizer\]\:appearance-none::-webkit-resizer {
|
|
6101
|
+
appearance: none;
|
|
6102
|
+
}
|
|
6095
6103
|
.\[\&\:\:-webkit-search-cancel-button\]\:hidden::-webkit-search-cancel-button {
|
|
6096
6104
|
display: none;
|
|
6097
6105
|
}
|
package/dist/theme.css
CHANGED
|
@@ -180,6 +180,7 @@
|
|
|
180
180
|
|
|
181
181
|
--shadow-glass-sm: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 0 40px 30px -40px rgba(0, 0, 0, 0.16) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-secondary-border, #E4E4E7), 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
|
182
182
|
--shadow-glass-md: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-primary-border, #D4D4D8), 0 4px 24px 0 rgba(0, 0, 0, 0.12);
|
|
183
|
+
--shadow-glass-lg: 0 1.5px 1.5px -0.5px rgb(255, 255, 255) inset, 0 -6px 3px -3px rgb(255, 255, 255) inset, 1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), -1.25px 0 0 -0.75px var(--tailwind-colors-zinc-400, #A1A1AA), 0 0 0 0.5px var(--base-secondary-border, #E4E4E7), 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
.dark {
|
|
@@ -344,6 +345,7 @@
|
|
|
344
345
|
|
|
345
346
|
--shadow-glass-sm: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -40px 80px -40px rgba(255, 255, 255, 0.30) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 16px 0 rgba(0, 0, 0, 0.04);
|
|
346
347
|
--shadow-glass-md: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -20px 250px -100px rgba(255, 255, 255, 0.20) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 48px 0 rgba(0, 0, 0, 0.48);
|
|
348
|
+
--shadow-glass-lg: 0 1px 1px -0.5px rgba(255, 255, 255, 0.40) inset, 0 -1px 1px -0.5px rgba(255, 255, 255, 0.30) inset, 0 -20px 250px -100px rgba(255, 255, 255, 0.20) inset, 1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), -1.25px 0 0 -0.75px rgba(0, 0, 0, 0.50), 0 0 0 0.5px rgba(0, 0, 0, 0.50), 0 8px 16px 0 rgba(0, 0, 0, 0.04);
|
|
347
349
|
}
|
|
348
350
|
|
|
349
351
|
.backdrop-glass-clear {
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { useMemo as W, useState as k, useRef as O, useCallback as n } from "react";
|
|
2
|
+
import { f as h } from "./formatBytes-C4QXq5lC.js";
|
|
3
|
+
const j = {
|
|
4
|
+
fileTooLarge: (s, c) => `File "${s}" exceeds the maximum size of ${h(c)}.`,
|
|
5
|
+
invalidFileType: (s) => `File "${s}" is not an accepted file type.`,
|
|
6
|
+
tooManyFiles: (s) => `You can only upload a maximum of ${s} files.`,
|
|
7
|
+
someFilesTooLarge: (s) => `Some files exceed the maximum size of ${h(s)}.`,
|
|
8
|
+
singleFileTooLarge: (s) => `File exceeds the maximum size of ${h(s)}.`
|
|
9
|
+
}, N = {
|
|
10
|
+
fileTooLarge: (s, c) => `Файл "${s}" превышает максимальный размер ${h(c)}`,
|
|
11
|
+
invalidFileType: (s) => `Файл "${s}" имеет недопустимый тип`,
|
|
12
|
+
tooManyFiles: (s) => `Можно загрузить максимум ${s} файлов`,
|
|
13
|
+
someFilesTooLarge: (s) => `Некоторые файлы превышают максимальный размер ${h(s)}`,
|
|
14
|
+
singleFileTooLarge: (s) => `Файл превышает максимальный размер ${h(s)}`
|
|
15
|
+
}, Y = (s = {}) => {
|
|
16
|
+
const {
|
|
17
|
+
maxFiles: c = 1 / 0,
|
|
18
|
+
maxSize: g = 1 / 0,
|
|
19
|
+
accept: T = "*",
|
|
20
|
+
multiple: o = !1,
|
|
21
|
+
initialFiles: z = [],
|
|
22
|
+
onFilesChange: m,
|
|
23
|
+
onFilesAdded: D,
|
|
24
|
+
errorMessages: w
|
|
25
|
+
} = s, p = W(() => ({ ...j, ...w }), [w]), [v, l] = k({
|
|
26
|
+
files: z.map((e) => ({
|
|
27
|
+
file: e,
|
|
28
|
+
id: e.id,
|
|
29
|
+
preview: e.url
|
|
30
|
+
})),
|
|
31
|
+
isDragging: !1,
|
|
32
|
+
errors: []
|
|
33
|
+
}), f = O(null), x = n(
|
|
34
|
+
(e) => {
|
|
35
|
+
const r = (e instanceof File, e.name);
|
|
36
|
+
if (e.size > g)
|
|
37
|
+
return p.fileTooLarge(r, g);
|
|
38
|
+
if (T !== "*") {
|
|
39
|
+
const i = T.split(",").map((u) => u.trim()), a = e instanceof File ? e.type || "" : e.type, t = `.${r.split(".").pop()}`;
|
|
40
|
+
if (!i.some((u) => {
|
|
41
|
+
if (u.startsWith("."))
|
|
42
|
+
return t.toLowerCase() === u.toLowerCase();
|
|
43
|
+
if (u.endsWith("/*")) {
|
|
44
|
+
const y = u.split("/")[0];
|
|
45
|
+
return a.startsWith(`${y}/`);
|
|
46
|
+
}
|
|
47
|
+
return a === u;
|
|
48
|
+
}))
|
|
49
|
+
return p.invalidFileType(r);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
[T, g, p]
|
|
54
|
+
), M = n((e) => e instanceof File ? URL.createObjectURL(e) : e.url, []), R = n((e) => e instanceof File ? `${e.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}` : e.id, []), L = n(() => {
|
|
55
|
+
l((e) => {
|
|
56
|
+
e.files.forEach((i) => {
|
|
57
|
+
i.preview && i.file instanceof File && i.file.type.startsWith("image/") && URL.revokeObjectURL(i.preview);
|
|
58
|
+
}), f.current && (f.current.value = "");
|
|
59
|
+
const r = {
|
|
60
|
+
...e,
|
|
61
|
+
files: [],
|
|
62
|
+
errors: []
|
|
63
|
+
};
|
|
64
|
+
return m?.(r.files), r;
|
|
65
|
+
});
|
|
66
|
+
}, [m]), d = n(
|
|
67
|
+
(e) => {
|
|
68
|
+
if (!e || e.length === 0) return;
|
|
69
|
+
const r = Array.from(e), i = [];
|
|
70
|
+
if (l((t) => ({ ...t, errors: [] })), o || L(), o && c !== 1 / 0 && v.files.length + r.length > c) {
|
|
71
|
+
i.push(p.tooManyFiles(c)), l((t) => ({ ...t, errors: i }));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const a = [];
|
|
75
|
+
r.forEach((t) => {
|
|
76
|
+
if (o && v.files.some(
|
|
77
|
+
(y) => y.file.name === t.name && y.file.size === t.size
|
|
78
|
+
))
|
|
79
|
+
return;
|
|
80
|
+
if (t.size > g) {
|
|
81
|
+
i.push(
|
|
82
|
+
o ? p.someFilesTooLarge(g) : p.singleFileTooLarge(g)
|
|
83
|
+
);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const F = x(t);
|
|
87
|
+
F ? i.push(F) : a.push({
|
|
88
|
+
file: t,
|
|
89
|
+
id: R(t),
|
|
90
|
+
preview: M(t)
|
|
91
|
+
});
|
|
92
|
+
}), a.length > 0 ? (D?.(a), l((t) => {
|
|
93
|
+
const F = o ? [...t.files, ...a] : a;
|
|
94
|
+
return m?.(F), {
|
|
95
|
+
...t,
|
|
96
|
+
files: F,
|
|
97
|
+
errors: i
|
|
98
|
+
};
|
|
99
|
+
})) : i.length > 0 && l((t) => ({
|
|
100
|
+
...t,
|
|
101
|
+
errors: i
|
|
102
|
+
})), f.current && (f.current.value = "");
|
|
103
|
+
},
|
|
104
|
+
[
|
|
105
|
+
v.files,
|
|
106
|
+
c,
|
|
107
|
+
o,
|
|
108
|
+
g,
|
|
109
|
+
x,
|
|
110
|
+
M,
|
|
111
|
+
R,
|
|
112
|
+
L,
|
|
113
|
+
m,
|
|
114
|
+
D,
|
|
115
|
+
p
|
|
116
|
+
]
|
|
117
|
+
), E = n(
|
|
118
|
+
(e) => {
|
|
119
|
+
l((r) => {
|
|
120
|
+
const i = r.files.find((t) => t.id === e);
|
|
121
|
+
i && i.preview && i.file instanceof File && i.file.type.startsWith("image/") && URL.revokeObjectURL(i.preview);
|
|
122
|
+
const a = r.files.filter((t) => t.id !== e);
|
|
123
|
+
return m?.(a), {
|
|
124
|
+
...r,
|
|
125
|
+
files: a,
|
|
126
|
+
errors: []
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
[m]
|
|
131
|
+
), U = n(() => {
|
|
132
|
+
l((e) => ({
|
|
133
|
+
...e,
|
|
134
|
+
errors: []
|
|
135
|
+
}));
|
|
136
|
+
}, []), b = n((e) => {
|
|
137
|
+
e.preventDefault(), e.stopPropagation(), l((r) => ({ ...r, isDragging: !0 }));
|
|
138
|
+
}, []), C = n((e) => {
|
|
139
|
+
e.preventDefault(), e.stopPropagation(), !e.currentTarget.contains(e.relatedTarget) && l((r) => ({ ...r, isDragging: !1 }));
|
|
140
|
+
}, []), P = n((e) => {
|
|
141
|
+
e.preventDefault(), e.stopPropagation();
|
|
142
|
+
}, []), S = n(
|
|
143
|
+
(e) => {
|
|
144
|
+
if (e.preventDefault(), e.stopPropagation(), l((r) => ({ ...r, isDragging: !1 })), !f.current?.disabled && e.dataTransfer.files && e.dataTransfer.files.length > 0)
|
|
145
|
+
if (o)
|
|
146
|
+
d(e.dataTransfer.files);
|
|
147
|
+
else {
|
|
148
|
+
const r = e.dataTransfer.files[0];
|
|
149
|
+
d([r]);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
[d, o]
|
|
153
|
+
), $ = n(
|
|
154
|
+
(e) => {
|
|
155
|
+
e.target.files && e.target.files.length > 0 && d(e.target.files);
|
|
156
|
+
},
|
|
157
|
+
[d]
|
|
158
|
+
), A = n(() => {
|
|
159
|
+
f.current && f.current.click();
|
|
160
|
+
}, []), I = n(
|
|
161
|
+
(e = {}) => ({
|
|
162
|
+
...e,
|
|
163
|
+
type: "file",
|
|
164
|
+
onChange: $,
|
|
165
|
+
accept: e.accept || T,
|
|
166
|
+
multiple: e.multiple !== void 0 ? e.multiple : o,
|
|
167
|
+
ref: f
|
|
168
|
+
}),
|
|
169
|
+
[T, o, $]
|
|
170
|
+
);
|
|
171
|
+
return [
|
|
172
|
+
v,
|
|
173
|
+
{
|
|
174
|
+
addFiles: d,
|
|
175
|
+
removeFile: E,
|
|
176
|
+
clearFiles: L,
|
|
177
|
+
clearErrors: U,
|
|
178
|
+
handleDragEnter: b,
|
|
179
|
+
handleDragLeave: C,
|
|
180
|
+
handleDragOver: P,
|
|
181
|
+
handleDrop: S,
|
|
182
|
+
handleFileChange: $,
|
|
183
|
+
openFileDialog: A,
|
|
184
|
+
getInputProps: I
|
|
185
|
+
}
|
|
186
|
+
];
|
|
187
|
+
};
|
|
188
|
+
export {
|
|
189
|
+
N as a,
|
|
190
|
+
j as d,
|
|
191
|
+
Y as u
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=useFileUpload-Bnl3P8mP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFileUpload-Bnl3P8mP.js","sources":["../src/hooks/use-file-upload/errorMessages.ts","../src/hooks/use-file-upload/useFileUpload.ts"],"sourcesContent":["import { formatBytes } from \"@/lib/utils/file/formatBytes\";\n\n/**\n * Интерфейс для кастомизации сообщений об ошибках в useFileUpload\n */\nexport interface FileUploadErrorMessages {\n\t/**\n\t * Сообщение когда файл превышает максимальный размер\n\t * @param fileName - имя файла\n\t * @param maxSizeBytes - максимальный размер в байтах\n\t */\n\tfileTooLarge?: (fileName: string, maxSizeBytes: number) => string;\n\n\t/**\n\t * Сообщение когда тип файла не разрешен\n\t * @param fileName - имя файла\n\t */\n\tinvalidFileType?: (fileName: string) => string;\n\n\t/**\n\t * Сообщение когда превышено максимальное количество файлов\n\t * @param maxFiles - максимальное количество файлов\n\t */\n\ttooManyFiles?: (maxFiles: number) => string;\n\n\t/**\n\t * Сообщение когда некоторые файлы превышают максимальный размер (для множественной загрузки)\n\t * @param maxSizeBytes - максимальный размер в байтах\n\t */\n\tsomeFilesTooLarge?: (maxSizeBytes: number) => string;\n\n\t/**\n\t * Сообщение когда файл превышает максимальный размер (для одиночной загрузки)\n\t * @param maxSizeBytes - максимальный размер в байтах\n\t */\n\tsingleFileTooLarge?: (maxSizeBytes: number) => string;\n}\n\n/**\n * Сообщения об ошибках по умолчанию\n */\nexport const defaultErrorMessages: Required<FileUploadErrorMessages> = {\n\tfileTooLarge: (fileName, maxSizeBytes) =>\n\t\t`File \"${fileName}\" exceeds the maximum size of ${formatBytes(maxSizeBytes)}.`,\n\tinvalidFileType: (fileName) => `File \"${fileName}\" is not an accepted file type.`,\n\ttooManyFiles: (maxFiles) => `You can only upload a maximum of ${maxFiles} files.`,\n\tsomeFilesTooLarge: (maxSizeBytes) => `Some files exceed the maximum size of ${formatBytes(maxSizeBytes)}.`,\n\tsingleFileTooLarge: (maxSizeBytes) => `File exceeds the maximum size of ${formatBytes(maxSizeBytes)}.`\n};\n\n/**\n * Сообщения об ошибках на русском языке\n */\nexport const defaultErrorMessagesRu: Required<FileUploadErrorMessages> = {\n\tfileTooLarge: (fileName, maxSizeBytes) =>\n\t\t`Файл \"${fileName}\" превышает максимальный размер ${formatBytes(maxSizeBytes)}`,\n\tinvalidFileType: (fileName) => `Файл \"${fileName}\" имеет недопустимый тип`,\n\ttooManyFiles: (maxFiles) => `Можно загрузить максимум ${maxFiles} файлов`,\n\tsomeFilesTooLarge: (maxSizeBytes) => `Некоторые файлы превышают максимальный размер ${formatBytes(maxSizeBytes)}`,\n\tsingleFileTooLarge: (maxSizeBytes) => `Файл превышает максимальный размер ${formatBytes(maxSizeBytes)}`\n};\n","import {\n\tuseCallback,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\ttype ChangeEvent,\n\ttype DragEvent,\n\ttype InputHTMLAttributes\n} from \"react\";\nimport { defaultErrorMessages, type FileUploadErrorMessages } from \"./errorMessages\";\n\nexport type FileData = {\n\tname: string;\n\tsize: number;\n\ttype: string;\n\tid?: string;\n};\n\nexport type FileMetadata = FileData & {\n\turl: string;\n\tid: string;\n};\n\nexport type FileValue = File | FileData;\n\nexport type FileWithPreview = {\n\tfile: FileValue;\n\tid: string;\n\tpreview?: string;\n};\n\n/**\n * Ограничения для загрузки файлов\n */\nexport type FileUploadConstraints = {\n\t/**\n\t * Максимальное количество файлов\n\t * Используется только когда multiple=true\n\t * @default Infinity\n\t */\n\tmaxFiles?: number;\n\n\t/**\n\t * Максимальный размер файла в байтах\n\t * @default Infinity\n\t */\n\tmaxSize?: number;\n\n\t/**\n\t * Допустимые типы файлов (строка MIME-типов или расширений через запятую)\n\t * @example \"image/jpeg,image/png,.pdf,.doc\"\n\t * @example \"*.jpg,*.png\"\n\t * @example \"image/*\"\n\t * @default \"*\"\n\t */\n\taccept?: string;\n\n\t/**\n\t * Разрешить выбор нескольких файлов\n\t * @default false\n\t */\n\tmultiple?: boolean;\n};\n\nexport type FileUploadOptions = FileUploadConstraints & {\n\tinitialFiles?: FileMetadata[];\n\tonFilesChange?: (files: FileWithPreview[]) => void;\n\tonFilesAdded?: (addedFiles: FileWithPreview[]) => void;\n\t/**\n\t * Кастомные сообщения об ошибках\n\t * Можно переопределить только нужные сообщения\n\t */\n\terrorMessages?: Partial<FileUploadErrorMessages>;\n};\n\nexport type FileUploadState = {\n\tfiles: FileWithPreview[];\n\tisDragging: boolean;\n\terrors: string[];\n};\n\nexport type FileUploadActions = {\n\taddFiles: (files: FileList | File[]) => void;\n\tremoveFile: (id: string) => void;\n\tclearFiles: () => void;\n\tclearErrors: () => void;\n\thandleDragEnter: (e: DragEvent<HTMLElement>) => void;\n\thandleDragLeave: (e: DragEvent<HTMLElement>) => void;\n\thandleDragOver: (e: DragEvent<HTMLElement>) => void;\n\thandleDrop: (e: DragEvent<HTMLElement>) => void;\n\thandleFileChange: (e: ChangeEvent<HTMLInputElement>) => void;\n\topenFileDialog: () => void;\n\tgetInputProps: (props?: InputHTMLAttributes<HTMLInputElement>) => InputHTMLAttributes<HTMLInputElement> & {\n\t\tref: React.Ref<HTMLInputElement>;\n\t};\n};\n\n/** Хук был взять из библиотеки originui.\n * Код можно посмотреть по ссылке: https://github.com/origin-space/originui/blob/main/docs/use-file-upload.md\n */\nexport const useFileUpload = (options: FileUploadOptions = {}): [FileUploadState, FileUploadActions] => {\n\tconst {\n\t\tmaxFiles = Infinity,\n\t\tmaxSize = Infinity,\n\t\taccept = \"*\",\n\t\tmultiple = false,\n\t\tinitialFiles = [],\n\t\tonFilesChange,\n\t\tonFilesAdded,\n\t\terrorMessages: customErrorMessages\n\t} = options;\n\n\t// Объединяем дефолтные и кастомные сообщения\n\tconst errorMessages = useMemo(() => ({ ...defaultErrorMessages, ...customErrorMessages }), [customErrorMessages]);\n\n\tconst [state, setState] = useState<FileUploadState>({\n\t\tfiles: initialFiles.map((file) => ({\n\t\t\tfile,\n\t\t\tid: file.id,\n\t\t\tpreview: file.url\n\t\t})),\n\t\tisDragging: false,\n\t\terrors: []\n\t});\n\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\n\tconst validateFile = useCallback(\n\t\t(file: FileValue): string | null => {\n\t\t\tconst fileName = file instanceof File ? file.name : file.name;\n\n\t\t\tif (file.size > maxSize) {\n\t\t\t\treturn errorMessages.fileTooLarge(fileName, maxSize);\n\t\t\t}\n\n\t\t\tif (accept !== \"*\") {\n\t\t\t\tconst acceptedTypes = accept.split(\",\").map((type) => type.trim());\n\t\t\t\tconst fileType = file instanceof File ? file.type || \"\" : file.type;\n\t\t\t\tconst fileExtension = `.${fileName.split(\".\").pop()}`;\n\n\t\t\t\tconst isAccepted = acceptedTypes.some((type) => {\n\t\t\t\t\tif (type.startsWith(\".\")) {\n\t\t\t\t\t\treturn fileExtension.toLowerCase() === type.toLowerCase();\n\t\t\t\t\t}\n\t\t\t\t\tif (type.endsWith(\"/*\")) {\n\t\t\t\t\t\tconst baseType = type.split(\"/\")[0];\n\t\t\t\t\t\treturn fileType.startsWith(`${baseType}/`);\n\t\t\t\t\t}\n\t\t\t\t\treturn fileType === type;\n\t\t\t\t});\n\n\t\t\t\tif (!isAccepted) {\n\t\t\t\t\treturn errorMessages.invalidFileType(fileName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t},\n\t\t[accept, maxSize, errorMessages]\n\t);\n\n\tconst createPreview = useCallback((file: File | FileMetadata): string | undefined => {\n\t\tif (file instanceof File) {\n\t\t\treturn URL.createObjectURL(file);\n\t\t}\n\t\treturn file.url;\n\t}, []);\n\n\tconst generateUniqueId = useCallback((file: File | FileMetadata): string => {\n\t\tif (file instanceof File) {\n\t\t\treturn `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n\t\t}\n\t\treturn file.id;\n\t}, []);\n\n\tconst clearFiles = useCallback(() => {\n\t\tsetState((prev) => {\n\t\t\t// Clean up object URLs\n\t\t\tprev.files.forEach((file) => {\n\t\t\t\tif (file.preview && file.file instanceof File && file.file.type.startsWith(\"image/\")) {\n\t\t\t\t\tURL.revokeObjectURL(file.preview);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (inputRef.current) {\n\t\t\t\tinputRef.current.value = \"\";\n\t\t\t}\n\n\t\t\tconst newState = {\n\t\t\t\t...prev,\n\t\t\t\tfiles: [],\n\t\t\t\terrors: []\n\t\t\t};\n\n\t\t\tonFilesChange?.(newState.files);\n\t\t\treturn newState;\n\t\t});\n\t}, [onFilesChange]);\n\n\tconst addFiles = useCallback(\n\t\t(newFiles: FileList | File[]) => {\n\t\t\tif (!newFiles || newFiles.length === 0) return;\n\n\t\t\tconst newFilesArray = Array.from(newFiles);\n\t\t\tconst errors: string[] = [];\n\n\t\t\t// Clear existing errors when new files are uploaded\n\t\t\tsetState((prev) => ({ ...prev, errors: [] }));\n\n\t\t\t// In single file mode, clear existing files first\n\t\t\tif (!multiple) {\n\t\t\t\tclearFiles();\n\t\t\t}\n\n\t\t\t// Check if adding these files would exceed maxFiles (only in multiple mode)\n\t\t\tif (multiple && maxFiles !== Infinity && state.files.length + newFilesArray.length > maxFiles) {\n\t\t\t\terrors.push(errorMessages.tooManyFiles(maxFiles));\n\t\t\t\tsetState((prev) => ({ ...prev, errors }));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst validFiles: FileWithPreview[] = [];\n\n\t\t\tnewFilesArray.forEach((file) => {\n\t\t\t\t// Only check for duplicates if multiple files are allowed\n\t\t\t\tif (multiple) {\n\t\t\t\t\tconst isDuplicate = state.files.some(\n\t\t\t\t\t\t(existingFile) => existingFile.file.name === file.name && existingFile.file.size === file.size\n\t\t\t\t\t);\n\n\t\t\t\t\t// Skip duplicate files silently\n\t\t\t\t\tif (isDuplicate) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check file size\n\t\t\t\tif (file.size > maxSize) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\tmultiple ? errorMessages.someFilesTooLarge(maxSize) : errorMessages.singleFileTooLarge(maxSize)\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst error = validateFile(file);\n\t\t\t\tif (error) {\n\t\t\t\t\terrors.push(error);\n\t\t\t\t} else {\n\t\t\t\t\tvalidFiles.push({\n\t\t\t\t\t\tfile,\n\t\t\t\t\t\tid: generateUniqueId(file),\n\t\t\t\t\t\tpreview: createPreview(file)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Only update state if we have valid files to add\n\t\t\tif (validFiles.length > 0) {\n\t\t\t\t// Call the onFilesAdded callback with the newly added valid files\n\t\t\t\tonFilesAdded?.(validFiles);\n\n\t\t\t\tsetState((prev) => {\n\t\t\t\t\tconst newFiles = !multiple ? validFiles : [...prev.files, ...validFiles];\n\t\t\t\t\tonFilesChange?.(newFiles);\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\tfiles: newFiles,\n\t\t\t\t\t\terrors\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t} else if (errors.length > 0) {\n\t\t\t\tsetState((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\terrors\n\t\t\t\t}));\n\t\t\t}\n\n\t\t\t// Reset input value after handling files\n\t\t\tif (inputRef.current) {\n\t\t\t\tinputRef.current.value = \"\";\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tstate.files,\n\t\t\tmaxFiles,\n\t\t\tmultiple,\n\t\t\tmaxSize,\n\t\t\tvalidateFile,\n\t\t\tcreatePreview,\n\t\t\tgenerateUniqueId,\n\t\t\tclearFiles,\n\t\t\tonFilesChange,\n\t\t\tonFilesAdded,\n\t\t\terrorMessages\n\t\t]\n\t);\n\n\tconst removeFile = useCallback(\n\t\t(id: string) => {\n\t\t\tsetState((prev) => {\n\t\t\t\tconst fileToRemove = prev.files.find((file) => file.id === id);\n\t\t\t\tif (\n\t\t\t\t\tfileToRemove &&\n\t\t\t\t\tfileToRemove.preview &&\n\t\t\t\t\tfileToRemove.file instanceof File &&\n\t\t\t\t\tfileToRemove.file.type.startsWith(\"image/\")\n\t\t\t\t) {\n\t\t\t\t\tURL.revokeObjectURL(fileToRemove.preview);\n\t\t\t\t}\n\n\t\t\t\tconst newFiles = prev.files.filter((file) => file.id !== id);\n\t\t\t\tonFilesChange?.(newFiles);\n\n\t\t\t\treturn {\n\t\t\t\t\t...prev,\n\t\t\t\t\tfiles: newFiles,\n\t\t\t\t\terrors: []\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t[onFilesChange]\n\t);\n\n\tconst clearErrors = useCallback(() => {\n\t\tsetState((prev) => ({\n\t\t\t...prev,\n\t\t\terrors: []\n\t\t}));\n\t}, []);\n\n\tconst handleDragEnter = useCallback((e: DragEvent<HTMLElement>) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tsetState((prev) => ({ ...prev, isDragging: true }));\n\t}, []);\n\n\tconst handleDragLeave = useCallback((e: DragEvent<HTMLElement>) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tif (e.currentTarget.contains(e.relatedTarget as Node)) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetState((prev) => ({ ...prev, isDragging: false }));\n\t}, []);\n\n\tconst handleDragOver = useCallback((e: DragEvent<HTMLElement>) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t}, []);\n\n\tconst handleDrop = useCallback(\n\t\t(e: DragEvent<HTMLElement>) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tsetState((prev) => ({ ...prev, isDragging: false }));\n\n\t\t\t// Don't process files if the input is disabled\n\t\t\tif (inputRef.current?.disabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n\t\t\t\t// In single file mode, only use the first file\n\t\t\t\tif (!multiple) {\n\t\t\t\t\tconst file = e.dataTransfer.files[0];\n\t\t\t\t\taddFiles([file]);\n\t\t\t\t} else {\n\t\t\t\t\taddFiles(e.dataTransfer.files);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[addFiles, multiple]\n\t);\n\n\tconst handleFileChange = useCallback(\n\t\t(e: ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (e.target.files && e.target.files.length > 0) {\n\t\t\t\taddFiles(e.target.files);\n\t\t\t}\n\t\t},\n\t\t[addFiles]\n\t);\n\n\tconst openFileDialog = useCallback(() => {\n\t\tif (inputRef.current) {\n\t\t\tinputRef.current.click();\n\t\t}\n\t}, []);\n\n\tconst getInputProps = useCallback(\n\t\t(props: InputHTMLAttributes<HTMLInputElement> = {}) => {\n\t\t\treturn {\n\t\t\t\t...props,\n\t\t\t\ttype: \"file\" as const,\n\t\t\t\tonChange: handleFileChange,\n\t\t\t\taccept: props.accept || accept,\n\t\t\t\tmultiple: props.multiple !== undefined ? props.multiple : multiple,\n\t\t\t\tref: inputRef\n\t\t\t};\n\t\t},\n\t\t[accept, multiple, handleFileChange]\n\t);\n\n\treturn [\n\t\tstate,\n\t\t{\n\t\t\taddFiles,\n\t\t\tremoveFile,\n\t\t\tclearFiles,\n\t\t\tclearErrors,\n\t\t\thandleDragEnter,\n\t\t\thandleDragLeave,\n\t\t\thandleDragOver,\n\t\t\thandleDrop,\n\t\t\thandleFileChange,\n\t\t\topenFileDialog,\n\t\t\tgetInputProps\n\t\t}\n\t];\n};\n"],"names":["defaultErrorMessages","fileName","maxSizeBytes","formatBytes","maxFiles","defaultErrorMessagesRu","useFileUpload","options","maxSize","accept","multiple","initialFiles","onFilesChange","onFilesAdded","customErrorMessages","errorMessages","useMemo","state","setState","useState","file","inputRef","useRef","validateFile","useCallback","acceptedTypes","type","fileType","fileExtension","baseType","createPreview","generateUniqueId","clearFiles","prev","newState","addFiles","newFiles","newFilesArray","errors","validFiles","existingFile","error","removeFile","id","fileToRemove","clearErrors","handleDragEnter","handleDragLeave","handleDragOver","handleDrop","handleFileChange","openFileDialog","getInputProps","props"],"mappings":"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"}
|
package/package.json
CHANGED
package/tailwind.preset.js
CHANGED
|
@@ -164,7 +164,7 @@ export default {
|
|
|
164
164
|
30: "hsl(var(--alpha-70))",
|
|
165
165
|
40: "hsl(var(--alpha-60))",
|
|
166
166
|
50: "hsl(var(--alpha-50))",
|
|
167
|
-
60: "hsl(var(--alpha-
|
|
167
|
+
60: "hsl(var(--alpha-40))",
|
|
168
168
|
70: "hsl(var(--alpha-30))",
|
|
169
169
|
80: "hsl(var(--alpha-20))",
|
|
170
170
|
90: "hsl(var(--alpha-10))",
|
|
@@ -178,7 +178,7 @@ export default {
|
|
|
178
178
|
30: "hsl(var(--alpha-high-70))",
|
|
179
179
|
40: "hsl(var(--alpha-high-60))",
|
|
180
180
|
50: "hsl(var(--alpha-high-50))",
|
|
181
|
-
60: "hsl(var(--alpha-high-
|
|
181
|
+
60: "hsl(var(--alpha-high-40))",
|
|
182
182
|
70: "hsl(var(--alpha-high-30))",
|
|
183
183
|
80: "hsl(var(--alpha-high-20))",
|
|
184
184
|
90: "hsl(var(--alpha-high-10))",
|
|
@@ -255,7 +255,8 @@ export default {
|
|
|
255
255
|
"0 4px 6px 0 rgba(2, 6, 23, 0.35), 0 0 0.5px 0 rgba(255, 255, 255, 0.35) inset, 0 12px 28px 0 rgba(2, 6, 23, 0.45), 0 0.5px 0 0 rgba(255, 255, 255, 0.08) inset",
|
|
256
256
|
|
|
257
257
|
"glass-sm": "var(--shadow-glass-sm)",
|
|
258
|
-
"glass-md": "var(--shadow-glass-md)"
|
|
258
|
+
"glass-md": "var(--shadow-glass-md)",
|
|
259
|
+
"glass-lg": "var(--shadow-glass-lg)"
|
|
259
260
|
},
|
|
260
261
|
lineHeight: {
|
|
261
262
|
none: "100%",
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { useMemo as A, useState as I, useRef as W, useCallback as n } from "react";
|
|
2
|
-
const T = (t, o = 2) => {
|
|
3
|
-
if (t === 0) return "0 Bytes";
|
|
4
|
-
const c = 1024, p = o < 0 ? 0 : o, a = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], v = Math.floor(Math.log(t) / Math.log(c));
|
|
5
|
-
return Number.parseFloat((t / Math.pow(c, v)).toFixed(p)) + a[v];
|
|
6
|
-
}, O = {
|
|
7
|
-
fileTooLarge: (t, o) => `File "${t}" exceeds the maximum size of ${T(o)}.`,
|
|
8
|
-
invalidFileType: (t) => `File "${t}" is not an accepted file type.`,
|
|
9
|
-
tooManyFiles: (t) => `You can only upload a maximum of ${t} files.`,
|
|
10
|
-
someFilesTooLarge: (t) => `Some files exceed the maximum size of ${T(t)}.`,
|
|
11
|
-
singleFileTooLarge: (t) => `File exceeds the maximum size of ${T(t)}.`
|
|
12
|
-
}, N = {
|
|
13
|
-
fileTooLarge: (t, o) => `Файл "${t}" превышает максимальный размер ${T(o)}`,
|
|
14
|
-
invalidFileType: (t) => `Файл "${t}" имеет недопустимый тип`,
|
|
15
|
-
tooManyFiles: (t) => `Можно загрузить максимум ${t} файлов`,
|
|
16
|
-
someFilesTooLarge: (t) => `Некоторые файлы превышают максимальный размер ${T(t)}`,
|
|
17
|
-
singleFileTooLarge: (t) => `Файл превышает максимальный размер ${T(t)}`
|
|
18
|
-
}, Y = (t = {}) => {
|
|
19
|
-
const {
|
|
20
|
-
maxFiles: o = 1 / 0,
|
|
21
|
-
maxSize: c = 1 / 0,
|
|
22
|
-
accept: p = "*",
|
|
23
|
-
multiple: a = !1,
|
|
24
|
-
initialFiles: v = [],
|
|
25
|
-
onFilesChange: m,
|
|
26
|
-
onFilesAdded: M,
|
|
27
|
-
errorMessages: w
|
|
28
|
-
} = t, d = A(() => ({ ...O, ...w }), [w]), [y, f] = I({
|
|
29
|
-
files: v.map((e) => ({
|
|
30
|
-
file: e,
|
|
31
|
-
id: e.id,
|
|
32
|
-
preview: e.url
|
|
33
|
-
})),
|
|
34
|
-
isDragging: !1,
|
|
35
|
-
errors: []
|
|
36
|
-
}), u = W(null), x = n(
|
|
37
|
-
(e) => {
|
|
38
|
-
const r = (e instanceof File, e.name);
|
|
39
|
-
if (e.size > c)
|
|
40
|
-
return d.fileTooLarge(r, c);
|
|
41
|
-
if (p !== "*") {
|
|
42
|
-
const i = p.split(",").map((g) => g.trim()), l = e instanceof File ? e.type || "" : e.type, s = `.${r.split(".").pop()}`;
|
|
43
|
-
if (!i.some((g) => {
|
|
44
|
-
if (g.startsWith("."))
|
|
45
|
-
return s.toLowerCase() === g.toLowerCase();
|
|
46
|
-
if (g.endsWith("/*")) {
|
|
47
|
-
const L = g.split("/")[0];
|
|
48
|
-
return l.startsWith(`${L}/`);
|
|
49
|
-
}
|
|
50
|
-
return l === g;
|
|
51
|
-
}))
|
|
52
|
-
return d.invalidFileType(r);
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
},
|
|
56
|
-
[p, c, d]
|
|
57
|
-
), B = n((e) => e instanceof File ? URL.createObjectURL(e) : e.url, []), R = n((e) => e instanceof File ? `${e.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}` : e.id, []), $ = n(() => {
|
|
58
|
-
f((e) => {
|
|
59
|
-
e.files.forEach((i) => {
|
|
60
|
-
i.preview && i.file instanceof File && i.file.type.startsWith("image/") && URL.revokeObjectURL(i.preview);
|
|
61
|
-
}), u.current && (u.current.value = "");
|
|
62
|
-
const r = {
|
|
63
|
-
...e,
|
|
64
|
-
files: [],
|
|
65
|
-
errors: []
|
|
66
|
-
};
|
|
67
|
-
return m?.(r.files), r;
|
|
68
|
-
});
|
|
69
|
-
}, [m]), F = n(
|
|
70
|
-
(e) => {
|
|
71
|
-
if (!e || e.length === 0) return;
|
|
72
|
-
const r = Array.from(e), i = [];
|
|
73
|
-
if (f((s) => ({ ...s, errors: [] })), a || $(), a && o !== 1 / 0 && y.files.length + r.length > o) {
|
|
74
|
-
i.push(d.tooManyFiles(o)), f((s) => ({ ...s, errors: i }));
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const l = [];
|
|
78
|
-
r.forEach((s) => {
|
|
79
|
-
if (a && y.files.some(
|
|
80
|
-
(L) => L.file.name === s.name && L.file.size === s.size
|
|
81
|
-
))
|
|
82
|
-
return;
|
|
83
|
-
if (s.size > c) {
|
|
84
|
-
i.push(
|
|
85
|
-
a ? d.someFilesTooLarge(c) : d.singleFileTooLarge(c)
|
|
86
|
-
);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const h = x(s);
|
|
90
|
-
h ? i.push(h) : l.push({
|
|
91
|
-
file: s,
|
|
92
|
-
id: R(s),
|
|
93
|
-
preview: B(s)
|
|
94
|
-
});
|
|
95
|
-
}), l.length > 0 ? (M?.(l), f((s) => {
|
|
96
|
-
const h = a ? [...s.files, ...l] : l;
|
|
97
|
-
return m?.(h), {
|
|
98
|
-
...s,
|
|
99
|
-
files: h,
|
|
100
|
-
errors: i
|
|
101
|
-
};
|
|
102
|
-
})) : i.length > 0 && f((s) => ({
|
|
103
|
-
...s,
|
|
104
|
-
errors: i
|
|
105
|
-
})), u.current && (u.current.value = "");
|
|
106
|
-
},
|
|
107
|
-
[
|
|
108
|
-
y.files,
|
|
109
|
-
o,
|
|
110
|
-
a,
|
|
111
|
-
c,
|
|
112
|
-
x,
|
|
113
|
-
B,
|
|
114
|
-
R,
|
|
115
|
-
$,
|
|
116
|
-
m,
|
|
117
|
-
M,
|
|
118
|
-
d
|
|
119
|
-
]
|
|
120
|
-
), z = n(
|
|
121
|
-
(e) => {
|
|
122
|
-
f((r) => {
|
|
123
|
-
const i = r.files.find((s) => s.id === e);
|
|
124
|
-
i && i.preview && i.file instanceof File && i.file.type.startsWith("image/") && URL.revokeObjectURL(i.preview);
|
|
125
|
-
const l = r.files.filter((s) => s.id !== e);
|
|
126
|
-
return m?.(l), {
|
|
127
|
-
...r,
|
|
128
|
-
files: l,
|
|
129
|
-
errors: []
|
|
130
|
-
};
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
[m]
|
|
134
|
-
), E = n(() => {
|
|
135
|
-
f((e) => ({
|
|
136
|
-
...e,
|
|
137
|
-
errors: []
|
|
138
|
-
}));
|
|
139
|
-
}, []), U = n((e) => {
|
|
140
|
-
e.preventDefault(), e.stopPropagation(), f((r) => ({ ...r, isDragging: !0 }));
|
|
141
|
-
}, []), P = n((e) => {
|
|
142
|
-
e.preventDefault(), e.stopPropagation(), !e.currentTarget.contains(e.relatedTarget) && f((r) => ({ ...r, isDragging: !1 }));
|
|
143
|
-
}, []), b = n((e) => {
|
|
144
|
-
e.preventDefault(), e.stopPropagation();
|
|
145
|
-
}, []), C = n(
|
|
146
|
-
(e) => {
|
|
147
|
-
if (e.preventDefault(), e.stopPropagation(), f((r) => ({ ...r, isDragging: !1 })), !u.current?.disabled && e.dataTransfer.files && e.dataTransfer.files.length > 0)
|
|
148
|
-
if (a)
|
|
149
|
-
F(e.dataTransfer.files);
|
|
150
|
-
else {
|
|
151
|
-
const r = e.dataTransfer.files[0];
|
|
152
|
-
F([r]);
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
[F, a]
|
|
156
|
-
), D = n(
|
|
157
|
-
(e) => {
|
|
158
|
-
e.target.files && e.target.files.length > 0 && F(e.target.files);
|
|
159
|
-
},
|
|
160
|
-
[F]
|
|
161
|
-
), S = n(() => {
|
|
162
|
-
u.current && u.current.click();
|
|
163
|
-
}, []), k = n(
|
|
164
|
-
(e = {}) => ({
|
|
165
|
-
...e,
|
|
166
|
-
type: "file",
|
|
167
|
-
onChange: D,
|
|
168
|
-
accept: e.accept || p,
|
|
169
|
-
multiple: e.multiple !== void 0 ? e.multiple : a,
|
|
170
|
-
ref: u
|
|
171
|
-
}),
|
|
172
|
-
[p, a, D]
|
|
173
|
-
);
|
|
174
|
-
return [
|
|
175
|
-
y,
|
|
176
|
-
{
|
|
177
|
-
addFiles: F,
|
|
178
|
-
removeFile: z,
|
|
179
|
-
clearFiles: $,
|
|
180
|
-
clearErrors: E,
|
|
181
|
-
handleDragEnter: U,
|
|
182
|
-
handleDragLeave: P,
|
|
183
|
-
handleDragOver: b,
|
|
184
|
-
handleDrop: C,
|
|
185
|
-
handleFileChange: D,
|
|
186
|
-
openFileDialog: S,
|
|
187
|
-
getInputProps: k
|
|
188
|
-
}
|
|
189
|
-
];
|
|
190
|
-
};
|
|
191
|
-
export {
|
|
192
|
-
N as a,
|
|
193
|
-
O as d,
|
|
194
|
-
T as f,
|
|
195
|
-
Y as u
|
|
196
|
-
};
|
|
197
|
-
//# sourceMappingURL=useFileUpload-iDag0iqM.js.map
|