@flipdish/portal-library 7.5.2 → 7.6.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.
Files changed (62) hide show
  1. package/README.md +0 -6
  2. package/dist/components/atoms/Card/index.cjs.js +1 -1
  3. package/dist/components/atoms/Card/index.cjs.js.map +1 -1
  4. package/dist/components/atoms/Card/index.d.ts +3 -2
  5. package/dist/components/atoms/Card/index.js +1 -1
  6. package/dist/components/atoms/Card/index.js.map +1 -1
  7. package/dist/components/molecules/Autocomplete/index.cjs.js +1 -1
  8. package/dist/components/molecules/Autocomplete/index.cjs.js.map +1 -1
  9. package/dist/components/molecules/Autocomplete/index.js +1 -1
  10. package/dist/components/molecules/Autocomplete/index.js.map +1 -1
  11. package/dist/components/molecules/Tooltip/index.cjs.js +2 -0
  12. package/dist/components/molecules/Tooltip/index.cjs.js.map +1 -0
  13. package/dist/components/molecules/Tooltip/index.d.ts +37 -0
  14. package/dist/components/molecules/Tooltip/index.js +2 -0
  15. package/dist/components/molecules/Tooltip/index.js.map +1 -0
  16. package/dist/components/organisms/AssetManager/index.cjs.js +2 -0
  17. package/dist/components/organisms/AssetManager/index.cjs.js.map +1 -0
  18. package/dist/components/organisms/AssetManager/index.d.ts +29 -0
  19. package/dist/components/organisms/AssetManager/index.js +2 -0
  20. package/dist/components/organisms/AssetManager/index.js.map +1 -0
  21. package/dist/components/organisms/AssetManager/types/index.cjs.js +2 -0
  22. package/dist/components/organisms/AssetManager/types/index.cjs.js.map +1 -0
  23. package/dist/components/organisms/AssetManager/types/index.d.ts +29 -0
  24. package/dist/components/organisms/AssetManager/types/index.js +2 -0
  25. package/dist/components/organisms/AssetManager/types/index.js.map +1 -0
  26. package/dist/components/organisms/FileUpload/components/FileDropZone.cjs.js.map +1 -1
  27. package/dist/components/organisms/FileUpload/components/FileDropZone.js.map +1 -1
  28. package/dist/components/organisms/FileUpload/components/FileItem.cjs.js.map +1 -1
  29. package/dist/components/organisms/FileUpload/components/FileItem.js.map +1 -1
  30. package/dist/components/organisms/FileUpload/components/FileThumbnail.cjs.js.map +1 -1
  31. package/dist/components/organisms/FileUpload/components/FileThumbnail.js.map +1 -1
  32. package/dist/components/organisms/FileUpload/index.cjs.js.map +1 -1
  33. package/dist/components/organisms/FileUpload/index.js.map +1 -1
  34. package/dist/components/organisms/ImageUploadWidget/components/FlipdishFonts.cjs.js +2 -2
  35. package/dist/components/organisms/ImageUploadWidget/components/FlipdishFonts.cjs.js.map +1 -1
  36. package/dist/components/organisms/ImageUploadWidget/components/FlipdishFonts.js +2 -2
  37. package/dist/components/organisms/ImageUploadWidget/components/FlipdishFonts.js.map +1 -1
  38. package/dist/components/organisms/ImageUploadWidget/components/ImageDropZone.cjs.js.map +1 -1
  39. package/dist/components/organisms/ImageUploadWidget/components/ImageDropZone.js.map +1 -1
  40. package/dist/components/organisms/ImageUploadWidget/index.cjs.js.map +1 -1
  41. package/dist/components/organisms/ImageUploadWidget/index.js.map +1 -1
  42. package/dist/icons/CheckmarkCircleSolid/checkmark-circle-solid.svg.cjs.js +1 -1
  43. package/dist/icons/CheckmarkCircleSolid/checkmark-circle-solid.svg.cjs.js.map +1 -1
  44. package/dist/icons/CheckmarkCircleSolid/checkmark-circle-solid.svg.js +1 -1
  45. package/dist/icons/CheckmarkCircleSolid/checkmark-circle-solid.svg.js.map +1 -1
  46. package/dist/icons/KitchenDisplaySystem/index.cjs.js +2 -0
  47. package/dist/icons/KitchenDisplaySystem/index.cjs.js.map +1 -0
  48. package/dist/icons/KitchenDisplaySystem/index.d.ts +6 -0
  49. package/dist/icons/KitchenDisplaySystem/index.js +2 -0
  50. package/dist/icons/KitchenDisplaySystem/index.js.map +1 -0
  51. package/dist/icons/{KitchenDisplayScreen/kitchen-display-screen.svg.cjs.js → KitchenDisplaySystem/kitchen-display-system.svg.cjs.js} +1 -1
  52. package/dist/icons/{KitchenDisplayScreen/kitchen-display-screen.svg.cjs.js.map → KitchenDisplaySystem/kitchen-display-system.svg.cjs.js.map} +1 -1
  53. package/dist/icons/{KitchenDisplayScreen/kitchen-display-screen.svg.js → KitchenDisplaySystem/kitchen-display-system.svg.js} +1 -1
  54. package/dist/icons/{KitchenDisplayScreen/kitchen-display-screen.svg.js.map → KitchenDisplaySystem/kitchen-display-system.svg.js.map} +1 -1
  55. package/dist/icons/helpers/withSvgIcon.cjs.js.map +1 -1
  56. package/dist/icons/helpers/withSvgIcon.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/icons/KitchenDisplayScreen/index.cjs.js +0 -2
  59. package/dist/icons/KitchenDisplayScreen/index.cjs.js.map +0 -1
  60. package/dist/icons/KitchenDisplayScreen/index.d.ts +0 -6
  61. package/dist/icons/KitchenDisplayScreen/index.js +0 -2
  62. package/dist/icons/KitchenDisplayScreen/index.js.map +0 -1
package/README.md CHANGED
@@ -76,12 +76,6 @@ import FlipdishUIThemeProvider from '@flipdish/portal-library/themes/ThemeProvid
76
76
  </FlipdishUIThemeProvider>;
