@shohojdhara/atomix 0.3.14 → 0.4.0
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/CHANGELOG.md +20 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +44 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +50 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +21044 -2618
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +77 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +44 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +50 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +1 -1
- package/dist/charts.js +86 -57
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +136 -112
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +2 -5
- package/dist/forms.js +140 -128
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +136 -112
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +152 -78
- package/dist/index.esm.js +346 -340
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +359 -353
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +9 -9
- package/dist/theme.js.map +1 -1
- package/package.json +23 -8
- package/scripts/atomix-cli.js +170 -73
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +161 -0
- package/scripts/cli/component-generator.js +253 -299
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/interactive-init.js +46 -5
- package/scripts/cli/template-manager.js +0 -2
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +148 -126
- package/scripts/cli/templates/index.js +23 -16
- package/scripts/cli/templates/project-templates.js +151 -23
- package/scripts/cli/templates/react-templates.js +280 -210
- package/scripts/cli/templates/scss-templates.js +90 -91
- package/scripts/cli/templates/testing-templates.js +206 -27
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/types-templates.js +70 -56
- package/scripts/cli/theme-bridge.js +8 -2
- package/scripts/cli/token-manager.js +318 -206
- package/scripts/cli/utils.js +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +358 -850
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +99 -94
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +6 -5
- package/src/components/AtomixGlass/shader-utils.ts +133 -52
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -36
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +195 -0
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +122 -352
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +30 -11
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +142 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
- package/src/components/Button/Button.stories.tsx +454 -1126
- package/src/components/Button/Button.test.tsx +123 -0
- package/src/components/Button/Button.tsx +88 -60
- package/src/components/Button/ButtonGroup.stories.tsx +376 -215
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +316 -568
- package/src/components/Card/Card.stories.tsx +292 -81
- package/src/components/Card/Card.tsx +30 -14
- package/src/components/Chart/AreaChart.tsx +1 -1
- package/src/components/Chart/CandlestickChart.tsx +23 -16
- package/src/components/Chart/Chart.stories.tsx +153 -16
- package/src/components/Chart/Chart.tsx +40 -44
- package/src/components/Chart/ChartRenderer.tsx +39 -12
- package/src/components/Chart/ChartToolbar.tsx +21 -5
- package/src/components/Chart/DonutChart.tsx +1 -1
- package/src/components/Chart/FunnelChart.tsx +4 -1
- package/src/components/Chart/GaugeChart.tsx +3 -1
- package/src/components/Chart/HeatmapChart.tsx +50 -37
- package/src/components/Chart/LineChart.tsx +3 -2
- package/src/components/Chart/MultiAxisChart.tsx +24 -16
- package/src/components/Chart/RadarChart.tsx +19 -17
- package/src/components/Chart/ScatterChart.tsx +29 -21
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +152 -66
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +114 -7
- package/src/components/DataTable/DataTable.stories.tsx +349 -144
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +310 -1066
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +153 -36
- package/src/components/Dropdown/Dropdown.tsx +313 -299
- package/src/components/EdgePanel/EdgePanel.stories.tsx +221 -25
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Footer/Footer.stories.tsx +396 -327
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +140 -6
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +122 -78
- package/src/components/Form/Form.stories.tsx +110 -19
- package/src/components/Form/FormGroup.stories.tsx +127 -4
- package/src/components/Form/Input.stories.tsx +22 -39
- package/src/components/Form/Input.test.tsx +38 -44
- package/src/components/Form/Radio.stories.tsx +146 -17
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +140 -8
- package/src/components/Form/Select.tsx +184 -182
- package/src/components/Form/Textarea.stories.tsx +149 -6
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +372 -38
- package/src/components/Hero/Hero.tsx +201 -55
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.stories.tsx +141 -3
- package/src/components/List/List.tsx +19 -23
- package/src/components/Modal/Modal.stories.tsx +183 -43
- package/src/components/Modal/Modal.tsx +130 -127
- package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
- package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
- package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
- package/src/components/Pagination/Pagination.stories.tsx +7 -4
- package/src/components/Pagination/Pagination.tsx +199 -202
- package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
- package/src/components/Popover/Popover.stories.tsx +354 -97
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +160 -7
- package/src/components/River/River.stories.tsx +3 -2
- package/src/components/SectionIntro/SectionIntro.stories.tsx +239 -47
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +104 -8
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +173 -42
- package/src/components/Tabs/Tabs.stories.tsx +141 -12
- package/src/components/Tabs/Tabs.tsx +74 -72
- package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +137 -36
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -100
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +241 -150
- package/src/components/Upload/Upload.tsx +287 -283
- package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
- package/src/components/index.ts +13 -2
- package/src/layouts/Grid/Grid.stories.tsx +9 -3
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
- package/src/lib/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +219 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +126 -97
- package/src/lib/composables/useChartExport.ts +3 -8
- package/src/lib/composables/useDataTable.ts +72 -43
- package/src/lib/composables/useHero.ts +58 -14
- package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
- package/src/lib/composables/useInput.ts +10 -8
- package/src/lib/composables/useSideMenu.ts +6 -5
- package/src/lib/composables/useTooltip.ts +1 -2
- package/src/lib/composables/useVideoPlayer.ts +44 -35
- package/src/lib/config/index.ts +154 -154
- package/src/lib/constants/components.ts +9 -32
- package/src/lib/constants/cssVariables.ts +29 -29
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
- package/src/lib/hooks/index.ts +1 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -17
- package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
- package/src/lib/patterns/__tests__/slots.test.ts +1 -1
- package/src/lib/patterns/index.ts +1 -1
- package/src/lib/patterns/slots.tsx +8 -13
- package/src/lib/storybook/InteractiveDemo.tsx +13 -18
- package/src/lib/storybook/PreviewContainer.tsx +1 -1
- package/src/lib/storybook/VariantsGrid.tsx +3 -7
- package/src/lib/storybook/index.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
- package/src/lib/theme/adapters/index.ts +3 -9
- package/src/lib/theme/adapters/themeAdapter.ts +41 -26
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +10 -5
- package/src/lib/theme/constants/constants.ts +2 -2
- package/src/lib/theme/constants/index.ts +1 -2
- package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
- package/src/lib/theme/core/composeTheme.ts +32 -26
- package/src/lib/theme/core/createTheme.ts +1 -1
- package/src/lib/theme/core/createThemeObject.ts +308 -301
- package/src/lib/theme/core/index.ts +3 -3
- package/src/lib/theme/devtools/CLI.ts +107 -105
- package/src/lib/theme/devtools/Comparator.tsx +50 -32
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
- package/src/lib/theme/devtools/Inspector.tsx +75 -60
- package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
- package/src/lib/theme/devtools/Preview.tsx +150 -106
- package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
- package/src/lib/theme/devtools/index.ts +3 -9
- package/src/lib/theme/devtools/useHistory.ts +23 -21
- package/src/lib/theme/errors/errors.ts +12 -11
- package/src/lib/theme/errors/index.ts +2 -7
- package/src/lib/theme/generators/generateCSS.ts +9 -13
- package/src/lib/theme/generators/generateCSSNested.ts +1 -6
- package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/i18n/index.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +13 -13
- package/src/lib/theme/index.ts +7 -16
- package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
- package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
- package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
- package/src/lib/theme/runtime/index.ts +2 -5
- package/src/lib/theme/runtime/useTheme.ts +18 -18
- package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
- package/src/lib/theme/test/testTheme.ts +15 -16
- package/src/lib/theme/tokens/index.ts +2 -7
- package/src/lib/theme/tokens/tokens.ts +25 -24
- package/src/lib/theme/types.ts +428 -411
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
- package/src/lib/theme/utils/componentTheming.ts +18 -18
- package/src/lib/theme/utils/domUtils.ts +277 -289
- package/src/lib/theme/utils/index.ts +1 -2
- package/src/lib/theme/utils/injectCSS.ts +10 -14
- package/src/lib/theme/utils/naming.ts +20 -16
- package/src/lib/theme/utils/themeHelpers.ts +10 -12
- package/src/lib/theme/utils/themeUtils.ts +85 -86
- package/src/lib/theme/utils/themeValidation.ts +82 -33
- package/src/lib/theme-tools.ts +8 -6
- package/src/lib/types/components.ts +172 -71
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +19 -0
- package/src/lib/utils/dataTableExport.ts +2 -15
- package/src/lib/utils/fontPreloader.ts +10 -19
- package/src/lib/utils/icons.ts +4 -1
- package/src/lib/utils/index.ts +2 -6
- package/src/lib/utils/memoryMonitor.ts +10 -8
- package/src/lib/utils/themeNaming.ts +2 -2
- package/src/styles/01-settings/_index.scss +1 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +3 -4
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.typography.scss +4 -4
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +38 -12
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.accordion.scss +56 -14
- package/src/styles/06-components/_components.atomix-glass.scss +13 -9
- package/src/styles/06-components/_components.button.scss +16 -4
- package/src/styles/06-components/_components.callout.scss +27 -21
- package/src/styles/06-components/_components.card.scss +5 -14
- package/src/styles/06-components/_components.chart.scss +22 -19
- package/src/styles/06-components/_components.checkbox.scss +25 -17
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
- package/src/styles/06-components/_components.edge-panel.scss +9 -2
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.side-menu.scss +5 -5
- package/src/styles/06-components/_components.toggle.scss +18 -0
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/06-components/old.chart.styles.scss +0 -2
- package/src/styles/99-utilities/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.border.scss +69 -27
- package/src/styles/99-utilities/_utilities.display.scss +1 -1
- package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
- package/src/styles/99-utilities/_utilities.position.scss +16 -9
- package/src/styles/99-utilities/_utilities.scss +2 -0
- package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
- package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
- package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +67 -46
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/templates-original-backup.js +0 -1655
- package/scripts/cli/templates_backup.js +0 -684
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- package/src/lib/composables/useCheckbox.ts +0 -70
|
@@ -319,336 +319,342 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
319
319
|
// Calculate time remaining based on upload speed
|
|
320
320
|
const calculateTimeRemaining = useCallback((progress: number, elapsedTime: number): string => {
|
|
321
321
|
if (progress <= 0 || elapsedTime <= 0) return '';
|
|
322
|
-
|
|
322
|
+
|
|
323
323
|
const estimatedTotalTime = (elapsedTime / progress) * 100;
|
|
324
324
|
const remainingTime = estimatedTotalTime - elapsedTime;
|
|
325
|
-
|
|
325
|
+
|
|
326
326
|
if (remainingTime <= 0) return 'Almost done...';
|
|
327
|
-
|
|
327
|
+
|
|
328
328
|
const seconds = Math.ceil(remainingTime / 1000);
|
|
329
329
|
if (seconds < 60) {
|
|
330
330
|
return `${seconds} second${seconds !== 1 ? 's' : ''} left`;
|
|
331
331
|
}
|
|
332
|
-
|
|
332
|
+
|
|
333
333
|
const minutes = Math.floor(seconds / 60);
|
|
334
334
|
const remainingSeconds = seconds % 60;
|
|
335
335
|
return `${minutes}m ${remainingSeconds}s left`;
|
|
336
336
|
}, []);
|
|
337
337
|
|
|
338
338
|
// Upload file chunk
|
|
339
|
-
const uploadChunk = useCallback(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
339
|
+
const uploadChunk = useCallback(
|
|
340
|
+
(
|
|
341
|
+
file: File,
|
|
342
|
+
chunkIndex: number,
|
|
343
|
+
totalChunks: number,
|
|
344
|
+
chunkSize: number,
|
|
345
|
+
chunkXhrs: XMLHttpRequest[]
|
|
346
|
+
): Promise<any> => {
|
|
347
|
+
return new Promise((resolve, reject) => {
|
|
348
|
+
const start = chunkIndex * chunkSize;
|
|
349
|
+
const end = Math.min(start + chunkSize, file.size);
|
|
350
|
+
const chunk = file.slice(start, end);
|
|
351
|
+
|
|
352
|
+
const formData = new FormData();
|
|
353
|
+
formData.append('file', chunk, file.name);
|
|
354
|
+
formData.append('chunkIndex', chunkIndex.toString());
|
|
355
|
+
formData.append('totalChunks', totalChunks.toString());
|
|
356
|
+
formData.append('fileName', file.name);
|
|
357
|
+
formData.append('fileSize', file.size.toString());
|
|
358
|
+
|
|
359
|
+
// Add additional form data
|
|
360
|
+
Object.entries(uploadData).forEach(([key, value]) => {
|
|
361
|
+
formData.append(key, value);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const xhr = new XMLHttpRequest();
|
|
365
|
+
|
|
366
|
+
// Store XHR for cancellation
|
|
367
|
+
chunkXhrs[chunkIndex] = xhr;
|
|
368
|
+
|
|
369
|
+
// Set up progress tracking for this chunk
|
|
370
|
+
xhr.upload.addEventListener('progress', e => {
|
|
371
|
+
if (e.lengthComputable && uploadRequestRef.current) {
|
|
372
|
+
const chunkProgress = (e.loaded / e.total) * 100;
|
|
373
|
+
const overallProgress = ((chunkIndex * chunkSize + e.loaded) / file.size) * 100;
|
|
362
374
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
const overallProgress = ((chunkIndex * chunkSize + e.loaded) / file.size) * 100;
|
|
373
|
-
|
|
374
|
-
setUploadProgress(Math.min(overallProgress, 100));
|
|
375
|
-
|
|
376
|
-
const elapsedTime = startTimeRef.current ? Date.now() - startTimeRef.current : 0;
|
|
377
|
-
const timeRemaining = calculateTimeRemaining(overallProgress, elapsedTime);
|
|
378
|
-
setTimeLeft(timeRemaining);
|
|
379
|
-
|
|
380
|
-
if (onFileUpload) {
|
|
381
|
-
onFileUpload(file, overallProgress);
|
|
375
|
+
setUploadProgress(Math.min(overallProgress, 100));
|
|
376
|
+
|
|
377
|
+
const elapsedTime = startTimeRef.current ? Date.now() - startTimeRef.current : 0;
|
|
378
|
+
const timeRemaining = calculateTimeRemaining(overallProgress, elapsedTime);
|
|
379
|
+
setTimeLeft(timeRemaining);
|
|
380
|
+
|
|
381
|
+
if (onFileUpload) {
|
|
382
|
+
onFileUpload(file, overallProgress);
|
|
383
|
+
}
|
|
382
384
|
}
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
+
});
|
|
385
386
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
387
|
+
xhr.addEventListener('load', () => {
|
|
388
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
389
|
+
try {
|
|
390
|
+
const response = xhr.responseText ? JSON.parse(xhr.responseText) : {};
|
|
391
|
+
resolve(response);
|
|
392
|
+
} catch {
|
|
393
|
+
resolve({});
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
reject(new Error(`Upload failed with status ${xhr.status}: ${xhr.statusText}`));
|
|
393
397
|
}
|
|
394
|
-
}
|
|
395
|
-
reject(new Error(`Upload failed with status ${xhr.status}: ${xhr.statusText}`));
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
+
});
|
|
398
399
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
400
|
+
xhr.addEventListener('error', () => {
|
|
401
|
+
reject(new Error('Network error occurred during upload'));
|
|
402
|
+
});
|
|
402
403
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
404
|
+
xhr.addEventListener('abort', () => {
|
|
405
|
+
reject(new Error('Upload was cancelled'));
|
|
406
|
+
});
|
|
406
407
|
|
|
407
|
-
|
|
408
|
+
xhr.open(uploadMethod, uploadEndpoint!);
|
|
408
409
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
410
|
+
// Set headers
|
|
411
|
+
Object.entries(uploadHeaders).forEach(([key, value]) => {
|
|
412
|
+
xhr.setRequestHeader(key, value);
|
|
413
|
+
});
|
|
413
414
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
415
|
+
xhr.send(formData);
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
[uploadEndpoint, uploadMethod, uploadHeaders, uploadData, onFileUpload, calculateTimeRemaining]
|
|
419
|
+
);
|
|
417
420
|
|
|
418
421
|
// Upload file (with chunking support)
|
|
419
|
-
const uploadFile = useCallback(
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
// Simulate progress updates
|
|
427
|
-
let progress = 0;
|
|
428
|
-
const interval = setInterval(() => {
|
|
429
|
-
progress += 5;
|
|
422
|
+
const uploadFile = useCallback(
|
|
423
|
+
async (file: File, retryCount: number = 0) => {
|
|
424
|
+
// If no endpoint is provided, simulate upload for backward compatibility
|
|
425
|
+
if (!uploadEndpoint) {
|
|
426
|
+
setStatus('loading');
|
|
427
|
+
setUploadProgress(0);
|
|
428
|
+
startTimeRef.current = Date.now();
|
|
430
429
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
setTimeLeft(timeRemaining);
|
|
430
|
+
// Simulate progress updates
|
|
431
|
+
let progress = 0;
|
|
432
|
+
const interval = setInterval(() => {
|
|
433
|
+
progress += 5;
|
|
436
434
|
|
|
437
|
-
if (
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
setStatus('success');
|
|
443
|
-
setSuccessMessage('Upload successful');
|
|
444
|
-
startTimeRef.current = null;
|
|
435
|
+
if (progress < 100) {
|
|
436
|
+
setUploadProgress(progress);
|
|
437
|
+
const elapsedTime = Date.now() - (startTimeRef.current || Date.now());
|
|
438
|
+
const timeRemaining = calculateTimeRemaining(progress, elapsedTime);
|
|
439
|
+
setTimeLeft(timeRemaining);
|
|
445
440
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
// Store interval for cleanup
|
|
455
|
-
uploadRequestRef.current = {
|
|
456
|
-
xhr: null,
|
|
457
|
-
abortController: new AbortController(),
|
|
458
|
-
file,
|
|
459
|
-
retryCount,
|
|
460
|
-
intervalId: interval,
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
441
|
+
if (onFileUpload) {
|
|
442
|
+
onFileUpload(file, progress);
|
|
443
|
+
}
|
|
444
|
+
} else {
|
|
445
|
+
clearInterval(interval);
|
|
446
|
+
setStatus('success');
|
|
447
|
+
setSuccessMessage('Upload successful');
|
|
448
|
+
startTimeRef.current = null;
|
|
465
449
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
setSuccessMessage(null);
|
|
470
|
-
startTimeRef.current = Date.now();
|
|
450
|
+
if (onFileUploadComplete) {
|
|
451
|
+
onFileUploadComplete(file);
|
|
452
|
+
}
|
|
471
453
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
454
|
+
uploadRequestRef.current = null;
|
|
455
|
+
}
|
|
456
|
+
}, 500);
|
|
475
457
|
|
|
476
|
-
|
|
477
|
-
// Chunked upload
|
|
478
|
-
const chunkXhrs: XMLHttpRequest[] = [];
|
|
479
|
-
|
|
480
|
-
// Initialize upload request with chunk array
|
|
458
|
+
// Store interval for cleanup
|
|
481
459
|
uploadRequestRef.current = {
|
|
482
460
|
xhr: null,
|
|
483
461
|
abortController: new AbortController(),
|
|
484
462
|
file,
|
|
485
463
|
retryCount,
|
|
486
|
-
|
|
464
|
+
intervalId: interval,
|
|
487
465
|
};
|
|
488
466
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
for (let i = 0; i < totalChunks; i++) {
|
|
492
|
-
// Check if upload was cancelled
|
|
493
|
-
if (!uploadRequestRef.current) {
|
|
494
|
-
throw new Error('Upload was cancelled');
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
const result = await uploadChunk(file, i, totalChunks, chunkSize, chunkXhrs);
|
|
498
|
-
chunkResults.push(result);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
setStatus('success');
|
|
502
|
-
setSuccessMessage('Upload successful');
|
|
503
|
-
setUploadProgress(100);
|
|
504
|
-
setTimeLeft(null);
|
|
505
|
-
startTimeRef.current = null;
|
|
506
|
-
|
|
507
|
-
if (onFileUploadComplete) {
|
|
508
|
-
onFileUploadComplete(file, chunkResults);
|
|
509
|
-
}
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
510
469
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
xhr.abort();
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
throw error;
|
|
520
|
-
}
|
|
521
|
-
} else {
|
|
522
|
-
// Single upload - wrap in Promise for proper error handling
|
|
523
|
-
await new Promise<void>((resolve, reject) => {
|
|
524
|
-
const formData = new FormData();
|
|
525
|
-
formData.append('file', file);
|
|
526
|
-
|
|
527
|
-
// Add additional form data
|
|
528
|
-
Object.entries(uploadData).forEach(([key, value]) => {
|
|
529
|
-
formData.append(key, value);
|
|
530
|
-
});
|
|
470
|
+
setStatus('loading');
|
|
471
|
+
setUploadProgress(0);
|
|
472
|
+
setErrorMessage(null);
|
|
473
|
+
setSuccessMessage(null);
|
|
474
|
+
startTimeRef.current = Date.now();
|
|
531
475
|
|
|
532
|
-
|
|
533
|
-
|
|
476
|
+
try {
|
|
477
|
+
const chunkSize = chunkSizeInMB > 0 ? chunkSizeInMB * 1024 * 1024 : file.size;
|
|
478
|
+
const totalChunks = chunkSizeInMB > 0 ? Math.ceil(file.size / chunkSize) : 1;
|
|
534
479
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const progress = (e.loaded / e.total) * 100;
|
|
539
|
-
setUploadProgress(progress);
|
|
480
|
+
if (totalChunks > 1) {
|
|
481
|
+
// Chunked upload
|
|
482
|
+
const chunkXhrs: XMLHttpRequest[] = [];
|
|
540
483
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
484
|
+
// Initialize upload request with chunk array
|
|
485
|
+
uploadRequestRef.current = {
|
|
486
|
+
xhr: null,
|
|
487
|
+
abortController: new AbortController(),
|
|
488
|
+
file,
|
|
489
|
+
retryCount,
|
|
490
|
+
chunkXhrs,
|
|
491
|
+
};
|
|
544
492
|
|
|
545
|
-
|
|
546
|
-
|
|
493
|
+
try {
|
|
494
|
+
const chunkResults = [];
|
|
495
|
+
for (let i = 0; i < totalChunks; i++) {
|
|
496
|
+
// Check if upload was cancelled
|
|
497
|
+
if (!uploadRequestRef.current) {
|
|
498
|
+
throw new Error('Upload was cancelled');
|
|
547
499
|
}
|
|
500
|
+
|
|
501
|
+
const result = await uploadChunk(file, i, totalChunks, chunkSize, chunkXhrs);
|
|
502
|
+
chunkResults.push(result);
|
|
548
503
|
}
|
|
549
|
-
});
|
|
550
504
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
505
|
+
setStatus('success');
|
|
506
|
+
setSuccessMessage('Upload successful');
|
|
507
|
+
setUploadProgress(100);
|
|
508
|
+
setTimeLeft(null);
|
|
509
|
+
startTimeRef.current = null;
|
|
510
|
+
|
|
511
|
+
if (onFileUploadComplete) {
|
|
512
|
+
onFileUploadComplete(file, chunkResults);
|
|
513
|
+
}
|
|
558
514
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
515
|
+
uploadRequestRef.current = null;
|
|
516
|
+
} catch (error) {
|
|
517
|
+
// Abort all remaining chunks
|
|
518
|
+
chunkXhrs.forEach(xhr => {
|
|
519
|
+
if (xhr && xhr.readyState !== XMLHttpRequest.DONE) {
|
|
520
|
+
xhr.abort();
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
throw error;
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
// Single upload - wrap in Promise for proper error handling
|
|
527
|
+
await new Promise<void>((resolve, reject) => {
|
|
528
|
+
const formData = new FormData();
|
|
529
|
+
formData.append('file', file);
|
|
530
|
+
|
|
531
|
+
// Add additional form data
|
|
532
|
+
Object.entries(uploadData).forEach(([key, value]) => {
|
|
533
|
+
formData.append(key, value);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
const xhr = new XMLHttpRequest();
|
|
537
|
+
const abortController = new AbortController();
|
|
538
|
+
|
|
539
|
+
// Set up progress tracking
|
|
540
|
+
xhr.upload.addEventListener('progress', e => {
|
|
541
|
+
if (e.lengthComputable) {
|
|
542
|
+
const progress = (e.loaded / e.total) * 100;
|
|
543
|
+
setUploadProgress(progress);
|
|
544
|
+
|
|
545
|
+
const elapsedTime = startTimeRef.current ? Date.now() - startTimeRef.current : 0;
|
|
546
|
+
const timeRemaining = calculateTimeRemaining(progress, elapsedTime);
|
|
547
|
+
setTimeLeft(timeRemaining);
|
|
548
|
+
|
|
549
|
+
if (onFileUpload) {
|
|
550
|
+
onFileUpload(file, progress);
|
|
563
551
|
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
xhr.addEventListener('load', () => {
|
|
556
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
557
|
+
setStatus('success');
|
|
558
|
+
setSuccessMessage('Upload successful');
|
|
559
|
+
setUploadProgress(100);
|
|
560
|
+
setTimeLeft(null);
|
|
561
|
+
startTimeRef.current = null;
|
|
562
|
+
|
|
563
|
+
try {
|
|
564
|
+
const response = xhr.responseText ? JSON.parse(xhr.responseText) : {};
|
|
565
|
+
if (onFileUploadComplete) {
|
|
566
|
+
onFileUploadComplete(file, response);
|
|
567
|
+
}
|
|
568
|
+
} catch {
|
|
569
|
+
if (onFileUploadComplete) {
|
|
570
|
+
onFileUploadComplete(file);
|
|
571
|
+
}
|
|
567
572
|
}
|
|
573
|
+
|
|
574
|
+
uploadRequestRef.current = null;
|
|
575
|
+
resolve();
|
|
576
|
+
} else {
|
|
577
|
+
reject(new Error(`Upload failed with status ${xhr.status}: ${xhr.statusText}`));
|
|
568
578
|
}
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
xhr.addEventListener('error', () => {
|
|
582
|
+
reject(new Error('Network error occurred during upload'));
|
|
583
|
+
});
|
|
569
584
|
|
|
585
|
+
xhr.addEventListener('abort', () => {
|
|
586
|
+
setStatus('idle');
|
|
587
|
+
setUploadProgress(0);
|
|
588
|
+
setTimeLeft(null);
|
|
589
|
+
startTimeRef.current = null;
|
|
570
590
|
uploadRequestRef.current = null;
|
|
571
|
-
resolve();
|
|
572
|
-
} else {
|
|
573
|
-
reject(new Error(`Upload failed with status ${xhr.status}: ${xhr.statusText}`));
|
|
574
|
-
}
|
|
575
|
-
});
|
|
576
591
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
592
|
+
if (onUploadCancel) {
|
|
593
|
+
onUploadCancel(file);
|
|
594
|
+
}
|
|
580
595
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
setUploadProgress(0);
|
|
584
|
-
setTimeLeft(null);
|
|
585
|
-
startTimeRef.current = null;
|
|
586
|
-
uploadRequestRef.current = null;
|
|
596
|
+
reject(new Error('Upload was cancelled'));
|
|
597
|
+
});
|
|
587
598
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
599
|
+
xhr.open(uploadMethod, uploadEndpoint);
|
|
600
|
+
|
|
601
|
+
// Set headers
|
|
602
|
+
Object.entries(uploadHeaders).forEach(([key, value]) => {
|
|
603
|
+
xhr.setRequestHeader(key, value);
|
|
604
|
+
});
|
|
594
605
|
|
|
595
|
-
|
|
606
|
+
// Store request for cancellation
|
|
607
|
+
uploadRequestRef.current = {
|
|
608
|
+
xhr,
|
|
609
|
+
abortController,
|
|
610
|
+
file,
|
|
611
|
+
retryCount,
|
|
612
|
+
};
|
|
596
613
|
|
|
597
|
-
|
|
598
|
-
Object.entries(uploadHeaders).forEach(([key, value]) => {
|
|
599
|
-
xhr.setRequestHeader(key, value);
|
|
614
|
+
xhr.send(formData);
|
|
600
615
|
});
|
|
616
|
+
}
|
|
617
|
+
} catch (error) {
|
|
618
|
+
const errorMessage = error instanceof Error ? error.message : 'Upload failed';
|
|
601
619
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
file,
|
|
607
|
-
retryCount,
|
|
608
|
-
};
|
|
620
|
+
// Retry logic
|
|
621
|
+
if (retryCount < maxRetries && !errorMessage.includes('cancelled')) {
|
|
622
|
+
setStatus('loading');
|
|
623
|
+
setErrorMessage(`Upload failed. Retrying... (${retryCount + 1}/${maxRetries})`);
|
|
609
624
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
setTimeout(() => {
|
|
622
|
-
uploadFile(file, retryCount + 1);
|
|
623
|
-
}, retryDelay);
|
|
624
|
-
} else {
|
|
625
|
-
setStatus('error');
|
|
626
|
-
setErrorMessage(errorMessage);
|
|
627
|
-
setUploadProgress(0);
|
|
628
|
-
setTimeLeft(null);
|
|
629
|
-
startTimeRef.current = null;
|
|
630
|
-
uploadRequestRef.current = null;
|
|
625
|
+
setTimeout(() => {
|
|
626
|
+
uploadFile(file, retryCount + 1);
|
|
627
|
+
}, retryDelay);
|
|
628
|
+
} else {
|
|
629
|
+
setStatus('error');
|
|
630
|
+
setErrorMessage(errorMessage);
|
|
631
|
+
setUploadProgress(0);
|
|
632
|
+
setTimeLeft(null);
|
|
633
|
+
startTimeRef.current = null;
|
|
634
|
+
uploadRequestRef.current = null;
|
|
631
635
|
|
|
632
|
-
|
|
633
|
-
|
|
636
|
+
if (onFileUploadError) {
|
|
637
|
+
onFileUploadError(file, errorMessage);
|
|
638
|
+
}
|
|
634
639
|
}
|
|
635
640
|
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
641
|
+
},
|
|
642
|
+
[
|
|
643
|
+
uploadEndpoint,
|
|
644
|
+
uploadMethod,
|
|
645
|
+
uploadHeaders,
|
|
646
|
+
uploadData,
|
|
647
|
+
chunkSizeInMB,
|
|
648
|
+
maxRetries,
|
|
649
|
+
retryDelay,
|
|
650
|
+
onFileUpload,
|
|
651
|
+
onFileUploadComplete,
|
|
652
|
+
onFileUploadError,
|
|
653
|
+
onUploadCancel,
|
|
654
|
+
uploadChunk,
|
|
655
|
+
calculateTimeRemaining,
|
|
656
|
+
]
|
|
657
|
+
);
|
|
652
658
|
|
|
653
659
|
// Reset upload
|
|
654
660
|
const resetUpload = useCallback(() => {
|
|
@@ -658,7 +664,7 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
658
664
|
if (uploadRequestRef.current.xhr) {
|
|
659
665
|
uploadRequestRef.current.xhr.abort();
|
|
660
666
|
}
|
|
661
|
-
|
|
667
|
+
|
|
662
668
|
// Cancel all chunk XHR requests
|
|
663
669
|
if (uploadRequestRef.current.chunkXhrs) {
|
|
664
670
|
uploadRequestRef.current.chunkXhrs.forEach(xhr => {
|
|
@@ -667,12 +673,12 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
667
673
|
}
|
|
668
674
|
});
|
|
669
675
|
}
|
|
670
|
-
|
|
676
|
+
|
|
671
677
|
// Clear interval if it exists
|
|
672
678
|
if (uploadRequestRef.current.intervalId) {
|
|
673
679
|
clearInterval(uploadRequestRef.current.intervalId);
|
|
674
680
|
}
|
|
675
|
-
|
|
681
|
+
|
|
676
682
|
uploadRequestRef.current = null;
|
|
677
683
|
}
|
|
678
684
|
|
|
@@ -692,7 +698,7 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
692
698
|
if (uploadRequestRef.current.xhr) {
|
|
693
699
|
uploadRequestRef.current.xhr.abort();
|
|
694
700
|
}
|
|
695
|
-
|
|
701
|
+
|
|
696
702
|
// Cancel all chunk XHR requests
|
|
697
703
|
if (uploadRequestRef.current.chunkXhrs) {
|
|
698
704
|
uploadRequestRef.current.chunkXhrs.forEach(xhr => {
|
|
@@ -701,19 +707,19 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
701
707
|
}
|
|
702
708
|
});
|
|
703
709
|
}
|
|
704
|
-
|
|
710
|
+
|
|
705
711
|
// Clear interval if it exists (for simulated uploads)
|
|
706
712
|
if (uploadRequestRef.current.intervalId) {
|
|
707
713
|
clearInterval(uploadRequestRef.current.intervalId);
|
|
708
714
|
}
|
|
709
|
-
|
|
715
|
+
|
|
710
716
|
uploadRequestRef.current.abortController.abort();
|
|
711
|
-
|
|
717
|
+
|
|
712
718
|
if (onUploadCancel && uploadRequestRef.current.file) {
|
|
713
719
|
onUploadCancel(uploadRequestRef.current.file);
|
|
714
720
|
}
|
|
715
721
|
}
|
|
716
|
-
|
|
722
|
+
|
|
717
723
|
uploadRequestRef.current = null;
|
|
718
724
|
resetUpload();
|
|
719
725
|
}, [onUploadCancel, resetUpload]);
|
|
@@ -726,7 +732,7 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
726
732
|
if (uploadRequestRef.current.xhr) {
|
|
727
733
|
uploadRequestRef.current.xhr.abort();
|
|
728
734
|
}
|
|
729
|
-
|
|
735
|
+
|
|
730
736
|
// Cancel all chunk XHR requests
|
|
731
737
|
if (uploadRequestRef.current.chunkXhrs) {
|
|
732
738
|
uploadRequestRef.current.chunkXhrs.forEach(xhr => {
|
|
@@ -735,7 +741,7 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
735
741
|
}
|
|
736
742
|
});
|
|
737
743
|
}
|
|
738
|
-
|
|
744
|
+
|
|
739
745
|
// Clear interval if it exists
|
|
740
746
|
if (uploadRequestRef.current.intervalId) {
|
|
741
747
|
clearInterval(uploadRequestRef.current.intervalId);
|
|
@@ -857,7 +863,7 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
857
863
|
)}
|
|
858
864
|
</div>
|
|
859
865
|
)}
|
|
860
|
-
|
|
866
|
+
|
|
861
867
|
{errorMessage && status === 'error' && (
|
|
862
868
|
<div className="c-upload__error-message">
|
|
863
869
|
{errorMessage}
|
|
@@ -876,11 +882,9 @@ export const Upload: React.FC<UploadProps> = ({
|
|
|
876
882
|
)}
|
|
877
883
|
</div>
|
|
878
884
|
)}
|
|
879
|
-
|
|
885
|
+
|
|
880
886
|
{successMessage && status === 'success' && (
|
|
881
|
-
<div className="c-upload__success-message">
|
|
882
|
-
{successMessage}
|
|
883
|
-
</div>
|
|
887
|
+
<div className="c-upload__success-message">{successMessage}</div>
|
|
884
888
|
)}
|
|
885
889
|
</div>
|
|
886
890
|
)}
|