@flipdish/portal-library 8.2.0 → 8.3.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.
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react/jsx-runtime"),r=require("react"),t=require("@mui/material/Box/Box"),i=require("@mui/material/Stack/Stack"),a=require("@mui/material/styles/styled"),l=require("@mui/material/styles/useTheme"),n=require("../../../atoms/Button/index.cjs.js"),o=require("@mui/material/FormHelperText"),s=require("@mui/material/Typography"),c=require("../../../../icons/CancelCircle/index.cjs.js"),u=require("../../../../icons/Upload/index.cjs.js"),d=require("../../../../providers/TranslationProvider.cjs.js");const p=a(t,{shouldForwardProp:e=>"hasError"!==e})((({theme:e,hasError:r})=>({flex:"1",display:"flex",flexDirection:"column",height:"100%",boxSizing:"border-box",alignItems:"center",justifyContent:"center",padding:e.spacing(4),borderRadius:e.radius["radius-8"],border:r?`1px solid ${e.palette.semantic.stroke["stroke-error-weak"]}`:`1px dashed ${e.palette.semantic.stroke["stroke-strong"]}`,background:r?e.palette.semantic.fill["fill-error-weak"]:e.palette.semantic.fill["fill-weaker"],cursor:"pointer",transition:"all 0.2s ease-in-out",[e.breakpoints.only("mobile")]:{justifyContent:"center",gap:e.spacing(4)}}))),m=a("input")({clip:"rect(0 0 0 0)",clipPath:"inset(50%)",height:1,overflow:"hidden",position:"absolute",bottom:0,left:0,whiteSpace:"nowrap",width:1}),f=a(t,{shouldForwardProp:e=>"hasError"!==e})((({hasError:e,theme:r})=>({display:"flex",flexDirection:"column",width:"48px",height:"48px",padding:"0px",justifyContent:"center",alignItems:"center",borderRadius:r.radius["radius-32"],backgroundColor:e?r.palette.semantic.fill["fill-error-weak"]:r.palette.semantic.fill["fill-primary-weak"]}))),h=a(n.Button)({alignSelf:"center"});module.exports=({handleUpload:t,multiple:a,maxFiles:n,maxFileSize:g,allowedFileTypes:x=[],disabled:b=!1,dragActiveText:k,dragInactiveText:j,browseButtonText:y,invalidFileTypesText:v,invalidFileSizeText:C,invalidFileCountText:w})=>{const _=l(),[T,F]=r.useState(!1),D=r.useRef(null),[S,q]=r.useState(null),{translate:P}=d.useTranslation(),E=r.useCallback((e=>{if(g&&e.size>g)return q(C||P("File_size_is_too_large",{maxFileSize:g?.toString()||""})),!1;const r=e.name.split(".").pop()?.toLowerCase();return!(x.length>0&&r&&!x.includes(r))||(q(v||P("File_type_is_not_allowed",{allowedFileTypes:x.join(", ")})),!1)}),[g,x,v,C,P]),z=r.useCallback((e=>{const r=Array.from(e),i=[];n&&r.length>n?q(w||P("Too_many_files_selected",{maxFiles:n.toString()})):(r.forEach((e=>{E(e)&&i.push(e)})),i.length>0&&(q(null),t(i)))}),[n,E,t,w,P]),B=r.useCallback((e=>{e.preventDefault(),e.stopPropagation(),b||F(!0)}),[b]),I=r.useCallback((e=>{e.preventDefault(),e.stopPropagation(),b||F(!1)}),[b]),R=r.useCallback((e=>{e.preventDefault(),e.stopPropagation()}),[]),A=r.useCallback((e=>{if(e.preventDefault(),e.stopPropagation(),b)return;F(!1);const r=e.dataTransfer.files;r&&r.length>0&&z(r)}),[b,z]),L=r.useCallback((e=>{if(b)return;const r=e.target.files;r&&r.length>0&&z(r),D.current&&(D.current.value="")}),[b,z]),U=r.useCallback((e=>{e.preventDefault(),e.stopPropagation(),D.current?.click()}),[]),$=r.useCallback((()=>{b||D.current?.click()}),[b]);return e.jsxs(e.Fragment,{children:[!!S&&e.jsxs(o,{error:!0,children:[e.jsx(c,{}),S]}),e.jsxs(p,{"data-fd":"file-drop-zone",hasError:!!S,onClick:b?void 0:$,onDragEnter:B,onDragLeave:I,onDragOver:R,onDrop:A,children:[e.jsx(m,{ref:D,"data-fd":"file-upload-input",disabled:b,multiple:a,onChange:L,type:"file"}),e.jsxs(i,{alignItems:"center",direction:"column",gap:_.spacing(2),justifyContent:"center",width:"100%",children:[e.jsx(f,{hasError:!!S,children:e.jsx(u,{color:S?_.palette.semantic.icon["icon-error"]:_.palette.semantic.icon["icon-primary"]})}),e.jsx(s,{variant:"b1Strong",children:T?k||P("Drop_files_here"):j||P("Drag_and_drop_files_here")}),e.jsx(h,{disabled:b,fdKey:"file-upload-btn",onClick:b?void 0:U,variant:"secondary",children:y||P("Browse_files")})]})]})]})};
1
+ "use strict";var e=require("react/jsx-runtime"),r=require("react"),t=require("@mui/material/Box/Box"),i=require("@mui/material/Stack/Stack"),a=require("@mui/material/styles/styled"),l=require("@mui/material/styles/useTheme"),n=require("../../../atoms/Button/index.cjs.js"),o=require("@mui/material/FormHelperText"),s=require("@mui/material/Typography"),c=require("../../../../icons/CancelCircle/index.cjs.js"),u=require("../../../../icons/Upload/index.cjs.js"),d=require("../../../../providers/TranslationProvider.cjs.js");const p=a(t,{shouldForwardProp:e=>"hasError"!==e})((({theme:e,hasError:r})=>({flex:"1",display:"flex",flexDirection:"column",height:"100%",boxSizing:"border-box",alignItems:"center",justifyContent:"center",padding:e.spacing(4),borderRadius:e.radius["radius-8"],border:r?`1px solid ${e.palette.semantic.stroke["stroke-error-weak"]}`:`1px dashed ${e.palette.semantic.stroke["stroke-strong"]}`,background:r?e.palette.semantic.fill["fill-error-weak"]:e.palette.semantic.fill["fill-weaker"],cursor:"pointer",transition:"all 0.2s ease-in-out",[e.breakpoints.only("mobile")]:{justifyContent:"center",gap:e.spacing(4)}}))),m=a("input")({clip:"rect(0 0 0 0)",clipPath:"inset(50%)",height:1,overflow:"hidden",position:"absolute",bottom:0,left:0,whiteSpace:"nowrap",width:1}),f=a(t,{shouldForwardProp:e=>"hasError"!==e})((({hasError:e,theme:r})=>({display:"flex",flexDirection:"column",width:"48px",height:"48px",padding:"0px",justifyContent:"center",alignItems:"center",borderRadius:r.radius["radius-32"],backgroundColor:e?r.palette.semantic.fill["fill-error-weak"]:r.palette.semantic.fill["fill-primary-weak"]}))),h=a(n.Button)({alignSelf:"center"});module.exports=({handleUpload:t,multiple:a,maxFiles:n,maxFileSize:g,allowedFileTypes:x=[],disabled:b=!1,error:k,dragActiveText:j,dragInactiveText:y,browseButtonText:v,invalidFileTypesText:C,invalidFileSizeText:w,invalidFileCountText:_})=>{const T=l(),[F,D]=r.useState(!1),S=r.useRef(null),[q,P]=r.useState(null),{translate:E}=d.useTranslation(),z=k??q,B=r.useCallback((e=>{if(g&&e.size>g)return P(w||E("File_size_is_too_large",{maxFileSize:g?.toString()||""})),!1;const r=e.name.split(".").pop()?.toLowerCase();return!(x.length>0&&r&&!x.includes(r))||(P(C||E("File_type_is_not_allowed",{allowedFileTypes:x.join(", ")})),!1)}),[g,x,C,w,E]),I=r.useCallback((e=>{const r=Array.from(e),i=[];n&&r.length>n?P(_||E("Too_many_files_selected",{maxFiles:n.toString()})):(r.forEach((e=>{B(e)&&i.push(e)})),i.length>0&&(P(null),t(i)))}),[n,B,t,_,E]),R=r.useCallback((e=>{e.preventDefault(),e.stopPropagation(),b||D(!0)}),[b]),A=r.useCallback((e=>{e.preventDefault(),e.stopPropagation(),b||D(!1)}),[b]),L=r.useCallback((e=>{e.preventDefault(),e.stopPropagation()}),[]),U=r.useCallback((e=>{if(e.preventDefault(),e.stopPropagation(),b)return;D(!1);const r=e.dataTransfer.files;r&&r.length>0&&I(r)}),[b,I]),$=r.useCallback((e=>{if(b)return;const r=e.target.files;r&&r.length>0&&I(r),S.current&&(S.current.value="")}),[b,I]),H=r.useCallback((e=>{e.preventDefault(),e.stopPropagation(),S.current?.click()}),[]),K=r.useCallback((()=>{b||S.current?.click()}),[b]);return e.jsxs(e.Fragment,{children:[!!z&&e.jsxs(o,{error:!0,children:[e.jsx(c,{}),z]}),e.jsxs(p,{"data-fd":"file-drop-zone",hasError:!!z,onClick:b?void 0:K,onDragEnter:R,onDragLeave:A,onDragOver:L,onDrop:U,children:[e.jsx(m,{ref:S,"data-fd":"file-upload-input",disabled:b,multiple:a,onChange:$,type:"file"}),e.jsxs(i,{alignItems:"center",direction:"column",gap:T.spacing(2),justifyContent:"center",width:"100%",children:[e.jsx(f,{hasError:!!z,children:e.jsx(u,{color:z?T.palette.semantic.icon["icon-error"]:T.palette.semantic.icon["icon-primary"]})}),e.jsx(s,{variant:"b1Strong",children:F?j||E("Drop_files_here"):y||E("Drag_and_drop_files_here")}),e.jsx(h,{disabled:b,fdKey:"file-upload-btn",onClick:b?void 0:H,variant:"secondary",children:v||E("Browse_files")})]})]})]})};
2
2
  //# sourceMappingURL=FileDropZone.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileDropZone.cjs.js","sources":["../../../../../src/components/organisms/FileUpload/components/FileDropZone.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\n\nimport Box from '@mui/material/Box/Box';\nimport Stack from '@mui/material/Stack/Stack';\nimport styled from '@mui/material/styles/styled';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport FlipdishButton from '@fd/components/atoms/Button';\nimport FlipdishFormHelperText from '@fd/components/atoms/FormHelperText';\nimport FlipdishTypography from '@fd/components/atoms/Typography';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport UploadIcon from '@fd/icons/Upload';\nimport { useTranslation } from '@fd/providers/TranslationProvider';\n\nconst StyledUploadAreaContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ theme, hasError }) => ({\n flex: '1',\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n boxSizing: 'border-box',\n alignItems: 'center',\n justifyContent: 'center',\n padding: theme.spacing(4),\n borderRadius: theme.radius['radius-8'],\n border: hasError\n ? `1px solid ${theme.palette.semantic.stroke['stroke-error-weak']}`\n : `1px dashed ${theme.palette.semantic.stroke['stroke-strong']}`,\n background: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-weaker'],\n cursor: 'pointer',\n transition: 'all 0.2s ease-in-out',\n [theme.breakpoints.only('mobile')]: {\n justifyContent: 'center',\n gap: theme.spacing(4),\n },\n}));\n\nconst VisuallyHiddenInput = styled('input')({\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n height: 1,\n overflow: 'hidden',\n position: 'absolute',\n bottom: 0,\n left: 0,\n whiteSpace: 'nowrap',\n width: 1,\n});\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ hasError, theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n width: '48px',\n height: '48px',\n padding: '0px',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: theme.radius['radius-32'],\n backgroundColor: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-primary-weak'],\n}));\n\nconst StyledButton = styled(FlipdishButton)({\n alignSelf: 'center',\n});\n\n/**\n * Props for the FileDropZone component.\n * Provides a drag-and-drop file upload interface with validation.\n */\nexport interface FileDropZoneProps {\n /**\n * Callback function invoked when files are successfully validated and ready to upload.\n * @param files - Array of File objects to be uploaded\n */\n handleUpload: (files: File[]) => void;\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be selected in a single operation.\n * If exceeded, an error message will be displayed.\n * @default undefined (no limit)\n */\n maxFiles?: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Files exceeding this size will be rejected with an error message.\n * Example: 10 * 1024 * 1024 for 10MB\n * @default undefined (no limit)\n */\n maxFileSize?: number;\n\n /**\n * Array of allowed file extensions (without dots).\n * Files with extensions not in this list will be rejected.\n * Example: ['jpg', 'png', 'pdf']\n * @default [] (all file types allowed)\n */\n allowedFileTypes?: string[];\n\n /**\n * Whether the file drop zone is disabled.\n * When true, prevents all file selection and drag-and-drop interactions.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n}\n\nconst FileDropZone: React.FC<FileDropZoneProps> = ({\n handleUpload,\n multiple,\n maxFiles,\n maxFileSize,\n allowedFileTypes = [],\n disabled = false,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText,\n invalidFileSizeText,\n invalidFileCountText,\n}) => {\n const theme = useTheme();\n const [isDragActive, setIsDragActive] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [error, setError] = useState<string | null>(null);\n const { translate } = useTranslation();\n\n const validateFile = useCallback(\n (file: File): boolean => {\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n setError(\n invalidFileSizeText ||\n translate('File_size_is_too_large', { maxFileSize: maxFileSize?.toString() || '' }),\n );\n return false;\n }\n\n // Check file type\n const fileExtension = file.name.split('.').pop()?.toLowerCase();\n if (allowedFileTypes.length > 0 && fileExtension && !allowedFileTypes.includes(fileExtension)) {\n setError(\n invalidFileTypesText ||\n translate('File_type_is_not_allowed', { allowedFileTypes: allowedFileTypes.join(', ') }),\n );\n return false;\n }\n\n return true;\n },\n [maxFileSize, allowedFileTypes, invalidFileTypesText, invalidFileSizeText, translate],\n );\n\n const processFiles = useCallback(\n (files: File[] | FileList) => {\n const fileArray = Array.from(files);\n const validFiles: File[] = [];\n\n // Check max files limit\n if (maxFiles && fileArray.length > maxFiles) {\n setError(\n invalidFileCountText || translate('Too_many_files_selected', { maxFiles: maxFiles.toString() }),\n );\n return;\n }\n\n // Validate each file\n fileArray.forEach((file) => {\n if (validateFile(file)) {\n validFiles.push(file);\n }\n });\n\n if (validFiles.length > 0) {\n setError(null);\n handleUpload(validFiles);\n }\n },\n [maxFiles, validateFile, handleUpload, invalidFileCountText, translate],\n );\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(true);\n },\n [disabled],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n },\n [disabled],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n\n const files = e.dataTransfer.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n },\n [disabled, processFiles],\n );\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n const files = e.target.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n\n // Reset input value to allow selecting the same file again\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n },\n [disabled, processFiles],\n );\n\n const handleButtonClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n fileInputRef.current?.click();\n }, []);\n\n const handleContainerClick = useCallback(() => {\n if (disabled) return;\n\n fileInputRef.current?.click();\n }, [disabled]);\n\n return (\n <>\n {!!error && (\n <FlipdishFormHelperText error>\n <CancelCircleIcon />\n {error}\n </FlipdishFormHelperText>\n )}\n <StyledUploadAreaContainer\n data-fd=\"file-drop-zone\"\n hasError={!!error}\n onClick={disabled ? undefined : handleContainerClick}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n <VisuallyHiddenInput\n ref={fileInputRef}\n data-fd=\"file-upload-input\"\n disabled={disabled}\n multiple={multiple}\n onChange={handleFileInputChange}\n type=\"file\"\n />\n\n <Stack\n alignItems=\"center\"\n direction=\"column\"\n gap={theme.spacing(2)}\n justifyContent=\"center\"\n width=\"100%\"\n >\n <StyledIconContainer hasError={!!error}>\n <UploadIcon\n color={\n error\n ? theme.palette.semantic.icon['icon-error']\n : theme.palette.semantic.icon['icon-primary']\n }\n />\n </StyledIconContainer>\n\n <FlipdishTypography variant=\"b1Strong\">\n {isDragActive\n ? dragActiveText || translate('Drop_files_here')\n : dragInactiveText || translate('Drag_and_drop_files_here')}\n </FlipdishTypography>\n\n <StyledButton\n disabled={disabled}\n fdKey=\"file-upload-btn\"\n onClick={disabled ? undefined : handleButtonClick}\n variant=\"secondary\"\n >\n {browseButtonText || translate('Browse_files')}\n </StyledButton>\n </Stack>\n </StyledUploadAreaContainer>\n </>\n );\n};\n\nexport default FileDropZone;\n"],"names":["StyledUploadAreaContainer","styled","Box","shouldForwardProp","prop","theme","hasError","flex","display","flexDirection","height","boxSizing","alignItems","justifyContent","padding","spacing","borderRadius","radius","border","palette","semantic","stroke","background","fill","cursor","transition","breakpoints","only","gap","VisuallyHiddenInput","clip","clipPath","overflow","position","bottom","left","whiteSpace","width","StyledIconContainer","backgroundColor","StyledButton","FlipdishButton","alignSelf","handleUpload","multiple","maxFiles","maxFileSize","allowedFileTypes","disabled","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","useTheme","isDragActive","setIsDragActive","useState","fileInputRef","useRef","error","setError","translate","useTranslation","validateFile","useCallback","file","size","toString","fileExtension","name","split","pop","toLowerCase","length","includes","join","processFiles","files","fileArray","Array","from","validFiles","forEach","push","handleDragEnter","e","preventDefault","stopPropagation","handleDragLeave","handleDragOver","handleDrop","dataTransfer","handleFileInputChange","target","current","value","handleButtonClick","event","click","handleContainerClick","_jsxs","_Fragment","children","FlipdishFormHelperText","_jsx","CancelCircleIcon","onClick","undefined","onDragEnter","onDragLeave","onDragOver","onDrop","ref","onChange","type","Stack","direction","UploadIcon","color","icon","FlipdishTypography","variant","fdKey"],"mappings":"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"}
