@flipdish/portal-library 8.1.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"),t=require("react"),r=require("@mui/material/Alert"),a=require("@mui/material/AlertTitle"),n=require("@mui/material/Box"),i=require("@mui/material/styles"),s=require("../../../icons/Alert/index.cjs.js"),l=require("../../../icons/CancelCircle/index.cjs.js"),o=require("../../../icons/CheckmarkCircle/index.cjs.js"),c=require("../../../icons/Diamond/index.cjs.js"),m=require("../../../icons/InformationCircle/index.cjs.js"),d=require("../../atoms/Button/index.cjs.js"),u=require("../../atoms/Link/index.cjs.js");const x={neutral:t=>e.jsx(c,{color:t.palette.semantic.icon["icon-strong"]}),brand:t=>e.jsx(c,{color:t.palette.semantic.icon["icon-primary"]}),destructive:t=>e.jsx(l,{color:t.palette.semantic.icon["icon-error"]}),warning:t=>e.jsx(s,{color:t.palette.semantic.icon["icon-warning"]}),information:t=>e.jsx(m,{color:t.palette.semantic.icon["icon-information"]}),"neutral-inverse":t=>e.jsx(c,{color:t.palette.semantic.icon["icon-inverse"]}),"brand-inverse":t=>e.jsx(c,{color:t.palette.semantic.icon["icon-inverse"]}),success:t=>e.jsx(o,{color:t.palette.semantic.icon["icon-success"]})},p={background:{neutral:e=>e.palette.semantic.fill["fill-weak"],brand:e=>e.palette.semantic.fill["fill-primary-weak"],destructive:e=>e.palette.semantic.fill["fill-error-weak"],warning:e=>e.palette.semantic.fill["fill-warning-weak"],success:e=>e.palette.semantic.fill["fill-success-weak"],information:e=>e.palette.semantic.fill["fill-information-weak"],"neutral-inverse":e=>e.palette.semantic.background["background-inverse"],"brand-inverse":e=>e.palette.semantic.fill["fill-primary-strong"]},border:{neutral:e=>e.palette.semantic.stroke["stroke-weak"],brand:e=>e.palette.semantic.stroke["stroke-primary-weak"],destructive:e=>e.palette.semantic.stroke["stroke-error-weak"],warning:e=>e.palette.semantic.stroke["stroke-warning-weak"],success:e=>e.palette.semantic.stroke["stroke-success-weak"],information:e=>e.palette.semantic.stroke["stroke-information-weak"],"neutral-inverse":e=>"transparent","brand-inverse":e=>"transparent"},header:{neutral:e=>e.palette.semantic.text["text-strong"],brand:e=>e.palette.semantic.text["text-strong"],destructive:e=>e.palette.semantic.text["text-strong"],warning:e=>e.palette.semantic.text["text-strong"],success:e=>e.palette.semantic.text["text-strong"],information:e=>e.palette.semantic.text["text-strong"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-strong"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-strong"]},text:{neutral:e=>e.palette.semantic.text["text-weak"],brand:e=>e.palette.semantic.text["text-weak"],destructive:e=>e.palette.semantic.text["text-weak"],warning:e=>e.palette.semantic.text["text-weak"],success:e=>e.palette.semantic.text["text-weak"],information:e=>e.palette.semantic.text["text-weak"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-weak"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-weak"]}},k=(e,t)=>x[t](e),f=(e,t)=>p.background[t](e),b=(e,t)=>p.border[t](e),w=(e,t)=>p.header[t](e),j=(e,t)=>p.text[t](e),g=i.styled(n)((()=>({marginTop:"16px"}))),v=i.styled(u.Link)((()=>({padding:0}))),y=i.styled(r,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({backgroundColor:f(e,t),border:"1px solid",borderColor:b(e,t),color:j(e,t)}))),h=t.memo((({title:r,description:s,tone:l="neutral",icon:o,onClose:c,className:m,fdKey:u,action:x})=>{const p=i.useTheme(),f=t.useId(),b=Boolean(r),j=b?`alert-title-${u??f}`:void 0,h=`alert-description-${u??f}`;return e.jsxs(y,{"aria-describedby":h,"aria-labelledby":j,className:m,"data-fd":u,icon:void 0===o?k(p,l):o,onClose:c,role:"alert",tone:l,children:[b&&e.jsx(a,{color:w(p,l),id:j,children:r}),e.jsx(n,{id:h,children:s}),(()=>{if(!x)return null;const t=r?`${x.label} - ${r}`:x.label;if("link"===x.kind){const r=x.fdKey??`action-link-${x.label.replace(/\s+/g,"-").toLowerCase()}`;return e.jsx(g,{children:e.jsx(v,{"aria-label":t,fdKey:r,href:x.href,rel:x.rel,target:x.target,children:x.label})})}const a=x.fdKey??`action-button-${x.label.replace(/\s+/g,"-").toLowerCase()}`;return e.jsx(g,{children:e.jsx(d.Button,{"aria-label":t,fdKey:a,onClick:x.onClick,size:"small",variant:x.type??"primary",children:x.label})})})()]})}));h.displayName="Alert",module.exports=h;
1
+ "use strict";var e=require("react/jsx-runtime"),t=require("react"),r=require("@mui/material/Alert"),a=require("@mui/material/AlertTitle"),n=require("@mui/material/Box"),i=require("@mui/material/styles"),s=require("../../../icons/Alert/index.cjs.js"),l=require("../../../icons/CancelCircle/index.cjs.js"),o=require("../../../icons/CheckmarkCircle/index.cjs.js"),c=require("../../../icons/Diamond/index.cjs.js"),m=require("../../../icons/InformationCircle/index.cjs.js"),d=require("../../atoms/Button/index.cjs.js"),u=require("../../atoms/Link/index.cjs.js");const x={neutral:t=>e.jsx(c,{color:t.palette.semantic.icon["icon-strong"]}),brand:t=>e.jsx(c,{color:t.palette.semantic.icon["icon-primary"]}),destructive:t=>e.jsx(l,{color:t.palette.semantic.icon["icon-error"]}),warning:t=>e.jsx(s,{color:t.palette.semantic.icon["icon-warning"]}),information:t=>e.jsx(m,{color:t.palette.semantic.icon["icon-information"]}),"neutral-inverse":t=>e.jsx(c,{color:t.palette.semantic.icon["icon-inverse"]}),"brand-inverse":t=>e.jsx(c,{color:t.palette.semantic.icon["icon-inverse"]}),success:t=>e.jsx(o,{color:t.palette.semantic.icon["icon-success"]})},p={background:{neutral:e=>e.palette.semantic.fill["fill-weak"],brand:e=>e.palette.semantic.fill["fill-primary-weak"],destructive:e=>e.palette.semantic.fill["fill-error-weak"],warning:e=>e.palette.semantic.fill["fill-warning-weak"],success:e=>e.palette.semantic.fill["fill-success-weak"],information:e=>e.palette.semantic.fill["fill-information-weak"],"neutral-inverse":e=>e.palette.semantic.background["background-inverse"],"brand-inverse":e=>e.palette.semantic.fill["fill-primary-strong"]},border:{neutral:e=>e.palette.semantic.stroke["stroke-weak"],brand:e=>e.palette.semantic.stroke["stroke-primary-weak"],destructive:e=>e.palette.semantic.stroke["stroke-error-weak"],warning:e=>e.palette.semantic.stroke["stroke-warning-weak"],success:e=>e.palette.semantic.stroke["stroke-success-weak"],information:e=>e.palette.semantic.stroke["stroke-information-weak"],"neutral-inverse":e=>"transparent","brand-inverse":e=>"transparent"},header:{neutral:e=>e.palette.semantic.text["text-strong"],brand:e=>e.palette.semantic.text["text-strong"],destructive:e=>e.palette.semantic.text["text-strong"],warning:e=>e.palette.semantic.text["text-strong"],success:e=>e.palette.semantic.text["text-strong"],information:e=>e.palette.semantic.text["text-strong"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-strong"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-strong"]},text:{neutral:e=>e.palette.semantic.text["text-weak"],brand:e=>e.palette.semantic.text["text-weak"],destructive:e=>e.palette.semantic.text["text-weak"],warning:e=>e.palette.semantic.text["text-weak"],success:e=>e.palette.semantic.text["text-weak"],information:e=>e.palette.semantic.text["text-weak"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-weak"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-weak"]}},k=(e,t)=>x[t](e),f=(e,t)=>p.background[t](e),b=(e,t)=>p.border[t](e),w=(e,t)=>p.header[t](e),j=(e,t)=>p.text[t](e),g=i.styled(n)((()=>({marginTop:"16px"}))),v=i.styled(u.Link)((()=>({padding:0}))),y=i.styled(r,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({backgroundColor:f(e,t),border:"1px solid",borderColor:b(e,t),color:j(e,t)}))),h=t.memo((({title:r,description:s,children:l,tone:o="neutral",icon:c,onClose:m,className:u,fdKey:x,action:p})=>{const f=i.useTheme(),b=t.useId(),j=l??s,h=Boolean(r),q=null!=j,C=h?`alert-title-${x??b}`:void 0,$=q?`alert-description-${x??b}`:void 0;return e.jsxs(y,{"aria-describedby":$,"aria-labelledby":C,className:u,"data-fd":x,icon:void 0===c?k(f,o):c,onClose:m,role:"alert",tone:o,children:[h&&e.jsx(a,{color:w(f,o),id:C,children:r}),q&&e.jsx(n,{id:$,children:j}),(()=>{if(!p)return null;const t=r?`${p.label} - ${r}`:p.label;if("link"===p.kind){const r=p.fdKey??`action-link-${p.label.replace(/\s+/g,"-").toLowerCase()}`;return e.jsx(g,{children:e.jsx(v,{"aria-label":t,fdKey:r,href:p.href,rel:p.rel,target:p.target,children:p.label})})}const a=p.fdKey??`action-button-${p.label.replace(/\s+/g,"-").toLowerCase()}`;return e.jsx(g,{children:e.jsx(d.Button,{"aria-label":t,fdKey:a,onClick:p.onClick,size:"small",variant:p.type??"primary",children:p.label})})})()]})}));h.displayName="Alert",module.exports=h;
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/Alert/index.tsx"],"sourcesContent":["import { memo, type ReactNode, useId } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\nimport MuiAlertTitle from '@mui/material/AlertTitle';\nimport Box from '@mui/material/Box';\nimport { styled, type Theme, useTheme } from '@mui/material/styles';\n\nimport AlertIcon from '../../../icons/Alert';\nimport CancelCircleIcon from '../../../icons/CancelCircle';\nimport CheckmarkCircleIcon from '../../../icons/CheckmarkCircle';\nimport DiamondIcon from '../../../icons/Diamond';\nimport InformationCircleIcon from '../../../icons/InformationCircle';\nimport Button from '../../atoms/Button';\nimport type { ButtonType } from '../../atoms/Button/getButtonStyles';\nimport Link from '../../atoms/Link';\n\n/** Visual tone of the alert */\nexport type AlertTones =\n | 'brand-inverse'\n | 'brand'\n | 'destructive'\n | 'information'\n | 'neutral-inverse'\n | 'neutral'\n | 'success'\n | 'warning';\n\n/** Props for the Alert component */\nexport interface AlertProps {\n /** Optional main heading text of the alert */\n title?: string;\n /** Detailed description text of the alert */\n description: string;\n /** Visual tone of the alert */\n tone?: AlertTones;\n /** Optional icon override; pass null to hide the icon */\n icon?: ReactNode | null;\n /** Callback function when the alert is closed */\n onClose?: () => void;\n /** Action configuration (button by default, or link) */\n action?: AlertAction;\n /** Additional CSS class names */\n className?: string;\n /** Test ID for testing and automation */\n fdKey?: string;\n}\n\nexport type AlertAction =\n | {\n /** Defaults to button when omitted */\n kind?: 'button';\n /** Text label for the action button */\n label: string;\n /** Visual style of the action button */\n type?: ButtonType;\n /** Callback function when the action button is clicked */\n onClick: () => void;\n /** Test ID for the action button */\n fdKey?: string;\n }\n | {\n /** Render a link action */\n kind: 'link';\n /** Text label for the link */\n label: string;\n /** Destination URL */\n href: string;\n /** Target for the link */\n target?: '_blank' | '_parent' | '_self' | '_top';\n /** rel attribute for the link */\n rel?: string;\n /** Test ID for the link */\n fdKey?: string;\n };\n\nconst ICONS = {\n neutral: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-strong']} />,\n brand: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-primary']} />,\n destructive: (theme: Theme): JSX.Element => (\n <CancelCircleIcon color={theme.palette.semantic.icon['icon-error']} />\n ),\n warning: (theme: Theme): JSX.Element => <AlertIcon color={theme.palette.semantic.icon['icon-warning']} />,\n information: (theme: Theme): JSX.Element => (\n <InformationCircleIcon color={theme.palette.semantic.icon['icon-information']} />\n ),\n 'neutral-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n 'brand-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n success: (theme: Theme): JSX.Element => (\n <CheckmarkCircleIcon color={theme.palette.semantic.icon['icon-success']} />\n ),\n};\n\nconst COLOURS = {\n background: {\n neutral: (theme: Theme): string => theme.palette.semantic.fill['fill-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.fill['fill-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.fill['fill-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.fill['fill-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.fill['fill-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.fill['fill-information-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.background['background-inverse'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.fill['fill-primary-strong'],\n },\n border: {\n neutral: (theme: Theme): string => theme.palette.semantic.stroke['stroke-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.stroke['stroke-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.stroke['stroke-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.stroke['stroke-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.stroke['stroke-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.stroke['stroke-information-weak'],\n 'neutral-inverse': (_theme: Theme): string => 'transparent',\n 'brand-inverse': (_theme: Theme): string => 'transparent',\n },\n header: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n },\n text: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n },\n};\n\nconst getIcon = (theme: Theme, tone: AlertTones): JSX.Element => {\n return ICONS[tone](theme);\n};\n\nconst getBackgroundColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.background[tone](theme);\n};\n\nconst getBorderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.border[tone](theme);\n};\n\nconst getHeaderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.header[tone](theme);\n};\n\nconst getTextColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.text[tone](theme);\n};\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledActionContainer = styled(Box)(() => ({\n marginTop: '16px',\n}));\n\nconst StyledActionLink = styled(Link)(() => ({\n padding: 0,\n}));\n\nconst StyledAlert = styled(MuiAlert, {\n shouldForwardProp: (prop) => !['tone'].includes(prop as string),\n})<StyledAlertProps>(({ theme, tone }) => ({\n backgroundColor: getBackgroundColour(theme, tone),\n border: '1px solid',\n borderColor: getBorderColour(theme, tone),\n color: getTextColour(theme, tone),\n}));\n\n/**\n * Alert component is used to display important messages or notifications to users.\n * It supports different visual tones to convey different semantic meanings and can include\n * an optional action button and close button.\n *\n * The component is wrapped with React.memo to optimize performance by preventing unnecessary\n * re-renders when the component's props haven't changed, which is beneficial for components\n * that may be used frequently throughout the application.\n */\nconst Alert = memo(\n ({ title, description, tone = 'neutral', icon, onClose, className, fdKey, action }: AlertProps) => {\n const theme = useTheme();\n const alertId = useId();\n const hasTitle = Boolean(title);\n const titleId = hasTitle ? `alert-title-${fdKey ?? alertId}` : undefined;\n const descriptionId = `alert-description-${fdKey ?? alertId}`;\n\n const renderAction = (): JSX.Element | null => {\n if (!action) {\n return null;\n }\n\n const actionLabel = title ? `${action.label} - ${title}` : action.label;\n\n if (action.kind === 'link') {\n const actionFdKey = action.fdKey ?? `action-link-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <StyledActionLink\n aria-label={actionLabel}\n fdKey={actionFdKey}\n href={action.href}\n rel={action.rel}\n target={action.target}\n >\n {action.label}\n </StyledActionLink>\n </StyledActionContainer>\n );\n }\n\n const actionFdKey = action.fdKey ?? `action-button-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <Button\n aria-label={actionLabel}\n fdKey={actionFdKey}\n onClick={action.onClick}\n size=\"small\"\n variant={action.type ?? 'primary'}\n >\n {action.label}\n </Button>\n </StyledActionContainer>\n );\n };\n\n return (\n <StyledAlert\n aria-describedby={descriptionId}\n aria-labelledby={titleId}\n className={className}\n data-fd={fdKey}\n icon={icon === undefined ? getIcon(theme, tone) : icon}\n onClose={onClose}\n role=\"alert\"\n tone={tone}\n >\n {hasTitle && (\n <MuiAlertTitle color={getHeaderColour(theme, tone)} id={titleId}>\n {title}\n </MuiAlertTitle>\n )}\n <Box id={descriptionId}>{description}</Box>\n {renderAction()}\n </StyledAlert>\n );\n },\n);\n\nAlert.displayName = 'Alert';\n\nexport default Alert;\n"],"names":["ICONS","neutral","theme","_jsx","DiamondIcon","color","palette","semantic","icon","brand","destructive","CancelCircleIcon","warning","AlertIcon","information","InformationCircleIcon","success","CheckmarkCircleIcon","COLOURS","background","fill","border","stroke","_theme","header","text","getIcon","tone","getBackgroundColour","getBorderColour","getHeaderColour","getTextColour","StyledActionContainer","styled","Box","marginTop","StyledActionLink","Link","padding","StyledAlert","MuiAlert","shouldForwardProp","prop","includes","backgroundColor","borderColor","Alert","memo","title","description","onClose","className","fdKey","action","useTheme","alertId","useId","hasTitle","Boolean","titleId","undefined","descriptionId","_jsxs","role","children","MuiAlertTitle","id","actionLabel","label","kind","actionFdKey","replace","toLowerCase","href","rel","target","Button","onClick","size","variant","type","renderAction","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/Alert/index.tsx"],"sourcesContent":["import { memo, type ReactNode, useId } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\nimport MuiAlertTitle from '@mui/material/AlertTitle';\nimport Box from '@mui/material/Box';\nimport { styled, type Theme, useTheme } from '@mui/material/styles';\n\nimport AlertIcon from '../../../icons/Alert';\nimport CancelCircleIcon from '../../../icons/CancelCircle';\nimport CheckmarkCircleIcon from '../../../icons/CheckmarkCircle';\nimport DiamondIcon from '../../../icons/Diamond';\nimport InformationCircleIcon from '../../../icons/InformationCircle';\nimport Button from '../../atoms/Button';\nimport type { ButtonType } from '../../atoms/Button/getButtonStyles';\nimport Link from '../../atoms/Link';\n\n/** Visual tone of the alert */\nexport type AlertTones =\n | 'brand-inverse'\n | 'brand'\n | 'destructive'\n | 'information'\n | 'neutral-inverse'\n | 'neutral'\n | 'success'\n | 'warning';\n\n/** Props for the Alert component */\nexport interface AlertProps {\n /** Optional main heading text of the alert */\n title?: string;\n /** Detailed description text of the alert */\n description?: string;\n /** Optional custom content; when provided it replaces description */\n children?: ReactNode;\n /** Visual tone of the alert */\n tone?: AlertTones;\n /** Optional icon override; pass null to hide the icon */\n icon?: ReactNode | null;\n /** Callback function when the alert is closed */\n onClose?: () => void;\n /** Action configuration (button by default, or link) */\n action?: AlertAction;\n /** Additional CSS class names */\n className?: string;\n /** Test ID for testing and automation */\n fdKey?: string;\n}\n\nexport type AlertAction =\n | {\n /** Defaults to button when omitted */\n kind?: 'button';\n /** Text label for the action button */\n label: string;\n /** Visual style of the action button */\n type?: ButtonType;\n /** Callback function when the action button is clicked */\n onClick: () => void;\n /** Test ID for the action button */\n fdKey?: string;\n }\n | {\n /** Render a link action */\n kind: 'link';\n /** Text label for the link */\n label: string;\n /** Destination URL */\n href: string;\n /** Target for the link */\n target?: '_blank' | '_parent' | '_self' | '_top';\n /** rel attribute for the link */\n rel?: string;\n /** Test ID for the link */\n fdKey?: string;\n };\n\nconst ICONS = {\n neutral: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-strong']} />,\n brand: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-primary']} />,\n destructive: (theme: Theme): JSX.Element => (\n <CancelCircleIcon color={theme.palette.semantic.icon['icon-error']} />\n ),\n warning: (theme: Theme): JSX.Element => <AlertIcon color={theme.palette.semantic.icon['icon-warning']} />,\n information: (theme: Theme): JSX.Element => (\n <InformationCircleIcon color={theme.palette.semantic.icon['icon-information']} />\n ),\n 'neutral-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n 'brand-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n success: (theme: Theme): JSX.Element => (\n <CheckmarkCircleIcon color={theme.palette.semantic.icon['icon-success']} />\n ),\n};\n\nconst COLOURS = {\n background: {\n neutral: (theme: Theme): string => theme.palette.semantic.fill['fill-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.fill['fill-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.fill['fill-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.fill['fill-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.fill['fill-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.fill['fill-information-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.background['background-inverse'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.fill['fill-primary-strong'],\n },\n border: {\n neutral: (theme: Theme): string => theme.palette.semantic.stroke['stroke-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.stroke['stroke-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.stroke['stroke-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.stroke['stroke-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.stroke['stroke-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.stroke['stroke-information-weak'],\n 'neutral-inverse': (_theme: Theme): string => 'transparent',\n 'brand-inverse': (_theme: Theme): string => 'transparent',\n },\n header: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n },\n text: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n },\n};\n\nconst getIcon = (theme: Theme, tone: AlertTones): JSX.Element => {\n return ICONS[tone](theme);\n};\n\nconst getBackgroundColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.background[tone](theme);\n};\n\nconst getBorderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.border[tone](theme);\n};\n\nconst getHeaderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.header[tone](theme);\n};\n\nconst getTextColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.text[tone](theme);\n};\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledActionContainer = styled(Box)(() => ({\n marginTop: '16px',\n}));\n\nconst StyledActionLink = styled(Link)(() => ({\n padding: 0,\n}));\n\nconst StyledAlert = styled(MuiAlert, {\n shouldForwardProp: (prop) => !['tone'].includes(prop as string),\n})<StyledAlertProps>(({ theme, tone }) => ({\n backgroundColor: getBackgroundColour(theme, tone),\n border: '1px solid',\n borderColor: getBorderColour(theme, tone),\n color: getTextColour(theme, tone),\n}));\n\n/**\n * Alert component is used to display important messages or notifications to users.\n * It supports different visual tones to convey different semantic meanings and can include\n * an optional action button and close button.\n *\n * The component is wrapped with React.memo to optimize performance by preventing unnecessary\n * re-renders when the component's props haven't changed, which is beneficial for components\n * that may be used frequently throughout the application.\n */\nconst Alert = memo(\n ({\n title,\n description,\n children,\n tone = 'neutral',\n icon,\n onClose,\n className,\n fdKey,\n action,\n }: AlertProps) => {\n const theme = useTheme();\n const alertId = useId();\n const content = children ?? description;\n const hasTitle = Boolean(title);\n const hasContent = content !== undefined && content !== null;\n const titleId = hasTitle ? `alert-title-${fdKey ?? alertId}` : undefined;\n const descriptionId = hasContent ? `alert-description-${fdKey ?? alertId}` : undefined;\n\n const renderAction = (): JSX.Element | null => {\n if (!action) {\n return null;\n }\n\n const actionLabel = title ? `${action.label} - ${title}` : action.label;\n\n if (action.kind === 'link') {\n const actionFdKey = action.fdKey ?? `action-link-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <StyledActionLink\n aria-label={actionLabel}\n fdKey={actionFdKey}\n href={action.href}\n rel={action.rel}\n target={action.target}\n >\n {action.label}\n </StyledActionLink>\n </StyledActionContainer>\n );\n }\n\n const actionFdKey = action.fdKey ?? `action-button-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <Button\n aria-label={actionLabel}\n fdKey={actionFdKey}\n onClick={action.onClick}\n size=\"small\"\n variant={action.type ?? 'primary'}\n >\n {action.label}\n </Button>\n </StyledActionContainer>\n );\n };\n\n return (\n <StyledAlert\n aria-describedby={descriptionId}\n aria-labelledby={titleId}\n className={className}\n data-fd={fdKey}\n icon={icon === undefined ? getIcon(theme, tone) : icon}\n onClose={onClose}\n role=\"alert\"\n tone={tone}\n >\n {hasTitle && (\n <MuiAlertTitle color={getHeaderColour(theme, tone)} id={titleId}>\n {title}\n </MuiAlertTitle>\n )}\n {hasContent && <Box id={descriptionId}>{content}</Box>}\n {renderAction()}\n </StyledAlert>\n );\n },\n);\n\nAlert.displayName = 'Alert';\n\nexport default Alert;\n"],"names":["ICONS","neutral","theme","_jsx","DiamondIcon","color","palette","semantic","icon","brand","destructive","CancelCircleIcon","warning","AlertIcon","information","InformationCircleIcon","success","CheckmarkCircleIcon","COLOURS","background","fill","border","stroke","_theme","header","text","getIcon","tone","getBackgroundColour","getBorderColour","getHeaderColour","getTextColour","StyledActionContainer","styled","Box","marginTop","StyledActionLink","Link","padding","StyledAlert","MuiAlert","shouldForwardProp","prop","includes","backgroundColor","borderColor","Alert","memo","title","description","children","onClose","className","fdKey","action","useTheme","alertId","useId","content","hasTitle","Boolean","hasContent","titleId","undefined","descriptionId","_jsxs","role","MuiAlertTitle","id","actionLabel","label","kind","actionFdKey","replace","toLowerCase","href","rel","target","Button","onClick","size","variant","type","renderAction","displayName"],"mappings":"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"}
@@ -10,7 +10,9 @@ interface AlertProps {
10
10
  /** Optional main heading text of the alert */
11
11
  title?: string;
12
12
  /** Detailed description text of the alert */
13
- description: string;
13
+ description?: string;
14
+ /** Optional custom content; when provided it replaces description */
15
+ children?: ReactNode;
14
16
  /** Visual tone of the alert */
15
17
  tone?: AlertTones;
16
18
  /** Optional icon override; pass null to hide the icon */
@@ -58,7 +60,7 @@ type AlertAction = {
58
60
  * re-renders when the component's props haven't changed, which is beneficial for components
59
61
  * that may be used frequently throughout the application.
60
62
  */
61
- declare const Alert: react.MemoExoticComponent<({ title, description, tone, icon, onClose, className, fdKey, action }: AlertProps) => react_jsx_runtime.JSX.Element>;
63
+ declare const Alert: react.MemoExoticComponent<({ title, description, children, tone, icon, onClose, className, fdKey, action, }: AlertProps) => react_jsx_runtime.JSX.Element>;
62
64
 
63
65
  export { Alert as default };
64
66
  export type { AlertAction, AlertProps, AlertTones };
@@ -1,2 +1,2 @@
1
- import{jsxs as e,jsx as t}from"react/jsx-runtime";import{memo as r,useId as a}from"react";import n from"@mui/material/Alert";import i from"@mui/material/AlertTitle";import o from"@mui/material/Box";import{styled as l,useTheme as s}from"@mui/material/styles";import c from"../../../icons/Alert/index.js";import m from"../../../icons/CancelCircle/index.js";import p from"../../../icons/CheckmarkCircle/index.js";import d from"../../../icons/Diamond/index.js";import f from"../../../icons/InformationCircle/index.js";import{Button as x}from"../../atoms/Button/index.js";import{Link as k}from"../../atoms/Link/index.js";const u={neutral:e=>t(d,{color:e.palette.semantic.icon["icon-strong"]}),brand:e=>t(d,{color:e.palette.semantic.icon["icon-primary"]}),destructive:e=>t(m,{color:e.palette.semantic.icon["icon-error"]}),warning:e=>t(c,{color:e.palette.semantic.icon["icon-warning"]}),information:e=>t(f,{color:e.palette.semantic.icon["icon-information"]}),"neutral-inverse":e=>t(d,{color:e.palette.semantic.icon["icon-inverse"]}),"brand-inverse":e=>t(d,{color:e.palette.semantic.icon["icon-inverse"]}),success:e=>t(p,{color:e.palette.semantic.icon["icon-success"]})},b={background:{neutral:e=>e.palette.semantic.fill["fill-weak"],brand:e=>e.palette.semantic.fill["fill-primary-weak"],destructive:e=>e.palette.semantic.fill["fill-error-weak"],warning:e=>e.palette.semantic.fill["fill-warning-weak"],success:e=>e.palette.semantic.fill["fill-success-weak"],information:e=>e.palette.semantic.fill["fill-information-weak"],"neutral-inverse":e=>e.palette.semantic.background["background-inverse"],"brand-inverse":e=>e.palette.semantic.fill["fill-primary-strong"]},border:{neutral:e=>e.palette.semantic.stroke["stroke-weak"],brand:e=>e.palette.semantic.stroke["stroke-primary-weak"],destructive:e=>e.palette.semantic.stroke["stroke-error-weak"],warning:e=>e.palette.semantic.stroke["stroke-warning-weak"],success:e=>e.palette.semantic.stroke["stroke-success-weak"],information:e=>e.palette.semantic.stroke["stroke-information-weak"],"neutral-inverse":e=>"transparent","brand-inverse":e=>"transparent"},header:{neutral:e=>e.palette.semantic.text["text-strong"],brand:e=>e.palette.semantic.text["text-strong"],destructive:e=>e.palette.semantic.text["text-strong"],warning:e=>e.palette.semantic.text["text-strong"],success:e=>e.palette.semantic.text["text-strong"],information:e=>e.palette.semantic.text["text-strong"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-strong"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-strong"]},text:{neutral:e=>e.palette.semantic.text["text-weak"],brand:e=>e.palette.semantic.text["text-weak"],destructive:e=>e.palette.semantic.text["text-weak"],warning:e=>e.palette.semantic.text["text-weak"],success:e=>e.palette.semantic.text["text-weak"],information:e=>e.palette.semantic.text["text-weak"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-weak"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-weak"]}},w=(e,t)=>u[t](e),g=(e,t)=>b.background[t](e),v=(e,t)=>b.border[t](e),y=(e,t)=>b.header[t](e),h=(e,t)=>b.text[t](e),C=l(o)((()=>({marginTop:"16px"}))),j=l(k)((()=>({padding:0}))),$=l(n,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({backgroundColor:g(e,t),border:"1px solid",borderColor:v(e,t),color:h(e,t)}))),K=r((({title:r,description:n,tone:l="neutral",icon:c,onClose:m,className:p,fdKey:d,action:f})=>{const k=s(),u=a(),b=Boolean(r),g=b?`alert-title-${d??u}`:void 0,v=`alert-description-${d??u}`;return e($,{"aria-describedby":v,"aria-labelledby":g,className:p,"data-fd":d,icon:void 0===c?w(k,l):c,onClose:m,role:"alert",tone:l,children:[b&&t(i,{color:y(k,l),id:g,children:r}),t(o,{id:v,children:n}),(()=>{if(!f)return null;const e=r?`${f.label} - ${r}`:f.label;if("link"===f.kind){const r=f.fdKey??`action-link-${f.label.replace(/\s+/g,"-").toLowerCase()}`;return t(C,{children:t(j,{"aria-label":e,fdKey:r,href:f.href,rel:f.rel,target:f.target,children:f.label})})}const a=f.fdKey??`action-button-${f.label.replace(/\s+/g,"-").toLowerCase()}`;return t(C,{children:t(x,{"aria-label":e,fdKey:a,onClick:f.onClick,size:"small",variant:f.type??"primary",children:f.label})})})()]})}));K.displayName="Alert";export{K as default};
1
+ import{jsxs as e,jsx as t}from"react/jsx-runtime";import{memo as r,useId as a}from"react";import n from"@mui/material/Alert";import i from"@mui/material/AlertTitle";import o from"@mui/material/Box";import{styled as l,useTheme as s}from"@mui/material/styles";import c from"../../../icons/Alert/index.js";import m from"../../../icons/CancelCircle/index.js";import p from"../../../icons/CheckmarkCircle/index.js";import d from"../../../icons/Diamond/index.js";import f from"../../../icons/InformationCircle/index.js";import{Button as x}from"../../atoms/Button/index.js";import{Link as k}from"../../atoms/Link/index.js";const u={neutral:e=>t(d,{color:e.palette.semantic.icon["icon-strong"]}),brand:e=>t(d,{color:e.palette.semantic.icon["icon-primary"]}),destructive:e=>t(m,{color:e.palette.semantic.icon["icon-error"]}),warning:e=>t(c,{color:e.palette.semantic.icon["icon-warning"]}),information:e=>t(f,{color:e.palette.semantic.icon["icon-information"]}),"neutral-inverse":e=>t(d,{color:e.palette.semantic.icon["icon-inverse"]}),"brand-inverse":e=>t(d,{color:e.palette.semantic.icon["icon-inverse"]}),success:e=>t(p,{color:e.palette.semantic.icon["icon-success"]})},b={background:{neutral:e=>e.palette.semantic.fill["fill-weak"],brand:e=>e.palette.semantic.fill["fill-primary-weak"],destructive:e=>e.palette.semantic.fill["fill-error-weak"],warning:e=>e.palette.semantic.fill["fill-warning-weak"],success:e=>e.palette.semantic.fill["fill-success-weak"],information:e=>e.palette.semantic.fill["fill-information-weak"],"neutral-inverse":e=>e.palette.semantic.background["background-inverse"],"brand-inverse":e=>e.palette.semantic.fill["fill-primary-strong"]},border:{neutral:e=>e.palette.semantic.stroke["stroke-weak"],brand:e=>e.palette.semantic.stroke["stroke-primary-weak"],destructive:e=>e.palette.semantic.stroke["stroke-error-weak"],warning:e=>e.palette.semantic.stroke["stroke-warning-weak"],success:e=>e.palette.semantic.stroke["stroke-success-weak"],information:e=>e.palette.semantic.stroke["stroke-information-weak"],"neutral-inverse":e=>"transparent","brand-inverse":e=>"transparent"},header:{neutral:e=>e.palette.semantic.text["text-strong"],brand:e=>e.palette.semantic.text["text-strong"],destructive:e=>e.palette.semantic.text["text-strong"],warning:e=>e.palette.semantic.text["text-strong"],success:e=>e.palette.semantic.text["text-strong"],information:e=>e.palette.semantic.text["text-strong"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-strong"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-strong"]},text:{neutral:e=>e.palette.semantic.text["text-weak"],brand:e=>e.palette.semantic.text["text-weak"],destructive:e=>e.palette.semantic.text["text-weak"],warning:e=>e.palette.semantic.text["text-weak"],success:e=>e.palette.semantic.text["text-weak"],information:e=>e.palette.semantic.text["text-weak"],"neutral-inverse":e=>e.palette.semantic.text["text-inverse-weak"],"brand-inverse":e=>e.palette.semantic.text["text-inverse-weak"]}},w=(e,t)=>u[t](e),g=(e,t)=>b.background[t](e),v=(e,t)=>b.border[t](e),h=(e,t)=>b.header[t](e),y=(e,t)=>b.text[t](e),C=l(o)((()=>({marginTop:"16px"}))),j=l(k)((()=>({padding:0}))),$=l(n,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({backgroundColor:g(e,t),border:"1px solid",borderColor:v(e,t),color:y(e,t)}))),K=r((({title:r,description:n,children:l,tone:c="neutral",icon:m,onClose:p,className:d,fdKey:f,action:k})=>{const u=s(),b=a(),g=l??n,v=Boolean(r),y=null!=g,K=v?`alert-title-${f??b}`:void 0,A=y?`alert-description-${f??b}`:void 0;return e($,{"aria-describedby":A,"aria-labelledby":K,className:d,"data-fd":f,icon:void 0===m?w(u,c):m,onClose:p,role:"alert",tone:c,children:[v&&t(i,{color:h(u,c),id:K,children:r}),y&&t(o,{id:A,children:g}),(()=>{if(!k)return null;const e=r?`${k.label} - ${r}`:k.label;if("link"===k.kind){const r=k.fdKey??`action-link-${k.label.replace(/\s+/g,"-").toLowerCase()}`;return t(C,{children:t(j,{"aria-label":e,fdKey:r,href:k.href,rel:k.rel,target:k.target,children:k.label})})}const a=k.fdKey??`action-button-${k.label.replace(/\s+/g,"-").toLowerCase()}`;return t(C,{children:t(x,{"aria-label":e,fdKey:a,onClick:k.onClick,size:"small",variant:k.type??"primary",children:k.label})})})()]})}));K.displayName="Alert";export{K as default};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/molecules/Alert/index.tsx"],"sourcesContent":["import { memo, type ReactNode, useId } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\nimport MuiAlertTitle from '@mui/material/AlertTitle';\nimport Box from '@mui/material/Box';\nimport { styled, type Theme, useTheme } from '@mui/material/styles';\n\nimport AlertIcon from '../../../icons/Alert';\nimport CancelCircleIcon from '../../../icons/CancelCircle';\nimport CheckmarkCircleIcon from '../../../icons/CheckmarkCircle';\nimport DiamondIcon from '../../../icons/Diamond';\nimport InformationCircleIcon from '../../../icons/InformationCircle';\nimport Button from '../../atoms/Button';\nimport type { ButtonType } from '../../atoms/Button/getButtonStyles';\nimport Link from '../../atoms/Link';\n\n/** Visual tone of the alert */\nexport type AlertTones =\n | 'brand-inverse'\n | 'brand'\n | 'destructive'\n | 'information'\n | 'neutral-inverse'\n | 'neutral'\n | 'success'\n | 'warning';\n\n/** Props for the Alert component */\nexport interface AlertProps {\n /** Optional main heading text of the alert */\n title?: string;\n /** Detailed description text of the alert */\n description: string;\n /** Visual tone of the alert */\n tone?: AlertTones;\n /** Optional icon override; pass null to hide the icon */\n icon?: ReactNode | null;\n /** Callback function when the alert is closed */\n onClose?: () => void;\n /** Action configuration (button by default, or link) */\n action?: AlertAction;\n /** Additional CSS class names */\n className?: string;\n /** Test ID for testing and automation */\n fdKey?: string;\n}\n\nexport type AlertAction =\n | {\n /** Defaults to button when omitted */\n kind?: 'button';\n /** Text label for the action button */\n label: string;\n /** Visual style of the action button */\n type?: ButtonType;\n /** Callback function when the action button is clicked */\n onClick: () => void;\n /** Test ID for the action button */\n fdKey?: string;\n }\n | {\n /** Render a link action */\n kind: 'link';\n /** Text label for the link */\n label: string;\n /** Destination URL */\n href: string;\n /** Target for the link */\n target?: '_blank' | '_parent' | '_self' | '_top';\n /** rel attribute for the link */\n rel?: string;\n /** Test ID for the link */\n fdKey?: string;\n };\n\nconst ICONS = {\n neutral: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-strong']} />,\n brand: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-primary']} />,\n destructive: (theme: Theme): JSX.Element => (\n <CancelCircleIcon color={theme.palette.semantic.icon['icon-error']} />\n ),\n warning: (theme: Theme): JSX.Element => <AlertIcon color={theme.palette.semantic.icon['icon-warning']} />,\n information: (theme: Theme): JSX.Element => (\n <InformationCircleIcon color={theme.palette.semantic.icon['icon-information']} />\n ),\n 'neutral-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n 'brand-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n success: (theme: Theme): JSX.Element => (\n <CheckmarkCircleIcon color={theme.palette.semantic.icon['icon-success']} />\n ),\n};\n\nconst COLOURS = {\n background: {\n neutral: (theme: Theme): string => theme.palette.semantic.fill['fill-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.fill['fill-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.fill['fill-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.fill['fill-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.fill['fill-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.fill['fill-information-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.background['background-inverse'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.fill['fill-primary-strong'],\n },\n border: {\n neutral: (theme: Theme): string => theme.palette.semantic.stroke['stroke-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.stroke['stroke-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.stroke['stroke-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.stroke['stroke-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.stroke['stroke-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.stroke['stroke-information-weak'],\n 'neutral-inverse': (_theme: Theme): string => 'transparent',\n 'brand-inverse': (_theme: Theme): string => 'transparent',\n },\n header: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n },\n text: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n },\n};\n\nconst getIcon = (theme: Theme, tone: AlertTones): JSX.Element => {\n return ICONS[tone](theme);\n};\n\nconst getBackgroundColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.background[tone](theme);\n};\n\nconst getBorderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.border[tone](theme);\n};\n\nconst getHeaderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.header[tone](theme);\n};\n\nconst getTextColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.text[tone](theme);\n};\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledActionContainer = styled(Box)(() => ({\n marginTop: '16px',\n}));\n\nconst StyledActionLink = styled(Link)(() => ({\n padding: 0,\n}));\n\nconst StyledAlert = styled(MuiAlert, {\n shouldForwardProp: (prop) => !['tone'].includes(prop as string),\n})<StyledAlertProps>(({ theme, tone }) => ({\n backgroundColor: getBackgroundColour(theme, tone),\n border: '1px solid',\n borderColor: getBorderColour(theme, tone),\n color: getTextColour(theme, tone),\n}));\n\n/**\n * Alert component is used to display important messages or notifications to users.\n * It supports different visual tones to convey different semantic meanings and can include\n * an optional action button and close button.\n *\n * The component is wrapped with React.memo to optimize performance by preventing unnecessary\n * re-renders when the component's props haven't changed, which is beneficial for components\n * that may be used frequently throughout the application.\n */\nconst Alert = memo(\n ({ title, description, tone = 'neutral', icon, onClose, className, fdKey, action }: AlertProps) => {\n const theme = useTheme();\n const alertId = useId();\n const hasTitle = Boolean(title);\n const titleId = hasTitle ? `alert-title-${fdKey ?? alertId}` : undefined;\n const descriptionId = `alert-description-${fdKey ?? alertId}`;\n\n const renderAction = (): JSX.Element | null => {\n if (!action) {\n return null;\n }\n\n const actionLabel = title ? `${action.label} - ${title}` : action.label;\n\n if (action.kind === 'link') {\n const actionFdKey = action.fdKey ?? `action-link-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <StyledActionLink\n aria-label={actionLabel}\n fdKey={actionFdKey}\n href={action.href}\n rel={action.rel}\n target={action.target}\n >\n {action.label}\n </StyledActionLink>\n </StyledActionContainer>\n );\n }\n\n const actionFdKey = action.fdKey ?? `action-button-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <Button\n aria-label={actionLabel}\n fdKey={actionFdKey}\n onClick={action.onClick}\n size=\"small\"\n variant={action.type ?? 'primary'}\n >\n {action.label}\n </Button>\n </StyledActionContainer>\n );\n };\n\n return (\n <StyledAlert\n aria-describedby={descriptionId}\n aria-labelledby={titleId}\n className={className}\n data-fd={fdKey}\n icon={icon === undefined ? getIcon(theme, tone) : icon}\n onClose={onClose}\n role=\"alert\"\n tone={tone}\n >\n {hasTitle && (\n <MuiAlertTitle color={getHeaderColour(theme, tone)} id={titleId}>\n {title}\n </MuiAlertTitle>\n )}\n <Box id={descriptionId}>{description}</Box>\n {renderAction()}\n </StyledAlert>\n );\n },\n);\n\nAlert.displayName = 'Alert';\n\nexport default Alert;\n"],"names":["ICONS","neutral","theme","_jsx","DiamondIcon","color","palette","semantic","icon","brand","destructive","CancelCircleIcon","warning","AlertIcon","information","InformationCircleIcon","success","CheckmarkCircleIcon","COLOURS","background","fill","border","stroke","_theme","header","text","getIcon","tone","getBackgroundColour","getBorderColour","getHeaderColour","getTextColour","StyledActionContainer","styled","Box","marginTop","StyledActionLink","Link","padding","StyledAlert","MuiAlert","shouldForwardProp","prop","includes","backgroundColor","borderColor","Alert","memo","title","description","onClose","className","fdKey","action","useTheme","alertId","useId","hasTitle","Boolean","titleId","undefined","descriptionId","_jsxs","role","children","MuiAlertTitle","id","actionLabel","label","kind","actionFdKey","replace","toLowerCase","href","rel","target","Button","onClick","size","variant","type","renderAction","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/molecules/Alert/index.tsx"],"sourcesContent":["import { memo, type ReactNode, useId } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\nimport MuiAlertTitle from '@mui/material/AlertTitle';\nimport Box from '@mui/material/Box';\nimport { styled, type Theme, useTheme } from '@mui/material/styles';\n\nimport AlertIcon from '../../../icons/Alert';\nimport CancelCircleIcon from '../../../icons/CancelCircle';\nimport CheckmarkCircleIcon from '../../../icons/CheckmarkCircle';\nimport DiamondIcon from '../../../icons/Diamond';\nimport InformationCircleIcon from '../../../icons/InformationCircle';\nimport Button from '../../atoms/Button';\nimport type { ButtonType } from '../../atoms/Button/getButtonStyles';\nimport Link from '../../atoms/Link';\n\n/** Visual tone of the alert */\nexport type AlertTones =\n | 'brand-inverse'\n | 'brand'\n | 'destructive'\n | 'information'\n | 'neutral-inverse'\n | 'neutral'\n | 'success'\n | 'warning';\n\n/** Props for the Alert component */\nexport interface AlertProps {\n /** Optional main heading text of the alert */\n title?: string;\n /** Detailed description text of the alert */\n description?: string;\n /** Optional custom content; when provided it replaces description */\n children?: ReactNode;\n /** Visual tone of the alert */\n tone?: AlertTones;\n /** Optional icon override; pass null to hide the icon */\n icon?: ReactNode | null;\n /** Callback function when the alert is closed */\n onClose?: () => void;\n /** Action configuration (button by default, or link) */\n action?: AlertAction;\n /** Additional CSS class names */\n className?: string;\n /** Test ID for testing and automation */\n fdKey?: string;\n}\n\nexport type AlertAction =\n | {\n /** Defaults to button when omitted */\n kind?: 'button';\n /** Text label for the action button */\n label: string;\n /** Visual style of the action button */\n type?: ButtonType;\n /** Callback function when the action button is clicked */\n onClick: () => void;\n /** Test ID for the action button */\n fdKey?: string;\n }\n | {\n /** Render a link action */\n kind: 'link';\n /** Text label for the link */\n label: string;\n /** Destination URL */\n href: string;\n /** Target for the link */\n target?: '_blank' | '_parent' | '_self' | '_top';\n /** rel attribute for the link */\n rel?: string;\n /** Test ID for the link */\n fdKey?: string;\n };\n\nconst ICONS = {\n neutral: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-strong']} />,\n brand: (theme: Theme): JSX.Element => <DiamondIcon color={theme.palette.semantic.icon['icon-primary']} />,\n destructive: (theme: Theme): JSX.Element => (\n <CancelCircleIcon color={theme.palette.semantic.icon['icon-error']} />\n ),\n warning: (theme: Theme): JSX.Element => <AlertIcon color={theme.palette.semantic.icon['icon-warning']} />,\n information: (theme: Theme): JSX.Element => (\n <InformationCircleIcon color={theme.palette.semantic.icon['icon-information']} />\n ),\n 'neutral-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n 'brand-inverse': (theme: Theme): JSX.Element => (\n <DiamondIcon color={theme.palette.semantic.icon['icon-inverse']} />\n ),\n success: (theme: Theme): JSX.Element => (\n <CheckmarkCircleIcon color={theme.palette.semantic.icon['icon-success']} />\n ),\n};\n\nconst COLOURS = {\n background: {\n neutral: (theme: Theme): string => theme.palette.semantic.fill['fill-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.fill['fill-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.fill['fill-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.fill['fill-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.fill['fill-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.fill['fill-information-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.background['background-inverse'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.fill['fill-primary-strong'],\n },\n border: {\n neutral: (theme: Theme): string => theme.palette.semantic.stroke['stroke-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.stroke['stroke-primary-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.stroke['stroke-error-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.stroke['stroke-warning-weak'],\n success: (theme: Theme): string => theme.palette.semantic.stroke['stroke-success-weak'],\n information: (theme: Theme): string => theme.palette.semantic.stroke['stroke-information-weak'],\n 'neutral-inverse': (_theme: Theme): string => 'transparent',\n 'brand-inverse': (_theme: Theme): string => 'transparent',\n },\n header: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-strong'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-strong'],\n },\n text: {\n neutral: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n brand: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n destructive: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n warning: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n success: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n information: (theme: Theme): string => theme.palette.semantic.text['text-weak'],\n 'neutral-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n 'brand-inverse': (theme: Theme): string => theme.palette.semantic.text['text-inverse-weak'],\n },\n};\n\nconst getIcon = (theme: Theme, tone: AlertTones): JSX.Element => {\n return ICONS[tone](theme);\n};\n\nconst getBackgroundColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.background[tone](theme);\n};\n\nconst getBorderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.border[tone](theme);\n};\n\nconst getHeaderColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.header[tone](theme);\n};\n\nconst getTextColour = (theme: Theme, tone: AlertTones): string => {\n return COLOURS.text[tone](theme);\n};\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledActionContainer = styled(Box)(() => ({\n marginTop: '16px',\n}));\n\nconst StyledActionLink = styled(Link)(() => ({\n padding: 0,\n}));\n\nconst StyledAlert = styled(MuiAlert, {\n shouldForwardProp: (prop) => !['tone'].includes(prop as string),\n})<StyledAlertProps>(({ theme, tone }) => ({\n backgroundColor: getBackgroundColour(theme, tone),\n border: '1px solid',\n borderColor: getBorderColour(theme, tone),\n color: getTextColour(theme, tone),\n}));\n\n/**\n * Alert component is used to display important messages or notifications to users.\n * It supports different visual tones to convey different semantic meanings and can include\n * an optional action button and close button.\n *\n * The component is wrapped with React.memo to optimize performance by preventing unnecessary\n * re-renders when the component's props haven't changed, which is beneficial for components\n * that may be used frequently throughout the application.\n */\nconst Alert = memo(\n ({\n title,\n description,\n children,\n tone = 'neutral',\n icon,\n onClose,\n className,\n fdKey,\n action,\n }: AlertProps) => {\n const theme = useTheme();\n const alertId = useId();\n const content = children ?? description;\n const hasTitle = Boolean(title);\n const hasContent = content !== undefined && content !== null;\n const titleId = hasTitle ? `alert-title-${fdKey ?? alertId}` : undefined;\n const descriptionId = hasContent ? `alert-description-${fdKey ?? alertId}` : undefined;\n\n const renderAction = (): JSX.Element | null => {\n if (!action) {\n return null;\n }\n\n const actionLabel = title ? `${action.label} - ${title}` : action.label;\n\n if (action.kind === 'link') {\n const actionFdKey = action.fdKey ?? `action-link-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <StyledActionLink\n aria-label={actionLabel}\n fdKey={actionFdKey}\n href={action.href}\n rel={action.rel}\n target={action.target}\n >\n {action.label}\n </StyledActionLink>\n </StyledActionContainer>\n );\n }\n\n const actionFdKey = action.fdKey ?? `action-button-${action.label.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <StyledActionContainer>\n <Button\n aria-label={actionLabel}\n fdKey={actionFdKey}\n onClick={action.onClick}\n size=\"small\"\n variant={action.type ?? 'primary'}\n >\n {action.label}\n </Button>\n </StyledActionContainer>\n );\n };\n\n return (\n <StyledAlert\n aria-describedby={descriptionId}\n aria-labelledby={titleId}\n className={className}\n data-fd={fdKey}\n icon={icon === undefined ? getIcon(theme, tone) : icon}\n onClose={onClose}\n role=\"alert\"\n tone={tone}\n >\n {hasTitle && (\n <MuiAlertTitle color={getHeaderColour(theme, tone)} id={titleId}>\n {title}\n </MuiAlertTitle>\n )}\n {hasContent && <Box id={descriptionId}>{content}</Box>}\n {renderAction()}\n </StyledAlert>\n );\n },\n);\n\nAlert.displayName = 'Alert';\n\nexport default Alert;\n"],"names":["ICONS","neutral","theme","_jsx","DiamondIcon","color","palette","semantic","icon","brand","destructive","CancelCircleIcon","warning","AlertIcon","information","InformationCircleIcon","success","CheckmarkCircleIcon","COLOURS","background","fill","border","stroke","_theme","header","text","getIcon","tone","getBackgroundColour","getBorderColour","getHeaderColour","getTextColour","StyledActionContainer","styled","Box","marginTop","StyledActionLink","Link","padding","StyledAlert","MuiAlert","shouldForwardProp","prop","includes","backgroundColor","borderColor","Alert","memo","title","description","children","onClose","className","fdKey","action","useTheme","alertId","useId","content","hasTitle","Boolean","hasContent","titleId","undefined","descriptionId","_jsxs","role","MuiAlertTitle","id","actionLabel","label","kind","actionFdKey","replace","toLowerCase","href","rel","target","Button","onClick","size","variant","type","renderAction","displayName"],"mappings":"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"}
@@ -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":"smBAcA,MAAMA,EAA4BC,EAAOC,EAAK,CAC5CC,kBAAoBC,GAAkB,aAATA,GADGH,EAEP,EAAGI,QAAOC,eAAU,CAC7CC,KAAM,IACNC,QAAS,OACTC,cAAe,SACfC,OAAQ,OACRC,UAAW,aACXC,WAAY,SACZC,eAAgB,SAChBC,QAAST,EAAMU,QAAQ,GACvBC,aAAcX,EAAMY,OAAO,YAC3BC,OAAQZ,EACJ,aAAaD,EAAMc,QAAQC,SAASC,OAAO,uBAC3C,cAAchB,EAAMc,QAAQC,SAASC,OAAO,mBAChDC,WAAYhB,EACRD,EAAMc,QAAQC,SAASG,KAAK,mBAC5BlB,EAAMc,QAAQC,SAASG,KAAK,eAChCC,OAAQ,UACRC,WAAY,uBACZ,CAACpB,EAAMqB,YAAYC,KAAK,WAAY,CAClCd,eAAgB,SAChBe,IAAKvB,EAAMU,QAAQ,QAIjBc,EAAsB5B,EAAO,QAAPA,CAAgB,CAC1C6B,KAAM,gBACNC,SAAU,aACVrB,OAAQ,EACRsB,SAAU,SACVC,SAAU,WACVC,OAAQ,EACRC,KAAM,EACNC,WAAY,SACZC,MAAO,IAGHC,EAAsBrC,EAAOC,EAAK,CACtCC,kBAAoBC,GAAkB,aAATA,GADHH,EAED,EAAGK,WAAUD,YAAO,CAC7CG,QAAS,OACTC,cAAe,SACf4B,MAAO,OACP3B,OAAQ,OACRI,QAAS,MACTD,eAAgB,SAChBD,WAAY,SACZI,aAAcX,EAAMY,OAAO,aAC3BsB,gBAAiBjC,EACbD,EAAMc,QAAQC,SAASG,KAAK,mBAC5BlB,EAAMc,QAAQC,SAASG,KAAK,yBAG5BiB,EAAevC,EAAOwC,EAAPxC,CAAuB,CAC1CyC,UAAW,WA4FPC,EAA4C,EAChDC,eACAC,WACAC,WACAC,cACAC,mBAAmB,GACnBC,YAAW,EACXC,QACAC,iBACAC,mBACAC,mBACAC,uBACAC,sBACAC,2BAEA,MAAMnD,EAAQoD,KACPC,EAAcC,GAAmBC,GAAS,GAC3CC,EAAeC,EAAyB,OACvCC,EAAiBC,GAAsBJ,EAAwB,OAChEK,UAAEA,GAAcC,IAChBC,EAAejB,GAASa,EAExBK,EAAeC,GAClBC,IAEC,GAAIvB,GAAeuB,EAAKC,KAAOxB,EAK7B,OAJAiB,EACET,GACEU,EAAU,yBAA0B,CAAElB,YAAaA,GAAayB,YAAc,OAE3E,EAIT,MAAMC,EAAgBH,EAAKI,KAAKC,MAAM,KAAKC,OAAOC,cAClD,QAAI7B,EAAiB8B,OAAS,GAAKL,IAAkBzB,EAAiB+B,SAASN,MAC7ET,EACEV,GACEW,EAAU,2BAA4B,CAAEjB,iBAAkBA,EAAiBgC,KAAK,UAE7E,KAKX,CAACjC,EAAaC,EAAkBM,EAAsBC,EAAqBU,IAGvEgB,EAAeZ,GAClBa,IACC,MAAMC,EAAYC,MAAMC,KAAKH,GACvBI,EAAqB,GAGvBxC,GAAYqC,EAAUL,OAAShC,EACjCkB,EACER,GAAwBS,EAAU,0BAA2B,CAAEnB,SAAUA,EAAS0B,eAMtFW,EAAUI,SAASjB,IACbF,EAAaE,IACfgB,EAAWE,KAAKlB,MAIhBgB,EAAWR,OAAS,IACtBd,EAAmB,MACnBpB,EAAa0C,OAGjB,CAACxC,EAAUsB,EAAcxB,EAAcY,EAAsBS,IAGzDwB,EAAkBpB,GACrBqB,IACCA,EAAEC,iBACFD,EAAEE,kBAEE3C,GAEJU,GAAgB,KAElB,CAACV,IAGG4C,EAAkBxB,GACrBqB,IACCA,EAAEC,iBACFD,EAAEE,kBAEE3C,GAEJU,GAAgB,KAElB,CAACV,IAGG6C,EAAiBzB,GAAaqB,IAClCA,EAAEC,iBACFD,EAAEE,oBACD,IAEGG,EAAa1B,GAChBqB,IAIC,GAHAA,EAAEC,iBACFD,EAAEE,kBAEE3C,EAAU,OAEdU,GAAgB,GAEhB,MAAMuB,EAAQQ,EAAEM,aAAad,MACzBA,GAASA,EAAMJ,OAAS,GAC1BG,EAAaC,KAGjB,CAACjC,EAAUgC,IAGPgB,EAAwB5B,GAC3BqB,IACC,GAAIzC,EAAU,OAEd,MAAMiC,EAAQQ,EAAEQ,OAAOhB,MACnBA,GAASA,EAAMJ,OAAS,GAC1BG,EAAaC,GAIXrB,EAAasC,UACftC,EAAasC,QAAQC,MAAQ,MAGjC,CAACnD,EAAUgC,IAGPoB,EAAoBhC,GAAaiC,IACrCA,EAAMX,iBACNW,EAAMV,kBACN/B,EAAasC,SAASI,UACrB,IAEGC,EAAuBnC,GAAY,KACnCpB,GAEJY,EAAasC,SAASI,UACrB,CAACtD,IAEJ,OACEwD,EAAAC,EAAA,CAAAC,SAAA,GACKxC,GACDsC,EAACG,EAAsB,CAAC1D,OAAK,EAAAyD,SAAA,CAC3BE,EAACC,EAAgB,CAAA,GAChB3C,KAGLsC,EAACzG,EAAyB,CAAA,UAChB,iBACRM,WAAY6D,EACZ4C,QAAS9D,OAAW+D,EAAYR,EAChCS,YAAaxB,EACbyB,YAAarB,EACbsB,WAAYrB,EACZsB,OAAQrB,EAAUY,SAAA,CAElBE,EAAChF,EAAmB,CAClBwF,IAAKxD,EAAY,UACT,oBACRZ,SAAUA,EACVJ,SAAUA,EACVyE,SAAUrB,EACVsB,KAAK,SAGPd,EAACe,EAAK,CACJ5G,WAAW,SACX6G,UAAU,SACV7F,IAAKvB,EAAMU,QAAQ,GACnBF,eAAe,SACfwB,MAAM,OAAMsE,SAAA,CAEZE,EAACvE,EAAmB,CAAChC,WAAY6D,EAAYwC,SAC3CE,EAACa,EAAU,CACTC,MACExD,EACI9D,EAAMc,QAAQC,SAASwG,KAAK,cAC5BvH,EAAMc,QAAQC,SAASwG,KAAK,oBAKtCf,EAACgB,GAAmBC,QAAQ,WAAUnB,SACnCjD,EACGP,GAAkBc,EAAU,mBAC5Bb,GAAoBa,EAAU,8BAGpC4C,EAACrE,EAAY,CACXS,SAAUA,EACV8E,MAAM,kBACNhB,QAAS9D,OAAW+D,EAAYX,EAChCyB,QAAQ,YAAWnB,SAElBtD,GAAoBY,EAAU"}
@@ -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.1.0",
3
+ "version": "8.3.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],