77
77
  ```
78
78
 
79
- ## Contributing
80
-
81
- Start with the contributing guide for editor setup, conventions, and component guidelines:
82
-
83
- - [CONTRIBUTING.md](./CONTRIBUTING.md)
84
-
85
79
  ## Using Icons
86
80
 
87
81
  To use an icon in your project, import the icon and use it like any other component. You can specify the size using the `size` prop.
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react/jsx-runtime"),r=require("@mui/material/Box"),t=require("@mui/material/Card"),i=require("@mui/material/CardContent"),n=require("@mui/material/CardMedia"),a=require("@mui/material/styles"),s=require("@mui/material/Typography"),o=require("../../../icons/ArrowRight02/index.cjs.js"),l=require("../Badge/index.cjs.js"),d=require("../IconContainer/index.cjs.js"),c=require("../Link/index.cjs.js");const h=a.styled(t)((({theme:e,type:r})=>({borderRadius:e.radius["radius-16"],border:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,..."horizontal"===r&&{display:"flex",flexDirection:"row",overflow:"hidden"}}))),m=a.styled(i)((({theme:e,type:r})=>({"&:last-child":{paddingBottom:e.spacing(2)},..."horizontal"===r&&{flex:1,display:"flex",flexDirection:"column",justifyContent:"space-between"}}))),p=a.styled(r)((({theme:e})=>({display:"flex",alignItems:"flex-start",gap:e.spacing(2),flex:1}))),u=a.styled(r)((()=>({flex:1,display:"flex",flexDirection:"column"}))),x=a.styled(s)((({theme:e})=>({marginBottom:e.spacing(1)}))),g=a.styled(r)((({theme:e})=>({marginTop:e.spacing(1.5)}))),y=a.styled(c.Link)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(1)}))),f=a.styled(n)((({theme:e,type:r})=>({..."horizontal"===r?{width:200,height:"auto",borderRight:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,borderBottom:"none",flexShrink:0}:{height:204,borderBottom:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`}}))),j=a.styled(r,{shouldForwardProp:e=>!["hasIcon","hasBadge"].includes(e)})((({theme:e,hasIcon:r,hasBadge:t})=>({display:"flex",flexDirection:"row",justifyContent:t&&!r?"flex-end":"space-between",alignItems:"flex-start",gap:e.spacing(2),marginBottom:e.spacing(1.5)})));module.exports=({fdKey:r,heading:t,content:i,imageSrc:n,icon:a,badge:c,link:k,onMouseEnter:w,onMouseLeave:b,type:B="vertical",...C})=>{if(a&&(q=a,q?.type!==d))throw new Error("Card icon prop must be an IconContainer component");var q;if(c&&!(e=>e?.type===l.Badge)(c))throw new Error("Card badge prop must be a Badge component");const v=!!c||!!a,I=()=>k?e.jsx(g,{children:e.jsx(y,{fdKey:`card-link-${k.label}`,href:k.href,iconRight:e.jsx(o,{}),onClick:k.onClick,underline:!1,children:k.label})}):null,M=()=>e.jsx(x,{variant:"h4Strong",children:t}),z=()=>e.jsx(s,{variant:"b1Weak",children:i});return e.jsxs(h,{"data-fd":r,type:B,...C,onMouseEnter:w,onMouseLeave:b,children:[n?e.jsx(f,{image:n,type:B}):null,e.jsx(m,{type:B,children:"horizontal"===B?e.jsxs(e.Fragment,{children:[e.jsxs(p,{children:[a&&a,e.jsxs(u,{children:[M(),z()]}),c&&c]}),I()]}):e.jsxs(e.Fragment,{children:[v&&e.jsxs(j,{hasBadge:!!c,hasIcon:!!a,children:[a&&a,c&&c]}),M(),z(),I()]})})]})};
1
+ "use strict";var e=require("react/jsx-runtime"),t=require("@mui/material/Box"),r=require("@mui/material/Card"),i=require("@mui/material/CardContent"),a=require("@mui/material/CardMedia"),n=require("@mui/material/styles"),s=require("@mui/material/Typography"),o=require("../../../icons/ArrowRight02/index.cjs.js"),l=require("../Badge/index.cjs.js"),d=require("../IconContainer/index.cjs.js"),c=require("../Link/index.cjs.js");const m=n.styled(r)((({theme:e,type:t})=>({borderRadius:e.radius["radius-16"],border:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,..."horizontal"===t&&{display:"flex",flexDirection:"row",overflow:"hidden"}}))),h=n.styled(i)((({theme:e,type:t})=>({"&:last-child":{paddingBottom:e.spacing(2)},..."horizontal"===t&&{flex:1,display:"flex",flexDirection:"column",justifyContent:"space-between"}}))),p=n.styled(t)((({theme:e})=>({display:"flex",alignItems:"flex-start",gap:e.spacing(2),flex:1}))),x=n.styled(t)((()=>({flex:1,display:"flex",flexDirection:"column"}))),u=n.styled(s)((({theme:e})=>({marginBottom:e.spacing(1)}))),g=n.styled(s)((({theme:e})=>({color:e.palette.semantic.text["text-weak"]}))),y=n.styled(t)((({theme:e})=>({marginTop:e.spacing(1.5)}))),f=n.styled(c.Link)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(1)}))),j=n.styled(a)((({theme:e,type:t})=>({..."horizontal"===t?{width:200,height:"auto",borderRight:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,borderBottom:"none",flexShrink:0}:{height:204,borderBottom:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`}}))),k=n.styled(t,{shouldForwardProp:e=>!["hasIcon","hasBadge"].includes(e)})((({theme:e,hasIcon:t,hasBadge:r})=>({display:"flex",flexDirection:"row",justifyContent:r&&!t?"flex-end":"space-between",alignItems:"flex-start",gap:e.spacing(2),marginBottom:e.spacing(1.5)})));module.exports=({fdKey:t,heading:r,content:i,imageSrc:a,imageAlt:n,icon:s,badge:c,link:w,onMouseEnter:b,onMouseLeave:B,type:C="vertical",...q})=>{if(s&&(v=s,v?.type!==d))throw new Error("Card icon prop must be an IconContainer component");var v;if(c&&!(e=>e?.type===l.Badge)(c))throw new Error("Card badge prop must be a Badge component");const I=!!c||!!s,M=()=>w?e.jsx(y,{children:e.jsx(f,{fdKey:`card-link-${w.label}`,href:w.href,iconRight:e.jsx(o,{}),onClick:w.onClick,underline:!1,children:w.label})}):null,z=()=>r?e.jsx(u,{variant:"h4Strong",children:r}):null,D=()=>e.jsx(g,{variant:"b1Weak",children:i});return e.jsxs(m,{"data-fd":t,type:C,...q,onMouseEnter:b,onMouseLeave:B,children:[a?e.jsx(j,{alt:n||"",component:"img",image:a,type:C}):null,e.jsx(h,{type:C,children:"horizontal"===C?e.jsxs(e.Fragment,{children:[e.jsxs(p,{children:[s&&s,e.jsxs(x,{children:[z(),D()]}),c&&c]}),M()]}):e.jsxs(e.Fragment,{children:[I&&e.jsxs(k,{hasBadge:!!c,hasIcon:!!s,children:[s&&s,c&&c]}),z(),D(),M()]})})]})};
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/Card/index.tsx"],"sourcesContent":["\nimport Box from '@mui/material/Box';\nimport MuiCard from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport CardMedia from '@mui/material/CardMedia';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nimport RightArrowIcon from '../../../icons/ArrowRight02';\nimport Badge from '../Badge';\nimport IconContainer from '../IconContainer';\nimport Link, { type LinkProps } from '../Link';\n\nexport interface CardProps {\n fdKey?: string;\n heading: string;\n content: string;\n imageSrc?: string;\n icon?: React.ReactElement<typeof IconContainer>;\n badge?: React.ReactElement<typeof Badge>;\n link?: {\n label: string;\n href?: string;\n onClick?: () => void;\n }\n onMouseEnter?: () => void;\n onMouseLeave?: () => void;\n type?: 'horizontal' | 'vertical';\n}\n\nconst StyledCard = styled(MuiCard)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n borderRadius: theme.radius['radius-16'],\n border: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n ...(type === 'horizontal' && {\n display: 'flex',\n flexDirection: 'row',\n overflow: 'hidden',\n }),\n}));\n\nconst StyledCardContent = styled(CardContent)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n '&:last-child': {\n paddingBottom: theme.spacing(2),\n },\n ...(type === 'horizontal' && {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n }),\n}));\n\nconst StyledHorizontalContentWrapper = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n flex: 1,\n}));\n\nconst StyledHorizontalTextContent = styled(Box)(() => ({\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n}));\n\nconst StyledHeading = styled(Typography)(({ theme }) => ({\n marginBottom: theme.spacing(1),\n}));\n\nconst StyledLinkContainer = styled(Box)(({ theme }) => ({\n marginTop: theme.spacing(1.5),\n}));\n\nconst StyledLink = styled(Link)<{ component?: LinkProps['component'] }>(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n}));\n\nconst StyledCardMedia = styled(CardMedia)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n ...(type === 'horizontal' ? {\n width: 200,\n height: 'auto',\n borderRight: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n borderBottom: 'none',\n flexShrink: 0,\n } : {\n height: 204,\n borderBottom: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n }),\n}));\n\ninterface StyledTopContentContainerProps {\n hasIcon: boolean;\n hasBadge: boolean;\n}\n\nconst StyledTopContentContainer = styled(Box, {\n shouldForwardProp: (prop) => !['hasIcon', 'hasBadge'].includes(prop as string),\n})<StyledTopContentContainerProps>(({ theme, hasIcon, hasBadge }) => {\n\n const onlyHasRightContent = hasBadge && !hasIcon;\n return {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: onlyHasRightContent ? 'flex-end' : 'space-between',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(1.5),\n }\n});\n\n// Validation function to ensure only IconContainer components are passed\nconst isValidIconContainer = (element: React.ReactElement): boolean => {\n return element?.type === IconContainer;\n};\n\nconst isValidBadge = (element: React.ReactElement): boolean => {\n return element?.type === Badge;\n};\n\nconst Card = ({\n fdKey,\n heading,\n content,\n imageSrc,\n icon,\n badge,\n link,\n onMouseEnter,\n onMouseLeave,\n type = 'vertical',\n ...rest\n}: CardProps): React.ReactElement => {\n if (icon && !isValidIconContainer(icon)) {\n throw new Error('Card icon prop must be an IconContainer component');\n }\n if (badge && !isValidBadge(badge)) {\n throw new Error('Card badge prop must be a Badge component');\n }\n\n const hasTopContent = !!badge || !!icon;\n\n const renderImage = (): React.ReactElement | null => {\n if (!imageSrc) return null;\n return <StyledCardMedia image={imageSrc} type={type} />;\n };\n\n const renderLink = (): React.ReactElement | null => {\n if (!link) return null;\n return (\n <StyledLinkContainer>\n <StyledLink\n fdKey={`card-link-${link.label}`}\n href={link.href}\n iconRight={<RightArrowIcon />}\n onClick={link.onClick}\n underline={false}\n >\n {link.label}\n </StyledLink>\n </StyledLinkContainer>\n );\n };\n\n const renderHeading = (): React.ReactElement => {\n return (\n <StyledHeading variant=\"h4Strong\">\n {heading}\n </StyledHeading>\n );\n };\n\n const renderContent = (): React.ReactElement => {\n return (\n <Typography variant=\"b1Weak\">\n {content}\n </Typography>\n );\n };\n\n const renderHorizontalContent = (): React.ReactElement => {\n return (\n <>\n <StyledHorizontalContentWrapper>\n {icon && icon}\n <StyledHorizontalTextContent>\n {renderHeading()}\n {renderContent()}\n </StyledHorizontalTextContent>\n {badge && badge}\n </StyledHorizontalContentWrapper>\n {renderLink()}\n </>\n );\n };\n\n const renderVerticalContent = (): React.ReactElement => {\n return (\n <>\n {hasTopContent && (\n <StyledTopContentContainer hasBadge={!!badge} hasIcon={!!icon}>\n {icon && icon}\n {badge && badge}\n </StyledTopContentContainer>\n )}\n {renderHeading()}\n {renderContent()}\n {renderLink()}\n </>\n );\n };\n\n const renderCardContent = (): React.ReactElement => {\n if (type === 'horizontal') {\n return renderHorizontalContent();\n }\n return renderVerticalContent();\n };\n\n return (\n <StyledCard data-fd={fdKey} type={type} {...rest} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>\n {renderImage()}\n <StyledCardContent type={type}>\n {renderCardContent()}\n </StyledCardContent>\n </StyledCard>\n );\n};\n\nexport default Card;"],"names":["StyledCard","styled","MuiCard","theme","type","borderRadius","radius","border","palette","semantic","stroke","display","flexDirection","overflow","StyledCardContent","CardContent","paddingBottom","spacing","flex","justifyContent","StyledHorizontalContentWrapper","Box","alignItems","gap","StyledHorizontalTextContent","StyledHeading","Typography","marginBottom","StyledLinkContainer","marginTop","StyledLink","Link","StyledCardMedia","CardMedia","width","height","borderRight","borderBottom","flexShrink","StyledTopContentContainer","shouldForwardProp","prop","includes","hasIcon","hasBadge","fdKey","heading","content","imageSrc","icon","badge","link","onMouseEnter","onMouseLeave","rest","element","IconContainer","Error","Badge","isValidBadge","hasTopContent","renderLink","_jsx","label","href","iconRight","RightArrowIcon","onClick","underline","renderHeading","variant","children","renderContent","_jsxs","image","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/Card/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport MuiCard from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport CardMedia from '@mui/material/CardMedia';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nimport RightArrowIcon from '../../../icons/ArrowRight02';\nimport Badge from '../Badge';\nimport IconContainer from '../IconContainer';\nimport Link, { type LinkProps } from '../Link';\n\nexport interface CardProps {\n fdKey?: string;\n heading?: string;\n content: string;\n imageSrc?: string;\n imageAlt?: string;\n icon?: React.ReactElement<typeof IconContainer>;\n badge?: React.ReactElement<typeof Badge>;\n link?: {\n label: string;\n href?: string;\n onClick?: () => void;\n };\n onMouseEnter?: () => void;\n onMouseLeave?: () => void;\n type?: 'horizontal' | 'vertical';\n}\n\nconst StyledCard = styled(MuiCard)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n borderRadius: theme.radius['radius-16'],\n border: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n ...(type === 'horizontal' && {\n display: 'flex',\n flexDirection: 'row',\n overflow: 'hidden',\n }),\n}));\n\nconst StyledCardContent = styled(CardContent)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n '&:last-child': {\n paddingBottom: theme.spacing(2),\n },\n ...(type === 'horizontal' && {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n }),\n}));\n\nconst StyledHorizontalContentWrapper = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n flex: 1,\n}));\n\nconst StyledHorizontalTextContent = styled(Box)(() => ({\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n}));\n\nconst StyledHeading = styled(Typography)(({ theme }) => ({\n marginBottom: theme.spacing(1),\n}));\n\nconst StyledContent = styled(Typography)(({ theme }) => ({\n color: theme.palette.semantic.text['text-weak'],\n}));\n\nconst StyledLinkContainer = styled(Box)(({ theme }) => ({\n marginTop: theme.spacing(1.5),\n}));\n\nconst StyledLink = styled(Link)<{ component?: LinkProps['component'] }>(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n}));\n\nconst StyledCardMedia = styled(CardMedia)<{\n alt?: string;\n component?: string;\n type?: 'horizontal' | 'vertical';\n}>(({ theme, type }) => ({\n ...(type === 'horizontal'\n ? {\n width: 200,\n height: 'auto',\n borderRight: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n borderBottom: 'none',\n flexShrink: 0,\n }\n : {\n height: 204,\n borderBottom: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n }),\n}));\n\ninterface StyledTopContentContainerProps {\n hasIcon: boolean;\n hasBadge: boolean;\n}\n\nconst StyledTopContentContainer = styled(Box, {\n shouldForwardProp: (prop) => !['hasIcon', 'hasBadge'].includes(prop as string),\n})<StyledTopContentContainerProps>(({ theme, hasIcon, hasBadge }) => {\n const onlyHasRightContent = hasBadge && !hasIcon;\n return {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: onlyHasRightContent ? 'flex-end' : 'space-between',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(1.5),\n };\n});\n\n// Validation function to ensure only IconContainer components are passed\nconst isValidIconContainer = (element: React.ReactElement): boolean => {\n return element?.type === IconContainer;\n};\n\nconst isValidBadge = (element: React.ReactElement): boolean => {\n return element?.type === Badge;\n};\n\nconst Card = ({\n fdKey,\n heading,\n content,\n imageSrc,\n imageAlt,\n icon,\n badge,\n link,\n onMouseEnter,\n onMouseLeave,\n type = 'vertical',\n ...rest\n}: CardProps): React.ReactElement => {\n if (icon && !isValidIconContainer(icon)) {\n throw new Error('Card icon prop must be an IconContainer component');\n }\n if (badge && !isValidBadge(badge)) {\n throw new Error('Card badge prop must be a Badge component');\n }\n\n const hasTopContent = !!badge || !!icon;\n\n const renderImage = (): React.ReactElement | null => {\n if (!imageSrc) return null;\n return <StyledCardMedia alt={imageAlt || ''} component=\"img\" image={imageSrc} type={type} />;\n };\n\n const renderLink = (): React.ReactElement | null => {\n if (!link) return null;\n return (\n <StyledLinkContainer>\n <StyledLink\n fdKey={`card-link-${link.label}`}\n href={link.href}\n iconRight={<RightArrowIcon />}\n onClick={link.onClick}\n underline={false}\n >\n {link.label}\n </StyledLink>\n </StyledLinkContainer>\n );\n };\n\n const renderHeading = (): React.ReactElement | null => {\n if (!heading) return null;\n return <StyledHeading variant=\"h4Strong\">{heading}</StyledHeading>;\n };\n\n const renderContent = (): React.ReactElement => {\n return <StyledContent variant=\"b1Weak\">{content}</StyledContent>;\n };\n\n const renderHorizontalContent = (): React.ReactElement => {\n return (\n <>\n <StyledHorizontalContentWrapper>\n {icon && icon}\n <StyledHorizontalTextContent>\n {renderHeading()}\n {renderContent()}\n </StyledHorizontalTextContent>\n {badge && badge}\n </StyledHorizontalContentWrapper>\n {renderLink()}\n </>\n );\n };\n\n const renderVerticalContent = (): React.ReactElement => {\n return (\n <>\n {hasTopContent && (\n <StyledTopContentContainer hasBadge={!!badge} hasIcon={!!icon}>\n {icon && icon}\n {badge && badge}\n </StyledTopContentContainer>\n )}\n {renderHeading()}\n {renderContent()}\n {renderLink()}\n </>\n );\n };\n\n const renderCardContent = (): React.ReactElement => {\n if (type === 'horizontal') {\n return renderHorizontalContent();\n }\n return renderVerticalContent();\n };\n\n return (\n <StyledCard data-fd={fdKey} type={type} {...rest} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>\n {renderImage()}\n <StyledCardContent type={type}>{renderCardContent()}</StyledCardContent>\n </StyledCard>\n );\n};\n\nexport default Card;\n"],"names":["StyledCard","styled","MuiCard","theme","type","borderRadius","radius","border","palette","semantic","stroke","display","flexDirection","overflow","StyledCardContent","CardContent","paddingBottom","spacing","flex","justifyContent","StyledHorizontalContentWrapper","Box","alignItems","gap","StyledHorizontalTextContent","StyledHeading","Typography","marginBottom","StyledContent","color","text","StyledLinkContainer","marginTop","StyledLink","Link","StyledCardMedia","CardMedia","width","height","borderRight","borderBottom","flexShrink","StyledTopContentContainer","shouldForwardProp","prop","includes","hasIcon","hasBadge","fdKey","heading","content","imageSrc","imageAlt","icon","badge","link","onMouseEnter","onMouseLeave","rest","element","IconContainer","Error","Badge","isValidBadge","hasTopContent","renderLink","_jsx","label","href","iconRight","RightArrowIcon","onClick","underline","renderHeading","variant","children","renderContent","_jsxs","alt","component","image","_Fragment"],"mappings":"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"}
@@ -3,9 +3,10 @@ import IconContainer from '../IconContainer/index.js';
3
3
 
4
4
  interface CardProps {
5
5
  fdKey?: string;
6
- heading: string;
6
+ heading?: string;
7
7
  content: string;
8
8
  imageSrc?: string;
9
+ imageAlt?: string;
9
10
  icon?: React.ReactElement<typeof IconContainer>;
10
11
  badge?: React.ReactElement<typeof Badge>;
11
12
  link?: {
@@ -17,7 +18,7 @@ interface CardProps {
17
18
  onMouseLeave?: () => void;
18
19
  type?: 'horizontal' | 'vertical';
19
20
  }
20
- declare const Card: ({ fdKey, heading, content, imageSrc, icon, badge, link, onMouseEnter, onMouseLeave, type, ...rest }: CardProps) => React.ReactElement;
21
+ declare const Card: ({ fdKey, heading, content, imageSrc, imageAlt, icon, badge, link, onMouseEnter, onMouseLeave, type, ...rest }: CardProps) => React.ReactElement;
21
22
 
22
23
  export { Card as default };
23
24
  export type { CardProps };
@@ -1,2 +1,2 @@
1
- import{jsxs as e,jsx as t,Fragment as r}from"react/jsx-runtime";import i from"@mui/material/Box";import o from"@mui/material/Card";import a from"@mui/material/CardContent";import n from"@mui/material/CardMedia";import{styled as l}from"@mui/material/styles";import m from"@mui/material/Typography";import d from"../../../icons/ArrowRight02/index.js";import{Badge as s}from"../Badge/index.js";import p from"../IconContainer/index.js";import{Link as c}from"../Link/index.js";const h=l(o)((({theme:e,type:t})=>({borderRadius:e.radius["radius-16"],border:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,..."horizontal"===t&&{display:"flex",flexDirection:"row",overflow:"hidden"}}))),f=l(a)((({theme:e,type:t})=>({"&:last-child":{paddingBottom:e.spacing(2)},..."horizontal"===t&&{flex:1,display:"flex",flexDirection:"column",justifyContent:"space-between"}}))),g=l(i)((({theme:e})=>({display:"flex",alignItems:"flex-start",gap:e.spacing(2),flex:1}))),u=l(i)((()=>({flex:1,display:"flex",flexDirection:"column"}))),x=l(m)((({theme:e})=>({marginBottom:e.spacing(1)}))),y=l(i)((({theme:e})=>({marginTop:e.spacing(1.5)}))),k=l(c)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(1)}))),w=l(n)((({theme:e,type:t})=>({..."horizontal"===t?{width:200,height:"auto",borderRight:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,borderBottom:"none",flexShrink:0}:{height:204,borderBottom:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`}}))),b=l(i,{shouldForwardProp:e=>!["hasIcon","hasBadge"].includes(e)})((({theme:e,hasIcon:t,hasBadge:r})=>({display:"flex",flexDirection:"row",justifyContent:r&&!t?"flex-end":"space-between",alignItems:"flex-start",gap:e.spacing(2),marginBottom:e.spacing(1.5)}))),C=({fdKey:i,heading:o,content:a,imageSrc:n,icon:l,badge:c,link:C,onMouseEnter:B,onMouseLeave:I,type:j="vertical",...v})=>{if(l&&(M=l,M?.type!==p))throw new Error("Card icon prop must be an IconContainer component");var M;if(c&&!(e=>e?.type===s)(c))throw new Error("Card badge prop must be a Badge component");const z=!!c||!!l,D=()=>C?t(y,{children:t(k,{fdKey:`card-link-${C.label}`,href:C.href,iconRight:t(d,{}),onClick:C.onClick,underline:!1,children:C.label})}):null,E=()=>t(x,{variant:"h4Strong",children:o}),R=()=>t(m,{variant:"b1Weak",children:a});return e(h,{"data-fd":i,type:j,...v,onMouseEnter:B,onMouseLeave:I,children:[n?t(w,{image:n,type:j}):null,t(f,{type:j,children:e(r,"horizontal"===j?{children:[e(g,{children:[l&&l,e(u,{children:[E(),R()]}),c&&c]}),D()]}:{children:[z&&e(b,{hasBadge:!!c,hasIcon:!!l,children:[l&&l,c&&c]}),E(),R(),D()]})})]})};export{C as default};
1
+ import{jsxs as e,jsx as t,Fragment as i}from"react/jsx-runtime";import o from"@mui/material/Box";import r from"@mui/material/Card";import a from"@mui/material/CardContent";import n from"@mui/material/CardMedia";import{styled as l}from"@mui/material/styles";import m from"@mui/material/Typography";import s from"../../../icons/ArrowRight02/index.js";import{Badge as d}from"../Badge/index.js";import p from"../IconContainer/index.js";import{Link as c}from"../Link/index.js";const h=l(r)((({theme:e,type:t})=>({borderRadius:e.radius["radius-16"],border:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,..."horizontal"===t&&{display:"flex",flexDirection:"row",overflow:"hidden"}}))),f=l(a)((({theme:e,type:t})=>({"&:last-child":{paddingBottom:e.spacing(2)},..."horizontal"===t&&{flex:1,display:"flex",flexDirection:"column",justifyContent:"space-between"}}))),g=l(o)((({theme:e})=>({display:"flex",alignItems:"flex-start",gap:e.spacing(2),flex:1}))),u=l(o)((()=>({flex:1,display:"flex",flexDirection:"column"}))),x=l(m)((({theme:e})=>({marginBottom:e.spacing(1)}))),y=l(m)((({theme:e})=>({color:e.palette.semantic.text["text-weak"]}))),k=l(o)((({theme:e})=>({marginTop:e.spacing(1.5)}))),w=l(c)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(1)}))),b=l(n)((({theme:e,type:t})=>({..."horizontal"===t?{width:200,height:"auto",borderRight:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,borderBottom:"none",flexShrink:0}:{height:204,borderBottom:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`}}))),C=l(o,{shouldForwardProp:e=>!["hasIcon","hasBadge"].includes(e)})((({theme:e,hasIcon:t,hasBadge:i})=>({display:"flex",flexDirection:"row",justifyContent:i&&!t?"flex-end":"space-between",alignItems:"flex-start",gap:e.spacing(2),marginBottom:e.spacing(1.5)}))),B=({fdKey:o,heading:r,content:a,imageSrc:n,imageAlt:l,icon:m,badge:c,link:B,onMouseEnter:I,onMouseLeave:j,type:v="vertical",...M})=>{if(m&&(z=m,z?.type!==p))throw new Error("Card icon prop must be an IconContainer component");var z;if(c&&!(e=>e?.type===d)(c))throw new Error("Card badge prop must be a Badge component");const D=!!c||!!m,E=()=>B?t(k,{children:t(w,{fdKey:`card-link-${B.label}`,href:B.href,iconRight:t(s,{}),onClick:B.onClick,underline:!1,children:B.label})}):null,R=()=>r?t(x,{variant:"h4Strong",children:r}):null,$=()=>t(y,{variant:"b1Weak",children:a});return e(h,{"data-fd":o,type:v,...M,onMouseEnter:I,onMouseLeave:j,children:[n?t(b,{alt:l||"",component:"img",image:n,type:v}):null,t(f,{type:v,children:e(i,"horizontal"===v?{children:[e(g,{children:[m&&m,e(u,{children:[R(),$()]}),c&&c]}),E()]}:{children:[D&&e(C,{hasBadge:!!c,hasIcon:!!m,children:[m&&m,c&&c]}),R(),$(),E()]})})]})};export{B as default};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/atoms/Card/index.tsx"],"sourcesContent":["\nimport Box from '@mui/material/Box';\nimport MuiCard from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport CardMedia from '@mui/material/CardMedia';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nimport RightArrowIcon from '../../../icons/ArrowRight02';\nimport Badge from '../Badge';\nimport IconContainer from '../IconContainer';\nimport Link, { type LinkProps } from '../Link';\n\nexport interface CardProps {\n fdKey?: string;\n heading: string;\n content: string;\n imageSrc?: string;\n icon?: React.ReactElement<typeof IconContainer>;\n badge?: React.ReactElement<typeof Badge>;\n link?: {\n label: string;\n href?: string;\n onClick?: () => void;\n }\n onMouseEnter?: () => void;\n onMouseLeave?: () => void;\n type?: 'horizontal' | 'vertical';\n}\n\nconst StyledCard = styled(MuiCard)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n borderRadius: theme.radius['radius-16'],\n border: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n ...(type === 'horizontal' && {\n display: 'flex',\n flexDirection: 'row',\n overflow: 'hidden',\n }),\n}));\n\nconst StyledCardContent = styled(CardContent)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n '&:last-child': {\n paddingBottom: theme.spacing(2),\n },\n ...(type === 'horizontal' && {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n }),\n}));\n\nconst StyledHorizontalContentWrapper = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n flex: 1,\n}));\n\nconst StyledHorizontalTextContent = styled(Box)(() => ({\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n}));\n\nconst StyledHeading = styled(Typography)(({ theme }) => ({\n marginBottom: theme.spacing(1),\n}));\n\nconst StyledLinkContainer = styled(Box)(({ theme }) => ({\n marginTop: theme.spacing(1.5),\n}));\n\nconst StyledLink = styled(Link)<{ component?: LinkProps['component'] }>(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n}));\n\nconst StyledCardMedia = styled(CardMedia)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n ...(type === 'horizontal' ? {\n width: 200,\n height: 'auto',\n borderRight: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n borderBottom: 'none',\n flexShrink: 0,\n } : {\n height: 204,\n borderBottom: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n }),\n}));\n\ninterface StyledTopContentContainerProps {\n hasIcon: boolean;\n hasBadge: boolean;\n}\n\nconst StyledTopContentContainer = styled(Box, {\n shouldForwardProp: (prop) => !['hasIcon', 'hasBadge'].includes(prop as string),\n})<StyledTopContentContainerProps>(({ theme, hasIcon, hasBadge }) => {\n\n const onlyHasRightContent = hasBadge && !hasIcon;\n return {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: onlyHasRightContent ? 'flex-end' : 'space-between',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(1.5),\n }\n});\n\n// Validation function to ensure only IconContainer components are passed\nconst isValidIconContainer = (element: React.ReactElement): boolean => {\n return element?.type === IconContainer;\n};\n\nconst isValidBadge = (element: React.ReactElement): boolean => {\n return element?.type === Badge;\n};\n\nconst Card = ({\n fdKey,\n heading,\n content,\n imageSrc,\n icon,\n badge,\n link,\n onMouseEnter,\n onMouseLeave,\n type = 'vertical',\n ...rest\n}: CardProps): React.ReactElement => {\n if (icon && !isValidIconContainer(icon)) {\n throw new Error('Card icon prop must be an IconContainer component');\n }\n if (badge && !isValidBadge(badge)) {\n throw new Error('Card badge prop must be a Badge component');\n }\n\n const hasTopContent = !!badge || !!icon;\n\n const renderImage = (): React.ReactElement | null => {\n if (!imageSrc) return null;\n return <StyledCardMedia image={imageSrc} type={type} />;\n };\n\n const renderLink = (): React.ReactElement | null => {\n if (!link) return null;\n return (\n <StyledLinkContainer>\n <StyledLink\n fdKey={`card-link-${link.label}`}\n href={link.href}\n iconRight={<RightArrowIcon />}\n onClick={link.onClick}\n underline={false}\n >\n {link.label}\n </StyledLink>\n </StyledLinkContainer>\n );\n };\n\n const renderHeading = (): React.ReactElement => {\n return (\n <StyledHeading variant=\"h4Strong\">\n {heading}\n </StyledHeading>\n );\n };\n\n const renderContent = (): React.ReactElement => {\n return (\n <Typography variant=\"b1Weak\">\n {content}\n </Typography>\n );\n };\n\n const renderHorizontalContent = (): React.ReactElement => {\n return (\n <>\n <StyledHorizontalContentWrapper>\n {icon && icon}\n <StyledHorizontalTextContent>\n {renderHeading()}\n {renderContent()}\n </StyledHorizontalTextContent>\n {badge && badge}\n </StyledHorizontalContentWrapper>\n {renderLink()}\n </>\n );\n };\n\n const renderVerticalContent = (): React.ReactElement => {\n return (\n <>\n {hasTopContent && (\n <StyledTopContentContainer hasBadge={!!badge} hasIcon={!!icon}>\n {icon && icon}\n {badge && badge}\n </StyledTopContentContainer>\n )}\n {renderHeading()}\n {renderContent()}\n {renderLink()}\n </>\n );\n };\n\n const renderCardContent = (): React.ReactElement => {\n if (type === 'horizontal') {\n return renderHorizontalContent();\n }\n return renderVerticalContent();\n };\n\n return (\n <StyledCard data-fd={fdKey} type={type} {...rest} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>\n {renderImage()}\n <StyledCardContent type={type}>\n {renderCardContent()}\n </StyledCardContent>\n </StyledCard>\n );\n};\n\nexport default Card;"],"names":["StyledCard","styled","MuiCard","theme","type","borderRadius","radius","border","palette","semantic","stroke","display","flexDirection","overflow","StyledCardContent","CardContent","paddingBottom","spacing","flex","justifyContent","StyledHorizontalContentWrapper","Box","alignItems","gap","StyledHorizontalTextContent","StyledHeading","Typography","marginBottom","StyledLinkContainer","marginTop","StyledLink","Link","StyledCardMedia","CardMedia","width","height","borderRight","borderBottom","flexShrink","StyledTopContentContainer","shouldForwardProp","prop","includes","hasIcon","hasBadge","Card","fdKey","heading","content","imageSrc","icon","badge","link","onMouseEnter","onMouseLeave","rest","element","IconContainer","Error","Badge","isValidBadge","hasTopContent","renderLink","_jsx","label","href","iconRight","RightArrowIcon","onClick","underline","renderHeading","variant","children","renderContent","_jsxs","image","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/atoms/Card/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport MuiCard from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport CardMedia from '@mui/material/CardMedia';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nimport RightArrowIcon from '../../../icons/ArrowRight02';\nimport Badge from '../Badge';\nimport IconContainer from '../IconContainer';\nimport Link, { type LinkProps } from '../Link';\n\nexport interface CardProps {\n fdKey?: string;\n heading?: string;\n content: string;\n imageSrc?: string;\n imageAlt?: string;\n icon?: React.ReactElement<typeof IconContainer>;\n badge?: React.ReactElement<typeof Badge>;\n link?: {\n label: string;\n href?: string;\n onClick?: () => void;\n };\n onMouseEnter?: () => void;\n onMouseLeave?: () => void;\n type?: 'horizontal' | 'vertical';\n}\n\nconst StyledCard = styled(MuiCard)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n borderRadius: theme.radius['radius-16'],\n border: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n ...(type === 'horizontal' && {\n display: 'flex',\n flexDirection: 'row',\n overflow: 'hidden',\n }),\n}));\n\nconst StyledCardContent = styled(CardContent)<{ type?: 'horizontal' | 'vertical' }>(({ theme, type }) => ({\n '&:last-child': {\n paddingBottom: theme.spacing(2),\n },\n ...(type === 'horizontal' && {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n }),\n}));\n\nconst StyledHorizontalContentWrapper = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n flex: 1,\n}));\n\nconst StyledHorizontalTextContent = styled(Box)(() => ({\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n}));\n\nconst StyledHeading = styled(Typography)(({ theme }) => ({\n marginBottom: theme.spacing(1),\n}));\n\nconst StyledContent = styled(Typography)(({ theme }) => ({\n color: theme.palette.semantic.text['text-weak'],\n}));\n\nconst StyledLinkContainer = styled(Box)(({ theme }) => ({\n marginTop: theme.spacing(1.5),\n}));\n\nconst StyledLink = styled(Link)<{ component?: LinkProps['component'] }>(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n}));\n\nconst StyledCardMedia = styled(CardMedia)<{\n alt?: string;\n component?: string;\n type?: 'horizontal' | 'vertical';\n}>(({ theme, type }) => ({\n ...(type === 'horizontal'\n ? {\n width: 200,\n height: 'auto',\n borderRight: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n borderBottom: 'none',\n flexShrink: 0,\n }\n : {\n height: 204,\n borderBottom: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n }),\n}));\n\ninterface StyledTopContentContainerProps {\n hasIcon: boolean;\n hasBadge: boolean;\n}\n\nconst StyledTopContentContainer = styled(Box, {\n shouldForwardProp: (prop) => !['hasIcon', 'hasBadge'].includes(prop as string),\n})<StyledTopContentContainerProps>(({ theme, hasIcon, hasBadge }) => {\n const onlyHasRightContent = hasBadge && !hasIcon;\n return {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: onlyHasRightContent ? 'flex-end' : 'space-between',\n alignItems: 'flex-start',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(1.5),\n };\n});\n\n// Validation function to ensure only IconContainer components are passed\nconst isValidIconContainer = (element: React.ReactElement): boolean => {\n return element?.type === IconContainer;\n};\n\nconst isValidBadge = (element: React.ReactElement): boolean => {\n return element?.type === Badge;\n};\n\nconst Card = ({\n fdKey,\n heading,\n content,\n imageSrc,\n imageAlt,\n icon,\n badge,\n link,\n onMouseEnter,\n onMouseLeave,\n type = 'vertical',\n ...rest\n}: CardProps): React.ReactElement => {\n if (icon && !isValidIconContainer(icon)) {\n throw new Error('Card icon prop must be an IconContainer component');\n }\n if (badge && !isValidBadge(badge)) {\n throw new Error('Card badge prop must be a Badge component');\n }\n\n const hasTopContent = !!badge || !!icon;\n\n const renderImage = (): React.ReactElement | null => {\n if (!imageSrc) return null;\n return <StyledCardMedia alt={imageAlt || ''} component=\"img\" image={imageSrc} type={type} />;\n };\n\n const renderLink = (): React.ReactElement | null => {\n if (!link) return null;\n return (\n <StyledLinkContainer>\n <StyledLink\n fdKey={`card-link-${link.label}`}\n href={link.href}\n iconRight={<RightArrowIcon />}\n onClick={link.onClick}\n underline={false}\n >\n {link.label}\n </StyledLink>\n </StyledLinkContainer>\n );\n };\n\n const renderHeading = (): React.ReactElement | null => {\n if (!heading) return null;\n return <StyledHeading variant=\"h4Strong\">{heading}</StyledHeading>;\n };\n\n const renderContent = (): React.ReactElement => {\n return <StyledContent variant=\"b1Weak\">{content}</StyledContent>;\n };\n\n const renderHorizontalContent = (): React.ReactElement => {\n return (\n <>\n <StyledHorizontalContentWrapper>\n {icon && icon}\n <StyledHorizontalTextContent>\n {renderHeading()}\n {renderContent()}\n </StyledHorizontalTextContent>\n {badge && badge}\n </StyledHorizontalContentWrapper>\n {renderLink()}\n </>\n );\n };\n\n const renderVerticalContent = (): React.ReactElement => {\n return (\n <>\n {hasTopContent && (\n <StyledTopContentContainer hasBadge={!!badge} hasIcon={!!icon}>\n {icon && icon}\n {badge && badge}\n </StyledTopContentContainer>\n )}\n {renderHeading()}\n {renderContent()}\n {renderLink()}\n </>\n );\n };\n\n const renderCardContent = (): React.ReactElement => {\n if (type === 'horizontal') {\n return renderHorizontalContent();\n }\n return renderVerticalContent();\n };\n\n return (\n <StyledCard data-fd={fdKey} type={type} {...rest} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>\n {renderImage()}\n <StyledCardContent type={type}>{renderCardContent()}</StyledCardContent>\n </StyledCard>\n );\n};\n\nexport default Card;\n"],"names":["StyledCard","styled","MuiCard","theme","type","borderRadius","radius","border","palette","semantic","stroke","display","flexDirection","overflow","StyledCardContent","CardContent","paddingBottom","spacing","flex","justifyContent","StyledHorizontalContentWrapper","Box","alignItems","gap","StyledHorizontalTextContent","StyledHeading","Typography","marginBottom","StyledContent","color","text","StyledLinkContainer","marginTop","StyledLink","Link","StyledCardMedia","CardMedia","width","height","borderRight","borderBottom","flexShrink","StyledTopContentContainer","shouldForwardProp","prop","includes","hasIcon","hasBadge","Card","fdKey","heading","content","imageSrc","imageAlt","icon","badge","link","onMouseEnter","onMouseLeave","rest","element","IconContainer","Error","Badge","isValidBadge","hasTopContent","renderLink","_jsx","label","href","iconRight","RightArrowIcon","onClick","underline","renderHeading","variant","children","renderContent","_jsxs","alt","component","image","_Fragment"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),i=require("react/jsx-runtime"),t=require("@mui/material/Autocomplete"),l=require("@mui/material/Box"),s=require("@mui/material/styles"),n=require("@mui/material/Tooltip"),r=require("../../../icons/ArrowDown01/index.cjs.js"),a=require("../../../icons/ArrowUp01/index.cjs.js"),o=require("../../../icons/Cancel/index.cjs.js"),d=require("../../../icons/Search/index.cjs.js"),c=require("../../../utilities/stringUtilities.cjs.js"),p=require("../../atoms/CircularProgress/index.cjs.js"),u=require("../../atoms/MenuItem/index.cjs.js"),m=require("../../atoms/Tag/index.cjs.js"),g=require("../../atoms/TextField/index.cjs.js"),x=require("./hooks/useDynamicLimitTags.cjs.js");const h=t,j=s.styled(h,{shouldForwardProp:e=>"fullWidth"!==e})((({fullWidth:e=!1})=>({width:e?"100%":"min(364px, 100%)"}))),b=s.styled(l,{shouldForwardProp:e=>!["clickable","disabled","placement"].includes(e)})((({theme:e,clickable:i=!1,disabled:t=!1,placement:l})=>({alignItems:"center",cursor:i?t?"not-allowed":"pointer":"default",display:"flex",justifyContent:"center",padding:0,pointerEvents:i?"auto":"none",..."start"===l&&{paddingRight:e.spacing(1)},..."middle"===l&&{padding:e.spacing(0,1)},"& svg":{color:t?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),y=s.styled(l,{shouldForwardProp:e=>"placement"!==e})((({theme:e,placement:i})=>({alignItems:"center",display:"flex",justifyContent:"center",padding:0,..."start"===i&&{paddingRight:e.spacing(1)},..."middle"===i&&{padding:e.spacing(0,1)}}))),f=({className:t,disabled:l=!1,errorText:s,fdKey:h,fullWidth:f=!1,helperText:T,label:q,loading:A=!1,multiple:C=!1,placeholder:I,onChange:P,onInputChange:k,options:v=[],required:L=!1,translations:O,type:w="search",value:E})=>{const[F,W]=e.useState(!1),D="search"===w,S="combobox"===w,{rootRef:M,limitTags:z}=x.useDynamicLimitTags({chipMax:130,gap:4,horizontalPadding:32,reservedPx:D?120:90});e.useEffect((()=>{l&&W(!1)}),[l]);const K=e=>{l||W(void 0===e?e=>!e:e)};return i.jsx(j,{ref:M,className:t,clearIcon:i.jsx(o,{size:"md"}),clearText:O.clearTextAriaLabel,disableClearable:l||A,disableCloseOnSelect:C,disabled:l,filterOptions:D?e=>e:void 0,forcePopupIcon:S,freeSolo:D,fullWidth:f,getOptionKey:e=>"string"==typeof e?e:String(e.value),getOptionLabel:e=>"string"==typeof e?e:e.label,isOptionEqualToValue:(e,i)=>null!=i&&("string"==typeof i?e.label===i||String(e.value)===i:e.value===i.value),limitTags:z,loading:A,loadingText:O.loadingText,multiple:C,noOptionsText:O.noOptionsText,onChange:(e,i,t,l)=>{P&&P(e,i,t,l)},onClose:()=>K(!1),onInputChange:(e,i,t)=>{k&&k(e,i,t)},onOpen:()=>K(!0),open:F,openText:O.openPopupAriaLabel,options:v,popupIcon:D?null:i.jsx(b,{clickable:!0,disabled:l,placement:"end",children:F?i.jsx(a,{}):i.jsx(r,{})}),renderInput:e=>i.jsx(g.TextField,{disabled:l,errorText:s,fdKey:h,fullWidth:f,helperText:T,label:q,placeholder:I,required:L,slotProps:{input:{...e.InputProps,endAdornment:i.jsxs(i.Fragment,{children:[A?i.jsx(y,{placement:D?"end":"middle",children:i.jsx(p.CircularProgress,{size:"small"})}):null,e.InputProps.endAdornment]}),startAdornment:i.jsxs(i.Fragment,{children:[D?i.jsx(b,{disabled:l,placement:"start",children:i.jsx(d,{"aria-hidden":"true"})}):null,e.InputProps.startAdornment]})},htmlInput:{...e.inputProps}}}),renderOption:(i,t,l)=>{const{key:s,onClick:n,...r}=i;return C?e.createElement(u.MenuItem,{...r,key:s,checked:l.selected,label:t.label,onCheckedChange:(e,i)=>{n?.(i)},type:"checkbox"}):e.createElement(u.MenuItem,{...r,key:s,label:t.label,onClick:n,selected:l.selected,type:"text"})},renderTags:(e,t)=>e.map(((e,l)=>{const{key:s,onDelete:r,...a}=t({index:l}),o="string"==typeof e?e:e.label,d=c.truncateWithEllipsis(o,13,{includeEllipsisInLimit:!0}),p=d.endsWith("..."),u=s??`tag-${"string"==typeof e?e:e.value}`;return p?i.jsx(n,{arrow:!0,placement:"top",title:o,children:i.jsx("span",{...a,children:i.jsx(m.Tag,{dismissAriaLabel:O.dismissTagAriaLabel,label:d,onDismiss:r})})},u):i.jsx("span",{...a,children:i.jsx(m.Tag,{dismissAriaLabel:O.dismissTagAriaLabel,label:d,onDismiss:r})},u)})),slotProps:{popupIndicator:{onClick:e=>{l||(e.stopPropagation(),K())}}},value:C?Array.isArray(E)?E:null==E?[]:[E]:Array.isArray(E)?E.length>0?E[0]:null:E??null})};exports.Autocomplete=f,exports.default=f;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),i=require("react/jsx-runtime"),t=require("@mui/material/Autocomplete"),l=require("@mui/material/Box"),s=require("@mui/material/styles"),n=require("../Tooltip/index.cjs.js"),r=require("../../../icons/ArrowDown01/index.cjs.js"),a=require("../../../icons/ArrowUp01/index.cjs.js"),o=require("../../../icons/Cancel/index.cjs.js"),d=require("../../../icons/Search/index.cjs.js"),c=require("../../../utilities/stringUtilities.cjs.js"),p=require("../../atoms/CircularProgress/index.cjs.js"),u=require("../../atoms/MenuItem/index.cjs.js"),m=require("../../atoms/Tag/index.cjs.js"),g=require("../../atoms/TextField/index.cjs.js"),x=require("./hooks/useDynamicLimitTags.cjs.js");const h=t,j=s.styled(h,{shouldForwardProp:e=>"fullWidth"!==e})((({fullWidth:e=!1})=>({width:e?"100%":"min(364px, 100%)"}))),b=s.styled(l,{shouldForwardProp:e=>!["clickable","disabled","placement"].includes(e)})((({theme:e,clickable:i=!1,disabled:t=!1,placement:l})=>({alignItems:"center",cursor:i?t?"not-allowed":"pointer":"default",display:"flex",justifyContent:"center",padding:0,pointerEvents:i?"auto":"none",..."start"===l&&{paddingRight:e.spacing(1)},..."middle"===l&&{padding:e.spacing(0,1)},"& svg":{color:t?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),y=s.styled(l,{shouldForwardProp:e=>"placement"!==e})((({theme:e,placement:i})=>({alignItems:"center",display:"flex",justifyContent:"center",padding:0,..."start"===i&&{paddingRight:e.spacing(1)},..."middle"===i&&{padding:e.spacing(0,1)}}))),f=({className:t,disabled:l=!1,errorText:s,fdKey:h,fullWidth:f=!1,helperText:T,label:q,loading:A=!1,multiple:C=!1,placeholder:I,onChange:P,onInputChange:k,options:v=[],required:L=!1,translations:O,type:w="search",value:E})=>{const[F,W]=e.useState(!1),D="search"===w,S="combobox"===w,{rootRef:M,limitTags:z}=x.useDynamicLimitTags({chipMax:130,gap:4,horizontalPadding:32,reservedPx:D?120:90});e.useEffect((()=>{l&&W(!1)}),[l]);const K=e=>{l||W(void 0===e?e=>!e:e)};return i.jsx(j,{ref:M,className:t,clearIcon:i.jsx(o,{size:"md"}),clearText:O.clearTextAriaLabel,disableClearable:l||A,disableCloseOnSelect:C,disabled:l,filterOptions:D?e=>e:void 0,forcePopupIcon:S,freeSolo:D,fullWidth:f,getOptionKey:e=>"string"==typeof e?e:String(e.value),getOptionLabel:e=>"string"==typeof e?e:e.label,isOptionEqualToValue:(e,i)=>null!=i&&("string"==typeof i?e.label===i||String(e.value)===i:e.value===i.value),limitTags:z,loading:A,loadingText:O.loadingText,multiple:C,noOptionsText:O.noOptionsText,onChange:(e,i,t,l)=>{P&&P(e,i,t,l)},onClose:()=>K(!1),onInputChange:(e,i,t)=>{k&&k(e,i,t)},onOpen:()=>K(!0),open:F,openText:O.openPopupAriaLabel,options:v,popupIcon:D?null:i.jsx(b,{clickable:!0,disabled:l,placement:"end",children:F?i.jsx(a,{}):i.jsx(r,{})}),renderInput:e=>i.jsx(g.TextField,{disabled:l,errorText:s,fdKey:h,fullWidth:f,helperText:T,label:q,placeholder:I,required:L,slotProps:{input:{...e.InputProps,endAdornment:i.jsxs(i.Fragment,{children:[A?i.jsx(y,{placement:D?"end":"middle",children:i.jsx(p.CircularProgress,{size:"small"})}):null,e.InputProps.endAdornment]}),startAdornment:i.jsxs(i.Fragment,{children:[D?i.jsx(b,{disabled:l,placement:"start",children:i.jsx(d,{"aria-hidden":"true"})}):null,e.InputProps.startAdornment]})},htmlInput:{...e.inputProps}}}),renderOption:(i,t,l)=>{const{key:s,onClick:n,...r}=i;return C?e.createElement(u.MenuItem,{...r,key:s,checked:l.selected,label:t.label,onCheckedChange:(e,i)=>{n?.(i)},type:"checkbox"}):e.createElement(u.MenuItem,{...r,key:s,label:t.label,onClick:n,selected:l.selected,type:"text"})},renderTags:(e,t)=>e.map(((e,l)=>{const{key:s,onDelete:r,...a}=t({index:l}),o="string"==typeof e?e:e.label,d=c.truncateWithEllipsis(o,13,{includeEllipsisInLimit:!0}),p=d.endsWith("..."),u=s??`tag-${"string"==typeof e?e:e.value}`;return p?i.jsx(n.Tooltip,{title:o,children:i.jsx("span",{...a,children:i.jsx(m.Tag,{dismissAriaLabel:O.dismissTagAriaLabel,label:d,onDismiss:r})})},u):i.jsx("span",{...a,children:i.jsx(m.Tag,{dismissAriaLabel:O.dismissTagAriaLabel,label:d,onDismiss:r})},u)})),slotProps:{popupIndicator:{onClick:e=>{l||(e.stopPropagation(),K())}}},value:C?Array.isArray(E)?E:null==E?[]:[E]:Array.isArray(E)?E.length>0?E[0]:null:E??null})};exports.Autocomplete=f,exports.default=f;
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/Autocomplete/index.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport MuiAutocomplete, {\n type AutocompleteChangeDetails,\n type AutocompleteChangeReason,\n type AutocompleteInputChangeReason,\n type AutocompleteProps as MuiAutocompleteProps,\n type AutocompleteRenderGetTagProps,\n type AutocompleteRenderInputParams,\n type AutocompleteRenderOptionState,\n type AutocompleteValue,\n} from '@mui/material/Autocomplete';\nimport Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\n// TODO: Replace with our own Tooltip component\nimport MuiTooltip from '@mui/material/Tooltip';\n\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelIcon from '@fd/icons/Cancel';\nimport SearchIcon from '@fd/icons/Search';\nimport { truncateWithEllipsis } from '@fd/utilities/stringUtilities';\n\nimport CircularProgress from '../../atoms/CircularProgress';\nimport MenuItem from '../../atoms/MenuItem';\nimport Tag from '../../atoms/Tag';\nimport TextField, { type TextFieldProps } from '../../atoms/TextField';\nimport { useDynamicLimitTags } from './hooks/useDynamicLimitTags';\n\n// Bind flags to MuiAutocomplete\ntype MuiCustomAutocompleteProps<\n M extends boolean = boolean, // Multiple\n DC extends boolean = boolean, // DisableClearable\n FS extends boolean = boolean, // FreeSolo\n> = MuiAutocompleteProps<AutocompleteOption, M, DC, FS>;\n\n/**\n * Represents an option in the Autocomplete dropdown.\n */\nexport interface AutocompleteOption {\n /** The label to display in the dropdown option. */\n label: string;\n /** The value to store in the dropdown option. */\n value: number | string;\n}\n\n/**\n * Props for the Autocomplete component.\n * Supports both single and multiple selection modes with optional search functionality.\n */\nexport interface AutocompleteProps\n extends Omit<TextFieldProps, 'endAdornment' | 'multiline' | 'onChange' | 'options' | 'startAdornment'> {\n /** Shows a loading indicator inside the input (e.g., while fetching). */\n loading?: boolean;\n /** Enables selection of multiple options and shows checkboxes and tags for selected values. */\n multiple?: MuiCustomAutocompleteProps['multiple'];\n /** Called when the selected value(s) change. */\n onChange: MuiCustomAutocompleteProps['onChange'];\n /** Called when the input text changes (typing or programmatic updates). */\n onInputChange?: MuiCustomAutocompleteProps['onInputChange'];\n /** Options to display in the dropdown list. */\n options: AutocompleteOption[];\n /** UI and accessibility labels used by the component. */\n translations: {\n /** Aria-label for the clear button. */\n clearTextAriaLabel: string;\n /** Aria-label for the dismiss tag button. */\n dismissTagAriaLabel: string;\n /** Text shown while loading options. */\n loadingText: string;\n /** Text shown when there are no options to display. */\n noOptionsText: string;\n /** Aria-label for the popup indicator button. */\n openPopupAriaLabel: string;\n };\n /** Visual behavior: 'search' shows a leading search icon; 'combobox' shows a popup button. */\n type?: 'combobox' | 'search';\n /** Controlled value (single option, array for multiple, or null). */\n value: MuiCustomAutocompleteProps['value'];\n}\n\n// Bind flags to MuiAutocomplete, see MuiCustomAutocompleteProps for more details\nconst MuiCustomAutocomplete = MuiAutocomplete<AutocompleteOption, boolean, boolean, boolean>;\nconst StyledAutocomplete = styled(MuiCustomAutocomplete, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n width: fullWidth ? '100%' : 'min(364px, 100%)',\n}));\n\nconst StyledAdornment = styled(Box, {\n shouldForwardProp: (prop) => !['clickable', 'disabled', 'placement'].includes(prop as string),\n})<{ clickable?: boolean; error?: boolean; disabled?: boolean; placement: 'end' | 'middle' | 'start' }>(\n ({ theme, clickable = false, disabled = false, placement }) => ({\n alignItems: 'center',\n cursor: clickable ? (disabled ? 'not-allowed' : 'pointer') : 'default',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n pointerEvents: clickable ? 'auto' : 'none',\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n }),\n);\n\nconst StyledLoadingSpinnerContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'placement',\n})<{ placement?: 'end' | 'middle' | 'start' }>(({ theme, placement }) => ({\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n}));\n\n/**\n * A customizable Autocomplete component supporting search and combobox modes.\n * Supports single and multiple selection with dynamic tag rendering and optional loading states.\n *\n * @param props - The component props\n * @returns The rendered Autocomplete component\n */\nexport const Autocomplete = ({\n className,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n loading = false,\n multiple = false,\n placeholder,\n onChange,\n onInputChange,\n options = [],\n required = false,\n translations,\n type = 'search',\n value,\n}: AutocompleteProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const isSearch = type === 'search';\n const isCombobox = type === 'combobox';\n\n const { rootRef, limitTags } = useDynamicLimitTags({\n chipMax: 130,\n gap: 4,\n horizontalPadding: 32,\n reservedPx: isSearch ? 120 : 90,\n });\n\n // Close the dropdown (if open) when the component is dynamically disabled\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n /**\n * Toggles or sets the dropdown open state.\n * Does nothing when the component is disabled.\n *\n * @param open - Optional boolean to explicitly set open state; if undefined, toggles current state\n */\n const toggleOpen = (open?: boolean): void => {\n if (disabled) {\n return;\n }\n\n if (open !== undefined) {\n setIsOpen(open);\n return;\n }\n\n setIsOpen((prevOpen) => !prevOpen);\n };\n\n const renderSearchIcon = (): JSX.Element => {\n return (\n <StyledAdornment disabled={disabled} placement=\"start\">\n <SearchIcon aria-hidden=\"true\" />\n </StyledAdornment>\n );\n };\n\n const renderPopupIcon = (): JSX.Element => {\n return (\n <StyledAdornment clickable disabled={disabled} placement=\"end\">\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledAdornment>\n );\n };\n\n const renderLoadingSpinner = (): JSX.Element => {\n return (\n <StyledLoadingSpinnerContainer placement={isSearch ? 'end' : 'middle'}>\n <CircularProgress size=\"small\" />\n </StyledLoadingSpinnerContainer>\n );\n };\n\n const renderInputField = (params: AutocompleteRenderInputParams): JSX.Element => (\n <TextField\n disabled={disabled}\n errorText={errorText}\n fdKey={fdKey}\n fullWidth={fullWidth}\n helperText={helperText}\n label={label}\n placeholder={placeholder}\n required={required}\n slotProps={{\n input: {\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? renderLoadingSpinner() : null}\n {params.InputProps.endAdornment}\n </>\n ),\n startAdornment: (\n <>\n {isSearch ? renderSearchIcon() : null}\n {params.InputProps.startAdornment}\n </>\n ),\n },\n htmlInput: {\n ...params.inputProps,\n },\n }}\n />\n );\n\n const renderMenuOption = (\n optionProps: React.HTMLAttributes<HTMLLIElement> & { key: React.Key },\n option: AutocompleteOption,\n state: AutocompleteRenderOptionState,\n ): JSX.Element => {\n const { key, onClick, ...rest } = optionProps;\n\n if (multiple) {\n return (\n <MenuItem\n {...rest}\n key={key}\n checked={state.selected}\n label={option.label}\n onCheckedChange={(_checked, e) => {\n onClick?.(e as React.MouseEvent<HTMLLIElement, MouseEvent>);\n }}\n type=\"checkbox\"\n />\n );\n }\n\n return (\n <MenuItem\n {...rest}\n key={key}\n label={option.label}\n onClick={onClick}\n selected={state.selected}\n type=\"text\"\n />\n );\n };\n\n const renderSelectedTags = (\n selected: AutocompleteOption[],\n getTagProps: AutocompleteRenderGetTagProps,\n ): React.ReactNode =>\n selected.map((tag, index) => {\n const { key, onDelete, ...tagProps } = getTagProps({ index });\n const rawLabel = typeof tag === 'string' ? tag : tag.label;\n const label = truncateWithEllipsis(rawLabel, 13, { includeEllipsisInLimit: true });\n const isTruncated = label.endsWith('...');\n const tagKey = key ?? `tag-${typeof tag === 'string' ? tag : tag.value}`;\n\n if (isTruncated) {\n return (\n <MuiTooltip key={tagKey} arrow placement=\"top\" title={rawLabel}>\n <span {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n </MuiTooltip>\n );\n }\n\n return (\n <span key={tagKey} {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n );\n });\n\n const handlePopupIndicatorClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n toggleOpen();\n };\n\n const handleChange = (\n event: React.SyntheticEvent,\n value: AutocompleteValue<AutocompleteOption, boolean, boolean, boolean>,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<AutocompleteOption>,\n ): void => {\n if (!onChange) {\n return;\n }\n onChange(event, value, reason, details);\n };\n\n const handleInputChange = (\n event: React.SyntheticEvent,\n value: string,\n reason: AutocompleteInputChangeReason,\n ): void => {\n if (!onInputChange) {\n return;\n }\n onInputChange(event, value, reason);\n };\n\n /**\n * Returns all options without filtering for search mode.\n * Disables MUI's built-in client-side filtering when type is 'search'.\n */\n const disableClientFilter = (opts: AutocompleteOption[]): AutocompleteOption[] => opts;\n\n /**\n * Extracts the display label from an option.\n * Supports both object options and freeSolo string values.\n */\n const getOptionLabel = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : option.label;\n };\n\n /**\n * Provides a stable unique key for each option to optimize DOM reconciliation.\n */\n const getOptionKey = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : String(option.value);\n };\n\n /**\n * Determines equality between an option and the current value.\n * Handles both freeSolo string values and object options to prevent selection glitches.\n */\n const getIsOptionEqualToValue = (a: AutocompleteOption, b: AutocompleteOption): boolean => {\n if (b === null || b === undefined) {\n return false;\n }\n return typeof b === 'string' ? a.label === b || String(a.value) === b : a.value === b.value;\n };\n\n /**\n * Normalizes the value prop for MUI Autocomplete.\n * Handles both single and multiple selection modes, ensuring the value\n * format matches the mode (array for multiple, single value/null for single).\n *\n * @returns Normalized value compatible with MUI Autocomplete\n */\n const getValue = (): AutocompleteProps['value'] => {\n // Multiple value selection\n if (multiple) {\n if (Array.isArray(value)) return value;\n if (value === null || value === undefined) return [];\n return [value as AutocompleteOption];\n }\n\n // Single value selection\n if (Array.isArray(value)) return value.length > 0 ? value[0] : null;\n return value ?? null;\n };\n\n return (\n <StyledAutocomplete\n ref={rootRef}\n className={className}\n clearIcon={<CancelIcon size=\"md\" />}\n clearText={translations.clearTextAriaLabel}\n disableClearable={disabled || loading}\n disableCloseOnSelect={multiple}\n disabled={disabled}\n filterOptions={isSearch ? disableClientFilter : undefined}\n forcePopupIcon={isCombobox}\n freeSolo={isSearch}\n fullWidth={fullWidth}\n getOptionKey={getOptionKey}\n getOptionLabel={getOptionLabel}\n isOptionEqualToValue={getIsOptionEqualToValue}\n limitTags={limitTags}\n loading={loading}\n loadingText={translations.loadingText}\n multiple={multiple}\n noOptionsText={translations.noOptionsText}\n onChange={handleChange}\n onClose={() => toggleOpen(false)}\n onInputChange={handleInputChange}\n onOpen={() => toggleOpen(true)}\n open={isOpen}\n openText={translations.openPopupAriaLabel}\n options={options}\n popupIcon={isSearch ? null : renderPopupIcon()}\n renderInput={renderInputField}\n renderOption={renderMenuOption}\n renderTags={renderSelectedTags}\n slotProps={{\n popupIndicator: {\n onClick: handlePopupIndicatorClick,\n },\n }}\n value={getValue()}\n />\n );\n};\n\nexport default Autocomplete;\n"],"names":["MuiCustomAutocomplete","StyledAutocomplete","styled","shouldForwardProp","prop","fullWidth","width","StyledAdornment","Box","includes","theme","clickable","disabled","placement","alignItems","cursor","display","justifyContent","padding","pointerEvents","paddingRight","spacing","color","palette","semantic","icon","StyledLoadingSpinnerContainer","Autocomplete","className","errorText","fdKey","helperText","label","loading","multiple","placeholder","onChange","onInputChange","options","required","translations","type","value","isOpen","setIsOpen","useState","isSearch","isCombobox","rootRef","limitTags","useDynamicLimitTags","chipMax","gap","horizontalPadding","reservedPx","useEffect","toggleOpen","open","undefined","prevOpen","_jsx","ref","clearIcon","CancelIcon","size","clearText","clearTextAriaLabel","disableClearable","disableCloseOnSelect","filterOptions","opts","forcePopupIcon","freeSolo","getOptionKey","option","String","getOptionLabel","isOptionEqualToValue","a","b","loadingText","noOptionsText","event","reason","details","onClose","onOpen","openText","openPopupAriaLabel","popupIcon","children","ArrowUp01Icon","ArrowDown01Icon","renderInput","params","TextField","slotProps","input","InputProps","endAdornment","_jsxs","_Fragment","CircularProgress","startAdornment","SearchIcon","htmlInput","inputProps","renderOption","optionProps","state","key","onClick","rest","_createElement","MenuItem","checked","selected","onCheckedChange","_checked","e","renderTags","getTagProps","map","tag","index","onDelete","tagProps","rawLabel","truncateWithEllipsis","includeEllipsisInLimit","isTruncated","endsWith","tagKey","MuiTooltip","arrow","title","Tag","dismissAriaLabel","dismissTagAriaLabel","onDismiss","popupIndicator","stopPropagation","Array","isArray","length"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/Autocomplete/index.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport MuiAutocomplete, {\n type AutocompleteChangeDetails,\n type AutocompleteChangeReason,\n type AutocompleteInputChangeReason,\n type AutocompleteProps as MuiAutocompleteProps,\n type AutocompleteRenderGetTagProps,\n type AutocompleteRenderInputParams,\n type AutocompleteRenderOptionState,\n type AutocompleteValue,\n} from '@mui/material/Autocomplete';\nimport Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\n\nimport Tooltip from '@fd/components/molecules/Tooltip';\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelIcon from '@fd/icons/Cancel';\nimport SearchIcon from '@fd/icons/Search';\nimport { truncateWithEllipsis } from '@fd/utilities/stringUtilities';\n\nimport CircularProgress from '../../atoms/CircularProgress';\nimport MenuItem from '../../atoms/MenuItem';\nimport Tag from '../../atoms/Tag';\nimport TextField, { type TextFieldProps } from '../../atoms/TextField';\nimport { useDynamicLimitTags } from './hooks/useDynamicLimitTags';\n\n// Bind flags to MuiAutocomplete\ntype MuiCustomAutocompleteProps<\n M extends boolean = boolean, // Multiple\n DC extends boolean = boolean, // DisableClearable\n FS extends boolean = boolean, // FreeSolo\n> = MuiAutocompleteProps<AutocompleteOption, M, DC, FS>;\n\n/**\n * Represents an option in the Autocomplete dropdown.\n */\nexport interface AutocompleteOption {\n /** The label to display in the dropdown option. */\n label: string;\n /** The value to store in the dropdown option. */\n value: number | string;\n}\n\n/**\n * Props for the Autocomplete component.\n * Supports both single and multiple selection modes with optional search functionality.\n */\nexport interface AutocompleteProps\n extends Omit<TextFieldProps, 'endAdornment' | 'multiline' | 'onChange' | 'options' | 'startAdornment'> {\n /** Shows a loading indicator inside the input (e.g., while fetching). */\n loading?: boolean;\n /** Enables selection of multiple options and shows checkboxes and tags for selected values. */\n multiple?: MuiCustomAutocompleteProps['multiple'];\n /** Called when the selected value(s) change. */\n onChange: MuiCustomAutocompleteProps['onChange'];\n /** Called when the input text changes (typing or programmatic updates). */\n onInputChange?: MuiCustomAutocompleteProps['onInputChange'];\n /** Options to display in the dropdown list. */\n options: AutocompleteOption[];\n /** UI and accessibility labels used by the component. */\n translations: {\n /** Aria-label for the clear button. */\n clearTextAriaLabel: string;\n /** Aria-label for the dismiss tag button. */\n dismissTagAriaLabel: string;\n /** Text shown while loading options. */\n loadingText: string;\n /** Text shown when there are no options to display. */\n noOptionsText: string;\n /** Aria-label for the popup indicator button. */\n openPopupAriaLabel: string;\n };\n /** Visual behavior: 'search' shows a leading search icon; 'combobox' shows a popup button. */\n type?: 'combobox' | 'search';\n /** Controlled value (single option, array for multiple, or null). */\n value: MuiCustomAutocompleteProps['value'];\n}\n\n// Bind flags to MuiAutocomplete, see MuiCustomAutocompleteProps for more details\nconst MuiCustomAutocomplete = MuiAutocomplete<AutocompleteOption, boolean, boolean, boolean>;\nconst StyledAutocomplete = styled(MuiCustomAutocomplete, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n width: fullWidth ? '100%' : 'min(364px, 100%)',\n}));\n\nconst StyledAdornment = styled(Box, {\n shouldForwardProp: (prop) => !['clickable', 'disabled', 'placement'].includes(prop as string),\n})<{ clickable?: boolean; error?: boolean; disabled?: boolean; placement: 'end' | 'middle' | 'start' }>(\n ({ theme, clickable = false, disabled = false, placement }) => ({\n alignItems: 'center',\n cursor: clickable ? (disabled ? 'not-allowed' : 'pointer') : 'default',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n pointerEvents: clickable ? 'auto' : 'none',\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n }),\n);\n\nconst StyledLoadingSpinnerContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'placement',\n})<{ placement?: 'end' | 'middle' | 'start' }>(({ theme, placement }) => ({\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n}));\n\n/**\n * A customizable Autocomplete component supporting search and combobox modes.\n * Supports single and multiple selection with dynamic tag rendering and optional loading states.\n *\n * @param props - The component props\n * @returns The rendered Autocomplete component\n */\nexport const Autocomplete = ({\n className,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n loading = false,\n multiple = false,\n placeholder,\n onChange,\n onInputChange,\n options = [],\n required = false,\n translations,\n type = 'search',\n value,\n}: AutocompleteProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const isSearch = type === 'search';\n const isCombobox = type === 'combobox';\n\n const { rootRef, limitTags } = useDynamicLimitTags({\n chipMax: 130,\n gap: 4,\n horizontalPadding: 32,\n reservedPx: isSearch ? 120 : 90,\n });\n\n // Close the dropdown (if open) when the component is dynamically disabled\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n /**\n * Toggles or sets the dropdown open state.\n * Does nothing when the component is disabled.\n *\n * @param open - Optional boolean to explicitly set open state; if undefined, toggles current state\n */\n const toggleOpen = (open?: boolean): void => {\n if (disabled) {\n return;\n }\n\n if (open !== undefined) {\n setIsOpen(open);\n return;\n }\n\n setIsOpen((prevOpen) => !prevOpen);\n };\n\n const renderSearchIcon = (): JSX.Element => {\n return (\n <StyledAdornment disabled={disabled} placement=\"start\">\n <SearchIcon aria-hidden=\"true\" />\n </StyledAdornment>\n );\n };\n\n const renderPopupIcon = (): JSX.Element => {\n return (\n <StyledAdornment clickable disabled={disabled} placement=\"end\">\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledAdornment>\n );\n };\n\n const renderLoadingSpinner = (): JSX.Element => {\n return (\n <StyledLoadingSpinnerContainer placement={isSearch ? 'end' : 'middle'}>\n <CircularProgress size=\"small\" />\n </StyledLoadingSpinnerContainer>\n );\n };\n\n const renderInputField = (params: AutocompleteRenderInputParams): JSX.Element => (\n <TextField\n disabled={disabled}\n errorText={errorText}\n fdKey={fdKey}\n fullWidth={fullWidth}\n helperText={helperText}\n label={label}\n placeholder={placeholder}\n required={required}\n slotProps={{\n input: {\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? renderLoadingSpinner() : null}\n {params.InputProps.endAdornment}\n </>\n ),\n startAdornment: (\n <>\n {isSearch ? renderSearchIcon() : null}\n {params.InputProps.startAdornment}\n </>\n ),\n },\n htmlInput: {\n ...params.inputProps,\n },\n }}\n />\n );\n\n const renderMenuOption = (\n optionProps: React.HTMLAttributes<HTMLLIElement> & { key: React.Key },\n option: AutocompleteOption,\n state: AutocompleteRenderOptionState,\n ): JSX.Element => {\n const { key, onClick, ...rest } = optionProps;\n\n if (multiple) {\n return (\n <MenuItem\n {...rest}\n key={key}\n checked={state.selected}\n label={option.label}\n onCheckedChange={(_checked, e) => {\n onClick?.(e as React.MouseEvent<HTMLLIElement, MouseEvent>);\n }}\n type=\"checkbox\"\n />\n );\n }\n\n return (\n <MenuItem\n {...rest}\n key={key}\n label={option.label}\n onClick={onClick}\n selected={state.selected}\n type=\"text\"\n />\n );\n };\n\n const renderSelectedTags = (\n selected: AutocompleteOption[],\n getTagProps: AutocompleteRenderGetTagProps,\n ): React.ReactNode =>\n selected.map((tag, index) => {\n const { key, onDelete, ...tagProps } = getTagProps({ index });\n const rawLabel = typeof tag === 'string' ? tag : tag.label;\n const label = truncateWithEllipsis(rawLabel, 13, { includeEllipsisInLimit: true });\n const isTruncated = label.endsWith('...');\n const tagKey = key ?? `tag-${typeof tag === 'string' ? tag : tag.value}`;\n\n if (isTruncated) {\n return (\n <Tooltip key={tagKey} title={rawLabel}>\n <span {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n </Tooltip>\n );\n }\n\n return (\n <span key={tagKey} {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n );\n });\n\n const handlePopupIndicatorClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n toggleOpen();\n };\n\n const handleChange = (\n event: React.SyntheticEvent,\n value: AutocompleteValue<AutocompleteOption, boolean, boolean, boolean>,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<AutocompleteOption>,\n ): void => {\n if (!onChange) {\n return;\n }\n onChange(event, value, reason, details);\n };\n\n const handleInputChange = (\n event: React.SyntheticEvent,\n value: string,\n reason: AutocompleteInputChangeReason,\n ): void => {\n if (!onInputChange) {\n return;\n }\n onInputChange(event, value, reason);\n };\n\n /**\n * Returns all options without filtering for search mode.\n * Disables MUI's built-in client-side filtering when type is 'search'.\n */\n const disableClientFilter = (opts: AutocompleteOption[]): AutocompleteOption[] => opts;\n\n /**\n * Extracts the display label from an option.\n * Supports both object options and freeSolo string values.\n */\n const getOptionLabel = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : option.label;\n };\n\n /**\n * Provides a stable unique key for each option to optimize DOM reconciliation.\n */\n const getOptionKey = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : String(option.value);\n };\n\n /**\n * Determines equality between an option and the current value.\n * Handles both freeSolo string values and object options to prevent selection glitches.\n */\n const getIsOptionEqualToValue = (a: AutocompleteOption, b: AutocompleteOption): boolean => {\n if (b === null || b === undefined) {\n return false;\n }\n return typeof b === 'string' ? a.label === b || String(a.value) === b : a.value === b.value;\n };\n\n /**\n * Normalizes the value prop for MUI Autocomplete.\n * Handles both single and multiple selection modes, ensuring the value\n * format matches the mode (array for multiple, single value/null for single).\n *\n * @returns Normalized value compatible with MUI Autocomplete\n */\n const getValue = (): AutocompleteProps['value'] => {\n // Multiple value selection\n if (multiple) {\n if (Array.isArray(value)) return value;\n if (value === null || value === undefined) return [];\n return [value as AutocompleteOption];\n }\n\n // Single value selection\n if (Array.isArray(value)) return value.length > 0 ? value[0] : null;\n return value ?? null;\n };\n\n return (\n <StyledAutocomplete\n ref={rootRef}\n className={className}\n clearIcon={<CancelIcon size=\"md\" />}\n clearText={translations.clearTextAriaLabel}\n disableClearable={disabled || loading}\n disableCloseOnSelect={multiple}\n disabled={disabled}\n filterOptions={isSearch ? disableClientFilter : undefined}\n forcePopupIcon={isCombobox}\n freeSolo={isSearch}\n fullWidth={fullWidth}\n getOptionKey={getOptionKey}\n getOptionLabel={getOptionLabel}\n isOptionEqualToValue={getIsOptionEqualToValue}\n limitTags={limitTags}\n loading={loading}\n loadingText={translations.loadingText}\n multiple={multiple}\n noOptionsText={translations.noOptionsText}\n onChange={handleChange}\n onClose={() => toggleOpen(false)}\n onInputChange={handleInputChange}\n onOpen={() => toggleOpen(true)}\n open={isOpen}\n openText={translations.openPopupAriaLabel}\n options={options}\n popupIcon={isSearch ? null : renderPopupIcon()}\n renderInput={renderInputField}\n renderOption={renderMenuOption}\n renderTags={renderSelectedTags}\n slotProps={{\n popupIndicator: {\n onClick: handlePopupIndicatorClick,\n },\n }}\n value={getValue()}\n />\n );\n};\n\nexport default Autocomplete;\n"],"names":["MuiCustomAutocomplete","StyledAutocomplete","styled","shouldForwardProp","prop","fullWidth","width","StyledAdornment","Box","includes","theme","clickable","disabled","placement","alignItems","cursor","display","justifyContent","padding","pointerEvents","paddingRight","spacing","color","palette","semantic","icon","StyledLoadingSpinnerContainer","Autocomplete","className","errorText","fdKey","helperText","label","loading","multiple","placeholder","onChange","onInputChange","options","required","translations","type","value","isOpen","setIsOpen","useState","isSearch","isCombobox","rootRef","limitTags","useDynamicLimitTags","chipMax","gap","horizontalPadding","reservedPx","useEffect","toggleOpen","open","undefined","prevOpen","_jsx","ref","clearIcon","CancelIcon","size","clearText","clearTextAriaLabel","disableClearable","disableCloseOnSelect","filterOptions","opts","forcePopupIcon","freeSolo","getOptionKey","option","String","getOptionLabel","isOptionEqualToValue","a","b","loadingText","noOptionsText","event","reason","details","onClose","onOpen","openText","openPopupAriaLabel","popupIcon","children","ArrowUp01Icon","ArrowDown01Icon","renderInput","params","TextField","slotProps","input","InputProps","endAdornment","_jsxs","_Fragment","CircularProgress","startAdornment","SearchIcon","htmlInput","inputProps","renderOption","optionProps","state","key","onClick","rest","_createElement","MenuItem","checked","selected","onCheckedChange","_checked","e","renderTags","getTagProps","map","tag","index","onDelete","tagProps","rawLabel","truncateWithEllipsis","includeEllipsisInLimit","isTruncated","endsWith","tagKey","Tooltip","title","Tag","dismissAriaLabel","dismissTagAriaLabel","onDismiss","popupIndicator","stopPropagation","Array","isArray","length"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{useState as e,useEffect as i,createElement as t}from"react";import{jsx as l,jsxs as n,Fragment as o}from"react/jsx-runtime";import r from"@mui/material/Autocomplete";import a from"@mui/material/Box";import{styled as s}from"@mui/material/styles";import d from"@mui/material/Tooltip";import p from"../../../icons/ArrowDown01/index.js";import m from"../../../icons/ArrowUp01/index.js";import c from"../../../icons/Cancel/index.js";import u from"../../../icons/Search/index.js";import{truncateWithEllipsis as g}from"../../../utilities/stringUtilities.js";import{CircularProgress as h}from"../../atoms/CircularProgress/index.js";import{MenuItem as f}from"../../atoms/MenuItem/index.js";import{Tag as b}from"../../atoms/Tag/index.js";import{TextField as x}from"../../atoms/TextField/index.js";import{useDynamicLimitTags as y}from"./hooks/useDynamicLimitTags.js";const T=s(r,{shouldForwardProp:e=>"fullWidth"!==e})((({fullWidth:e=!1})=>({width:e?"100%":"min(364px, 100%)"}))),A=s(a,{shouldForwardProp:e=>!["clickable","disabled","placement"].includes(e)})((({theme:e,clickable:i=!1,disabled:t=!1,placement:l})=>({alignItems:"center",cursor:i?t?"not-allowed":"pointer":"default",display:"flex",justifyContent:"center",padding:0,pointerEvents:i?"auto":"none",..."start"===l&&{paddingRight:e.spacing(1)},..."middle"===l&&{padding:e.spacing(0,1)},"& svg":{color:t?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),C=s(a,{shouldForwardProp:e=>"placement"!==e})((({theme:e,placement:i})=>({alignItems:"center",display:"flex",justifyContent:"center",padding:0,..."start"===i&&{paddingRight:e.spacing(1)},..."middle"===i&&{padding:e.spacing(0,1)}}))),I=({className:r,disabled:a=!1,errorText:s,fdKey:I,fullWidth:P=!1,helperText:k,label:j,loading:v=!1,multiple:w=!1,placeholder:L,onChange:O,onInputChange:W,options:D=[],required:S=!1,translations:F,type:q="search",value:z})=>{const[E,K]=e(!1),R="search"===q,M="combobox"===q,{rootRef:N,limitTags:U}=y({chipMax:130,gap:4,horizontalPadding:32,reservedPx:R?120:90});i((()=>{a&&K(!1)}),[a]);const B=e=>{a||K(void 0===e?e=>!e:e)};return l(T,{ref:N,className:r,clearIcon:l(c,{size:"md"}),clearText:F.clearTextAriaLabel,disableClearable:a||v,disableCloseOnSelect:w,disabled:a,filterOptions:R?e=>e:void 0,forcePopupIcon:M,freeSolo:R,fullWidth:P,getOptionKey:e=>"string"==typeof e?e:String(e.value),getOptionLabel:e=>"string"==typeof e?e:e.label,isOptionEqualToValue:(e,i)=>null!=i&&("string"==typeof i?e.label===i||String(e.value)===i:e.value===i.value),limitTags:U,loading:v,loadingText:F.loadingText,multiple:w,noOptionsText:F.noOptionsText,onChange:(e,i,t,l)=>{O&&O(e,i,t,l)},onClose:()=>B(!1),onInputChange:(e,i,t)=>{W&&W(e,i,t)},onOpen:()=>B(!0),open:E,openText:F.openPopupAriaLabel,options:D,popupIcon:R?null:l(A,{clickable:!0,disabled:a,placement:"end",children:l(E?m:p,{})}),renderInput:e=>l(x,{disabled:a,errorText:s,fdKey:I,fullWidth:P,helperText:k,label:j,placeholder:L,required:S,slotProps:{input:{...e.InputProps,endAdornment:n(o,{children:[v?l(C,{placement:R?"end":"middle",children:l(h,{size:"small"})}):null,e.InputProps.endAdornment]}),startAdornment:n(o,{children:[R?l(A,{disabled:a,placement:"start",children:l(u,{"aria-hidden":"true"})}):null,e.InputProps.startAdornment]})},htmlInput:{...e.inputProps}}}),renderOption:(e,i,l)=>{const{key:n,onClick:o,...r}=e;return t(f,w?{...r,key:n,checked:l.selected,label:i.label,onCheckedChange:(e,i)=>{o?.(i)},type:"checkbox"}:{...r,key:n,label:i.label,onClick:o,selected:l.selected,type:"text"})},renderTags:(e,i)=>e.map(((e,t)=>{const{key:n,onDelete:o,...r}=i({index:t}),a="string"==typeof e?e:e.label,s=g(a,13,{includeEllipsisInLimit:!0}),p=s.endsWith("..."),m=n??`tag-${"string"==typeof e?e:e.value}`;return p?l(d,{arrow:!0,placement:"top",title:a,children:l("span",{...r,children:l(b,{dismissAriaLabel:F.dismissTagAriaLabel,label:s,onDismiss:o})})},m):l("span",{...r,children:l(b,{dismissAriaLabel:F.dismissTagAriaLabel,label:s,onDismiss:o})},m)})),slotProps:{popupIndicator:{onClick:e=>{a||(e.stopPropagation(),B())}}},value:w?Array.isArray(z)?z:null==z?[]:[z]:Array.isArray(z)?z.length>0?z[0]:null:z??null})};export{I as Autocomplete,I as default};
1
+ import{useState as e,useEffect as i,createElement as t}from"react";import{jsx as l,jsxs as n,Fragment as o}from"react/jsx-runtime";import r from"@mui/material/Autocomplete";import a from"@mui/material/Box";import{styled as s}from"@mui/material/styles";import{Tooltip as d}from"../Tooltip/index.js";import p from"../../../icons/ArrowDown01/index.js";import m from"../../../icons/ArrowUp01/index.js";import c from"../../../icons/Cancel/index.js";import u from"../../../icons/Search/index.js";import{truncateWithEllipsis as g}from"../../../utilities/stringUtilities.js";import{CircularProgress as h}from"../../atoms/CircularProgress/index.js";import{MenuItem as f}from"../../atoms/MenuItem/index.js";import{Tag as b}from"../../atoms/Tag/index.js";import{TextField as x}from"../../atoms/TextField/index.js";import{useDynamicLimitTags as y}from"./hooks/useDynamicLimitTags.js";const T=s(r,{shouldForwardProp:e=>"fullWidth"!==e})((({fullWidth:e=!1})=>({width:e?"100%":"min(364px, 100%)"}))),A=s(a,{shouldForwardProp:e=>!["clickable","disabled","placement"].includes(e)})((({theme:e,clickable:i=!1,disabled:t=!1,placement:l})=>({alignItems:"center",cursor:i?t?"not-allowed":"pointer":"default",display:"flex",justifyContent:"center",padding:0,pointerEvents:i?"auto":"none",..."start"===l&&{paddingRight:e.spacing(1)},..."middle"===l&&{padding:e.spacing(0,1)},"& svg":{color:t?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),C=s(a,{shouldForwardProp:e=>"placement"!==e})((({theme:e,placement:i})=>({alignItems:"center",display:"flex",justifyContent:"center",padding:0,..."start"===i&&{paddingRight:e.spacing(1)},..."middle"===i&&{padding:e.spacing(0,1)}}))),I=({className:r,disabled:a=!1,errorText:s,fdKey:I,fullWidth:P=!1,helperText:j,label:k,loading:v=!1,multiple:L=!1,placeholder:O,onChange:w,onInputChange:W,options:D=[],required:S=!1,translations:F,type:q="search",value:z})=>{const[E,K]=e(!1),R="search"===q,M="combobox"===q,{rootRef:N,limitTags:U}=y({chipMax:130,gap:4,horizontalPadding:32,reservedPx:R?120:90});i((()=>{a&&K(!1)}),[a]);const B=e=>{a||K(void 0===e?e=>!e:e)};return l(T,{ref:N,className:r,clearIcon:l(c,{size:"md"}),clearText:F.clearTextAriaLabel,disableClearable:a||v,disableCloseOnSelect:L,disabled:a,filterOptions:R?e=>e:void 0,forcePopupIcon:M,freeSolo:R,fullWidth:P,getOptionKey:e=>"string"==typeof e?e:String(e.value),getOptionLabel:e=>"string"==typeof e?e:e.label,isOptionEqualToValue:(e,i)=>null!=i&&("string"==typeof i?e.label===i||String(e.value)===i:e.value===i.value),limitTags:U,loading:v,loadingText:F.loadingText,multiple:L,noOptionsText:F.noOptionsText,onChange:(e,i,t,l)=>{w&&w(e,i,t,l)},onClose:()=>B(!1),onInputChange:(e,i,t)=>{W&&W(e,i,t)},onOpen:()=>B(!0),open:E,openText:F.openPopupAriaLabel,options:D,popupIcon:R?null:l(A,{clickable:!0,disabled:a,placement:"end",children:l(E?m:p,{})}),renderInput:e=>l(x,{disabled:a,errorText:s,fdKey:I,fullWidth:P,helperText:j,label:k,placeholder:O,required:S,slotProps:{input:{...e.InputProps,endAdornment:n(o,{children:[v?l(C,{placement:R?"end":"middle",children:l(h,{size:"small"})}):null,e.InputProps.endAdornment]}),startAdornment:n(o,{children:[R?l(A,{disabled:a,placement:"start",children:l(u,{"aria-hidden":"true"})}):null,e.InputProps.startAdornment]})},htmlInput:{...e.inputProps}}}),renderOption:(e,i,l)=>{const{key:n,onClick:o,...r}=e;return t(f,L?{...r,key:n,checked:l.selected,label:i.label,onCheckedChange:(e,i)=>{o?.(i)},type:"checkbox"}:{...r,key:n,label:i.label,onClick:o,selected:l.selected,type:"text"})},renderTags:(e,i)=>e.map(((e,t)=>{const{key:n,onDelete:o,...r}=i({index:t}),a="string"==typeof e?e:e.label,s=g(a,13,{includeEllipsisInLimit:!0}),p=s.endsWith("..."),m=n??`tag-${"string"==typeof e?e:e.value}`;return p?l(d,{title:a,children:l("span",{...r,children:l(b,{dismissAriaLabel:F.dismissTagAriaLabel,label:s,onDismiss:o})})},m):l("span",{...r,children:l(b,{dismissAriaLabel:F.dismissTagAriaLabel,label:s,onDismiss:o})},m)})),slotProps:{popupIndicator:{onClick:e=>{a||(e.stopPropagation(),B())}}},value:L?Array.isArray(z)?z:null==z?[]:[z]:Array.isArray(z)?z.length>0?z[0]:null:z??null})};export{I as Autocomplete,I as default};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/molecules/Autocomplete/index.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport MuiAutocomplete, {\n type AutocompleteChangeDetails,\n type AutocompleteChangeReason,\n type AutocompleteInputChangeReason,\n type AutocompleteProps as MuiAutocompleteProps,\n type AutocompleteRenderGetTagProps,\n type AutocompleteRenderInputParams,\n type AutocompleteRenderOptionState,\n type AutocompleteValue,\n} from '@mui/material/Autocomplete';\nimport Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\n// TODO: Replace with our own Tooltip component\nimport MuiTooltip from '@mui/material/Tooltip';\n\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelIcon from '@fd/icons/Cancel';\nimport SearchIcon from '@fd/icons/Search';\nimport { truncateWithEllipsis } from '@fd/utilities/stringUtilities';\n\nimport CircularProgress from '../../atoms/CircularProgress';\nimport MenuItem from '../../atoms/MenuItem';\nimport Tag from '../../atoms/Tag';\nimport TextField, { type TextFieldProps } from '../../atoms/TextField';\nimport { useDynamicLimitTags } from './hooks/useDynamicLimitTags';\n\n// Bind flags to MuiAutocomplete\ntype MuiCustomAutocompleteProps<\n M extends boolean = boolean, // Multiple\n DC extends boolean = boolean, // DisableClearable\n FS extends boolean = boolean, // FreeSolo\n> = MuiAutocompleteProps<AutocompleteOption, M, DC, FS>;\n\n/**\n * Represents an option in the Autocomplete dropdown.\n */\nexport interface AutocompleteOption {\n /** The label to display in the dropdown option. */\n label: string;\n /** The value to store in the dropdown option. */\n value: number | string;\n}\n\n/**\n * Props for the Autocomplete component.\n * Supports both single and multiple selection modes with optional search functionality.\n */\nexport interface AutocompleteProps\n extends Omit<TextFieldProps, 'endAdornment' | 'multiline' | 'onChange' | 'options' | 'startAdornment'> {\n /** Shows a loading indicator inside the input (e.g., while fetching). */\n loading?: boolean;\n /** Enables selection of multiple options and shows checkboxes and tags for selected values. */\n multiple?: MuiCustomAutocompleteProps['multiple'];\n /** Called when the selected value(s) change. */\n onChange: MuiCustomAutocompleteProps['onChange'];\n /** Called when the input text changes (typing or programmatic updates). */\n onInputChange?: MuiCustomAutocompleteProps['onInputChange'];\n /** Options to display in the dropdown list. */\n options: AutocompleteOption[];\n /** UI and accessibility labels used by the component. */\n translations: {\n /** Aria-label for the clear button. */\n clearTextAriaLabel: string;\n /** Aria-label for the dismiss tag button. */\n dismissTagAriaLabel: string;\n /** Text shown while loading options. */\n loadingText: string;\n /** Text shown when there are no options to display. */\n noOptionsText: string;\n /** Aria-label for the popup indicator button. */\n openPopupAriaLabel: string;\n };\n /** Visual behavior: 'search' shows a leading search icon; 'combobox' shows a popup button. */\n type?: 'combobox' | 'search';\n /** Controlled value (single option, array for multiple, or null). */\n value: MuiCustomAutocompleteProps['value'];\n}\n\n// Bind flags to MuiAutocomplete, see MuiCustomAutocompleteProps for more details\nconst MuiCustomAutocomplete = MuiAutocomplete<AutocompleteOption, boolean, boolean, boolean>;\nconst StyledAutocomplete = styled(MuiCustomAutocomplete, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n width: fullWidth ? '100%' : 'min(364px, 100%)',\n}));\n\nconst StyledAdornment = styled(Box, {\n shouldForwardProp: (prop) => !['clickable', 'disabled', 'placement'].includes(prop as string),\n})<{ clickable?: boolean; error?: boolean; disabled?: boolean; placement: 'end' | 'middle' | 'start' }>(\n ({ theme, clickable = false, disabled = false, placement }) => ({\n alignItems: 'center',\n cursor: clickable ? (disabled ? 'not-allowed' : 'pointer') : 'default',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n pointerEvents: clickable ? 'auto' : 'none',\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n }),\n);\n\nconst StyledLoadingSpinnerContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'placement',\n})<{ placement?: 'end' | 'middle' | 'start' }>(({ theme, placement }) => ({\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n}));\n\n/**\n * A customizable Autocomplete component supporting search and combobox modes.\n * Supports single and multiple selection with dynamic tag rendering and optional loading states.\n *\n * @param props - The component props\n * @returns The rendered Autocomplete component\n */\nexport const Autocomplete = ({\n className,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n loading = false,\n multiple = false,\n placeholder,\n onChange,\n onInputChange,\n options = [],\n required = false,\n translations,\n type = 'search',\n value,\n}: AutocompleteProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const isSearch = type === 'search';\n const isCombobox = type === 'combobox';\n\n const { rootRef, limitTags } = useDynamicLimitTags({\n chipMax: 130,\n gap: 4,\n horizontalPadding: 32,\n reservedPx: isSearch ? 120 : 90,\n });\n\n // Close the dropdown (if open) when the component is dynamically disabled\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n /**\n * Toggles or sets the dropdown open state.\n * Does nothing when the component is disabled.\n *\n * @param open - Optional boolean to explicitly set open state; if undefined, toggles current state\n */\n const toggleOpen = (open?: boolean): void => {\n if (disabled) {\n return;\n }\n\n if (open !== undefined) {\n setIsOpen(open);\n return;\n }\n\n setIsOpen((prevOpen) => !prevOpen);\n };\n\n const renderSearchIcon = (): JSX.Element => {\n return (\n <StyledAdornment disabled={disabled} placement=\"start\">\n <SearchIcon aria-hidden=\"true\" />\n </StyledAdornment>\n );\n };\n\n const renderPopupIcon = (): JSX.Element => {\n return (\n <StyledAdornment clickable disabled={disabled} placement=\"end\">\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledAdornment>\n );\n };\n\n const renderLoadingSpinner = (): JSX.Element => {\n return (\n <StyledLoadingSpinnerContainer placement={isSearch ? 'end' : 'middle'}>\n <CircularProgress size=\"small\" />\n </StyledLoadingSpinnerContainer>\n );\n };\n\n const renderInputField = (params: AutocompleteRenderInputParams): JSX.Element => (\n <TextField\n disabled={disabled}\n errorText={errorText}\n fdKey={fdKey}\n fullWidth={fullWidth}\n helperText={helperText}\n label={label}\n placeholder={placeholder}\n required={required}\n slotProps={{\n input: {\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? renderLoadingSpinner() : null}\n {params.InputProps.endAdornment}\n </>\n ),\n startAdornment: (\n <>\n {isSearch ? renderSearchIcon() : null}\n {params.InputProps.startAdornment}\n </>\n ),\n },\n htmlInput: {\n ...params.inputProps,\n },\n }}\n />\n );\n\n const renderMenuOption = (\n optionProps: React.HTMLAttributes<HTMLLIElement> & { key: React.Key },\n option: AutocompleteOption,\n state: AutocompleteRenderOptionState,\n ): JSX.Element => {\n const { key, onClick, ...rest } = optionProps;\n\n if (multiple) {\n return (\n <MenuItem\n {...rest}\n key={key}\n checked={state.selected}\n label={option.label}\n onCheckedChange={(_checked, e) => {\n onClick?.(e as React.MouseEvent<HTMLLIElement, MouseEvent>);\n }}\n type=\"checkbox\"\n />\n );\n }\n\n return (\n <MenuItem\n {...rest}\n key={key}\n label={option.label}\n onClick={onClick}\n selected={state.selected}\n type=\"text\"\n />\n );\n };\n\n const renderSelectedTags = (\n selected: AutocompleteOption[],\n getTagProps: AutocompleteRenderGetTagProps,\n ): React.ReactNode =>\n selected.map((tag, index) => {\n const { key, onDelete, ...tagProps } = getTagProps({ index });\n const rawLabel = typeof tag === 'string' ? tag : tag.label;\n const label = truncateWithEllipsis(rawLabel, 13, { includeEllipsisInLimit: true });\n const isTruncated = label.endsWith('...');\n const tagKey = key ?? `tag-${typeof tag === 'string' ? tag : tag.value}`;\n\n if (isTruncated) {\n return (\n <MuiTooltip key={tagKey} arrow placement=\"top\" title={rawLabel}>\n <span {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n </MuiTooltip>\n );\n }\n\n return (\n <span key={tagKey} {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n );\n });\n\n const handlePopupIndicatorClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n toggleOpen();\n };\n\n const handleChange = (\n event: React.SyntheticEvent,\n value: AutocompleteValue<AutocompleteOption, boolean, boolean, boolean>,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<AutocompleteOption>,\n ): void => {\n if (!onChange) {\n return;\n }\n onChange(event, value, reason, details);\n };\n\n const handleInputChange = (\n event: React.SyntheticEvent,\n value: string,\n reason: AutocompleteInputChangeReason,\n ): void => {\n if (!onInputChange) {\n return;\n }\n onInputChange(event, value, reason);\n };\n\n /**\n * Returns all options without filtering for search mode.\n * Disables MUI's built-in client-side filtering when type is 'search'.\n */\n const disableClientFilter = (opts: AutocompleteOption[]): AutocompleteOption[] => opts;\n\n /**\n * Extracts the display label from an option.\n * Supports both object options and freeSolo string values.\n */\n const getOptionLabel = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : option.label;\n };\n\n /**\n * Provides a stable unique key for each option to optimize DOM reconciliation.\n */\n const getOptionKey = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : String(option.value);\n };\n\n /**\n * Determines equality between an option and the current value.\n * Handles both freeSolo string values and object options to prevent selection glitches.\n */\n const getIsOptionEqualToValue = (a: AutocompleteOption, b: AutocompleteOption): boolean => {\n if (b === null || b === undefined) {\n return false;\n }\n return typeof b === 'string' ? a.label === b || String(a.value) === b : a.value === b.value;\n };\n\n /**\n * Normalizes the value prop for MUI Autocomplete.\n * Handles both single and multiple selection modes, ensuring the value\n * format matches the mode (array for multiple, single value/null for single).\n *\n * @returns Normalized value compatible with MUI Autocomplete\n */\n const getValue = (): AutocompleteProps['value'] => {\n // Multiple value selection\n if (multiple) {\n if (Array.isArray(value)) return value;\n if (value === null || value === undefined) return [];\n return [value as AutocompleteOption];\n }\n\n // Single value selection\n if (Array.isArray(value)) return value.length > 0 ? value[0] : null;\n return value ?? null;\n };\n\n return (\n <StyledAutocomplete\n ref={rootRef}\n className={className}\n clearIcon={<CancelIcon size=\"md\" />}\n clearText={translations.clearTextAriaLabel}\n disableClearable={disabled || loading}\n disableCloseOnSelect={multiple}\n disabled={disabled}\n filterOptions={isSearch ? disableClientFilter : undefined}\n forcePopupIcon={isCombobox}\n freeSolo={isSearch}\n fullWidth={fullWidth}\n getOptionKey={getOptionKey}\n getOptionLabel={getOptionLabel}\n isOptionEqualToValue={getIsOptionEqualToValue}\n limitTags={limitTags}\n loading={loading}\n loadingText={translations.loadingText}\n multiple={multiple}\n noOptionsText={translations.noOptionsText}\n onChange={handleChange}\n onClose={() => toggleOpen(false)}\n onInputChange={handleInputChange}\n onOpen={() => toggleOpen(true)}\n open={isOpen}\n openText={translations.openPopupAriaLabel}\n options={options}\n popupIcon={isSearch ? null : renderPopupIcon()}\n renderInput={renderInputField}\n renderOption={renderMenuOption}\n renderTags={renderSelectedTags}\n slotProps={{\n popupIndicator: {\n onClick: handlePopupIndicatorClick,\n },\n }}\n value={getValue()}\n />\n );\n};\n\nexport default Autocomplete;\n"],"names":["StyledAutocomplete","styled","shouldForwardProp","prop","fullWidth","width","StyledAdornment","Box","includes","theme","clickable","disabled","placement","alignItems","cursor","display","justifyContent","padding","pointerEvents","paddingRight","spacing","color","palette","semantic","icon","StyledLoadingSpinnerContainer","Autocomplete","className","errorText","fdKey","helperText","label","loading","multiple","placeholder","onChange","onInputChange","options","required","translations","type","value","isOpen","setIsOpen","useState","isSearch","isCombobox","rootRef","limitTags","useDynamicLimitTags","chipMax","gap","horizontalPadding","reservedPx","useEffect","toggleOpen","open","undefined","prevOpen","_jsx","ref","clearIcon","CancelIcon","size","clearText","clearTextAriaLabel","disableClearable","disableCloseOnSelect","filterOptions","opts","forcePopupIcon","freeSolo","getOptionKey","option","String","getOptionLabel","isOptionEqualToValue","a","b","loadingText","noOptionsText","event","reason","details","onClose","onOpen","openText","openPopupAriaLabel","popupIcon","children","ArrowUp01Icon","ArrowDown01Icon","renderInput","params","TextField","slotProps","input","InputProps","endAdornment","_jsxs","_Fragment","CircularProgress","startAdornment","SearchIcon","htmlInput","inputProps","renderOption","optionProps","state","key","onClick","rest","_createElement","MenuItem","checked","selected","onCheckedChange","_checked","e","renderTags","getTagProps","map","tag","index","onDelete","tagProps","rawLabel","truncateWithEllipsis","includeEllipsisInLimit","isTruncated","endsWith","tagKey","MuiTooltip","arrow","title","Tag","dismissAriaLabel","dismissTagAriaLabel","onDismiss","popupIndicator","stopPropagation","Array","isArray","length"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/molecules/Autocomplete/index.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport MuiAutocomplete, {\n type AutocompleteChangeDetails,\n type AutocompleteChangeReason,\n type AutocompleteInputChangeReason,\n type AutocompleteProps as MuiAutocompleteProps,\n type AutocompleteRenderGetTagProps,\n type AutocompleteRenderInputParams,\n type AutocompleteRenderOptionState,\n type AutocompleteValue,\n} from '@mui/material/Autocomplete';\nimport Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\n\nimport Tooltip from '@fd/components/molecules/Tooltip';\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelIcon from '@fd/icons/Cancel';\nimport SearchIcon from '@fd/icons/Search';\nimport { truncateWithEllipsis } from '@fd/utilities/stringUtilities';\n\nimport CircularProgress from '../../atoms/CircularProgress';\nimport MenuItem from '../../atoms/MenuItem';\nimport Tag from '../../atoms/Tag';\nimport TextField, { type TextFieldProps } from '../../atoms/TextField';\nimport { useDynamicLimitTags } from './hooks/useDynamicLimitTags';\n\n// Bind flags to MuiAutocomplete\ntype MuiCustomAutocompleteProps<\n M extends boolean = boolean, // Multiple\n DC extends boolean = boolean, // DisableClearable\n FS extends boolean = boolean, // FreeSolo\n> = MuiAutocompleteProps<AutocompleteOption, M, DC, FS>;\n\n/**\n * Represents an option in the Autocomplete dropdown.\n */\nexport interface AutocompleteOption {\n /** The label to display in the dropdown option. */\n label: string;\n /** The value to store in the dropdown option. */\n value: number | string;\n}\n\n/**\n * Props for the Autocomplete component.\n * Supports both single and multiple selection modes with optional search functionality.\n */\nexport interface AutocompleteProps\n extends Omit<TextFieldProps, 'endAdornment' | 'multiline' | 'onChange' | 'options' | 'startAdornment'> {\n /** Shows a loading indicator inside the input (e.g., while fetching). */\n loading?: boolean;\n /** Enables selection of multiple options and shows checkboxes and tags for selected values. */\n multiple?: MuiCustomAutocompleteProps['multiple'];\n /** Called when the selected value(s) change. */\n onChange: MuiCustomAutocompleteProps['onChange'];\n /** Called when the input text changes (typing or programmatic updates). */\n onInputChange?: MuiCustomAutocompleteProps['onInputChange'];\n /** Options to display in the dropdown list. */\n options: AutocompleteOption[];\n /** UI and accessibility labels used by the component. */\n translations: {\n /** Aria-label for the clear button. */\n clearTextAriaLabel: string;\n /** Aria-label for the dismiss tag button. */\n dismissTagAriaLabel: string;\n /** Text shown while loading options. */\n loadingText: string;\n /** Text shown when there are no options to display. */\n noOptionsText: string;\n /** Aria-label for the popup indicator button. */\n openPopupAriaLabel: string;\n };\n /** Visual behavior: 'search' shows a leading search icon; 'combobox' shows a popup button. */\n type?: 'combobox' | 'search';\n /** Controlled value (single option, array for multiple, or null). */\n value: MuiCustomAutocompleteProps['value'];\n}\n\n// Bind flags to MuiAutocomplete, see MuiCustomAutocompleteProps for more details\nconst MuiCustomAutocomplete = MuiAutocomplete<AutocompleteOption, boolean, boolean, boolean>;\nconst StyledAutocomplete = styled(MuiCustomAutocomplete, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n width: fullWidth ? '100%' : 'min(364px, 100%)',\n}));\n\nconst StyledAdornment = styled(Box, {\n shouldForwardProp: (prop) => !['clickable', 'disabled', 'placement'].includes(prop as string),\n})<{ clickable?: boolean; error?: boolean; disabled?: boolean; placement: 'end' | 'middle' | 'start' }>(\n ({ theme, clickable = false, disabled = false, placement }) => ({\n alignItems: 'center',\n cursor: clickable ? (disabled ? 'not-allowed' : 'pointer') : 'default',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n pointerEvents: clickable ? 'auto' : 'none',\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n }),\n);\n\nconst StyledLoadingSpinnerContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'placement',\n})<{ placement?: 'end' | 'middle' | 'start' }>(({ theme, placement }) => ({\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'center',\n padding: 0,\n\n ...(placement === 'start' && { paddingRight: theme.spacing(1) }),\n ...(placement === 'middle' && { padding: theme.spacing(0, 1) }),\n}));\n\n/**\n * A customizable Autocomplete component supporting search and combobox modes.\n * Supports single and multiple selection with dynamic tag rendering and optional loading states.\n *\n * @param props - The component props\n * @returns The rendered Autocomplete component\n */\nexport const Autocomplete = ({\n className,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n loading = false,\n multiple = false,\n placeholder,\n onChange,\n onInputChange,\n options = [],\n required = false,\n translations,\n type = 'search',\n value,\n}: AutocompleteProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const isSearch = type === 'search';\n const isCombobox = type === 'combobox';\n\n const { rootRef, limitTags } = useDynamicLimitTags({\n chipMax: 130,\n gap: 4,\n horizontalPadding: 32,\n reservedPx: isSearch ? 120 : 90,\n });\n\n // Close the dropdown (if open) when the component is dynamically disabled\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n /**\n * Toggles or sets the dropdown open state.\n * Does nothing when the component is disabled.\n *\n * @param open - Optional boolean to explicitly set open state; if undefined, toggles current state\n */\n const toggleOpen = (open?: boolean): void => {\n if (disabled) {\n return;\n }\n\n if (open !== undefined) {\n setIsOpen(open);\n return;\n }\n\n setIsOpen((prevOpen) => !prevOpen);\n };\n\n const renderSearchIcon = (): JSX.Element => {\n return (\n <StyledAdornment disabled={disabled} placement=\"start\">\n <SearchIcon aria-hidden=\"true\" />\n </StyledAdornment>\n );\n };\n\n const renderPopupIcon = (): JSX.Element => {\n return (\n <StyledAdornment clickable disabled={disabled} placement=\"end\">\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledAdornment>\n );\n };\n\n const renderLoadingSpinner = (): JSX.Element => {\n return (\n <StyledLoadingSpinnerContainer placement={isSearch ? 'end' : 'middle'}>\n <CircularProgress size=\"small\" />\n </StyledLoadingSpinnerContainer>\n );\n };\n\n const renderInputField = (params: AutocompleteRenderInputParams): JSX.Element => (\n <TextField\n disabled={disabled}\n errorText={errorText}\n fdKey={fdKey}\n fullWidth={fullWidth}\n helperText={helperText}\n label={label}\n placeholder={placeholder}\n required={required}\n slotProps={{\n input: {\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? renderLoadingSpinner() : null}\n {params.InputProps.endAdornment}\n </>\n ),\n startAdornment: (\n <>\n {isSearch ? renderSearchIcon() : null}\n {params.InputProps.startAdornment}\n </>\n ),\n },\n htmlInput: {\n ...params.inputProps,\n },\n }}\n />\n );\n\n const renderMenuOption = (\n optionProps: React.HTMLAttributes<HTMLLIElement> & { key: React.Key },\n option: AutocompleteOption,\n state: AutocompleteRenderOptionState,\n ): JSX.Element => {\n const { key, onClick, ...rest } = optionProps;\n\n if (multiple) {\n return (\n <MenuItem\n {...rest}\n key={key}\n checked={state.selected}\n label={option.label}\n onCheckedChange={(_checked, e) => {\n onClick?.(e as React.MouseEvent<HTMLLIElement, MouseEvent>);\n }}\n type=\"checkbox\"\n />\n );\n }\n\n return (\n <MenuItem\n {...rest}\n key={key}\n label={option.label}\n onClick={onClick}\n selected={state.selected}\n type=\"text\"\n />\n );\n };\n\n const renderSelectedTags = (\n selected: AutocompleteOption[],\n getTagProps: AutocompleteRenderGetTagProps,\n ): React.ReactNode =>\n selected.map((tag, index) => {\n const { key, onDelete, ...tagProps } = getTagProps({ index });\n const rawLabel = typeof tag === 'string' ? tag : tag.label;\n const label = truncateWithEllipsis(rawLabel, 13, { includeEllipsisInLimit: true });\n const isTruncated = label.endsWith('...');\n const tagKey = key ?? `tag-${typeof tag === 'string' ? tag : tag.value}`;\n\n if (isTruncated) {\n return (\n <Tooltip key={tagKey} title={rawLabel}>\n <span {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n </Tooltip>\n );\n }\n\n return (\n <span key={tagKey} {...tagProps}>\n <Tag dismissAriaLabel={translations.dismissTagAriaLabel} label={label} onDismiss={onDelete} />\n </span>\n );\n });\n\n const handlePopupIndicatorClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n toggleOpen();\n };\n\n const handleChange = (\n event: React.SyntheticEvent,\n value: AutocompleteValue<AutocompleteOption, boolean, boolean, boolean>,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<AutocompleteOption>,\n ): void => {\n if (!onChange) {\n return;\n }\n onChange(event, value, reason, details);\n };\n\n const handleInputChange = (\n event: React.SyntheticEvent,\n value: string,\n reason: AutocompleteInputChangeReason,\n ): void => {\n if (!onInputChange) {\n return;\n }\n onInputChange(event, value, reason);\n };\n\n /**\n * Returns all options without filtering for search mode.\n * Disables MUI's built-in client-side filtering when type is 'search'.\n */\n const disableClientFilter = (opts: AutocompleteOption[]): AutocompleteOption[] => opts;\n\n /**\n * Extracts the display label from an option.\n * Supports both object options and freeSolo string values.\n */\n const getOptionLabel = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : option.label;\n };\n\n /**\n * Provides a stable unique key for each option to optimize DOM reconciliation.\n */\n const getOptionKey = (option: AutocompleteOption | string): string => {\n return typeof option === 'string' ? option : String(option.value);\n };\n\n /**\n * Determines equality between an option and the current value.\n * Handles both freeSolo string values and object options to prevent selection glitches.\n */\n const getIsOptionEqualToValue = (a: AutocompleteOption, b: AutocompleteOption): boolean => {\n if (b === null || b === undefined) {\n return false;\n }\n return typeof b === 'string' ? a.label === b || String(a.value) === b : a.value === b.value;\n };\n\n /**\n * Normalizes the value prop for MUI Autocomplete.\n * Handles both single and multiple selection modes, ensuring the value\n * format matches the mode (array for multiple, single value/null for single).\n *\n * @returns Normalized value compatible with MUI Autocomplete\n */\n const getValue = (): AutocompleteProps['value'] => {\n // Multiple value selection\n if (multiple) {\n if (Array.isArray(value)) return value;\n if (value === null || value === undefined) return [];\n return [value as AutocompleteOption];\n }\n\n // Single value selection\n if (Array.isArray(value)) return value.length > 0 ? value[0] : null;\n return value ?? null;\n };\n\n return (\n <StyledAutocomplete\n ref={rootRef}\n className={className}\n clearIcon={<CancelIcon size=\"md\" />}\n clearText={translations.clearTextAriaLabel}\n disableClearable={disabled || loading}\n disableCloseOnSelect={multiple}\n disabled={disabled}\n filterOptions={isSearch ? disableClientFilter : undefined}\n forcePopupIcon={isCombobox}\n freeSolo={isSearch}\n fullWidth={fullWidth}\n getOptionKey={getOptionKey}\n getOptionLabel={getOptionLabel}\n isOptionEqualToValue={getIsOptionEqualToValue}\n limitTags={limitTags}\n loading={loading}\n loadingText={translations.loadingText}\n multiple={multiple}\n noOptionsText={translations.noOptionsText}\n onChange={handleChange}\n onClose={() => toggleOpen(false)}\n onInputChange={handleInputChange}\n onOpen={() => toggleOpen(true)}\n open={isOpen}\n openText={translations.openPopupAriaLabel}\n options={options}\n popupIcon={isSearch ? null : renderPopupIcon()}\n renderInput={renderInputField}\n renderOption={renderMenuOption}\n renderTags={renderSelectedTags}\n slotProps={{\n popupIndicator: {\n onClick: handlePopupIndicatorClick,\n },\n }}\n value={getValue()}\n />\n );\n};\n\nexport default Autocomplete;\n"],"names":["StyledAutocomplete","styled","shouldForwardProp","prop","fullWidth","width","StyledAdornment","Box","includes","theme","clickable","disabled","placement","alignItems","cursor","display","justifyContent","padding","pointerEvents","paddingRight","spacing","color","palette","semantic","icon","StyledLoadingSpinnerContainer","Autocomplete","className","errorText","fdKey","helperText","label","loading","multiple","placeholder","onChange","onInputChange","options","required","translations","type","value","isOpen","setIsOpen","useState","isSearch","isCombobox","rootRef","limitTags","useDynamicLimitTags","chipMax","gap","horizontalPadding","reservedPx","useEffect","toggleOpen","open","undefined","prevOpen","_jsx","ref","clearIcon","CancelIcon","size","clearText","clearTextAriaLabel","disableClearable","disableCloseOnSelect","filterOptions","opts","forcePopupIcon","freeSolo","getOptionKey","option","String","getOptionLabel","isOptionEqualToValue","a","b","loadingText","noOptionsText","event","reason","details","onClose","onOpen","openText","openPopupAriaLabel","popupIcon","children","ArrowUp01Icon","ArrowDown01Icon","renderInput","params","TextField","slotProps","input","InputProps","endAdornment","_jsxs","_Fragment","CircularProgress","startAdornment","SearchIcon","htmlInput","inputProps","renderOption","optionProps","state","key","onClick","rest","_createElement","MenuItem","checked","selected","onCheckedChange","_checked","e","renderTags","getTagProps","map","tag","index","onDelete","tagProps","rawLabel","truncateWithEllipsis","includeEllipsisInLimit","isTruncated","endsWith","tagKey","Tooltip","title","Tag","dismissAriaLabel","dismissTagAriaLabel","onDismiss","popupIndicator","stopPropagation","Array","isArray","length"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),t=require("@mui/material/Box"),i=require("@mui/material/styles"),r=require("@mui/material/Tooltip"),n=require("../../atoms/Button/index.cjs.js"),a=require("../../atoms/Link/index.cjs.js"),o=require("@mui/material/Typography"),s=require("../ButtonGroup/index.cjs.js");const l=e=>({"bottom-right":"top-end","bottom-left":"top-start","bottom-center":"top",left:"left",right:"right"}[e]??"top"),c=i.styled((({className:t,...i})=>e.jsx(r,{...i,classes:{popper:t}})),{shouldForwardProp:e=>"isLarge"!==e})((({theme:e,isLarge:t})=>({"& .MuiTooltip-tooltip":{backgroundColor:e.palette.semantic.background["background-inverse"],color:e.palette.semantic.text["text-weak"],borderRadius:e.radius["radius-8"],paddingLeft:e.spacing(2),paddingRight:e.spacing(2),paddingTop:t?e.spacing(2):e.spacing(1),paddingBottom:t?e.spacing(2):e.spacing(1),width:t?"332px":"auto",boxShadow:e.customShadows?.overlay},"& .MuiTooltip-arrow":{color:e.palette.semantic.background["background-inverse"]}}))),d=i.styled(t)((({theme:e})=>({display:"flex",flexDirection:"column",marginTop:e.spacing(.5),gap:e.spacing(1),alignItems:"flex-start",justifyContent:"center",width:"100%"}))),p=i.styled(t)((()=>({display:"flex",alignItems:"center",width:"100%",justifyContent:"space-between"}))),u=i.styled(o)((({theme:e})=>({color:e.palette.semantic.text["text-inverse-strong"]}))),g=i.styled(o)((({theme:e})=>({color:e.palette.semantic.text["text-inverse-weak"]}))),m=i.styled(t)((()=>({display:"flex",justifyContent:"flex-end",flexGrow:1}))),x=({children:t,title:i,description:r,textLink:o,size:x="small",actionButtons:h,placement:f="bottom-center",...y})=>{const j="large"===x,b=Boolean(o||h),k=e.jsxs(e.Fragment,{children:[e.jsx(u,{variant:j?"captionStrong":"captionWeak",children:i}),j&&r&&e.jsxs(d,{children:[e.jsx(g,{variant:"captionWeak",children:r}),b&&e.jsxs(p,{children:[(()=>{if(o)return e.jsx(a.Link,{fdKey:o.fdKey,href:o.href,iconLeft:o.iconLeft,iconRight:o.iconRight,size:"caption",tone:"Inverse Strong",underline:!1,weight:"bold",children:o.children})})(),(()=>{if(h)return Array.isArray(h)?e.jsx(s,{align:"right",layout:"horizontal",order:"default",size:"small",children:h.map(((t,i)=>{const r=`action-button-${i}`;return e.jsx(n.Button,{fdKey:t.label,onClick:t.onClick,tone:"inverse",variant:t.variant,children:t.label},r)}))}):e.jsx(m,{children:e.jsx(n.Button,{fdKey:h.label,onClick:h.onClick,size:"small",tone:"inverse",variant:h.variant,children:h.label})})})()]})]})]});return e.jsx(c,{...y,arrow:!0,isLarge:j,placement:l(f),title:k,children:t})};exports.Tooltip=x,exports.default=x;
2
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/Tooltip/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\nimport MUITooltip, { type TooltipProps as MUITooltipProps } from '@mui/material/Tooltip';\n\nimport Button from '@fd/components/atoms/Button';\nimport type { ButtonType } from '@fd/components/atoms/Button/getButtonStyles';\nimport Link, { type StyledLinkProps } from '@fd/components/atoms/Link';\nimport Typography from '@fd/components/atoms/Typography';\nimport ButtonGroup from '@fd/components/molecules/ButtonGroup';\n\ntype TooltipPlacement = 'bottom-center' | 'bottom-left' | 'bottom-right' | 'left' | 'right';\n\n// Map custom placement values to MUI placement values\nconst mapPlacementToMUI = (placement: TooltipPlacement): MUITooltipProps['placement'] => {\n const placementMap: Record<TooltipPlacement, MUITooltipProps['placement']> = {\n 'bottom-right': 'top-end',\n 'bottom-left': 'top-start',\n 'bottom-center': 'top',\n left: 'left',\n right: 'right',\n };\n\n return placementMap[placement] ?? 'top';\n};\n\nconst StyledTooltip = styled(\n ({ className, ...props }: MUITooltipProps) => <MUITooltip {...props} classes={{ popper: className }} />,\n { shouldForwardProp: (prop) => prop !== 'isLarge' },\n)<{ isLarge: boolean }>(({ theme, isLarge }) => ({\n '& .MuiTooltip-tooltip': {\n backgroundColor: theme.palette.semantic.background['background-inverse'],\n color: theme.palette.semantic.text['text-weak'],\n borderRadius: theme.radius['radius-8'],\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2),\n paddingTop: isLarge ? theme.spacing(2) : theme.spacing(1),\n paddingBottom: isLarge ? theme.spacing(2) : theme.spacing(1),\n width: isLarge ? '332px' : 'auto',\n boxShadow: theme.customShadows?.overlay,\n },\n '& .MuiTooltip-arrow': {\n color: theme.palette.semantic.background['background-inverse'],\n },\n}));\n\nconst StyledTooltipContent = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n marginTop: theme.spacing(0.5),\n gap: theme.spacing(1),\n alignItems: 'flex-start',\n justifyContent: 'center',\n width: '100%',\n}));\n\nconst StyledTooltipActionContainer = styled(Box)(() => ({\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n justifyContent: 'space-between',\n}));\n\nconst StyledTitle = styled(Typography)(({ theme }) => ({\n color: theme.palette.semantic.text['text-inverse-strong'],\n}));\n\nconst StyledDescription = styled(Typography)(({ theme }) => ({\n color: theme.palette.semantic.text['text-inverse-weak'],\n}));\n\nconst StyledSingleButtonContainer = styled(Box)(() => ({\n display: 'flex',\n justifyContent: 'flex-end',\n flexGrow: 1,\n}));\n\n/** Props for the ActionButton component */\nexport interface ActionButton {\n /** Text label for the action button */\n label: string;\n /** Visual variant of the action button */\n variant?: ButtonType;\n /** Callback function when the action button is clicked */\n onClick: () => void;\n}\n\n/** Props for the Tooltip component */\nexport interface TooltipProps extends Omit<MUITooltipProps, 'arrow' | 'placement'> {\n /** Placement of the tooltip */\n placement?: TooltipPlacement;\n /** Size of the tooltip */\n size?: 'large' | 'small';\n /** Description of the tooltip */\n description?: string;\n /** Action buttons of the tooltip */\n actionButtons?: ActionButton | ActionButton[];\n /** Text link of the tooltip */\n textLink?: StyledLinkProps;\n}\n\n/**\n * A floating message that’s displayed on hover or press of an interactive element.\n *\n * @param props - The component props\n * @returns A component with a tooltip\n */\nexport const Tooltip = ({\n children,\n title,\n description,\n textLink,\n size = 'small',\n actionButtons,\n placement = 'bottom-center',\n ...props\n}: TooltipProps): JSX.Element => {\n const isLarge = size === 'large';\n\n const renderTextLink = (): React.ReactNode => {\n if (!textLink) {\n return undefined;\n }\n\n return (\n <Link\n fdKey={textLink.fdKey}\n href={textLink.href}\n iconLeft={textLink.iconLeft}\n iconRight={textLink.iconRight}\n size=\"caption\"\n tone=\"Inverse Strong\"\n underline={false}\n weight=\"bold\"\n >\n {textLink.children}\n </Link>\n );\n };\n\n const renderActions = (): React.ReactNode => {\n if (!actionButtons) {\n return undefined;\n }\n\n if (Array.isArray(actionButtons)) {\n return (\n <ButtonGroup align=\"right\" layout=\"horizontal\" order=\"default\" size=\"small\">\n {actionButtons.map((button, index) => {\n const key = `action-button-${index}`;\n\n return (\n <Button\n key={key}\n fdKey={button.label}\n onClick={button.onClick}\n tone=\"inverse\"\n variant={button.variant}\n >\n {button.label}\n </Button>\n );\n })}\n </ButtonGroup>\n );\n }\n\n return (\n <StyledSingleButtonContainer>\n <Button\n fdKey={actionButtons.label}\n onClick={actionButtons.onClick}\n size=\"small\"\n tone=\"inverse\"\n variant={actionButtons.variant}\n >\n {actionButtons.label}\n </Button>\n </StyledSingleButtonContainer>\n );\n };\n\n const hasActionContent = Boolean(textLink || actionButtons);\n\n const renderTooltipContent = (\n <>\n <StyledTitle variant={!isLarge ? 'captionWeak' : 'captionStrong'}>{title}</StyledTitle>\n {isLarge && description && (\n <StyledTooltipContent>\n <StyledDescription variant=\"captionWeak\">{description}</StyledDescription>\n {hasActionContent && (\n <StyledTooltipActionContainer>\n {renderTextLink()}\n {renderActions()}\n </StyledTooltipActionContainer>\n )}\n </StyledTooltipContent>\n )}\n </>\n );\n\n return (\n <StyledTooltip\n {...props}\n arrow\n isLarge={isLarge}\n placement={mapPlacementToMUI(placement)}\n title={renderTooltipContent}\n >\n {children}\n </StyledTooltip>\n );\n};\n\nexport default Tooltip;\n"],"names":["mapPlacementToMUI","placement","left","right","StyledTooltip","styled","className","props","_jsx","MUITooltip","classes","popper","shouldForwardProp","prop","theme","isLarge","backgroundColor","palette","semantic","background","color","text","borderRadius","radius","paddingLeft","spacing","paddingRight","paddingTop","paddingBottom","width","boxShadow","customShadows","overlay","StyledTooltipContent","Box","display","flexDirection","marginTop","gap","alignItems","justifyContent","StyledTooltipActionContainer","StyledTitle","Typography","StyledDescription","StyledSingleButtonContainer","flexGrow","Tooltip","children","title","description","textLink","size","actionButtons","hasActionContent","Boolean","renderTooltipContent","_jsxs","_Fragment","variant","Link","fdKey","href","iconLeft","iconRight","tone","underline","weight","renderTextLink","Array","isArray","ButtonGroup","align","layout","order","map","button","index","key","Button","label","onClick","renderActions","arrow"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { TooltipProps as TooltipProps$1 } from '@mui/material/Tooltip';
2
+ import { ButtonType } from '@fd/components/atoms/Button/getButtonStyles';
3
+ import { StyledLinkProps } from '@fd/components/atoms/Link';
4
+
5
+ type TooltipPlacement = 'bottom-center' | 'bottom-left' | 'bottom-right' | 'left' | 'right';
6
+ /** Props for the ActionButton component */
7
+ interface ActionButton {
8
+ /** Text label for the action button */
9
+ label: string;
10
+ /** Visual variant of the action button */
11
+ variant?: ButtonType;
12
+ /** Callback function when the action button is clicked */
13
+ onClick: () => void;
14
+ }
15
+ /** Props for the Tooltip component */
16
+ interface TooltipProps extends Omit<TooltipProps$1, 'arrow' | 'placement'> {
17
+ /** Placement of the tooltip */
18
+ placement?: TooltipPlacement;
19
+ /** Size of the tooltip */
20
+ size?: 'large' | 'small';
21
+ /** Description of the tooltip */
22
+ description?: string;
23
+ /** Action buttons of the tooltip */
24
+ actionButtons?: ActionButton | ActionButton[];
25
+ /** Text link of the tooltip */
26
+ textLink?: StyledLinkProps;
27
+ }
28
+ /**
29
+ * A floating message that’s displayed on hover or press of an interactive element.
30
+ *
31
+ * @param props - The component props
32
+ * @returns A component with a tooltip
33
+ */
34
+ declare const Tooltip: ({ children, title, description, textLink, size, actionButtons, placement, ...props }: TooltipProps) => JSX.Element;
35
+
36
+ export { Tooltip, Tooltip as default };
37
+ export type { ActionButton, TooltipProps };
@@ -0,0 +1,2 @@
1
+ import{jsx as t,jsxs as e,Fragment as i}from"react/jsx-runtime";import o from"@mui/material/Box";import{styled as r}from"@mui/material/styles";import n from"@mui/material/Tooltip";import{Button as a}from"../../atoms/Button/index.js";import{Link as l}from"../../atoms/Link/index.js";import s from"@mui/material/Typography";import c from"../ButtonGroup/index.js";const p=t=>({"bottom-right":"top-end","bottom-left":"top-start","bottom-center":"top",left:"left",right:"right"}[t]??"top"),d=r((({className:e,...i})=>t(n,{...i,classes:{popper:e}})),{shouldForwardProp:t=>"isLarge"!==t})((({theme:t,isLarge:e})=>({"& .MuiTooltip-tooltip":{backgroundColor:t.palette.semantic.background["background-inverse"],color:t.palette.semantic.text["text-weak"],borderRadius:t.radius["radius-8"],paddingLeft:t.spacing(2),paddingRight:t.spacing(2),paddingTop:e?t.spacing(2):t.spacing(1),paddingBottom:e?t.spacing(2):t.spacing(1),width:e?"332px":"auto",boxShadow:t.customShadows?.overlay},"& .MuiTooltip-arrow":{color:t.palette.semantic.background["background-inverse"]}}))),m=r(o)((({theme:t})=>({display:"flex",flexDirection:"column",marginTop:t.spacing(.5),gap:t.spacing(1),alignItems:"flex-start",justifyContent:"center",width:"100%"}))),g=r(o)((()=>({display:"flex",alignItems:"center",width:"100%",justifyContent:"space-between"}))),h=r(s)((({theme:t})=>({color:t.palette.semantic.text["text-inverse-strong"]}))),u=r(s)((({theme:t})=>({color:t.palette.semantic.text["text-inverse-weak"]}))),f=r(o)((()=>({display:"flex",justifyContent:"flex-end",flexGrow:1}))),x=({children:o,title:r,description:n,textLink:s,size:x="small",actionButtons:b,placement:y="bottom-center",...k})=>{const v="large"===x,w=Boolean(s||b),C=e(i,{children:[t(h,{variant:v?"captionStrong":"captionWeak",children:r}),v&&n&&e(m,{children:[t(u,{variant:"captionWeak",children:n}),w&&e(g,{children:[(()=>{if(s)return t(l,{fdKey:s.fdKey,href:s.href,iconLeft:s.iconLeft,iconRight:s.iconRight,size:"caption",tone:"Inverse Strong",underline:!1,weight:"bold",children:s.children})})(),(()=>{if(b)return Array.isArray(b)?t(c,{align:"right",layout:"horizontal",order:"default",size:"small",children:b.map(((e,i)=>{const o=`action-button-${i}`;return t(a,{fdKey:e.label,onClick:e.onClick,tone:"inverse",variant:e.variant,children:e.label},o)}))}):t(f,{children:t(a,{fdKey:b.label,onClick:b.onClick,size:"small",tone:"inverse",variant:b.variant,children:b.label})})})()]})]})]});return t(d,{...k,arrow:!0,isLarge:v,placement:p(y),title:C,children:o})};export{x as Tooltip,x as default};
2
+ //# sourceMappingURL=index.js.map