1
+ {"version":3,"file":"FileDropZone.cjs.js","sources":["../../../../../src/components/organisms/FileUpload/components/FileDropZone.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\n\nimport Box from '@mui/material/Box/Box';\nimport Stack from '@mui/material/Stack/Stack';\nimport styled from '@mui/material/styles/styled';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport FlipdishButton from '@fd/components/atoms/Button';\nimport FlipdishFormHelperText from '@fd/components/atoms/FormHelperText';\nimport FlipdishTypography from '@fd/components/atoms/Typography';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport UploadIcon from '@fd/icons/Upload';\nimport { useTranslation } from '@fd/providers/TranslationProvider';\n\nconst StyledUploadAreaContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ theme, hasError }) => ({\n flex: '1',\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n boxSizing: 'border-box',\n alignItems: 'center',\n justifyContent: 'center',\n padding: theme.spacing(4),\n borderRadius: theme.radius['radius-8'],\n border: hasError\n ? `1px solid ${theme.palette.semantic.stroke['stroke-error-weak']}`\n : `1px dashed ${theme.palette.semantic.stroke['stroke-strong']}`,\n background: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-weaker'],\n cursor: 'pointer',\n transition: 'all 0.2s ease-in-out',\n [theme.breakpoints.only('mobile')]: {\n justifyContent: 'center',\n gap: theme.spacing(4),\n },\n}));\n\nconst VisuallyHiddenInput = styled('input')({\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n height: 1,\n overflow: 'hidden',\n position: 'absolute',\n bottom: 0,\n left: 0,\n whiteSpace: 'nowrap',\n width: 1,\n});\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ hasError, theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n width: '48px',\n height: '48px',\n padding: '0px',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: theme.radius['radius-32'],\n backgroundColor: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-primary-weak'],\n}));\n\nconst StyledButton = styled(FlipdishButton)({\n alignSelf: 'center',\n});\n\n/**\n * Props for the FileDropZone component.\n * Provides a drag-and-drop file upload interface with validation.\n */\nexport interface FileDropZoneProps {\n /**\n * Callback function invoked when files are successfully validated and ready to upload.\n * @param files - Array of File objects to be uploaded\n */\n handleUpload: (files: File[]) => void;\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be selected in a single operation.\n * If exceeded, an error message will be displayed.\n * @default undefined (no limit)\n */\n maxFiles?: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Files exceeding this size will be rejected with an error message.\n * Example: 10 * 1024 * 1024 for 10MB\n * @default undefined (no limit)\n */\n maxFileSize?: number;\n\n /**\n * Array of allowed file extensions (without dots).\n * Files with extensions not in this list will be rejected.\n * Example: ['jpg', 'png', 'pdf']\n * @default [] (all file types allowed)\n */\n allowedFileTypes?: string[];\n\n /**\n * Whether the file drop zone is disabled.\n * When true, prevents all file selection and drag-and-drop interactions.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Optional custom error message to display at the top.\n */\n error?: string | null;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n}\n\nconst FileDropZone: React.FC<FileDropZoneProps> = ({\n handleUpload,\n multiple,\n maxFiles,\n maxFileSize,\n allowedFileTypes = [],\n disabled = false,\n error,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText,\n invalidFileSizeText,\n invalidFileCountText,\n}) => {\n const theme = useTheme();\n const [isDragActive, setIsDragActive] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [validationError, setValidationError] = useState<string | null>(null);\n const { translate } = useTranslation();\n const displayError = error ?? validationError;\n\n const validateFile = useCallback(\n (file: File): boolean => {\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n setValidationError(\n invalidFileSizeText ||\n translate('File_size_is_too_large', { maxFileSize: maxFileSize?.toString() || '' }),\n );\n return false;\n }\n\n // Check file type\n const fileExtension = file.name.split('.').pop()?.toLowerCase();\n if (allowedFileTypes.length > 0 && fileExtension && !allowedFileTypes.includes(fileExtension)) {\n setValidationError(\n invalidFileTypesText ||\n translate('File_type_is_not_allowed', { allowedFileTypes: allowedFileTypes.join(', ') }),\n );\n return false;\n }\n\n return true;\n },\n [maxFileSize, allowedFileTypes, invalidFileTypesText, invalidFileSizeText, translate],\n );\n\n const processFiles = useCallback(\n (files: File[] | FileList) => {\n const fileArray = Array.from(files);\n const validFiles: File[] = [];\n\n // Check max files limit\n if (maxFiles && fileArray.length > maxFiles) {\n setValidationError(\n invalidFileCountText || translate('Too_many_files_selected', { maxFiles: maxFiles.toString() }),\n );\n return;\n }\n\n // Validate each file\n fileArray.forEach((file) => {\n if (validateFile(file)) {\n validFiles.push(file);\n }\n });\n\n if (validFiles.length > 0) {\n setValidationError(null);\n handleUpload(validFiles);\n }\n },\n [maxFiles, validateFile, handleUpload, invalidFileCountText, translate],\n );\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(true);\n },\n [disabled],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n },\n [disabled],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n\n const files = e.dataTransfer.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n },\n [disabled, processFiles],\n );\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n const files = e.target.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n\n // Reset input value to allow selecting the same file again\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n },\n [disabled, processFiles],\n );\n\n const handleButtonClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n fileInputRef.current?.click();\n }, []);\n\n const handleContainerClick = useCallback(() => {\n if (disabled) return;\n\n fileInputRef.current?.click();\n }, [disabled]);\n\n return (\n <>\n {!!displayError && (\n <FlipdishFormHelperText error>\n <CancelCircleIcon />\n {displayError}\n </FlipdishFormHelperText>\n )}\n <StyledUploadAreaContainer\n data-fd=\"file-drop-zone\"\n hasError={!!displayError}\n onClick={disabled ? undefined : handleContainerClick}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n <VisuallyHiddenInput\n ref={fileInputRef}\n data-fd=\"file-upload-input\"\n disabled={disabled}\n multiple={multiple}\n onChange={handleFileInputChange}\n type=\"file\"\n />\n\n <Stack\n alignItems=\"center\"\n direction=\"column\"\n gap={theme.spacing(2)}\n justifyContent=\"center\"\n width=\"100%\"\n >\n <StyledIconContainer hasError={!!displayError}>\n <UploadIcon\n color={\n displayError\n ? theme.palette.semantic.icon['icon-error']\n : theme.palette.semantic.icon['icon-primary']\n }\n />\n </StyledIconContainer>\n\n <FlipdishTypography variant=\"b1Strong\">\n {isDragActive\n ? dragActiveText || translate('Drop_files_here')\n : dragInactiveText || translate('Drag_and_drop_files_here')}\n </FlipdishTypography>\n\n <StyledButton\n disabled={disabled}\n fdKey=\"file-upload-btn\"\n onClick={disabled ? undefined : handleButtonClick}\n variant=\"secondary\"\n >\n {browseButtonText || translate('Browse_files')}\n </StyledButton>\n </Stack>\n </StyledUploadAreaContainer>\n </>\n );\n};\n\nexport default FileDropZone;\n"],"names":["StyledUploadAreaContainer","styled","Box","shouldForwardProp","prop","theme","hasError","flex","display","flexDirection","height","boxSizing","alignItems","justifyContent","padding","spacing","borderRadius","radius","border","palette","semantic","stroke","background","fill","cursor","transition","breakpoints","only","gap","VisuallyHiddenInput","clip","clipPath","overflow","position","bottom","left","whiteSpace","width","StyledIconContainer","backgroundColor","StyledButton","FlipdishButton","alignSelf","handleUpload","multiple","maxFiles","maxFileSize","allowedFileTypes","disabled","error","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","useTheme","isDragActive","setIsDragActive","useState","fileInputRef","useRef","validationError","setValidationError","translate","useTranslation","displayError","validateFile","useCallback","file","size","toString","fileExtension","name","split","pop","toLowerCase","length","includes","join","processFiles","files","fileArray","Array","from","validFiles","forEach","push","handleDragEnter","e","preventDefault","stopPropagation","handleDragLeave","handleDragOver","handleDrop","dataTransfer","handleFileInputChange","target","current","value","handleButtonClick","event","click","handleContainerClick","_jsxs","_Fragment","children","FlipdishFormHelperText","_jsx","CancelCircleIcon","onClick","undefined","onDragEnter","onDragLeave","onDragOver","onDrop","ref","onChange","type","Stack","direction","UploadIcon","color","icon","FlipdishTypography","variant","fdKey"],"mappings":"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"}
@@ -41,6 +41,10 @@ interface FileDropZoneProps {
41
41
  * @default false
42
42
  */
43
43
  disabled?: boolean;
44
+ /**
45
+ * Optional custom error message to display at the top.
46
+ */
47
+ error?: string | null;
44
48
  /**
45
49
  * Text displayed when files are being dragged over the drop zone.
46
50
  * @default 'Drop files here'
@@ -1,2 +1,2 @@
1
- import{jsxs as e,Fragment as r,jsx as t}from"react/jsx-runtime";import{useState as i,useRef as o,useCallback as a}from"react";import l from"@mui/material/Box/Box";import n from"@mui/material/Stack/Stack";import s from"@mui/material/styles/styled";import p from"@mui/material/styles/useTheme";import{Button as d}from"../../../atoms/Button/index.js";import c from"@mui/material/FormHelperText";import m from"@mui/material/Typography";import f from"../../../../icons/CancelCircle/index.js";import u from"../../../../icons/Upload/index.js";import{useTranslation as h}from"../../../../providers/TranslationProvider.js";const g=s(l,{shouldForwardProp:e=>"hasError"!==e})((({theme:e,hasError:r})=>({flex:"1",display:"flex",flexDirection:"column",height:"100%",boxSizing:"border-box",alignItems:"center",justifyContent:"center",padding:e.spacing(4),borderRadius:e.radius["radius-8"],border:r?`1px solid ${e.palette.semantic.stroke["stroke-error-weak"]}`:`1px dashed ${e.palette.semantic.stroke["stroke-strong"]}`,background:r?e.palette.semantic.fill["fill-error-weak"]:e.palette.semantic.fill["fill-weaker"],cursor:"pointer",transition:"all 0.2s ease-in-out",[e.breakpoints.only("mobile")]:{justifyContent:"center",gap:e.spacing(4)}}))),x=s("input")({clip:"rect(0 0 0 0)",clipPath:"inset(50%)",height:1,overflow:"hidden",position:"absolute",bottom:0,left:0,whiteSpace:"nowrap",width:1}),y=s(l,{shouldForwardProp:e=>"hasError"!==e})((({hasError:e,theme:r})=>({display:"flex",flexDirection:"column",width:"48px",height:"48px",padding:"0px",justifyContent:"center",alignItems:"center",borderRadius:r.radius["radius-32"],backgroundColor:e?r.palette.semantic.fill["fill-error-weak"]:r.palette.semantic.fill["fill-primary-weak"]}))),v=s(d)({alignSelf:"center"}),w=({handleUpload:l,multiple:s,maxFiles:d,maxFileSize:w,allowedFileTypes:b=[],disabled:k=!1,dragActiveText:_,dragInactiveText:T,browseButtonText:F,invalidFileTypesText:D,invalidFileSizeText:C,invalidFileCountText:S})=>{const j=p(),[P,E]=i(!1),z=o(null),[B,I]=i(null),{translate:A}=h(),L=a((e=>{if(w&&e.size>w)return I(C||A("File_size_is_too_large",{maxFileSize:w?.toString()||""})),!1;const r=e.name.split(".").pop()?.toLowerCase();return!(b.length>0&&r&&!b.includes(r))||(I(D||A("File_type_is_not_allowed",{allowedFileTypes:b.join(", ")})),!1)}),[w,b,D,C,A]),R=a((e=>{const r=Array.from(e),t=[];d&&r.length>d?I(S||A("Too_many_files_selected",{maxFiles:d.toString()})):(r.forEach((e=>{L(e)&&t.push(e)})),t.length>0&&(I(null),l(t)))}),[d,L,l,S,A]),U=a((e=>{e.preventDefault(),e.stopPropagation(),k||E(!0)}),[k]),$=a((e=>{e.preventDefault(),e.stopPropagation(),k||E(!1)}),[k]),H=a((e=>{e.preventDefault(),e.stopPropagation()}),[]),K=a((e=>{if(e.preventDefault(),e.stopPropagation(),k)return;E(!1);const r=e.dataTransfer.files;r&&r.length>0&&R(r)}),[k,R]),O=a((e=>{if(k)return;const r=e.target.files;r&&r.length>0&&R(r),z.current&&(z.current.value="")}),[k,R]),q=a((e=>{e.preventDefault(),e.stopPropagation(),z.current?.click()}),[]),G=a((()=>{k||z.current?.click()}),[k]);return e(r,{children:[!!B&&e(c,{error:!0,children:[t(f,{}),B]}),e(g,{"data-fd":"file-drop-zone",hasError:!!B,onClick:k?void 0:G,onDragEnter:U,onDragLeave:$,onDragOver:H,onDrop:K,children:[t(x,{ref:z,"data-fd":"file-upload-input",disabled:k,multiple:s,onChange:O,type:"file"}),e(n,{alignItems:"center",direction:"column",gap:j.spacing(2),justifyContent:"center",width:"100%",children:[t(y,{hasError:!!B,children:t(u,{color:B?j.palette.semantic.icon["icon-error"]:j.palette.semantic.icon["icon-primary"]})}),t(m,{variant:"b1Strong",children:P?_||A("Drop_files_here"):T||A("Drag_and_drop_files_here")}),t(v,{disabled:k,fdKey:"file-upload-btn",onClick:k?void 0:q,variant:"secondary",children:F||A("Browse_files")})]})]})]})};export{w as default};
1
+ import{jsxs as e,Fragment as r,jsx as t}from"react/jsx-runtime";import{useState as i,useRef as o,useCallback as a}from"react";import l from"@mui/material/Box/Box";import n from"@mui/material/Stack/Stack";import s from"@mui/material/styles/styled";import p from"@mui/material/styles/useTheme";import{Button as d}from"../../../atoms/Button/index.js";import c from"@mui/material/FormHelperText";import m from"@mui/material/Typography";import f from"../../../../icons/CancelCircle/index.js";import u from"../../../../icons/Upload/index.js";import{useTranslation as h}from"../../../../providers/TranslationProvider.js";const g=s(l,{shouldForwardProp:e=>"hasError"!==e})((({theme:e,hasError:r})=>({flex:"1",display:"flex",flexDirection:"column",height:"100%",boxSizing:"border-box",alignItems:"center",justifyContent:"center",padding:e.spacing(4),borderRadius:e.radius["radius-8"],border:r?`1px solid ${e.palette.semantic.stroke["stroke-error-weak"]}`:`1px dashed ${e.palette.semantic.stroke["stroke-strong"]}`,background:r?e.palette.semantic.fill["fill-error-weak"]:e.palette.semantic.fill["fill-weaker"],cursor:"pointer",transition:"all 0.2s ease-in-out",[e.breakpoints.only("mobile")]:{justifyContent:"center",gap:e.spacing(4)}}))),x=s("input")({clip:"rect(0 0 0 0)",clipPath:"inset(50%)",height:1,overflow:"hidden",position:"absolute",bottom:0,left:0,whiteSpace:"nowrap",width:1}),y=s(l,{shouldForwardProp:e=>"hasError"!==e})((({hasError:e,theme:r})=>({display:"flex",flexDirection:"column",width:"48px",height:"48px",padding:"0px",justifyContent:"center",alignItems:"center",borderRadius:r.radius["radius-32"],backgroundColor:e?r.palette.semantic.fill["fill-error-weak"]:r.palette.semantic.fill["fill-primary-weak"]}))),v=s(d)({alignSelf:"center"}),w=({handleUpload:l,multiple:s,maxFiles:d,maxFileSize:w,allowedFileTypes:b=[],disabled:k=!1,error:_,dragActiveText:T,dragInactiveText:F,browseButtonText:D,invalidFileTypesText:C,invalidFileSizeText:S,invalidFileCountText:j})=>{const P=p(),[E,z]=i(!1),B=o(null),[I,A]=i(null),{translate:L}=h(),R=_??I,U=a((e=>{if(w&&e.size>w)return A(S||L("File_size_is_too_large",{maxFileSize:w?.toString()||""})),!1;const r=e.name.split(".").pop()?.toLowerCase();return!(b.length>0&&r&&!b.includes(r))||(A(C||L("File_type_is_not_allowed",{allowedFileTypes:b.join(", ")})),!1)}),[w,b,C,S,L]),$=a((e=>{const r=Array.from(e),t=[];d&&r.length>d?A(j||L("Too_many_files_selected",{maxFiles:d.toString()})):(r.forEach((e=>{U(e)&&t.push(e)})),t.length>0&&(A(null),l(t)))}),[d,U,l,j,L]),H=a((e=>{e.preventDefault(),e.stopPropagation(),k||z(!0)}),[k]),K=a((e=>{e.preventDefault(),e.stopPropagation(),k||z(!1)}),[k]),O=a((e=>{e.preventDefault(),e.stopPropagation()}),[]),q=a((e=>{if(e.preventDefault(),e.stopPropagation(),k)return;z(!1);const r=e.dataTransfer.files;r&&r.length>0&&$(r)}),[k,$]),G=a((e=>{if(k)return;const r=e.target.files;r&&r.length>0&&$(r),B.current&&(B.current.value="")}),[k,$]),J=a((e=>{e.preventDefault(),e.stopPropagation(),B.current?.click()}),[]),M=a((()=>{k||B.current?.click()}),[k]);return e(r,{children:[!!R&&e(c,{error:!0,children:[t(f,{}),R]}),e(g,{"data-fd":"file-drop-zone",hasError:!!R,onClick:k?void 0:M,onDragEnter:H,onDragLeave:K,onDragOver:O,onDrop:q,children:[t(x,{ref:B,"data-fd":"file-upload-input",disabled:k,multiple:s,onChange:G,type:"file"}),e(n,{alignItems:"center",direction:"column",gap:P.spacing(2),justifyContent:"center",width:"100%",children:[t(y,{hasError:!!R,children:t(u,{color:R?P.palette.semantic.icon["icon-error"]:P.palette.semantic.icon["icon-primary"]})}),t(m,{variant:"b1Strong",children:E?T||L("Drop_files_here"):F||L("Drag_and_drop_files_here")}),t(v,{disabled:k,fdKey:"file-upload-btn",onClick:k?void 0:J,variant:"secondary",children:D||L("Browse_files")})]})]})]})};export{w as default};
2
2
  //# sourceMappingURL=FileDropZone.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileDropZone.js","sources":["../../../../../src/components/organisms/FileUpload/components/FileDropZone.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\n\nimport Box from '@mui/material/Box/Box';\nimport Stack from '@mui/material/Stack/Stack';\nimport styled from '@mui/material/styles/styled';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport FlipdishButton from '@fd/components/atoms/Button';\nimport FlipdishFormHelperText from '@fd/components/atoms/FormHelperText';\nimport FlipdishTypography from '@fd/components/atoms/Typography';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport UploadIcon from '@fd/icons/Upload';\nimport { useTranslation } from '@fd/providers/TranslationProvider';\n\nconst StyledUploadAreaContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ theme, hasError }) => ({\n flex: '1',\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n boxSizing: 'border-box',\n alignItems: 'center',\n justifyContent: 'center',\n padding: theme.spacing(4),\n borderRadius: theme.radius['radius-8'],\n border: hasError\n ? `1px solid ${theme.palette.semantic.stroke['stroke-error-weak']}`\n : `1px dashed ${theme.palette.semantic.stroke['stroke-strong']}`,\n background: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-weaker'],\n cursor: 'pointer',\n transition: 'all 0.2s ease-in-out',\n [theme.breakpoints.only('mobile')]: {\n justifyContent: 'center',\n gap: theme.spacing(4),\n },\n}));\n\nconst VisuallyHiddenInput = styled('input')({\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n height: 1,\n overflow: 'hidden',\n position: 'absolute',\n bottom: 0,\n left: 0,\n whiteSpace: 'nowrap',\n width: 1,\n});\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ hasError, theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n width: '48px',\n height: '48px',\n padding: '0px',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: theme.radius['radius-32'],\n backgroundColor: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-primary-weak'],\n}));\n\nconst StyledButton = styled(FlipdishButton)({\n alignSelf: 'center',\n});\n\n/**\n * Props for the FileDropZone component.\n * Provides a drag-and-drop file upload interface with validation.\n */\nexport interface FileDropZoneProps {\n /**\n * Callback function invoked when files are successfully validated and ready to upload.\n * @param files - Array of File objects to be uploaded\n */\n handleUpload: (files: File[]) => void;\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be selected in a single operation.\n * If exceeded, an error message will be displayed.\n * @default undefined (no limit)\n */\n maxFiles?: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Files exceeding this size will be rejected with an error message.\n * Example: 10 * 1024 * 1024 for 10MB\n * @default undefined (no limit)\n */\n maxFileSize?: number;\n\n /**\n * Array of allowed file extensions (without dots).\n * Files with extensions not in this list will be rejected.\n * Example: ['jpg', 'png', 'pdf']\n * @default [] (all file types allowed)\n */\n allowedFileTypes?: string[];\n\n /**\n * Whether the file drop zone is disabled.\n * When true, prevents all file selection and drag-and-drop interactions.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n}\n\nconst FileDropZone: React.FC<FileDropZoneProps> = ({\n handleUpload,\n multiple,\n maxFiles,\n maxFileSize,\n allowedFileTypes = [],\n disabled = false,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText,\n invalidFileSizeText,\n invalidFileCountText,\n}) => {\n const theme = useTheme();\n const [isDragActive, setIsDragActive] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [error, setError] = useState<string | null>(null);\n const { translate } = useTranslation();\n\n const validateFile = useCallback(\n (file: File): boolean => {\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n setError(\n invalidFileSizeText ||\n translate('File_size_is_too_large', { maxFileSize: maxFileSize?.toString() || '' }),\n );\n return false;\n }\n\n // Check file type\n const fileExtension = file.name.split('.').pop()?.toLowerCase();\n if (allowedFileTypes.length > 0 && fileExtension && !allowedFileTypes.includes(fileExtension)) {\n setError(\n invalidFileTypesText ||\n translate('File_type_is_not_allowed', { allowedFileTypes: allowedFileTypes.join(', ') }),\n );\n return false;\n }\n\n return true;\n },\n [maxFileSize, allowedFileTypes, invalidFileTypesText, invalidFileSizeText, translate],\n );\n\n const processFiles = useCallback(\n (files: File[] | FileList) => {\n const fileArray = Array.from(files);\n const validFiles: File[] = [];\n\n // Check max files limit\n if (maxFiles && fileArray.length > maxFiles) {\n setError(\n invalidFileCountText || translate('Too_many_files_selected', { maxFiles: maxFiles.toString() }),\n );\n return;\n }\n\n // Validate each file\n fileArray.forEach((file) => {\n if (validateFile(file)) {\n validFiles.push(file);\n }\n });\n\n if (validFiles.length > 0) {\n setError(null);\n handleUpload(validFiles);\n }\n },\n [maxFiles, validateFile, handleUpload, invalidFileCountText, translate],\n );\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(true);\n },\n [disabled],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n },\n [disabled],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n\n const files = e.dataTransfer.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n },\n [disabled, processFiles],\n );\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n const files = e.target.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n\n // Reset input value to allow selecting the same file again\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n },\n [disabled, processFiles],\n );\n\n const handleButtonClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n fileInputRef.current?.click();\n }, []);\n\n const handleContainerClick = useCallback(() => {\n if (disabled) return;\n\n fileInputRef.current?.click();\n }, [disabled]);\n\n return (\n <>\n {!!error && (\n <FlipdishFormHelperText error>\n <CancelCircleIcon />\n {error}\n </FlipdishFormHelperText>\n )}\n <StyledUploadAreaContainer\n data-fd=\"file-drop-zone\"\n hasError={!!error}\n onClick={disabled ? undefined : handleContainerClick}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n <VisuallyHiddenInput\n ref={fileInputRef}\n data-fd=\"file-upload-input\"\n disabled={disabled}\n multiple={multiple}\n onChange={handleFileInputChange}\n type=\"file\"\n />\n\n <Stack\n alignItems=\"center\"\n direction=\"column\"\n gap={theme.spacing(2)}\n justifyContent=\"center\"\n width=\"100%\"\n >\n <StyledIconContainer hasError={!!error}>\n <UploadIcon\n color={\n error\n ? theme.palette.semantic.icon['icon-error']\n : theme.palette.semantic.icon['icon-primary']\n }\n />\n </StyledIconContainer>\n\n <FlipdishTypography variant=\"b1Strong\">\n {isDragActive\n ? dragActiveText || translate('Drop_files_here')\n : dragInactiveText || translate('Drag_and_drop_files_here')}\n </FlipdishTypography>\n\n <StyledButton\n disabled={disabled}\n fdKey=\"file-upload-btn\"\n onClick={disabled ? undefined : handleButtonClick}\n variant=\"secondary\"\n >\n {browseButtonText || translate('Browse_files')}\n </StyledButton>\n </Stack>\n </StyledUploadAreaContainer>\n </>\n );\n};\n\nexport default FileDropZone;\n"],"names":["StyledUploadAreaContainer","styled","Box","shouldForwardProp","prop","theme","hasError","flex","display","flexDirection","height","boxSizing","alignItems","justifyContent","padding","spacing","borderRadius","radius","border","palette","semantic","stroke","background","fill","cursor","transition","breakpoints","only","gap","VisuallyHiddenInput","clip","clipPath","overflow","position","bottom","left","whiteSpace","width","StyledIconContainer","backgroundColor","StyledButton","FlipdishButton","alignSelf","FileDropZone","handleUpload","multiple","maxFiles","maxFileSize","allowedFileTypes","disabled","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","useTheme","isDragActive","setIsDragActive","useState","fileInputRef","useRef","error","setError","translate","useTranslation","validateFile","useCallback","file","size","toString","fileExtension","name","split","pop","toLowerCase","length","includes","join","processFiles","files","fileArray","Array","from","validFiles","forEach","push","handleDragEnter","e","preventDefault","stopPropagation","handleDragLeave","handleDragOver","handleDrop","dataTransfer","handleFileInputChange","target","current","value","handleButtonClick","event","click","handleContainerClick","_jsxs","_Fragment","children","FlipdishFormHelperText","_jsx","CancelCircleIcon","onClick","undefined","onDragEnter","onDragLeave","onDragOver","onDrop","ref","onChange","type","Stack","direction","UploadIcon","color","icon","FlipdishTypography","variant","fdKey"],"mappings":"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"}
1
+ {"version":3,"file":"FileDropZone.js","sources":["../../../../../src/components/organisms/FileUpload/components/FileDropZone.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\n\nimport Box from '@mui/material/Box/Box';\nimport Stack from '@mui/material/Stack/Stack';\nimport styled from '@mui/material/styles/styled';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport FlipdishButton from '@fd/components/atoms/Button';\nimport FlipdishFormHelperText from '@fd/components/atoms/FormHelperText';\nimport FlipdishTypography from '@fd/components/atoms/Typography';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport UploadIcon from '@fd/icons/Upload';\nimport { useTranslation } from '@fd/providers/TranslationProvider';\n\nconst StyledUploadAreaContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ theme, hasError }) => ({\n flex: '1',\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n boxSizing: 'border-box',\n alignItems: 'center',\n justifyContent: 'center',\n padding: theme.spacing(4),\n borderRadius: theme.radius['radius-8'],\n border: hasError\n ? `1px solid ${theme.palette.semantic.stroke['stroke-error-weak']}`\n : `1px dashed ${theme.palette.semantic.stroke['stroke-strong']}`,\n background: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-weaker'],\n cursor: 'pointer',\n transition: 'all 0.2s ease-in-out',\n [theme.breakpoints.only('mobile')]: {\n justifyContent: 'center',\n gap: theme.spacing(4),\n },\n}));\n\nconst VisuallyHiddenInput = styled('input')({\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n height: 1,\n overflow: 'hidden',\n position: 'absolute',\n bottom: 0,\n left: 0,\n whiteSpace: 'nowrap',\n width: 1,\n});\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'hasError',\n})<{ hasError?: boolean }>(({ hasError, theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n width: '48px',\n height: '48px',\n padding: '0px',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: theme.radius['radius-32'],\n backgroundColor: hasError\n ? theme.palette.semantic.fill['fill-error-weak']\n : theme.palette.semantic.fill['fill-primary-weak'],\n}));\n\nconst StyledButton = styled(FlipdishButton)({\n alignSelf: 'center',\n});\n\n/**\n * Props for the FileDropZone component.\n * Provides a drag-and-drop file upload interface with validation.\n */\nexport interface FileDropZoneProps {\n /**\n * Callback function invoked when files are successfully validated and ready to upload.\n * @param files - Array of File objects to be uploaded\n */\n handleUpload: (files: File[]) => void;\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be selected in a single operation.\n * If exceeded, an error message will be displayed.\n * @default undefined (no limit)\n */\n maxFiles?: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Files exceeding this size will be rejected with an error message.\n * Example: 10 * 1024 * 1024 for 10MB\n * @default undefined (no limit)\n */\n maxFileSize?: number;\n\n /**\n * Array of allowed file extensions (without dots).\n * Files with extensions not in this list will be rejected.\n * Example: ['jpg', 'png', 'pdf']\n * @default [] (all file types allowed)\n */\n allowedFileTypes?: string[];\n\n /**\n * Whether the file drop zone is disabled.\n * When true, prevents all file selection and drag-and-drop interactions.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Optional custom error message to display at the top.\n */\n error?: string | null;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n}\n\nconst FileDropZone: React.FC<FileDropZoneProps> = ({\n handleUpload,\n multiple,\n maxFiles,\n maxFileSize,\n allowedFileTypes = [],\n disabled = false,\n error,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText,\n invalidFileSizeText,\n invalidFileCountText,\n}) => {\n const theme = useTheme();\n const [isDragActive, setIsDragActive] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [validationError, setValidationError] = useState<string | null>(null);\n const { translate } = useTranslation();\n const displayError = error ?? validationError;\n\n const validateFile = useCallback(\n (file: File): boolean => {\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n setValidationError(\n invalidFileSizeText ||\n translate('File_size_is_too_large', { maxFileSize: maxFileSize?.toString() || '' }),\n );\n return false;\n }\n\n // Check file type\n const fileExtension = file.name.split('.').pop()?.toLowerCase();\n if (allowedFileTypes.length > 0 && fileExtension && !allowedFileTypes.includes(fileExtension)) {\n setValidationError(\n invalidFileTypesText ||\n translate('File_type_is_not_allowed', { allowedFileTypes: allowedFileTypes.join(', ') }),\n );\n return false;\n }\n\n return true;\n },\n [maxFileSize, allowedFileTypes, invalidFileTypesText, invalidFileSizeText, translate],\n );\n\n const processFiles = useCallback(\n (files: File[] | FileList) => {\n const fileArray = Array.from(files);\n const validFiles: File[] = [];\n\n // Check max files limit\n if (maxFiles && fileArray.length > maxFiles) {\n setValidationError(\n invalidFileCountText || translate('Too_many_files_selected', { maxFiles: maxFiles.toString() }),\n );\n return;\n }\n\n // Validate each file\n fileArray.forEach((file) => {\n if (validateFile(file)) {\n validFiles.push(file);\n }\n });\n\n if (validFiles.length > 0) {\n setValidationError(null);\n handleUpload(validFiles);\n }\n },\n [maxFiles, validateFile, handleUpload, invalidFileCountText, translate],\n );\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(true);\n },\n [disabled],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n },\n [disabled],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (disabled) return;\n\n setIsDragActive(false);\n\n const files = e.dataTransfer.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n },\n [disabled, processFiles],\n );\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n const files = e.target.files;\n if (files && files.length > 0) {\n processFiles(files);\n }\n\n // Reset input value to allow selecting the same file again\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n },\n [disabled, processFiles],\n );\n\n const handleButtonClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n fileInputRef.current?.click();\n }, []);\n\n const handleContainerClick = useCallback(() => {\n if (disabled) return;\n\n fileInputRef.current?.click();\n }, [disabled]);\n\n return (\n <>\n {!!displayError && (\n <FlipdishFormHelperText error>\n <CancelCircleIcon />\n {displayError}\n </FlipdishFormHelperText>\n )}\n <StyledUploadAreaContainer\n data-fd=\"file-drop-zone\"\n hasError={!!displayError}\n onClick={disabled ? undefined : handleContainerClick}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n <VisuallyHiddenInput\n ref={fileInputRef}\n data-fd=\"file-upload-input\"\n disabled={disabled}\n multiple={multiple}\n onChange={handleFileInputChange}\n type=\"file\"\n />\n\n <Stack\n alignItems=\"center\"\n direction=\"column\"\n gap={theme.spacing(2)}\n justifyContent=\"center\"\n width=\"100%\"\n >\n <StyledIconContainer hasError={!!displayError}>\n <UploadIcon\n color={\n displayError\n ? theme.palette.semantic.icon['icon-error']\n : theme.palette.semantic.icon['icon-primary']\n }\n />\n </StyledIconContainer>\n\n <FlipdishTypography variant=\"b1Strong\">\n {isDragActive\n ? dragActiveText || translate('Drop_files_here')\n : dragInactiveText || translate('Drag_and_drop_files_here')}\n </FlipdishTypography>\n\n <StyledButton\n disabled={disabled}\n fdKey=\"file-upload-btn\"\n onClick={disabled ? undefined : handleButtonClick}\n variant=\"secondary\"\n >\n {browseButtonText || translate('Browse_files')}\n </StyledButton>\n </Stack>\n </StyledUploadAreaContainer>\n </>\n );\n};\n\nexport default FileDropZone;\n"],"names":["StyledUploadAreaContainer","styled","Box","shouldForwardProp","prop","theme","hasError","flex","display","flexDirection","height","boxSizing","alignItems","justifyContent","padding","spacing","borderRadius","radius","border","palette","semantic","stroke","background","fill","cursor","transition","breakpoints","only","gap","VisuallyHiddenInput","clip","clipPath","overflow","position","bottom","left","whiteSpace","width","StyledIconContainer","backgroundColor","StyledButton","FlipdishButton","alignSelf","FileDropZone","handleUpload","multiple","maxFiles","maxFileSize","allowedFileTypes","disabled","error","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","useTheme","isDragActive","setIsDragActive","useState","fileInputRef","useRef","validationError","setValidationError","translate","useTranslation","displayError","validateFile","useCallback","file","size","toString","fileExtension","name","split","pop","toLowerCase","length","includes","join","processFiles","files","fileArray","Array","from","validFiles","forEach","push","handleDragEnter","e","preventDefault","stopPropagation","handleDragLeave","handleDragOver","handleDrop","dataTransfer","handleFileInputChange","target","current","value","handleButtonClick","event","click","handleContainerClick","_jsxs","_Fragment","children","FlipdishFormHelperText","_jsx","CancelCircleIcon","onClick","undefined","onDragEnter","onDragLeave","onDragOver","onDrop","ref","onChange","type","Stack","direction","UploadIcon","color","icon","FlipdishTypography","variant","fdKey"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react/jsx-runtime");require("react");var i=require("@mui/material/Stack/Stack"),l=require("@mui/material/styles/useTheme"),a=require("@mui/material/Typography"),t=require("./components/FileDropZone.cjs.js"),s=require("./components/FileItem.cjs.js");module.exports=n=>{const o=l(),{label:r="Upload File",files:d,allowedFileTypes:m,maxFiles:x,maxFileSize:p,onUpload:c,onRemove:u,multiple:F=!0,dragActiveText:T,dragInactiveText:g,browseButtonText:v,invalidFileTypesText:j="File type is not allowed. Allowed types: {allowedFileTypes}",invalidFileSizeText:y="File size is too large. Maximum size: {maxFileSize}",invalidFileCountText:f="Too many files selected. Maximum allowed: {maxFiles}"}=n,h=e=>{u(e)};return e.jsxs(e.Fragment,{children:[e.jsx(a,{paddingBottom:o.spacing(1),variant:"b1Weak",children:r}),e.jsxs(i,{direction:"column",flex:1,gap:o.spacing(1),children:[e.jsx(t,{allowedFileTypes:m,browseButtonText:v,dragActiveText:T,dragInactiveText:g,handleUpload:e=>{c(e)},invalidFileCountText:f,invalidFileSizeText:y,invalidFileTypesText:j,maxFiles:x,maxFileSize:p,multiple:F}),d.length>0&&e.jsx(i,{direction:"column",gap:o.spacing(1.5),children:d.map((i=>e.jsx(s,{file:i.file,isUploading:i.isUploading,onRemove:h},`${i.file.name}-${i.file.size}-${i.file.lastModified}`)))})]})]})};
1
+ "use strict";var e=require("react/jsx-runtime");require("react");var i=require("@mui/material/Stack/Stack"),l=require("@mui/material/styles/useTheme"),a=require("@mui/material/Typography"),t=require("./components/FileDropZone.cjs.js"),r=require("./components/FileItem.cjs.js");module.exports=s=>{const o=l(),{label:n="Upload File",files:d,allowedFileTypes:m,maxFiles:x,maxFileSize:p,onUpload:c,onRemove:u,multiple:F=!0,dragActiveText:T,dragInactiveText:g,browseButtonText:v,invalidFileTypesText:j="File type is not allowed. Allowed types: {allowedFileTypes}",invalidFileSizeText:y="File size is too large. Maximum size: {maxFileSize}",invalidFileCountText:f="Too many files selected. Maximum allowed: {maxFiles}",error:h}=s,w=e=>{u(e)};return e.jsxs(e.Fragment,{children:[e.jsx(a,{paddingBottom:o.spacing(1),variant:"b1Weak",children:n}),e.jsxs(i,{direction:"column",flex:1,gap:o.spacing(1),children:[e.jsx(t,{allowedFileTypes:m,browseButtonText:v,dragActiveText:T,dragInactiveText:g,error:h,handleUpload:e=>{c(e)},invalidFileCountText:f,invalidFileSizeText:y,invalidFileTypesText:j,maxFiles:x,maxFileSize:p,multiple:F}),d.length>0&&e.jsx(i,{direction:"column",gap:o.spacing(1.5),children:d.map((i=>e.jsx(r,{file:i.file,isUploading:i.isUploading,onRemove:w},`${i.file.name}-${i.file.size}-${i.file.lastModified}`)))})]})]})};
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/organisms/FileUpload/index.tsx"],"sourcesContent":["import React from 'react';\n\nimport Stack from '@mui/material/Stack/Stack';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport Typography from '@fd/components/atoms/Typography';\n\nimport FileDropZone from './components/FileDropZone';\nimport FileItem from './components/FileItem';\n\nexport interface FileUploadState {\n file: File;\n isUploading?: boolean;\n}\n\nexport interface FileUploadProps {\n /**\n * Label text displayed above the file upload area.\n * @default 'Upload File'\n */\n label?: string;\n\n /**\n * Array of file upload states (file object with optional isUploading flag).\n */\n files: FileUploadState[];\n\n /**\n * Array of allowed file extensions (without dots).\n * Example: ['jpg', 'png', 'pdf']\n */\n allowedFileTypes: string[];\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be uploaded.\n */\n maxFiles: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Example: 10 * 1024 * 1024 for 10MB\n */\n maxFileSize: number;\n\n /**\n * Callback fired when files are uploaded.\n */\n onUpload: (files: File[]) => void;\n\n /**\n * Callback fired when a file is removed.\n */\n onRemove: (file: File) => void;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n}\n\nconst FileUpload: React.FC<FileUploadProps> = (props) => {\n const theme = useTheme();\n const {\n label = 'Upload File',\n files,\n allowedFileTypes,\n maxFiles,\n maxFileSize,\n onUpload,\n onRemove,\n multiple = true,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText = 'File type is not allowed. Allowed types: {allowedFileTypes}',\n invalidFileSizeText = 'File size is too large. Maximum size: {maxFileSize}',\n invalidFileCountText = 'Too many files selected. Maximum allowed: {maxFiles}',\n } = props;\n\n const handleUpload = (newFiles: File[]): void => {\n // Notify parent - parent will manage state\n onUpload(newFiles);\n };\n\n const handleRemoveFile = (fileToRemove: File): void => {\n // Notify parent - parent will manage state\n onRemove(fileToRemove);\n };\n\n return (\n <>\n <Typography paddingBottom={theme.spacing(1)} variant=\"b1Weak\">\n {label}\n </Typography>\n <Stack direction=\"column\" flex={1} gap={theme.spacing(1)}>\n <FileDropZone\n allowedFileTypes={allowedFileTypes}\n browseButtonText={browseButtonText}\n dragActiveText={dragActiveText}\n dragInactiveText={dragInactiveText}\n handleUpload={handleUpload}\n invalidFileCountText={invalidFileCountText}\n invalidFileSizeText={invalidFileSizeText}\n invalidFileTypesText={invalidFileTypesText}\n maxFiles={maxFiles}\n maxFileSize={maxFileSize}\n multiple={multiple}\n />\n\n {files.length > 0 && (\n <Stack direction=\"column\" gap={theme.spacing(1.5)}>\n {files.map((fileState) => (\n <FileItem\n key={`${fileState.file.name}-${fileState.file.size}-${fileState.file.lastModified}`}\n file={fileState.file}\n isUploading={fileState.isUploading}\n onRemove={handleRemoveFile}\n />\n ))}\n </Stack>\n )}\n </Stack>\n </>\n );\n};\n\nexport default FileUpload;\n"],"names":["props","theme","useTheme","label","files","allowedFileTypes","maxFiles","maxFileSize","onUpload","onRemove","multiple","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","handleRemoveFile","fileToRemove","_jsxs","_Fragment","children","_jsx","Typography","paddingBottom","spacing","variant","Stack","direction","flex","gap","FileDropZone","handleUpload","newFiles","length","map","fileState","FileItem","file","isUploading","name","size","lastModified"],"mappings":"oSAiG+CA,IAC7C,MAAMC,EAAQC,KACRC,MACJA,EAAQ,cAAaC,MACrBA,EAAKC,iBACLA,EAAgBC,SAChBA,EAAQC,YACRA,EAAWC,SACXA,EAAQC,SACRA,EAAQC,SACRA,GAAW,EAAIC,eACfA,EAAcC,iBACdA,EAAgBC,iBAChBA,EAAgBC,qBAChBA,EAAuB,8DAA6DC,oBACpFA,EAAsB,sDAAqDC,qBAC3EA,EAAuB,wDACrBhB,EAOEiB,EAAoBC,IAExBT,EAASS,IAGX,OACEC,OAAAC,EAAAA,SAAA,CAAAC,SAAA,CACEC,EAAAA,IAACC,EAAU,CAACC,cAAevB,EAAMwB,QAAQ,GAAIC,QAAQ,SAAQL,SAC1DlB,IAEHgB,EAAAA,KAACQ,EAAK,CAACC,UAAU,SAASC,KAAM,EAAGC,IAAK7B,EAAMwB,QAAQ,GAAEJ,SAAA,CACtDC,MAACS,GACC1B,iBAAkBA,EAClBQ,iBAAkBA,EAClBF,eAAgBA,EAChBC,iBAAkBA,EAClBoB,aArBcC,IAEpBzB,EAASyB,IAoBHjB,qBAAsBA,EACtBD,oBAAqBA,EACrBD,qBAAsBA,EACtBR,SAAUA,EACVC,YAAaA,EACbG,SAAUA,IAGXN,EAAM8B,OAAS,GACdZ,MAACK,EAAK,CAACC,UAAU,SAASE,IAAK7B,EAAMwB,QAAQ,KAAIJ,SAC9CjB,EAAM+B,KAAKC,GACVd,EAAAA,IAACe,GAECC,KAAMF,EAAUE,KAChBC,YAAaH,EAAUG,YACvB9B,SAAUQ,GAHL,GAAGmB,EAAUE,KAAKE,QAAQJ,EAAUE,KAAKG,QAAQL,EAAUE,KAAKI"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/organisms/FileUpload/index.tsx"],"sourcesContent":["import React from 'react';\n\nimport Stack from '@mui/material/Stack/Stack';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport Typography from '@fd/components/atoms/Typography';\n\nimport FileDropZone from './components/FileDropZone';\nimport FileItem from './components/FileItem';\n\nexport interface FileUploadState {\n file: File;\n isUploading?: boolean;\n}\n\nexport interface FileUploadProps {\n /**\n * Label text displayed above the file upload area.\n * @default 'Upload File'\n */\n label?: string;\n\n /**\n * Array of file upload states (file object with optional isUploading flag).\n */\n files: FileUploadState[];\n\n /**\n * Array of allowed file extensions (without dots).\n * Example: ['jpg', 'png', 'pdf']\n */\n allowedFileTypes: string[];\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be uploaded.\n */\n maxFiles: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Example: 10 * 1024 * 1024 for 10MB\n */\n maxFileSize: number;\n\n /**\n * Callback fired when files are uploaded.\n */\n onUpload: (files: File[]) => void;\n\n /**\n * Callback fired when a file is removed.\n */\n onRemove: (file: File) => void;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n\n /**\n * Optional error message coming from external sources (e.g., API failures) to show on the drop zone.\n */\n error?: string | null;\n}\n\nconst FileUpload: React.FC<FileUploadProps> = (props) => {\n const theme = useTheme();\n const {\n label = 'Upload File',\n files,\n allowedFileTypes,\n maxFiles,\n maxFileSize,\n onUpload,\n onRemove,\n multiple = true,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText = 'File type is not allowed. Allowed types: {allowedFileTypes}',\n invalidFileSizeText = 'File size is too large. Maximum size: {maxFileSize}',\n invalidFileCountText = 'Too many files selected. Maximum allowed: {maxFiles}',\n error,\n } = props;\n\n const handleUpload = (newFiles: File[]): void => {\n // Notify parent - parent will manage state\n onUpload(newFiles);\n };\n\n const handleRemoveFile = (fileToRemove: File): void => {\n // Notify parent - parent will manage state\n onRemove(fileToRemove);\n };\n\n return (\n <>\n <Typography paddingBottom={theme.spacing(1)} variant=\"b1Weak\">\n {label}\n </Typography>\n <Stack direction=\"column\" flex={1} gap={theme.spacing(1)}>\n <FileDropZone\n allowedFileTypes={allowedFileTypes}\n browseButtonText={browseButtonText}\n dragActiveText={dragActiveText}\n dragInactiveText={dragInactiveText}\n error={error}\n handleUpload={handleUpload}\n invalidFileCountText={invalidFileCountText}\n invalidFileSizeText={invalidFileSizeText}\n invalidFileTypesText={invalidFileTypesText}\n maxFiles={maxFiles}\n maxFileSize={maxFileSize}\n multiple={multiple}\n />\n\n {files.length > 0 && (\n <Stack direction=\"column\" gap={theme.spacing(1.5)}>\n {files.map((fileState) => (\n <FileItem\n key={`${fileState.file.name}-${fileState.file.size}-${fileState.file.lastModified}`}\n file={fileState.file}\n isUploading={fileState.isUploading}\n onRemove={handleRemoveFile}\n />\n ))}\n </Stack>\n )}\n </Stack>\n </>\n );\n};\n\nexport default FileUpload;\n"],"names":["props","theme","useTheme","label","files","allowedFileTypes","maxFiles","maxFileSize","onUpload","onRemove","multiple","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","error","handleRemoveFile","fileToRemove","_jsxs","_Fragment","children","_jsx","Typography","paddingBottom","spacing","variant","Stack","direction","flex","gap","FileDropZone","handleUpload","newFiles","length","map","fileState","FileItem","file","isUploading","name","size","lastModified"],"mappings":"oSAsG+CA,IAC7C,MAAMC,EAAQC,KACRC,MACJA,EAAQ,cAAaC,MACrBA,EAAKC,iBACLA,EAAgBC,SAChBA,EAAQC,YACRA,EAAWC,SACXA,EAAQC,SACRA,EAAQC,SACRA,GAAW,EAAIC,eACfA,EAAcC,iBACdA,EAAgBC,iBAChBA,EAAgBC,qBAChBA,EAAuB,8DAA6DC,oBACpFA,EAAsB,sDAAqDC,qBAC3EA,EAAuB,uDAAsDC,MAC7EA,GACEjB,EAOEkB,EAAoBC,IAExBV,EAASU,IAGX,OACEC,OAAAC,EAAAA,SAAA,CAAAC,SAAA,CACEC,EAAAA,IAACC,EAAU,CAACC,cAAexB,EAAMyB,QAAQ,GAAIC,QAAQ,kBAClDxB,IAEHiB,EAAAA,KAACQ,EAAK,CAACC,UAAU,SAASC,KAAM,EAAGC,IAAK9B,EAAMyB,QAAQ,GAAEJ,SAAA,CACtDC,EAAAA,IAACS,EAAY,CACX3B,iBAAkBA,EAClBQ,iBAAkBA,EAClBF,eAAgBA,EAChBC,iBAAkBA,EAClBK,MAAOA,EACPgB,aAtBcC,IAEpB1B,EAAS0B,IAqBHlB,qBAAsBA,EACtBD,oBAAqBA,EACrBD,qBAAsBA,EACtBR,SAAUA,EACVC,YAAaA,EACbG,SAAUA,IAGXN,EAAM+B,OAAS,GACdZ,EAAAA,IAACK,GAAMC,UAAU,SAASE,IAAK9B,EAAMyB,QAAQ,KAAIJ,SAC9ClB,EAAMgC,KAAKC,GACVd,EAAAA,IAACe,EAAQ,CAEPC,KAAMF,EAAUE,KAChBC,YAAaH,EAAUG,YACvB/B,SAAUS,GAHL,GAAGmB,EAAUE,KAAKE,QAAQJ,EAAUE,KAAKG,QAAQL,EAAUE,KAAKI"}
@@ -71,6 +71,10 @@ interface FileUploadProps {
71
71
  * @default 'Too many files selected. Maximum allowed: {maxFiles}'
72
72
  */
73
73
  invalidFileCountText?: string;
74
+ /**
75
+ * Optional error message coming from external sources (e.g., API failures) to show on the drop zone.
76
+ */
77
+ error?: string | null;
74
78
  }
75
79
  declare const FileUpload: react__default.FC<FileUploadProps>;
76
80
 
@@ -1,2 +1,2 @@
1
- import{jsxs as e,Fragment as i,jsx as l}from"react/jsx-runtime";import"react";import t from"@mui/material/Stack/Stack";import a from"@mui/material/styles/useTheme";import o from"@mui/material/Typography";import m from"./components/FileDropZone.js";import n from"./components/FileItem.js";const r=r=>{const s=a(),{label:d="Upload File",files:p,allowedFileTypes:c,maxFiles:x,maxFileSize:F,onUpload:T,onRemove:u,multiple:f=!0,dragActiveText:g,dragInactiveText:v,browseButtonText:y,invalidFileTypesText:h="File type is not allowed. Allowed types: {allowedFileTypes}",invalidFileSizeText:w="File size is too large. Maximum size: {maxFileSize}",invalidFileCountText:z="Too many files selected. Maximum allowed: {maxFiles}"}=r,S=e=>{u(e)};return e(i,{children:[l(o,{paddingBottom:s.spacing(1),variant:"b1Weak",children:d}),e(t,{direction:"column",flex:1,gap:s.spacing(1),children:[l(m,{allowedFileTypes:c,browseButtonText:y,dragActiveText:g,dragInactiveText:v,handleUpload:e=>{T(e)},invalidFileCountText:z,invalidFileSizeText:w,invalidFileTypesText:h,maxFiles:x,maxFileSize:F,multiple:f}),p.length>0&&l(t,{direction:"column",gap:s.spacing(1.5),children:p.map((e=>l(n,{file:e.file,isUploading:e.isUploading,onRemove:S},`${e.file.name}-${e.file.size}-${e.file.lastModified}`)))})]})]})};export{r as default};
1
+ import{jsxs as e,Fragment as i,jsx as l}from"react/jsx-runtime";import"react";import t from"@mui/material/Stack/Stack";import a from"@mui/material/styles/useTheme";import o from"@mui/material/Typography";import m from"./components/FileDropZone.js";import n from"./components/FileItem.js";const r=r=>{const s=a(),{label:d="Upload File",files:p,allowedFileTypes:c,maxFiles:x,maxFileSize:F,onUpload:T,onRemove:u,multiple:f=!0,dragActiveText:g,dragInactiveText:v,browseButtonText:y,invalidFileTypesText:h="File type is not allowed. Allowed types: {allowedFileTypes}",invalidFileSizeText:w="File size is too large. Maximum size: {maxFileSize}",invalidFileCountText:z="Too many files selected. Maximum allowed: {maxFiles}",error:S}=r,U=e=>{u(e)};return e(i,{children:[l(o,{paddingBottom:s.spacing(1),variant:"b1Weak",children:d}),e(t,{direction:"column",flex:1,gap:s.spacing(1),children:[l(m,{allowedFileTypes:c,browseButtonText:y,dragActiveText:g,dragInactiveText:v,error:S,handleUpload:e=>{T(e)},invalidFileCountText:z,invalidFileSizeText:w,invalidFileTypesText:h,maxFiles:x,maxFileSize:F,multiple:f}),p.length>0&&l(t,{direction:"column",gap:s.spacing(1.5),children:p.map((e=>l(n,{file:e.file,isUploading:e.isUploading,onRemove:U},`${e.file.name}-${e.file.size}-${e.file.lastModified}`)))})]})]})};export{r as default};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/organisms/FileUpload/index.tsx"],"sourcesContent":["import React from 'react';\n\nimport Stack from '@mui/material/Stack/Stack';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport Typography from '@fd/components/atoms/Typography';\n\nimport FileDropZone from './components/FileDropZone';\nimport FileItem from './components/FileItem';\n\nexport interface FileUploadState {\n file: File;\n isUploading?: boolean;\n}\n\nexport interface FileUploadProps {\n /**\n * Label text displayed above the file upload area.\n * @default 'Upload File'\n */\n label?: string;\n\n /**\n * Array of file upload states (file object with optional isUploading flag).\n */\n files: FileUploadState[];\n\n /**\n * Array of allowed file extensions (without dots).\n * Example: ['jpg', 'png', 'pdf']\n */\n allowedFileTypes: string[];\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be uploaded.\n */\n maxFiles: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Example: 10 * 1024 * 1024 for 10MB\n */\n maxFileSize: number;\n\n /**\n * Callback fired when files are uploaded.\n */\n onUpload: (files: File[]) => void;\n\n /**\n * Callback fired when a file is removed.\n */\n onRemove: (file: File) => void;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n}\n\nconst FileUpload: React.FC<FileUploadProps> = (props) => {\n const theme = useTheme();\n const {\n label = 'Upload File',\n files,\n allowedFileTypes,\n maxFiles,\n maxFileSize,\n onUpload,\n onRemove,\n multiple = true,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText = 'File type is not allowed. Allowed types: {allowedFileTypes}',\n invalidFileSizeText = 'File size is too large. Maximum size: {maxFileSize}',\n invalidFileCountText = 'Too many files selected. Maximum allowed: {maxFiles}',\n } = props;\n\n const handleUpload = (newFiles: File[]): void => {\n // Notify parent - parent will manage state\n onUpload(newFiles);\n };\n\n const handleRemoveFile = (fileToRemove: File): void => {\n // Notify parent - parent will manage state\n onRemove(fileToRemove);\n };\n\n return (\n <>\n <Typography paddingBottom={theme.spacing(1)} variant=\"b1Weak\">\n {label}\n </Typography>\n <Stack direction=\"column\" flex={1} gap={theme.spacing(1)}>\n <FileDropZone\n allowedFileTypes={allowedFileTypes}\n browseButtonText={browseButtonText}\n dragActiveText={dragActiveText}\n dragInactiveText={dragInactiveText}\n handleUpload={handleUpload}\n invalidFileCountText={invalidFileCountText}\n invalidFileSizeText={invalidFileSizeText}\n invalidFileTypesText={invalidFileTypesText}\n maxFiles={maxFiles}\n maxFileSize={maxFileSize}\n multiple={multiple}\n />\n\n {files.length > 0 && (\n <Stack direction=\"column\" gap={theme.spacing(1.5)}>\n {files.map((fileState) => (\n <FileItem\n key={`${fileState.file.name}-${fileState.file.size}-${fileState.file.lastModified}`}\n file={fileState.file}\n isUploading={fileState.isUploading}\n onRemove={handleRemoveFile}\n />\n ))}\n </Stack>\n )}\n </Stack>\n </>\n );\n};\n\nexport default FileUpload;\n"],"names":["FileUpload","props","theme","useTheme","label","files","allowedFileTypes","maxFiles","maxFileSize","onUpload","onRemove","multiple","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","handleRemoveFile","fileToRemove","_jsxs","_Fragment","children","_jsx","Typography","paddingBottom","spacing","variant","Stack","direction","flex","gap","FileDropZone","handleUpload","newFiles","length","map","fileState","FileItem","file","isUploading","name","size","lastModified"],"mappings":"gSAiGA,MAAMA,EAAyCC,IAC7C,MAAMC,EAAQC,KACRC,MACJA,EAAQ,cAAaC,MACrBA,EAAKC,iBACLA,EAAgBC,SAChBA,EAAQC,YACRA,EAAWC,SACXA,EAAQC,SACRA,EAAQC,SACRA,GAAW,EAAIC,eACfA,EAAcC,iBACdA,EAAgBC,iBAChBA,EAAgBC,qBAChBA,EAAuB,8DAA6DC,oBACpFA,EAAsB,sDAAqDC,qBAC3EA,EAAuB,wDACrBhB,EAOEiB,EAAoBC,IAExBT,EAASS,IAGX,OACEC,EAAAC,EAAA,CAAAC,SAAA,CACEC,EAACC,EAAU,CAACC,cAAevB,EAAMwB,QAAQ,GAAIC,QAAQ,SAAQL,SAC1DlB,IAEHgB,EAACQ,EAAK,CAACC,UAAU,SAASC,KAAM,EAAGC,IAAK7B,EAAMwB,QAAQ,GAAEJ,SAAA,CACtDC,EAACS,GACC1B,iBAAkBA,EAClBQ,iBAAkBA,EAClBF,eAAgBA,EAChBC,iBAAkBA,EAClBoB,aArBcC,IAEpBzB,EAASyB,IAoBHjB,qBAAsBA,EACtBD,oBAAqBA,EACrBD,qBAAsBA,EACtBR,SAAUA,EACVC,YAAaA,EACbG,SAAUA,IAGXN,EAAM8B,OAAS,GACdZ,EAACK,EAAK,CAACC,UAAU,SAASE,IAAK7B,EAAMwB,QAAQ,KAAIJ,SAC9CjB,EAAM+B,KAAKC,GACVd,EAACe,GAECC,KAAMF,EAAUE,KAChBC,YAAaH,EAAUG,YACvB9B,SAAUQ,GAHL,GAAGmB,EAAUE,KAAKE,QAAQJ,EAAUE,KAAKG,QAAQL,EAAUE,KAAKI"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/organisms/FileUpload/index.tsx"],"sourcesContent":["import React from 'react';\n\nimport Stack from '@mui/material/Stack/Stack';\nimport useTheme from '@mui/material/styles/useTheme';\n\nimport Typography from '@fd/components/atoms/Typography';\n\nimport FileDropZone from './components/FileDropZone';\nimport FileItem from './components/FileItem';\n\nexport interface FileUploadState {\n file: File;\n isUploading?: boolean;\n}\n\nexport interface FileUploadProps {\n /**\n * Label text displayed above the file upload area.\n * @default 'Upload File'\n */\n label?: string;\n\n /**\n * Array of file upload states (file object with optional isUploading flag).\n */\n files: FileUploadState[];\n\n /**\n * Array of allowed file extensions (without dots).\n * Example: ['jpg', 'png', 'pdf']\n */\n allowedFileTypes: string[];\n\n /**\n * Whether multiple files can be selected at once.\n * @default true\n */\n multiple?: boolean;\n\n /**\n * Maximum number of files that can be uploaded.\n */\n maxFiles: number;\n\n /**\n * Maximum file size allowed in bytes.\n * Example: 10 * 1024 * 1024 for 10MB\n */\n maxFileSize: number;\n\n /**\n * Callback fired when files are uploaded.\n */\n onUpload: (files: File[]) => void;\n\n /**\n * Callback fired when a file is removed.\n */\n onRemove: (file: File) => void;\n\n /**\n * Text displayed when files are being dragged over the drop zone.\n * @default 'Drop files here'\n */\n dragActiveText?: string;\n\n /**\n * Text displayed when no files are being dragged (idle state).\n * @default 'Drag and drop files here'\n */\n dragInactiveText?: string;\n\n /**\n * Text displayed on the browse/upload button.\n * @default 'Browse files'\n */\n browseButtonText?: string;\n\n /**\n * Text displayed when a file type is not allowed.\n * @default 'File type is not allowed. Allowed types: {allowedFileTypes}'\n */\n invalidFileTypesText?: string;\n\n /**\n * Text displayed when a file size is too large.\n * @default 'File size is too large. Maximum size: {maxFileSize}'\n */\n invalidFileSizeText?: string;\n\n /**\n * Text displayed when too many files are selected.\n * @default 'Too many files selected. Maximum allowed: {maxFiles}'\n */\n invalidFileCountText?: string;\n\n /**\n * Optional error message coming from external sources (e.g., API failures) to show on the drop zone.\n */\n error?: string | null;\n}\n\nconst FileUpload: React.FC<FileUploadProps> = (props) => {\n const theme = useTheme();\n const {\n label = 'Upload File',\n files,\n allowedFileTypes,\n maxFiles,\n maxFileSize,\n onUpload,\n onRemove,\n multiple = true,\n dragActiveText,\n dragInactiveText,\n browseButtonText,\n invalidFileTypesText = 'File type is not allowed. Allowed types: {allowedFileTypes}',\n invalidFileSizeText = 'File size is too large. Maximum size: {maxFileSize}',\n invalidFileCountText = 'Too many files selected. Maximum allowed: {maxFiles}',\n error,\n } = props;\n\n const handleUpload = (newFiles: File[]): void => {\n // Notify parent - parent will manage state\n onUpload(newFiles);\n };\n\n const handleRemoveFile = (fileToRemove: File): void => {\n // Notify parent - parent will manage state\n onRemove(fileToRemove);\n };\n\n return (\n <>\n <Typography paddingBottom={theme.spacing(1)} variant=\"b1Weak\">\n {label}\n </Typography>\n <Stack direction=\"column\" flex={1} gap={theme.spacing(1)}>\n <FileDropZone\n allowedFileTypes={allowedFileTypes}\n browseButtonText={browseButtonText}\n dragActiveText={dragActiveText}\n dragInactiveText={dragInactiveText}\n error={error}\n handleUpload={handleUpload}\n invalidFileCountText={invalidFileCountText}\n invalidFileSizeText={invalidFileSizeText}\n invalidFileTypesText={invalidFileTypesText}\n maxFiles={maxFiles}\n maxFileSize={maxFileSize}\n multiple={multiple}\n />\n\n {files.length > 0 && (\n <Stack direction=\"column\" gap={theme.spacing(1.5)}>\n {files.map((fileState) => (\n <FileItem\n key={`${fileState.file.name}-${fileState.file.size}-${fileState.file.lastModified}`}\n file={fileState.file}\n isUploading={fileState.isUploading}\n onRemove={handleRemoveFile}\n />\n ))}\n </Stack>\n )}\n </Stack>\n </>\n );\n};\n\nexport default FileUpload;\n"],"names":["FileUpload","props","theme","useTheme","label","files","allowedFileTypes","maxFiles","maxFileSize","onUpload","onRemove","multiple","dragActiveText","dragInactiveText","browseButtonText","invalidFileTypesText","invalidFileSizeText","invalidFileCountText","error","handleRemoveFile","fileToRemove","_jsxs","_Fragment","children","_jsx","Typography","paddingBottom","spacing","variant","Stack","direction","flex","gap","FileDropZone","handleUpload","newFiles","length","map","fileState","FileItem","file","isUploading","name","size","lastModified"],"mappings":"gSAsGA,MAAMA,EAAyCC,IAC7C,MAAMC,EAAQC,KACRC,MACJA,EAAQ,cAAaC,MACrBA,EAAKC,iBACLA,EAAgBC,SAChBA,EAAQC,YACRA,EAAWC,SACXA,EAAQC,SACRA,EAAQC,SACRA,GAAW,EAAIC,eACfA,EAAcC,iBACdA,EAAgBC,iBAChBA,EAAgBC,qBAChBA,EAAuB,8DAA6DC,oBACpFA,EAAsB,sDAAqDC,qBAC3EA,EAAuB,uDAAsDC,MAC7EA,GACEjB,EAOEkB,EAAoBC,IAExBV,EAASU,IAGX,OACEC,EAAAC,EAAA,CAAAC,SAAA,CACEC,EAACC,EAAU,CAACC,cAAexB,EAAMyB,QAAQ,GAAIC,QAAQ,kBAClDxB,IAEHiB,EAACQ,EAAK,CAACC,UAAU,SAASC,KAAM,EAAGC,IAAK9B,EAAMyB,QAAQ,GAAEJ,SAAA,CACtDC,EAACS,EAAY,CACX3B,iBAAkBA,EAClBQ,iBAAkBA,EAClBF,eAAgBA,EAChBC,iBAAkBA,EAClBK,MAAOA,EACPgB,aAtBcC,IAEpB1B,EAAS0B,IAqBHlB,qBAAsBA,EACtBD,oBAAqBA,EACrBD,qBAAsBA,EACtBR,SAAUA,EACVC,YAAaA,EACbG,SAAUA,IAGXN,EAAM+B,OAAS,GACdZ,EAACK,GAAMC,UAAU,SAASE,IAAK9B,EAAMyB,QAAQ,KAAIJ,SAC9ClB,EAAMgC,KAAKC,GACVd,EAACe,EAAQ,CAEPC,KAAMF,EAAUE,KAChBC,YAAaH,EAAUG,YACvB/B,SAAUS,GAHL,GAAGmB,EAAUE,KAAKE,QAAQJ,EAAUE,KAAKG,QAAQL,EAAUE,KAAKI"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e={value:"Show password"},o={value:"Hide password"},s={value:"Select Images"},a={value:"Upload Images"},t={value:"Upload"},r={value:"Library"},l={value:"Cancel"},_={value:"Save"},i={value:"Select"},p={value:"Drop files here"},u={value:"Drag and drop files here"},n={value:"Browse files"},v={value:"File type is not allowed. Allowed types: {allowedFileTypes}"},x={value:"File size is too large. Maximum size: {maxFileSize}"},d={value:"Too many files selected. Maximum allowed: {maxFiles}"},m={value:"Remove file"},c={value:"Clear selection"},g={value:"Loading"},f={value:"No options"},w={value:"Open popup"},y={value:"Press {hotkey} to focus search"},h={value:"Next"},b={value:"{page} of {count}"},S={value:"Previous"},P={value:"Showing {start} - {end} of {total}"},D={value:"Previous page"},F={value:"Next page"},C={value:"Page {number}"},I={value:"Selected page {number}"},N={value:"{number} out of {total} hearts"},q={value:"{number} out of {total} stars"},L={value:"From"},U={value:"{total} reviews"},z={value:"Close"},O={value:"Decrease quantity"},T={value:"Increase quantity"},k={value:"Quantity"},B={value:"Dismiss {dismissible}"},H={value:"1 review"},M={Show_password:e,Hide_password:o,Select_Images:s,Upload_Images:a,Upload:t,Library:r,Cancel:l,Save:_,Select:i,Drop_files_here:p,Drag_and_drop_files_here:u,Browse_files:n,File_type_is_not_allowed:v,File_size_is_too_large:x,Too_many_files_selected:d,Remove_file:m,Clear_selection:c,Loading:g,No_options:f,Open_popup:w,Press_hotkey_to_focus_search:y,Next:h,page_of_count:b,Previous:S,Showing_start_end_of_total:P,Previous_page:D,Next_page:F,Page_number:C,Selected_page_number:I,number_out_of_total_hearts:N,number_out_of_total_stars:q,From:L,total_reviews:U,Close:z,Decrease_quantity:O,Increase_quantity:T,Quantity:k,Dismiss_dismissible:B,one_review:H};exports.Browse_files=n,exports.Cancel=l,exports.Clear_selection=c,exports.Close=z,exports.Decrease_quantity=O,exports.Dismiss_dismissible=B,exports.Drag_and_drop_files_here=u,exports.Drop_files_here=p,exports.File_size_is_too_large=x,exports.File_type_is_not_allowed=v,exports.From=L,exports.Hide_password=o,exports.Increase_quantity=T,exports.Library=r,exports.Loading=g,exports.Next=h,exports.Next_page=F,exports.No_options=f,exports.Open_popup=w,exports.Page_number=C,exports.Press_hotkey_to_focus_search=y,exports.Previous=S,exports.Previous_page=D,exports.Quantity=k,exports.Remove_file=m,exports.Save=_,exports.Select=i,exports.Select_Images=s,exports.Selected_page_number=I,exports.Show_password=e,exports.Showing_start_end_of_total=P,exports.Too_many_files_selected=d,exports.Upload=t,exports.Upload_Images=a,exports.default=M,exports.number_out_of_total_hearts=N,exports.number_out_of_total_stars=q,exports.one_review=H,exports.page_of_count=b,exports.total_reviews=U;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e={value:"Show password"},o={value:"Hide password"},s={value:"Select images"},a={value:"Upload images"},t={value:"Upload"},r={value:"Library"},l={value:"Cancel"},_={value:"Save"},i={value:"Select"},p={value:"Drop files here"},u={value:"Drag and drop files here"},n={value:"Browse files"},v={value:"File type is not allowed. Allowed types: {allowedFileTypes}"},x={value:"File size is too large. Maximum size: {maxFileSize}"},d={value:"Too many files selected. Maximum allowed: {maxFiles}"},m={value:"Remove file"},c={value:"Clear selection"},g={value:"Loading"},f={value:"No options"},w={value:"Open popup"},y={value:"Press {hotkey} to focus search"},h={value:"Next"},b={value:"{page} of {count}"},S={value:"Previous"},P={value:"Showing {start} - {end} of {total}"},D={value:"Previous page"},F={value:"Next page"},C={value:"Page {number}"},N={value:"Selected page {number}"},I={value:"{number} out of {total} hearts"},q={value:"{number} out of {total} stars"},L={value:"From"},U={value:"{total} reviews"},z={value:"Close"},O={value:"Decrease quantity"},T={value:"Increase quantity"},k={value:"Quantity"},B={value:"Dismiss {dismissible}"},H={value:"1 review"},M={Show_password:e,Hide_password:o,Select_Images:s,Upload_Images:a,Upload:t,Library:r,Cancel:l,Save:_,Select:i,Drop_files_here:p,Drag_and_drop_files_here:u,Browse_files:n,File_type_is_not_allowed:v,File_size_is_too_large:x,Too_many_files_selected:d,Remove_file:m,Clear_selection:c,Loading:g,No_options:f,Open_popup:w,Press_hotkey_to_focus_search:y,Next:h,page_of_count:b,Previous:S,Showing_start_end_of_total:P,Previous_page:D,Next_page:F,Page_number:C,Selected_page_number:N,number_out_of_total_hearts:I,number_out_of_total_stars:q,From:L,total_reviews:U,Close:z,Decrease_quantity:O,Increase_quantity:T,Quantity:k,Dismiss_dismissible:B,one_review:H};exports.Browse_files=n,exports.Cancel=l,exports.Clear_selection=c,exports.Close=z,exports.Decrease_quantity=O,exports.Dismiss_dismissible=B,exports.Drag_and_drop_files_here=u,exports.Drop_files_here=p,exports.File_size_is_too_large=x,exports.File_type_is_not_allowed=v,exports.From=L,exports.Hide_password=o,exports.Increase_quantity=T,exports.Library=r,exports.Loading=g,exports.Next=h,exports.Next_page=F,exports.No_options=f,exports.Open_popup=w,exports.Page_number=C,exports.Press_hotkey_to_focus_search=y,exports.Previous=S,exports.Previous_page=D,exports.Quantity=k,exports.Remove_file=m,exports.Save=_,exports.Select=i,exports.Select_Images=s,exports.Selected_page_number=N,exports.Show_password=e,exports.Showing_start_end_of_total=P,exports.Too_many_files_selected=d,exports.Upload=t,exports.Upload_Images=a,exports.default=M,exports.number_out_of_total_hearts=I,exports.number_out_of_total_stars=q,exports.one_review=H,exports.page_of_count=b,exports.total_reviews=U;
2
2
  //# sourceMappingURL=en.json.cjs.js.map
@@ -1,2 +1,2 @@
1
- var e={value:"Show password"},a={value:"Hide password"},l={value:"Select Images"},o={value:"Upload Images"},s={value:"Upload"},t={value:"Library"},u={value:"Cancel"},i={value:"Save"},r={value:"Select"},_={value:"Drop files here"},v={value:"Drag and drop files here"},n={value:"Browse files"},p={value:"File type is not allowed. Allowed types: {allowedFileTypes}"},d={value:"File size is too large. Maximum size: {maxFileSize}"},m={value:"Too many files selected. Maximum allowed: {maxFiles}"},c={value:"Remove file"},g={value:"Clear selection"},f={value:"Loading"},w={value:"No options"},y={value:"Open popup"},h={value:"Press {hotkey} to focus search"},S={value:"Next"},b={value:"{page} of {count}"},x={value:"Previous"},F={value:"Showing {start} - {end} of {total}"},D={value:"Previous page"},P={value:"Next page"},C={value:"Page {number}"},I={value:"Selected page {number}"},N={value:"{number} out of {total} hearts"},q={value:"{number} out of {total} stars"},z={value:"From"},L={value:"{total} reviews"},U={value:"Close"},T={value:"Decrease quantity"},k={value:"Increase quantity"},B={value:"Quantity"},H={value:"Dismiss {dismissible}"},M={value:"1 review"},O={Show_password:e,Hide_password:a,Select_Images:l,Upload_Images:o,Upload:s,Library:t,Cancel:u,Save:i,Select:r,Drop_files_here:_,Drag_and_drop_files_here:v,Browse_files:n,File_type_is_not_allowed:p,File_size_is_too_large:d,Too_many_files_selected:m,Remove_file:c,Clear_selection:g,Loading:f,No_options:w,Open_popup:y,Press_hotkey_to_focus_search:h,Next:S,page_of_count:b,Previous:x,Showing_start_end_of_total:F,Previous_page:D,Next_page:P,Page_number:C,Selected_page_number:I,number_out_of_total_hearts:N,number_out_of_total_stars:q,From:z,total_reviews:L,Close:U,Decrease_quantity:T,Increase_quantity:k,Quantity:B,Dismiss_dismissible:H,one_review:M};export{n as Browse_files,u as Cancel,g as Clear_selection,U as Close,T as Decrease_quantity,H as Dismiss_dismissible,v as Drag_and_drop_files_here,_ as Drop_files_here,d as File_size_is_too_large,p as File_type_is_not_allowed,z as From,a as Hide_password,k as Increase_quantity,t as Library,f as Loading,S as Next,P as Next_page,w as No_options,y as Open_popup,C as Page_number,h as Press_hotkey_to_focus_search,x as Previous,D as Previous_page,B as Quantity,c as Remove_file,i as Save,r as Select,l as Select_Images,I as Selected_page_number,e as Show_password,F as Showing_start_end_of_total,m as Too_many_files_selected,s as Upload,o as Upload_Images,O as default,N as number_out_of_total_hearts,q as number_out_of_total_stars,M as one_review,b as page_of_count,L as total_reviews};
1
+ var e={value:"Show password"},a={value:"Hide password"},l={value:"Select images"},o={value:"Upload images"},s={value:"Upload"},t={value:"Library"},u={value:"Cancel"},i={value:"Save"},r={value:"Select"},_={value:"Drop files here"},v={value:"Drag and drop files here"},n={value:"Browse files"},p={value:"File type is not allowed. Allowed types: {allowedFileTypes}"},d={value:"File size is too large. Maximum size: {maxFileSize}"},m={value:"Too many files selected. Maximum allowed: {maxFiles}"},c={value:"Remove file"},g={value:"Clear selection"},f={value:"Loading"},w={value:"No options"},y={value:"Open popup"},h={value:"Press {hotkey} to focus search"},S={value:"Next"},b={value:"{page} of {count}"},x={value:"Previous"},F={value:"Showing {start} - {end} of {total}"},D={value:"Previous page"},P={value:"Next page"},C={value:"Page {number}"},N={value:"Selected page {number}"},q={value:"{number} out of {total} hearts"},z={value:"{number} out of {total} stars"},I={value:"From"},L={value:"{total} reviews"},U={value:"Close"},T={value:"Decrease quantity"},k={value:"Increase quantity"},B={value:"Quantity"},H={value:"Dismiss {dismissible}"},M={value:"1 review"},O={Show_password:e,Hide_password:a,Select_Images:l,Upload_Images:o,Upload:s,Library:t,Cancel:u,Save:i,Select:r,Drop_files_here:_,Drag_and_drop_files_here:v,Browse_files:n,File_type_is_not_allowed:p,File_size_is_too_large:d,Too_many_files_selected:m,Remove_file:c,Clear_selection:g,Loading:f,No_options:w,Open_popup:y,Press_hotkey_to_focus_search:h,Next:S,page_of_count:b,Previous:x,Showing_start_end_of_total:F,Previous_page:D,Next_page:P,Page_number:C,Selected_page_number:N,number_out_of_total_hearts:q,number_out_of_total_stars:z,From:I,total_reviews:L,Close:U,Decrease_quantity:T,Increase_quantity:k,Quantity:B,Dismiss_dismissible:H,one_review:M};export{n as Browse_files,u as Cancel,g as Clear_selection,U as Close,T as Decrease_quantity,H as Dismiss_dismissible,v as Drag_and_drop_files_here,_ as Drop_files_here,d as File_size_is_too_large,p as File_type_is_not_allowed,I as From,a as Hide_password,k as Increase_quantity,t as Library,f as Loading,S as Next,P as Next_page,w as No_options,y as Open_popup,C as Page_number,h as Press_hotkey_to_focus_search,x as Previous,D as Previous_page,B as Quantity,c as Remove_file,i as Save,r as Select,l as Select_Images,N as Selected_page_number,e as Show_password,F as Showing_start_end_of_total,m as Too_many_files_selected,s as Upload,o as Upload_Images,O as default,q as number_out_of_total_hearts,z as number_out_of_total_stars,M as one_review,b as page_of_count,L as total_reviews};
2
2
  //# sourceMappingURL=en.json.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flipdish/portal-library",
3
- "version": "8.2.0",
3
+ "version": "8.3.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],