@flipdish/portal-library 7.6.0 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/atoms/Avatar/index.cjs.js +1 -1
- package/dist/components/atoms/Avatar/index.cjs.js.map +1 -1
- package/dist/components/atoms/Avatar/index.d.ts +2 -0
- package/dist/components/atoms/Avatar/index.js +1 -1
- package/dist/components/atoms/Avatar/index.js.map +1 -1
- package/dist/components/atoms/Button/buttonThemeOverrides.cjs.js +1 -1
- package/dist/components/atoms/Button/buttonThemeOverrides.cjs.js.map +1 -1
- package/dist/components/atoms/Button/buttonThemeOverrides.js +1 -1
- package/dist/components/atoms/Button/buttonThemeOverrides.js.map +1 -1
- package/dist/components/atoms/Button/index.cjs.js +1 -1
- package/dist/components/atoms/Button/index.cjs.js.map +1 -1
- package/dist/components/atoms/Button/index.d.ts +1 -1
- package/dist/components/atoms/Button/index.js +1 -1
- package/dist/components/atoms/Button/index.js.map +1 -1
- package/dist/components/atoms/Checkbox/index.cjs.js +1 -1
- package/dist/components/atoms/Checkbox/index.cjs.js.map +1 -1
- package/dist/components/atoms/Checkbox/index.js +1 -1
- package/dist/components/atoms/Checkbox/index.js.map +1 -1
- package/dist/components/atoms/MenuItem/index.cjs.js +1 -1
- package/dist/components/atoms/MenuItem/index.cjs.js.map +1 -1
- package/dist/components/atoms/MenuItem/index.d.ts +45 -13
- package/dist/components/atoms/MenuItem/index.js +1 -1
- package/dist/components/atoms/MenuItem/index.js.map +1 -1
- package/dist/components/molecules/AlertGlobal/index.cjs.js +1 -1
- package/dist/components/molecules/AlertGlobal/index.cjs.js.map +1 -1
- package/dist/components/molecules/AlertGlobal/index.js +1 -1
- package/dist/components/molecules/AlertGlobal/index.js.map +1 -1
- package/dist/components/molecules/DropdownMenu/index.cjs.js +2 -0
- package/dist/components/molecules/DropdownMenu/index.cjs.js.map +1 -0
- package/dist/components/molecules/DropdownMenu/index.d.ts +120 -0
- package/dist/components/molecules/DropdownMenu/index.js +2 -0
- package/dist/components/molecules/DropdownMenu/index.js.map +1 -0
- package/dist/components/organisms/FileUpload/components/FileDropZone.cjs.js.map +1 -1
- package/dist/components/organisms/FileUpload/components/FileDropZone.js.map +1 -1
- package/dist/components/organisms/FileUpload/components/FileItem.cjs.js.map +1 -1
- package/dist/components/organisms/FileUpload/components/FileItem.js.map +1 -1
- package/dist/components/organisms/FileUpload/components/FileThumbnail.cjs.js.map +1 -1
- package/dist/components/organisms/FileUpload/components/FileThumbnail.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/components/FlipdishFonts.cjs.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/components/FlipdishFonts.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/components/ImageDisplay.cjs.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/components/ImageDisplay.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/components/ImageDropZone.cjs.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/components/ImageDropZone.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/index.cjs.js.map +1 -1
- package/dist/components/organisms/ImageUploadWidget/index.js.map +1 -1
- package/dist/themes/flipdishPublicTheme.cjs.js +1 -1
- package/dist/themes/flipdishPublicTheme.cjs.js.map +1 -1
- package/dist/themes/flipdishPublicTheme.js +1 -1
- package/dist/themes/flipdishPublicTheme.js.map +1 -1
- package/dist/themes/overrides/listSubheaderOverrides.cjs.js +2 -0
- package/dist/themes/overrides/listSubheaderOverrides.cjs.js.map +1 -0
- package/dist/themes/overrides/listSubheaderOverrides.d.ts +5 -0
- package/dist/themes/overrides/listSubheaderOverrides.js +2 -0
- package/dist/themes/overrides/listSubheaderOverrides.js.map +1 -0
- package/dist/themes/overrides/menuItemOverrides.cjs.js +1 -1
- package/dist/themes/overrides/menuItemOverrides.cjs.js.map +1 -1
- package/dist/themes/overrides/menuItemOverrides.js +1 -1
- package/dist/themes/overrides/menuItemOverrides.js.map +1 -1
- package/dist/themes/overrides/menuOverrides.cjs.js +1 -1
- package/dist/themes/overrides/menuOverrides.cjs.js.map +1 -1
- package/dist/themes/overrides/menuOverrides.js +1 -1
- package/dist/themes/overrides/menuOverrides.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,38 +1,70 @@
|
|
|
1
1
|
import { MenuItemProps as MenuItemProps$1 } from '@mui/material/MenuItem';
|
|
2
2
|
|
|
3
3
|
type BaseProps = Omit<MenuItemProps$1, 'children'> & {
|
|
4
|
+
/** Children of the menu item */
|
|
4
5
|
children?: React.ReactNode;
|
|
6
|
+
/** Label of the menu item */
|
|
5
7
|
label?: React.ReactNode;
|
|
8
|
+
/** Secondary text of the menu item */
|
|
6
9
|
secondaryText?: React.ReactNode;
|
|
7
|
-
type?: 'avatar' | 'checkbox' | 'icon' | 'text';
|
|
8
10
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
/** Props for an avatar menu item */
|
|
12
|
+
interface AvatarMenuItemProps extends BaseProps {
|
|
13
|
+
/** Source URL for the avatar image */
|
|
14
|
+
avatarSrc: string;
|
|
15
|
+
/** Checkbox of the menu item */
|
|
11
16
|
checkbox?: never;
|
|
17
|
+
/** Icon of the menu item */
|
|
12
18
|
icon?: never;
|
|
19
|
+
/** Type of the menu item */
|
|
13
20
|
type: 'avatar';
|
|
14
|
-
}
|
|
15
|
-
|
|
21
|
+
}
|
|
22
|
+
/** Props for a checkbox menu item */
|
|
23
|
+
interface CheckboxMenuItemProps extends BaseProps {
|
|
24
|
+
/** Avatar of the menu item */
|
|
16
25
|
avatar?: never;
|
|
17
|
-
|
|
26
|
+
/** Checked state of the menu item */
|
|
27
|
+
checked: boolean;
|
|
28
|
+
/** Icon of the menu item */
|
|
18
29
|
icon?: never;
|
|
19
|
-
|
|
30
|
+
/** Function to call when the checkbox is changed */
|
|
31
|
+
onCheckedChange: (checked: boolean, e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLLIElement>) => void;
|
|
32
|
+
/** Function to call when the menu item is clicked */
|
|
33
|
+
onClick?: never;
|
|
34
|
+
/** Type of the menu item */
|
|
20
35
|
type: 'checkbox';
|
|
21
|
-
}
|
|
22
|
-
|
|
36
|
+
}
|
|
37
|
+
/** Props for an icon menu item */
|
|
38
|
+
interface IconMenuItemProps extends BaseProps {
|
|
39
|
+
/** Avatar of the menu item */
|
|
23
40
|
avatar?: never;
|
|
41
|
+
/** Checkbox of the menu item */
|
|
24
42
|
checkbox?: never;
|
|
43
|
+
/** Icon of the menu item */
|
|
25
44
|
icon: React.ReactNode;
|
|
45
|
+
/** Type of the menu item */
|
|
26
46
|
type: 'icon';
|
|
27
|
-
}
|
|
28
|
-
|
|
47
|
+
}
|
|
48
|
+
/** Props for a text menu item */
|
|
49
|
+
interface TextMenuItemProps extends BaseProps {
|
|
50
|
+
/** Avatar of the menu item */
|
|
29
51
|
avatar?: never;
|
|
52
|
+
/** Checkbox of the menu item */
|
|
30
53
|
checkbox?: never;
|
|
54
|
+
/** Icon of the menu item */
|
|
31
55
|
icon?: never;
|
|
56
|
+
/** Type of the menu item */
|
|
32
57
|
type?: 'text';
|
|
33
|
-
}
|
|
58
|
+
}
|
|
59
|
+
/** Props for the MenuItem component */
|
|
34
60
|
type MenuItemProps = AvatarMenuItemProps | CheckboxMenuItemProps | IconMenuItemProps | TextMenuItemProps;
|
|
61
|
+
/**
|
|
62
|
+
* A customizable MenuItem component supporting text, avatar, icon and checkbox menu items.
|
|
63
|
+
*
|
|
64
|
+
* @param props - The component props
|
|
65
|
+
* @returns The rendered MenuItem component
|
|
66
|
+
*/
|
|
35
67
|
declare const MenuItem: ({ children, disabled, label, secondaryText, type, ...props }: MenuItemProps) => JSX.Element;
|
|
36
68
|
|
|
37
69
|
export { MenuItem, MenuItem as default };
|
|
38
|
-
export type { MenuItemProps };
|
|
70
|
+
export type { AvatarMenuItemProps, CheckboxMenuItemProps, IconMenuItemProps, MenuItemProps, TextMenuItemProps };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as t}from"react/jsx-runtime";import r from"@mui/material/
|
|
1
|
+
import{jsxs as e,jsx as t}from"react/jsx-runtime";import r from"@mui/material/MenuItem";import{styled as a}from"@mui/material/styles";import n from"../Avatar/index.js";import o from"@mui/material/Box";import c from"../Checkbox/index.js";import i from"@mui/material/ListItemText";const s=a(o,{shouldForwardProp:e=>"disabled"!==e})((({theme:e,disabled:t=!1})=>({alignItems:"center",display:"inline-flex",justifyContent:"center","& .MuiAvatar-img":{opacity:t?e.palette.action.disabledOpacity:1}}))),l=a(c)((()=>({pointerEvents:"none"}))),d=({children:a,disabled:o=!1,label:c,secondaryText:d,type:m="text",...u})=>{const h=(()=>{switch(m){case"checkbox":{const{checked:e,onCheckedChange:t,...r}=u;return r}case"avatar":{const{avatarSrc:e,...t}=u;return t}case"icon":{const{icon:e,...t}=u;return t}default:return u}})();return e(r,{...h,disabled:o,onClick:e=>{if(!o)if("checkbox"!==m)h?.onClick?.(e);else{e.preventDefault(),e.stopPropagation();const{checked:t,onCheckedChange:r}=u,a="boolean"==typeof t?t:Boolean(u.selected);r?.(!a,e)}},children:[(()=>{switch(m){case"avatar":return(()=>{const{avatarSrc:e}=u;return t(s,{className:"fd-MenuItem-startAdornment",disabled:o,children:t(n,{alt:"",src:e,type:"logo"})})})();case"checkbox":return(()=>{const{checked:e}=u,r="boolean"==typeof e?e:Boolean(u.selected);return t(l,{"aria-hidden":!0,checked:r,disabled:o,fdKey:"checkbox-menu-item",size:"small",tabIndex:-1})})();case"icon":return(()=>{const{icon:e}=u;return t(s,{className:"fd-MenuItem-startAdornment",children:e})})();default:return null}})(),c||d?t(i,{primary:c,secondary:d}):a]})};export{d as MenuItem,d as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/MenuItem/index.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/MenuItem/index.tsx"],"sourcesContent":["import MuiMenuItem, { type MenuItemProps as MuiMenuItemProps } from '@mui/material/MenuItem';\nimport { styled } from '@mui/material/styles';\n\nimport Avatar from '../Avatar';\nimport Box from '../Box';\nimport Checkbox from '../Checkbox';\nimport ListItemText from '../ListItemText';\n\ntype BaseProps = Omit<MuiMenuItemProps, 'children'> & {\n /** Children of the menu item */\n children?: React.ReactNode;\n /** Label of the menu item */\n label?: React.ReactNode;\n /** Secondary text of the menu item */\n secondaryText?: React.ReactNode;\n};\n\n/** Props for an avatar menu item */\nexport interface AvatarMenuItemProps extends BaseProps {\n /** Source URL for the avatar image */\n avatarSrc: string;\n /** Checkbox of the menu item */\n checkbox?: never;\n /** Icon of the menu item */\n icon?: never;\n /** Type of the menu item */\n type: 'avatar';\n}\n\n/** Props for a checkbox menu item */\nexport interface CheckboxMenuItemProps extends BaseProps {\n /** Avatar of the menu item */\n avatar?: never;\n /** Checked state of the menu item */\n checked: boolean;\n /** Icon of the menu item */\n icon?: never;\n /** Function to call when the checkbox is changed */\n onCheckedChange: (\n checked: boolean,\n e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLLIElement>,\n ) => void;\n /** Function to call when the menu item is clicked */\n onClick?: never;\n /** Type of the menu item */\n type: 'checkbox';\n}\n\n/** Props for an icon menu item */\nexport interface IconMenuItemProps extends BaseProps {\n /** Avatar of the menu item */\n avatar?: never;\n /** Checkbox of the menu item */\n checkbox?: never;\n /** Icon of the menu item */\n icon: React.ReactNode;\n /** Type of the menu item */\n type: 'icon';\n}\n\n/** Props for a text menu item */\nexport interface TextMenuItemProps extends BaseProps {\n /** Avatar of the menu item */\n avatar?: never;\n /** Checkbox of the menu item */\n checkbox?: never;\n /** Icon of the menu item */\n icon?: never;\n /** Type of the menu item */\n type?: 'text';\n}\n\n/** Props for the MenuItem component */\nexport type MenuItemProps =\n | AvatarMenuItemProps\n | CheckboxMenuItemProps\n | IconMenuItemProps\n | TextMenuItemProps;\n\nconst StyledStartAdornment = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ theme, disabled = false }) => ({\n alignItems: 'center',\n display: 'inline-flex',\n justifyContent: 'center',\n\n '& .MuiAvatar-img': {\n opacity: disabled ? theme.palette.action.disabledOpacity : 1,\n },\n}));\n\nconst StyledCheckbox = styled(Checkbox)(() => ({\n pointerEvents: 'none',\n}));\n\n/**\n * A customizable MenuItem component supporting text, avatar, icon and checkbox menu items.\n *\n * @param props - The component props\n * @returns The rendered MenuItem component\n */\nexport const MenuItem = ({\n children,\n disabled = false,\n label,\n secondaryText,\n type = 'text',\n ...props\n}: MenuItemProps): JSX.Element => {\n // Remove type-specific props from props object to avoid passing them to MuiMenuItem\n const muiProps: MuiMenuItemProps = ((): MuiMenuItemProps => {\n switch (type) {\n case 'checkbox': {\n const { checked: _c, onCheckedChange: _h, ...rest } = props as CheckboxMenuItemProps;\n return rest as MuiMenuItemProps;\n }\n case 'avatar': {\n const { avatarSrc: _avatarSrc, ...rest } = props as AvatarMenuItemProps;\n return rest as MuiMenuItemProps;\n }\n case 'icon': {\n const { icon: _i, ...rest } = props as IconMenuItemProps;\n return rest as MuiMenuItemProps;\n }\n default:\n return props as MuiMenuItemProps;\n }\n })();\n\n const handleClick = (event: React.MouseEvent<HTMLLIElement>): void => {\n if (disabled) {\n return;\n }\n\n // If menu item is a checkbox, clicking the menu item will toggle the checkbox\n if (type === 'checkbox') {\n event.preventDefault();\n event.stopPropagation();\n\n const { checked, onCheckedChange } = props as CheckboxMenuItemProps;\n const isChecked =\n typeof checked === 'boolean' ? checked : Boolean((props as MuiMenuItemProps).selected);\n\n onCheckedChange?.(!isChecked, event);\n return;\n }\n\n muiProps?.onClick?.(event);\n };\n\n const renderAvatar = (): React.ReactNode => {\n const { avatarSrc } = props as AvatarMenuItemProps;\n return (\n <StyledStartAdornment className=\"fd-MenuItem-startAdornment\" disabled={disabled}>\n <Avatar\n alt=\"\" // Avatar is described by the label\n src={avatarSrc}\n type=\"logo\"\n />\n </StyledStartAdornment>\n );\n };\n\n const renderCheckbox = (): React.ReactNode => {\n const { checked } = props as CheckboxMenuItemProps;\n const isChecked = typeof checked === 'boolean' ? checked : Boolean((props as MuiMenuItemProps).selected);\n\n return (\n <StyledCheckbox\n aria-hidden\n checked={isChecked}\n disabled={disabled}\n fdKey=\"checkbox-menu-item\"\n size=\"small\"\n tabIndex={-1}\n />\n );\n };\n\n const renderIcon = (): React.ReactNode => {\n const { icon } = props as IconMenuItemProps;\n return <StyledStartAdornment className=\"fd-MenuItem-startAdornment\">{icon}</StyledStartAdornment>;\n };\n\n const renderStartAdornment = (): React.ReactNode => {\n switch (type) {\n case 'avatar':\n return renderAvatar();\n case 'checkbox':\n return renderCheckbox();\n case 'icon':\n return renderIcon();\n default:\n return null;\n }\n };\n\n const renderText = (): React.ReactNode => {\n if (label || secondaryText) {\n return <ListItemText primary={label} secondary={secondaryText} />;\n }\n\n return children;\n };\n\n return (\n <MuiMenuItem {...muiProps} disabled={disabled} onClick={handleClick}>\n {renderStartAdornment()}\n {renderText()}\n </MuiMenuItem>\n );\n};\n\nexport default MenuItem;\n"],"names":["StyledStartAdornment","styled","Box","shouldForwardProp","prop","theme","disabled","alignItems","display","justifyContent","opacity","palette","action","disabledOpacity","StyledCheckbox","Checkbox","pointerEvents","MenuItem","children","label","secondaryText","type","props","muiProps","checked","_c","onCheckedChange","_h","rest","avatarSrc","_avatarSrc","icon","_i","_jsxs","MuiMenuItem","onClick","event","preventDefault","stopPropagation","isChecked","Boolean","selected","_jsx","className","Avatar","alt","src","renderAvatar","fdKey","size","tabIndex","renderCheckbox","renderIcon","renderStartAdornment","ListItemText","primary","secondary"],"mappings":"uRA+EA,MAAMA,EAAuBC,EAAOC,EAAK,CACvCC,kBAAoBC,GAAkB,aAATA,GADFH,EAEF,EAAGI,QAAOC,YAAW,MAAO,CACrDC,WAAY,SACZC,QAAS,cACTC,eAAgB,SAEhB,mBAAoB,CAClBC,QAASJ,EAAWD,EAAMM,QAAQC,OAAOC,gBAAkB,OAIzDC,EAAiBb,EAAOc,EAAPd,EAAiB,KAAA,CACtCe,cAAe,WASJC,EAAW,EACtBC,WACAZ,YAAW,EACXa,QACAC,gBACAC,OAAO,UACJC,MAGH,MAAMC,EAA6B,MACjC,OAAQF,GACN,IAAK,WAAY,CACf,MAAQG,QAASC,EAAIC,gBAAiBC,KAAOC,GAASN,EACtD,OAAOM,CACT,CACA,IAAK,SAAU,CACb,MAAQC,UAAWC,KAAeF,GAASN,EAC3C,OAAOM,CACT,CACA,IAAK,OAAQ,CACX,MAAQG,KAAMC,KAAOJ,GAASN,EAC9B,OAAOM,CACT,CACA,QACE,OAAON,EAEZ,EAjBkC,GA+FnC,OACEW,EAACC,EAAW,IAAKX,EAAUjB,SAAUA,EAAU6B,QA7E5BC,IACnB,IAAI9B,EAKJ,GAAa,aAATe,EAYJE,GAAUY,UAAUC,OAZpB,CACEA,EAAMC,iBACND,EAAME,kBAEN,MAAMd,QAAEA,EAAOE,gBAAEA,GAAoBJ,EAC/BiB,EACe,kBAAZf,EAAwBA,EAAUgB,QAASlB,EAA2BmB,UAE/Ef,KAAmBa,EAAWH,EAEhC,aAuC2B,MAC3B,OAAQf,GACN,IAAK,SACH,MArCe,MACnB,MAAMQ,UAAEA,GAAcP,EACtB,OACEoB,EAAC1C,GAAqB2C,UAAU,6BAA6BrC,SAAUA,EAAQY,SAC7EwB,EAACE,EAAM,CACLC,IAAI,GACJC,IAAKjB,EACLR,KAAK,YA8BA0B,GACT,IAAK,WACH,MA1BiB,MACrB,MAAMvB,QAAEA,GAAYF,EACdiB,EAA+B,kBAAZf,EAAwBA,EAAUgB,QAASlB,EAA2BmB,UAE/F,OACEC,EAAC5B,EAAc,CAAA,eAAA,EAEbU,QAASe,EACTjC,SAAUA,EACV0C,MAAM,qBACNC,KAAK,QACLC,UAAU,KAeHC,GACT,IAAK,OACH,MAZa,MACjB,MAAMpB,KAAEA,GAAST,EACjB,OAAOoB,EAAC1C,EAAoB,CAAC2C,UAAU,6BAA4BzB,SAAEa,KAU1DqB,GACT,QACE,OAAO,OAcRC,GATClC,GAASC,EACJsB,EAACY,EAAY,CAACC,QAASpC,EAAOqC,UAAWpC,IAG3CF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("@mui/material/Alert"),i=require("@mui/material/Box"),l=require("../../atoms/Button/index.cjs.js"),n=require("../../atoms/IconButton/index.cjs.js"),o=require("../ButtonGroup/index.cjs.js"),r=require("../../../icons/Cancel/index.cjs.js"),s=require("@mui/material/styles"),c=require("@mui/material/useMediaQuery"),d=require("@mui/material/styles/useTheme"),u=require("./alertGlobalTokens.cjs.js");const g=s.styled(a,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({alignItems:"center",backgroundColor:u.getAlertGlobalBackgroundColour(e,t),borderBottom:"1px solid",borderRadius:0,borderColor:u.getAlertGlobalBorderColour(e,t),color:u.getAlertGlobalTextColour(e,t),padding:e.spacing(3),paddingTop:e.spacing(1.5),paddingBottom:e.spacing(1.5),width:"100%",display:"flex",position:"relative","& .MuiAlert-icon":{alignSelf:"flex-start"},"& .MuiAlert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),flexGrow:1,minWidth:0},"& .MuiAlert-action":{display:"flex",alignItems:"center",gap:e.spacing(3),marginLeft:"auto"},"& .MuiAlert-action .MuiIconButton-root":{outline:"none",boxShadow:"none",border:"none"},"& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible":{outline:"none",boxShadow:"none"},"& .fd-alert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),width:"100%"},"& .fd-alert-description":{flexGrow:1,minWidth:0},"& .fd-alert-actions-inline":{marginLeft:"auto",display:"none"},"& .fd-alert-actions-action":{display:"flex"},[e.breakpoints.down("tablet")]:{"& .fd-alert-message":{flexDirection:"column",alignItems:"stretch",gap:e.spacing(2)},"& .fd-alert-actions-inline":{marginLeft:0,marginTop:e.spacing(2),width:"100%",justifyContent:"flex-end",display:"flex"},"& .fd-alert-actions-action":{display:"none"},"& .MuiAlert-action":{position:"absolute",top:e.spacing(3),right:e.spacing(3),marginLeft:0}}}))),p=s.styled(i)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(3)}))),m=t.memo((({description:t,tone:a="neutral",onClose:s,action:m,className:f,closeAriaLabel:x="Close","data-fd":h})=>{const b=d(),y=c(b.breakpoints.down("tablet")),j=(m?Array.isArray(m)?m:[m]:[]).map((t=>{const a=t.id??`${t.label.replace(/\s+/g,"-").toLowerCase()}-${t.type??"type"}`;return e.jsx(l.Button,{
|
|
1
|
+
"use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("@mui/material/Alert"),i=require("@mui/material/Box"),l=require("../../atoms/Button/index.cjs.js"),n=require("../../atoms/IconButton/index.cjs.js"),o=require("../ButtonGroup/index.cjs.js"),r=require("../../../icons/Cancel/index.cjs.js"),s=require("@mui/material/styles"),c=require("@mui/material/useMediaQuery"),d=require("@mui/material/styles/useTheme"),u=require("./alertGlobalTokens.cjs.js");const g=s.styled(a,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({alignItems:"center",backgroundColor:u.getAlertGlobalBackgroundColour(e,t),borderBottom:"1px solid",borderRadius:0,borderColor:u.getAlertGlobalBorderColour(e,t),color:u.getAlertGlobalTextColour(e,t),padding:e.spacing(3),paddingTop:e.spacing(1.5),paddingBottom:e.spacing(1.5),width:"100%",display:"flex",position:"relative","& .MuiAlert-icon":{alignSelf:"flex-start"},"& .MuiAlert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),flexGrow:1,minWidth:0},"& .MuiAlert-action":{display:"flex",alignItems:"center",gap:e.spacing(3),marginLeft:"auto"},"& .MuiAlert-action .MuiIconButton-root":{outline:"none",boxShadow:"none",border:"none"},"& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible":{outline:"none",boxShadow:"none"},"& .fd-alert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),width:"100%"},"& .fd-alert-description":{flexGrow:1,minWidth:0},"& .fd-alert-actions-inline":{marginLeft:"auto",display:"none"},"& .fd-alert-actions-action":{display:"flex"},[e.breakpoints.down("tablet")]:{"& .fd-alert-message":{flexDirection:"column",alignItems:"stretch",gap:e.spacing(2)},"& .fd-alert-actions-inline":{marginLeft:0,marginTop:e.spacing(2),width:"100%",justifyContent:"flex-end",display:"flex"},"& .fd-alert-actions-action":{display:"none"},"& .MuiAlert-action":{position:"absolute",top:e.spacing(3),right:e.spacing(3),marginLeft:0}}}))),p=s.styled(i)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(3)}))),m=t.memo((({description:t,tone:a="neutral",onClose:s,action:m,className:f,closeAriaLabel:x="Close","data-fd":h})=>{const b=d(),y=c(b.breakpoints.down("tablet")),j=(m?Array.isArray(m)?m:[m]:[]).map((t=>{const a=t.id??`${t.label.replace(/\s+/g,"-").toLowerCase()}-${t.type??"type"}`;return e.jsx(l.Button,{fdKey:t["data-fd"]??`action-button-${t.label.replace(/\s+/g,"-").toLowerCase()}`,onClick:t.onClick,size:"small",tone:"neutral",variant:t.type??"secondary",children:t.label},a)})),A=[];return j.length&&!y&&A.push(e.jsx(o,{align:"right",className:"fd-alert-actions-action",layout:"horizontal",size:"small",children:j},"action-group-action")),s&&A.push(e.jsx(n.IconButton,{"aria-label":x,"data-fd":"close-button",onClick:s,size:"small",tone:"neutral",variant:"tertiary",children:e.jsx(r,{})},"close")),e.jsx(g,{action:A.length?e.jsx(p,{children:A}):void 0,className:f,"data-fd":h,icon:u.getAlertGlobalIcon(b,a),role:"alert",tone:a,children:e.jsxs(i,{className:"fd-alert-message",children:[e.jsx(i,{className:"fd-alert-description",children:t}),y&&j.length?e.jsx(o,{align:"right",className:"fd-alert-actions-inline",layout:"horizontal",size:"small",children:j}):null]})})}));m.displayName="AlertGlobal",module.exports=m;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/AlertGlobal/index.tsx"],"sourcesContent":["import { memo, type ReactElement, type ReactNode } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\n\nimport Box from '@fd/components/atoms/Box';\nimport Button from '@fd/components/atoms/Button';\nimport type { ButtonType } from '@fd/components/atoms/Button/getButtonStyles';\nimport IconButton from '@fd/components/atoms/IconButton';\nimport type { AlertTones } from '@fd/components/molecules/Alert';\nimport ButtonGroup from '@fd/components/molecules/ButtonGroup';\nimport CancelIcon from '@fd/icons/Cancel';\nimport styled from '@fd/utilities/styledUtilities';\nimport useMediaQuery from '@fd/utilities/useMediaQuery';\nimport useTheme from '@fd/utilities/useTheme';\n\nimport {\n getAlertGlobalBackgroundColour,\n getAlertGlobalBorderColour,\n getAlertGlobalIcon,\n getAlertGlobalTextColour,\n} from './alertGlobalTokens';\n\n/**\n * Global alert component for prominent, page-level messages.\n *\n * - Renders an icon and description with optional actions and a close button\n * - `action` accepts a single action object or an array of action objects\n * (use an array to render multiple buttons side-by-side)\n * - Consumers are responsible for providing localized strings for any\n * user-visible text (e.g. `description`, action `label`, `closeAriaLabel`).\n */\nexport interface AlertGlobalProps {\n /**\n * Message content shown in the alert. Provide a localized string.\n */\n description: string;\n /**\n * Visual tone of the alert which controls icon and colors.\n * Defaults to `neutral`.\n */\n tone?: AlertTones;\n /**\n * Called when the close button is pressed. When omitted, no close button is rendered.\n */\n onClose?: () => void;\n /**\n * One or more actions to render as buttons. A single object renders one button;\n * an array renders multiple buttons. Provide localized `label` values.\n */\n action?: AlertAction | AlertAction[];\n /**\n * Accessible label for the close icon button. Provide a localized string.\n * Defaults to \"Close\".\n */\n closeAriaLabel?: string;\n /** Optional CSS class name for the root element. */\n className?: string;\n /** Optional test id for the root element. */\n 'data-fd'?: string;\n}\n\n/**\n * Describes a user action rendered as a button in the alert.\n */\nexport interface AlertAction {\n /** Optional unique identifier for this action. Recommended for stable React keys. */\n id?: string;\n /** Button text. Provide a localized string. */\n label: string;\n /** Visual variant of the button. Defaults to `secondary`. */\n type?: ButtonType;\n /** Click handler for the action. */\n onClick: () => void;\n /** Optional test id applied to the button. */\n 'data-fd'?: string;\n}\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledGlobalAlert = styled(MuiAlert, {\n shouldForwardProp: (prop: string): boolean => !['tone'].includes(prop),\n})<StyledAlertProps>(({ theme, tone }) => ({\n alignItems: 'center',\n backgroundColor: getAlertGlobalBackgroundColour(theme, tone),\n borderBottom: '1px solid',\n borderRadius: 0,\n borderColor: getAlertGlobalBorderColour(theme, tone),\n color: getAlertGlobalTextColour(theme, tone),\n padding: theme.spacing(3),\n paddingTop: theme.spacing(1.5),\n paddingBottom: theme.spacing(1.5),\n width: '100%',\n display: 'flex',\n position: 'relative',\n '& .MuiAlert-icon': {\n alignSelf: 'flex-start',\n },\n '& .MuiAlert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n flexGrow: 1,\n minWidth: 0,\n },\n '& .MuiAlert-action': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n marginLeft: 'auto',\n },\n '& .MuiAlert-action .MuiIconButton-root': {\n outline: 'none',\n boxShadow: 'none',\n border: 'none',\n },\n '& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible': {\n outline: 'none',\n boxShadow: 'none',\n },\n // Inline actions inside message container\n '& .fd-alert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n width: '100%',\n },\n '& .fd-alert-description': {\n flexGrow: 1,\n minWidth: 0,\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 'auto',\n display: 'none',\n },\n '& .fd-alert-actions-action': {\n display: 'flex',\n },\n // Mobile layout: stack and right-align button group below description\n [theme.breakpoints.down('tablet')]: {\n '& .fd-alert-message': {\n flexDirection: 'column',\n alignItems: 'stretch',\n gap: theme.spacing(2),\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 0,\n marginTop: theme.spacing(2),\n width: '100%',\n justifyContent: 'flex-end',\n display: 'flex',\n },\n '& .fd-alert-actions-action': {\n display: 'none',\n },\n '& .MuiAlert-action': {\n position: 'absolute',\n top: theme.spacing(3),\n right: theme.spacing(3),\n marginLeft: 0,\n },\n },\n}));\n\nconst ActionContainer = styled(Box)(\n ({ theme }): Record<string, unknown> => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n }),\n);\n\nconst AlertGlobalComponent = ({\n description,\n tone = 'neutral',\n onClose,\n action,\n className,\n closeAriaLabel = 'Close',\n 'data-fd': dataFd,\n}: AlertGlobalProps): ReactElement => {\n const theme = useTheme();\n const isMobile = useMediaQuery(theme.breakpoints.down('tablet'));\n\n const actionsArray = action ? (Array.isArray(action) ? action : [action]) : [];\n const actionButtons = actionsArray.map((actionItem) => {\n const uniqueKey =\n actionItem.id ?? `${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}-${actionItem.type ?? 'type'}`;\n return (\n <Button\n key={uniqueKey}\n data-fd={\n actionItem['data-fd'] ?? `action-button-${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}`\n }\n fdKey={actionItem.label}\n onClick={actionItem.onClick}\n size=\"small\"\n tone=\"neutral\"\n variant={actionItem.type ?? 'secondary'}\n >\n {actionItem.label}\n </Button>\n );\n });\n\n const nodes: ReactNode[] = [];\n if (actionButtons.length && !isMobile) {\n nodes.push(\n <ButtonGroup\n key=\"action-group-action\"\n align=\"right\"\n className=\"fd-alert-actions-action\"\n layout=\"horizontal\"\n size=\"small\"\n >\n {actionButtons}\n </ButtonGroup>,\n );\n }\n if (onClose) {\n nodes.push(\n <IconButton\n key=\"close\"\n aria-label={closeAriaLabel}\n data-fd=\"close-button\"\n onClick={onClose}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n <CancelIcon />\n </IconButton>,\n );\n }\n\n return (\n <StyledGlobalAlert\n action={nodes.length ? <ActionContainer>{nodes}</ActionContainer> : undefined}\n className={className}\n data-fd={dataFd}\n icon={getAlertGlobalIcon(theme, tone)}\n role=\"alert\"\n tone={tone}\n >\n <Box className=\"fd-alert-message\">\n <Box className=\"fd-alert-description\">{description}</Box>\n {isMobile && actionButtons.length ? (\n <ButtonGroup align=\"right\" className=\"fd-alert-actions-inline\" layout=\"horizontal\" size=\"small\">\n {actionButtons}\n </ButtonGroup>\n ) : null}\n </Box>\n </StyledGlobalAlert>\n );\n};\n\nconst AlertGlobal = memo(AlertGlobalComponent);\nAlertGlobal.displayName = 'AlertGlobal';\n\nexport default AlertGlobal;\n"],"names":["StyledGlobalAlert","styled","MuiAlert","shouldForwardProp","prop","includes","theme","tone","alignItems","backgroundColor","getAlertGlobalBackgroundColour","borderBottom","borderRadius","borderColor","getAlertGlobalBorderColour","color","getAlertGlobalTextColour","padding","spacing","paddingTop","paddingBottom","width","display","position","alignSelf","gap","flexGrow","minWidth","marginLeft","outline","boxShadow","border","breakpoints","down","flexDirection","marginTop","justifyContent","top","right","ActionContainer","Box","AlertGlobal","memo","description","onClose","action","className","closeAriaLabel","dataFd","useTheme","isMobile","useMediaQuery","actionButtons","Array","isArray","map","actionItem","uniqueKey","id","label","replace","toLowerCase","type","_jsx","Button","fdKey","onClick","size","variant","children","nodes","length","push","ButtonGroup","align","layout","IconButton","CancelIcon","undefined","icon","getAlertGlobalIcon","role","_jsxs","displayName"],"mappings":"wdAiFA,MAAMA,EAAoBC,EAAAA,OAAOC,EAAU,CACzCC,kBAAoBC,IAA2B,CAAC,QAAQC,SAASD,IADzCH,EAEL,EAAGK,QAAOC,WAAM,CACnCC,WAAY,SACZC,gBAAiBC,EAAAA,+BAA+BJ,EAAOC,GACvDI,aAAc,YACdC,aAAc,EACdC,YAAaC,EAAAA,2BAA2BR,EAAOC,GAC/CQ,MAAOC,EAAAA,yBAAyBV,EAAOC,GACvCU,QAASX,EAAMY,QAAQ,GACvBC,WAAYb,EAAMY,QAAQ,KAC1BE,cAAed,EAAMY,QAAQ,KAC7BG,MAAO,OACPC,QAAS,OACTC,SAAU,WACV,mBAAoB,CAClBC,UAAW,cAEb,sBAAuB,CACrBF,QAAS,OACTd,WAAY,SACZiB,IAAKnB,EAAMY,QAAQ,GACnBQ,SAAU,EACVC,SAAU,GAEZ,qBAAsB,CACpBL,QAAS,OACTd,WAAY,SACZiB,IAAKnB,EAAMY,QAAQ,GACnBU,WAAY,QAEd,yCAA0C,CACxCC,QAAS,OACTC,UAAW,OACXC,OAAQ,QAEV,qGAAsG,CACpGF,QAAS,OACTC,UAAW,QAGb,sBAAuB,CACrBR,QAAS,OACTd,WAAY,SACZiB,IAAKnB,EAAMY,QAAQ,GACnBG,MAAO,QAET,0BAA2B,CACzBK,SAAU,EACVC,SAAU,GAEZ,6BAA8B,CAC5BC,WAAY,OACZN,QAAS,QAEX,6BAA8B,CAC5BA,QAAS,QAGX,CAAChB,EAAM0B,YAAYC,KAAK,WAAY,CAClC,sBAAuB,CACrBC,cAAe,SACf1B,WAAY,UACZiB,IAAKnB,EAAMY,QAAQ,IAErB,6BAA8B,CAC5BU,WAAY,EACZO,UAAW7B,EAAMY,QAAQ,GACzBG,MAAO,OACPe,eAAgB,WAChBd,QAAS,QAEX,6BAA8B,CAC5BA,QAAS,QAEX,qBAAsB,CACpBC,SAAU,WACVc,IAAK/B,EAAMY,QAAQ,GACnBoB,MAAOhC,EAAMY,QAAQ,GACrBU,WAAY,QAKZW,EAAkBtC,EAAAA,OAAOuC,EAAPvC,EACtB,EAAGK,YAAO,CACRgB,QAAS,OACTd,WAAY,SACZiB,IAAKnB,EAAMY,QAAQ,OAwFjBuB,EAAcC,EAAAA,MApFS,EAC3BC,cACApC,OAAO,UACPqC,UACAC,SACAC,YACAC,iBAAiB,QACjB,UAAWC,MAEX,MAAM1C,EAAQ2C,IACRC,EAAWC,EAAc7C,EAAM0B,YAAYC,KAAK,WAGhDmB,GADeP,EAAUQ,MAAMC,QAAQT,GAAUA,EAAS,CAACA,GAAW,IACzCU,KAAKC,IACtC,MAAMC,EACJD,EAAWE,IAAM,GAAGF,EAAWG,MAAMC,QAAQ,OAAQ,KAAKC,iBAAiBL,EAAWM,MAAQ,SAChG,OACEC,EAAAA,IAACC,EAAAA,OAAM,CAAA,UAGHR,EAAW,YAAc,iBAAiBA,EAAWG,MAAMC,QAAQ,OAAQ,KAAKC,gBAElFI,MAAOT,EAAWG,MAClBO,QAASV,EAAWU,QACpBC,KAAK,QACL5D,KAAK,UACL6D,QAASZ,EAAWM,MAAQ,YAAWO,SAEtCb,EAAWG,OAVPF,MAeLa,EAAqB,GA8B3B,OA7BIlB,EAAcmB,SAAWrB,GAC3BoB,EAAME,KACJT,MAACU,EAAW,CAEVC,MAAM,QACN5B,UAAU,0BACV6B,OAAO,aACPR,KAAK,QAAOE,SAEXjB,GANG,wBAUNR,GACF0B,EAAME,KACJT,MAACa,EAAAA,WAAU,CAAA,aAEG7B,EAAc,UAClB,eACRmB,QAAStB,EACTuB,KAAK,QACL5D,KAAK,UACL6D,QAAQ,WAAUC,SAElBN,EAAAA,IAACc,EAAU,CAAA,IARP,UAcRd,EAAAA,IAAC/D,EAAiB,CAChB6C,OAAQyB,EAAMC,OAASR,EAAAA,IAACxB,YAAiB+B,SAA2BQ,EACpEhC,UAAWA,EAAS,UACXE,EACT+B,KAAMC,EAAAA,mBAAmB1E,EAAOC,GAChC0E,KAAK,QACL1E,KAAMA,EAAI8D,SAEVa,EAAAA,KAAC1C,EAAG,CAACM,UAAU,mBAAkBuB,SAAA,CAC/BN,EAAAA,IAACvB,EAAG,CAACM,UAAU,uBAAsBuB,SAAE1B,IACtCO,GAAYE,EAAcmB,OACzBR,EAAAA,IAACU,EAAW,CAACC,MAAM,QAAQ5B,UAAU,0BAA0B6B,OAAO,aAAaR,KAAK,iBACrFf,IAED,aAOZX,EAAY0C,YAAc"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/AlertGlobal/index.tsx"],"sourcesContent":["import { memo, type ReactElement, type ReactNode } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\n\nimport Box from '@fd/components/atoms/Box';\nimport Button from '@fd/components/atoms/Button';\nimport type { ButtonType } from '@fd/components/atoms/Button/getButtonStyles';\nimport IconButton from '@fd/components/atoms/IconButton';\nimport type { AlertTones } from '@fd/components/molecules/Alert';\nimport ButtonGroup from '@fd/components/molecules/ButtonGroup';\nimport CancelIcon from '@fd/icons/Cancel';\nimport styled from '@fd/utilities/styledUtilities';\nimport useMediaQuery from '@fd/utilities/useMediaQuery';\nimport useTheme from '@fd/utilities/useTheme';\n\nimport {\n getAlertGlobalBackgroundColour,\n getAlertGlobalBorderColour,\n getAlertGlobalIcon,\n getAlertGlobalTextColour,\n} from './alertGlobalTokens';\n\n/**\n * Global alert component for prominent, page-level messages.\n *\n * - Renders an icon and description with optional actions and a close button\n * - `action` accepts a single action object or an array of action objects\n * (use an array to render multiple buttons side-by-side)\n * - Consumers are responsible for providing localized strings for any\n * user-visible text (e.g. `description`, action `label`, `closeAriaLabel`).\n */\nexport interface AlertGlobalProps {\n /**\n * Message content shown in the alert. Provide a localized string.\n */\n description: string;\n /**\n * Visual tone of the alert which controls icon and colors.\n * Defaults to `neutral`.\n */\n tone?: AlertTones;\n /**\n * Called when the close button is pressed. When omitted, no close button is rendered.\n */\n onClose?: () => void;\n /**\n * One or more actions to render as buttons. A single object renders one button;\n * an array renders multiple buttons. Provide localized `label` values.\n */\n action?: AlertAction | AlertAction[];\n /**\n * Accessible label for the close icon button. Provide a localized string.\n * Defaults to \"Close\".\n */\n closeAriaLabel?: string;\n /** Optional CSS class name for the root element. */\n className?: string;\n /** Optional test id for the root element. */\n 'data-fd'?: string;\n}\n\n/**\n * Describes a user action rendered as a button in the alert.\n */\nexport interface AlertAction {\n /** Optional unique identifier for this action. Recommended for stable React keys. */\n id?: string;\n /** Button text. Provide a localized string. */\n label: string;\n /** Visual variant of the button. Defaults to `secondary`. */\n type?: ButtonType;\n /** Click handler for the action. */\n onClick: () => void;\n /** Optional test id applied to the button. */\n 'data-fd'?: string;\n}\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledGlobalAlert = styled(MuiAlert, {\n shouldForwardProp: (prop: string): boolean => !['tone'].includes(prop),\n})<StyledAlertProps>(({ theme, tone }) => ({\n alignItems: 'center',\n backgroundColor: getAlertGlobalBackgroundColour(theme, tone),\n borderBottom: '1px solid',\n borderRadius: 0,\n borderColor: getAlertGlobalBorderColour(theme, tone),\n color: getAlertGlobalTextColour(theme, tone),\n padding: theme.spacing(3),\n paddingTop: theme.spacing(1.5),\n paddingBottom: theme.spacing(1.5),\n width: '100%',\n display: 'flex',\n position: 'relative',\n '& .MuiAlert-icon': {\n alignSelf: 'flex-start',\n },\n '& .MuiAlert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n flexGrow: 1,\n minWidth: 0,\n },\n '& .MuiAlert-action': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n marginLeft: 'auto',\n },\n '& .MuiAlert-action .MuiIconButton-root': {\n outline: 'none',\n boxShadow: 'none',\n border: 'none',\n },\n '& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible': {\n outline: 'none',\n boxShadow: 'none',\n },\n // Inline actions inside message container\n '& .fd-alert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n width: '100%',\n },\n '& .fd-alert-description': {\n flexGrow: 1,\n minWidth: 0,\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 'auto',\n display: 'none',\n },\n '& .fd-alert-actions-action': {\n display: 'flex',\n },\n // Mobile layout: stack and right-align button group below description\n [theme.breakpoints.down('tablet')]: {\n '& .fd-alert-message': {\n flexDirection: 'column',\n alignItems: 'stretch',\n gap: theme.spacing(2),\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 0,\n marginTop: theme.spacing(2),\n width: '100%',\n justifyContent: 'flex-end',\n display: 'flex',\n },\n '& .fd-alert-actions-action': {\n display: 'none',\n },\n '& .MuiAlert-action': {\n position: 'absolute',\n top: theme.spacing(3),\n right: theme.spacing(3),\n marginLeft: 0,\n },\n },\n}));\n\nconst ActionContainer = styled(Box)(\n ({ theme }): Record<string, unknown> => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n }),\n);\n\nconst AlertGlobalComponent = ({\n description,\n tone = 'neutral',\n onClose,\n action,\n className,\n closeAriaLabel = 'Close',\n 'data-fd': dataFd,\n}: AlertGlobalProps): ReactElement => {\n const theme = useTheme();\n const isMobile = useMediaQuery(theme.breakpoints.down('tablet'));\n\n const actionsArray = action ? (Array.isArray(action) ? action : [action]) : [];\n const actionButtons = actionsArray.map((actionItem) => {\n const uniqueKey =\n actionItem.id ?? `${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}-${actionItem.type ?? 'type'}`;\n return (\n <Button\n key={uniqueKey}\n fdKey={\n actionItem['data-fd'] ?? `action-button-${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}`\n }\n onClick={actionItem.onClick}\n size=\"small\"\n tone=\"neutral\"\n variant={actionItem.type ?? 'secondary'}\n >\n {actionItem.label}\n </Button>\n );\n });\n\n const nodes: ReactNode[] = [];\n if (actionButtons.length && !isMobile) {\n nodes.push(\n <ButtonGroup\n key=\"action-group-action\"\n align=\"right\"\n className=\"fd-alert-actions-action\"\n layout=\"horizontal\"\n size=\"small\"\n >\n {actionButtons}\n </ButtonGroup>,\n );\n }\n if (onClose) {\n nodes.push(\n <IconButton\n key=\"close\"\n aria-label={closeAriaLabel}\n data-fd=\"close-button\"\n onClick={onClose}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n <CancelIcon />\n </IconButton>,\n );\n }\n\n return (\n <StyledGlobalAlert\n action={nodes.length ? <ActionContainer>{nodes}</ActionContainer> : undefined}\n className={className}\n data-fd={dataFd}\n icon={getAlertGlobalIcon(theme, tone)}\n role=\"alert\"\n tone={tone}\n >\n <Box className=\"fd-alert-message\">\n <Box className=\"fd-alert-description\">{description}</Box>\n {isMobile && actionButtons.length ? (\n <ButtonGroup align=\"right\" className=\"fd-alert-actions-inline\" layout=\"horizontal\" size=\"small\">\n {actionButtons}\n </ButtonGroup>\n ) : null}\n </Box>\n </StyledGlobalAlert>\n );\n};\n\nconst AlertGlobal = memo(AlertGlobalComponent);\nAlertGlobal.displayName = 'AlertGlobal';\n\nexport default AlertGlobal;\n"],"names":["StyledGlobalAlert","styled","MuiAlert","shouldForwardProp","prop","includes","theme","tone","alignItems","backgroundColor","getAlertGlobalBackgroundColour","borderBottom","borderRadius","borderColor","getAlertGlobalBorderColour","color","getAlertGlobalTextColour","padding","spacing","paddingTop","paddingBottom","width","display","position","alignSelf","gap","flexGrow","minWidth","marginLeft","outline","boxShadow","border","breakpoints","down","flexDirection","marginTop","justifyContent","top","right","ActionContainer","Box","AlertGlobal","memo","description","onClose","action","className","closeAriaLabel","dataFd","useTheme","isMobile","useMediaQuery","actionButtons","Array","isArray","map","actionItem","uniqueKey","id","label","replace","toLowerCase","type","_jsx","Button","fdKey","onClick","size","variant","children","nodes","length","push","ButtonGroup","align","layout","IconButton","CancelIcon","undefined","icon","getAlertGlobalIcon","role","_jsxs","displayName"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{memo as a}from"react";import i from"@mui/material/Alert";import o from"@mui/material/Box";import{Button as n}from"../../atoms/Button/index.js";import{IconButton as l}from"../../atoms/IconButton/index.js";import r from"../ButtonGroup/index.js";import s from"../../../icons/Cancel/index.js";import{styled as c}from"@mui/material/styles";import d from"@mui/material/useMediaQuery";import m from"@mui/material/styles/useTheme";import{getAlertGlobalTextColour as p,getAlertGlobalBorderColour as u,getAlertGlobalBackgroundColour as f,getAlertGlobalIcon as g}from"./alertGlobalTokens.js";const h=c(i,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({alignItems:"center",backgroundColor:f(e,t),borderBottom:"1px solid",borderRadius:0,borderColor:u(e,t),color:p(e,t),padding:e.spacing(3),paddingTop:e.spacing(1.5),paddingBottom:e.spacing(1.5),width:"100%",display:"flex",position:"relative","& .MuiAlert-icon":{alignSelf:"flex-start"},"& .MuiAlert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),flexGrow:1,minWidth:0},"& .MuiAlert-action":{display:"flex",alignItems:"center",gap:e.spacing(3),marginLeft:"auto"},"& .MuiAlert-action .MuiIconButton-root":{outline:"none",boxShadow:"none",border:"none"},"& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible":{outline:"none",boxShadow:"none"},"& .fd-alert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),width:"100%"},"& .fd-alert-description":{flexGrow:1,minWidth:0},"& .fd-alert-actions-inline":{marginLeft:"auto",display:"none"},"& .fd-alert-actions-action":{display:"flex"},[e.breakpoints.down("tablet")]:{"& .fd-alert-message":{flexDirection:"column",alignItems:"stretch",gap:e.spacing(2)},"& .fd-alert-actions-inline":{marginLeft:0,marginTop:e.spacing(2),width:"100%",justifyContent:"flex-end",display:"flex"},"& .fd-alert-actions-action":{display:"none"},"& .MuiAlert-action":{position:"absolute",top:e.spacing(3),right:e.spacing(3),marginLeft:0}}}))),y=c(o)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(3)}))),b=a((({description:a,tone:i="neutral",onClose:c,action:p,className:u,closeAriaLabel:f="Close","data-fd":b})=>{const x=m(),w=d(x.breakpoints.down("tablet")),A=(p?Array.isArray(p)?p:[p]:[]).map((t=>{const a=t.id??`${t.label.replace(/\s+/g,"-").toLowerCase()}-${t.type??"type"}`;return e(n,{
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{memo as a}from"react";import i from"@mui/material/Alert";import o from"@mui/material/Box";import{Button as n}from"../../atoms/Button/index.js";import{IconButton as l}from"../../atoms/IconButton/index.js";import r from"../ButtonGroup/index.js";import s from"../../../icons/Cancel/index.js";import{styled as c}from"@mui/material/styles";import d from"@mui/material/useMediaQuery";import m from"@mui/material/styles/useTheme";import{getAlertGlobalTextColour as p,getAlertGlobalBorderColour as u,getAlertGlobalBackgroundColour as f,getAlertGlobalIcon as g}from"./alertGlobalTokens.js";const h=c(i,{shouldForwardProp:e=>!["tone"].includes(e)})((({theme:e,tone:t})=>({alignItems:"center",backgroundColor:f(e,t),borderBottom:"1px solid",borderRadius:0,borderColor:u(e,t),color:p(e,t),padding:e.spacing(3),paddingTop:e.spacing(1.5),paddingBottom:e.spacing(1.5),width:"100%",display:"flex",position:"relative","& .MuiAlert-icon":{alignSelf:"flex-start"},"& .MuiAlert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),flexGrow:1,minWidth:0},"& .MuiAlert-action":{display:"flex",alignItems:"center",gap:e.spacing(3),marginLeft:"auto"},"& .MuiAlert-action .MuiIconButton-root":{outline:"none",boxShadow:"none",border:"none"},"& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible":{outline:"none",boxShadow:"none"},"& .fd-alert-message":{display:"flex",alignItems:"center",gap:e.spacing(2),width:"100%"},"& .fd-alert-description":{flexGrow:1,minWidth:0},"& .fd-alert-actions-inline":{marginLeft:"auto",display:"none"},"& .fd-alert-actions-action":{display:"flex"},[e.breakpoints.down("tablet")]:{"& .fd-alert-message":{flexDirection:"column",alignItems:"stretch",gap:e.spacing(2)},"& .fd-alert-actions-inline":{marginLeft:0,marginTop:e.spacing(2),width:"100%",justifyContent:"flex-end",display:"flex"},"& .fd-alert-actions-action":{display:"none"},"& .MuiAlert-action":{position:"absolute",top:e.spacing(3),right:e.spacing(3),marginLeft:0}}}))),y=c(o)((({theme:e})=>({display:"flex",alignItems:"center",gap:e.spacing(3)}))),b=a((({description:a,tone:i="neutral",onClose:c,action:p,className:u,closeAriaLabel:f="Close","data-fd":b})=>{const x=m(),w=d(x.breakpoints.down("tablet")),A=(p?Array.isArray(p)?p:[p]:[]).map((t=>{const a=t.id??`${t.label.replace(/\s+/g,"-").toLowerCase()}-${t.type??"type"}`;return e(n,{fdKey:t["data-fd"]??`action-button-${t.label.replace(/\s+/g,"-").toLowerCase()}`,onClick:t.onClick,size:"small",tone:"neutral",variant:t.type??"secondary",children:t.label},a)})),C=[];return A.length&&!w&&C.push(e(r,{align:"right",className:"fd-alert-actions-action",layout:"horizontal",size:"small",children:A},"action-group-action")),c&&C.push(e(l,{"aria-label":f,"data-fd":"close-button",onClick:c,size:"small",tone:"neutral",variant:"tertiary",children:e(s,{})},"close")),e(h,{action:C.length?e(y,{children:C}):void 0,className:u,"data-fd":b,icon:g(x,i),role:"alert",tone:i,children:t(o,{className:"fd-alert-message",children:[e(o,{className:"fd-alert-description",children:a}),w&&A.length?e(r,{align:"right",className:"fd-alert-actions-inline",layout:"horizontal",size:"small",children:A}):null]})})}));b.displayName="AlertGlobal";export{b as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/molecules/AlertGlobal/index.tsx"],"sourcesContent":["import { memo, type ReactElement, type ReactNode } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\n\nimport Box from '@fd/components/atoms/Box';\nimport Button from '@fd/components/atoms/Button';\nimport type { ButtonType } from '@fd/components/atoms/Button/getButtonStyles';\nimport IconButton from '@fd/components/atoms/IconButton';\nimport type { AlertTones } from '@fd/components/molecules/Alert';\nimport ButtonGroup from '@fd/components/molecules/ButtonGroup';\nimport CancelIcon from '@fd/icons/Cancel';\nimport styled from '@fd/utilities/styledUtilities';\nimport useMediaQuery from '@fd/utilities/useMediaQuery';\nimport useTheme from '@fd/utilities/useTheme';\n\nimport {\n getAlertGlobalBackgroundColour,\n getAlertGlobalBorderColour,\n getAlertGlobalIcon,\n getAlertGlobalTextColour,\n} from './alertGlobalTokens';\n\n/**\n * Global alert component for prominent, page-level messages.\n *\n * - Renders an icon and description with optional actions and a close button\n * - `action` accepts a single action object or an array of action objects\n * (use an array to render multiple buttons side-by-side)\n * - Consumers are responsible for providing localized strings for any\n * user-visible text (e.g. `description`, action `label`, `closeAriaLabel`).\n */\nexport interface AlertGlobalProps {\n /**\n * Message content shown in the alert. Provide a localized string.\n */\n description: string;\n /**\n * Visual tone of the alert which controls icon and colors.\n * Defaults to `neutral`.\n */\n tone?: AlertTones;\n /**\n * Called when the close button is pressed. When omitted, no close button is rendered.\n */\n onClose?: () => void;\n /**\n * One or more actions to render as buttons. A single object renders one button;\n * an array renders multiple buttons. Provide localized `label` values.\n */\n action?: AlertAction | AlertAction[];\n /**\n * Accessible label for the close icon button. Provide a localized string.\n * Defaults to \"Close\".\n */\n closeAriaLabel?: string;\n /** Optional CSS class name for the root element. */\n className?: string;\n /** Optional test id for the root element. */\n 'data-fd'?: string;\n}\n\n/**\n * Describes a user action rendered as a button in the alert.\n */\nexport interface AlertAction {\n /** Optional unique identifier for this action. Recommended for stable React keys. */\n id?: string;\n /** Button text. Provide a localized string. */\n label: string;\n /** Visual variant of the button. Defaults to `secondary`. */\n type?: ButtonType;\n /** Click handler for the action. */\n onClick: () => void;\n /** Optional test id applied to the button. */\n 'data-fd'?: string;\n}\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledGlobalAlert = styled(MuiAlert, {\n shouldForwardProp: (prop: string): boolean => !['tone'].includes(prop),\n})<StyledAlertProps>(({ theme, tone }) => ({\n alignItems: 'center',\n backgroundColor: getAlertGlobalBackgroundColour(theme, tone),\n borderBottom: '1px solid',\n borderRadius: 0,\n borderColor: getAlertGlobalBorderColour(theme, tone),\n color: getAlertGlobalTextColour(theme, tone),\n padding: theme.spacing(3),\n paddingTop: theme.spacing(1.5),\n paddingBottom: theme.spacing(1.5),\n width: '100%',\n display: 'flex',\n position: 'relative',\n '& .MuiAlert-icon': {\n alignSelf: 'flex-start',\n },\n '& .MuiAlert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n flexGrow: 1,\n minWidth: 0,\n },\n '& .MuiAlert-action': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n marginLeft: 'auto',\n },\n '& .MuiAlert-action .MuiIconButton-root': {\n outline: 'none',\n boxShadow: 'none',\n border: 'none',\n },\n '& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible': {\n outline: 'none',\n boxShadow: 'none',\n },\n // Inline actions inside message container\n '& .fd-alert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n width: '100%',\n },\n '& .fd-alert-description': {\n flexGrow: 1,\n minWidth: 0,\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 'auto',\n display: 'none',\n },\n '& .fd-alert-actions-action': {\n display: 'flex',\n },\n // Mobile layout: stack and right-align button group below description\n [theme.breakpoints.down('tablet')]: {\n '& .fd-alert-message': {\n flexDirection: 'column',\n alignItems: 'stretch',\n gap: theme.spacing(2),\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 0,\n marginTop: theme.spacing(2),\n width: '100%',\n justifyContent: 'flex-end',\n display: 'flex',\n },\n '& .fd-alert-actions-action': {\n display: 'none',\n },\n '& .MuiAlert-action': {\n position: 'absolute',\n top: theme.spacing(3),\n right: theme.spacing(3),\n marginLeft: 0,\n },\n },\n}));\n\nconst ActionContainer = styled(Box)(\n ({ theme }): Record<string, unknown> => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n }),\n);\n\nconst AlertGlobalComponent = ({\n description,\n tone = 'neutral',\n onClose,\n action,\n className,\n closeAriaLabel = 'Close',\n 'data-fd': dataFd,\n}: AlertGlobalProps): ReactElement => {\n const theme = useTheme();\n const isMobile = useMediaQuery(theme.breakpoints.down('tablet'));\n\n const actionsArray = action ? (Array.isArray(action) ? action : [action]) : [];\n const actionButtons = actionsArray.map((actionItem) => {\n const uniqueKey =\n actionItem.id ?? `${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}-${actionItem.type ?? 'type'}`;\n return (\n <Button\n key={uniqueKey}\n data-fd={\n actionItem['data-fd'] ?? `action-button-${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}`\n }\n fdKey={actionItem.label}\n onClick={actionItem.onClick}\n size=\"small\"\n tone=\"neutral\"\n variant={actionItem.type ?? 'secondary'}\n >\n {actionItem.label}\n </Button>\n );\n });\n\n const nodes: ReactNode[] = [];\n if (actionButtons.length && !isMobile) {\n nodes.push(\n <ButtonGroup\n key=\"action-group-action\"\n align=\"right\"\n className=\"fd-alert-actions-action\"\n layout=\"horizontal\"\n size=\"small\"\n >\n {actionButtons}\n </ButtonGroup>,\n );\n }\n if (onClose) {\n nodes.push(\n <IconButton\n key=\"close\"\n aria-label={closeAriaLabel}\n data-fd=\"close-button\"\n onClick={onClose}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n <CancelIcon />\n </IconButton>,\n );\n }\n\n return (\n <StyledGlobalAlert\n action={nodes.length ? <ActionContainer>{nodes}</ActionContainer> : undefined}\n className={className}\n data-fd={dataFd}\n icon={getAlertGlobalIcon(theme, tone)}\n role=\"alert\"\n tone={tone}\n >\n <Box className=\"fd-alert-message\">\n <Box className=\"fd-alert-description\">{description}</Box>\n {isMobile && actionButtons.length ? (\n <ButtonGroup align=\"right\" className=\"fd-alert-actions-inline\" layout=\"horizontal\" size=\"small\">\n {actionButtons}\n </ButtonGroup>\n ) : null}\n </Box>\n </StyledGlobalAlert>\n );\n};\n\nconst AlertGlobal = memo(AlertGlobalComponent);\nAlertGlobal.displayName = 'AlertGlobal';\n\nexport default AlertGlobal;\n"],"names":["StyledGlobalAlert","styled","MuiAlert","shouldForwardProp","prop","includes","theme","tone","alignItems","backgroundColor","getAlertGlobalBackgroundColour","borderBottom","borderRadius","borderColor","getAlertGlobalBorderColour","color","getAlertGlobalTextColour","padding","spacing","paddingTop","paddingBottom","width","display","position","alignSelf","gap","flexGrow","minWidth","marginLeft","outline","boxShadow","border","breakpoints","down","flexDirection","marginTop","justifyContent","top","right","ActionContainer","Box","AlertGlobal","memo","description","onClose","action","className","closeAriaLabel","dataFd","useTheme","isMobile","useMediaQuery","actionButtons","Array","isArray","map","actionItem","uniqueKey","id","label","replace","toLowerCase","type","_jsx","Button","fdKey","onClick","size","variant","children","nodes","length","push","ButtonGroup","align","layout","IconButton","CancelIcon","undefined","icon","getAlertGlobalIcon","role","_jsxs","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/molecules/AlertGlobal/index.tsx"],"sourcesContent":["import { memo, type ReactElement, type ReactNode } from 'react';\n\nimport MuiAlert from '@mui/material/Alert';\n\nimport Box from '@fd/components/atoms/Box';\nimport Button from '@fd/components/atoms/Button';\nimport type { ButtonType } from '@fd/components/atoms/Button/getButtonStyles';\nimport IconButton from '@fd/components/atoms/IconButton';\nimport type { AlertTones } from '@fd/components/molecules/Alert';\nimport ButtonGroup from '@fd/components/molecules/ButtonGroup';\nimport CancelIcon from '@fd/icons/Cancel';\nimport styled from '@fd/utilities/styledUtilities';\nimport useMediaQuery from '@fd/utilities/useMediaQuery';\nimport useTheme from '@fd/utilities/useTheme';\n\nimport {\n getAlertGlobalBackgroundColour,\n getAlertGlobalBorderColour,\n getAlertGlobalIcon,\n getAlertGlobalTextColour,\n} from './alertGlobalTokens';\n\n/**\n * Global alert component for prominent, page-level messages.\n *\n * - Renders an icon and description with optional actions and a close button\n * - `action` accepts a single action object or an array of action objects\n * (use an array to render multiple buttons side-by-side)\n * - Consumers are responsible for providing localized strings for any\n * user-visible text (e.g. `description`, action `label`, `closeAriaLabel`).\n */\nexport interface AlertGlobalProps {\n /**\n * Message content shown in the alert. Provide a localized string.\n */\n description: string;\n /**\n * Visual tone of the alert which controls icon and colors.\n * Defaults to `neutral`.\n */\n tone?: AlertTones;\n /**\n * Called when the close button is pressed. When omitted, no close button is rendered.\n */\n onClose?: () => void;\n /**\n * One or more actions to render as buttons. A single object renders one button;\n * an array renders multiple buttons. Provide localized `label` values.\n */\n action?: AlertAction | AlertAction[];\n /**\n * Accessible label for the close icon button. Provide a localized string.\n * Defaults to \"Close\".\n */\n closeAriaLabel?: string;\n /** Optional CSS class name for the root element. */\n className?: string;\n /** Optional test id for the root element. */\n 'data-fd'?: string;\n}\n\n/**\n * Describes a user action rendered as a button in the alert.\n */\nexport interface AlertAction {\n /** Optional unique identifier for this action. Recommended for stable React keys. */\n id?: string;\n /** Button text. Provide a localized string. */\n label: string;\n /** Visual variant of the button. Defaults to `secondary`. */\n type?: ButtonType;\n /** Click handler for the action. */\n onClick: () => void;\n /** Optional test id applied to the button. */\n 'data-fd'?: string;\n}\n\ninterface StyledAlertProps {\n tone: AlertTones;\n}\n\nconst StyledGlobalAlert = styled(MuiAlert, {\n shouldForwardProp: (prop: string): boolean => !['tone'].includes(prop),\n})<StyledAlertProps>(({ theme, tone }) => ({\n alignItems: 'center',\n backgroundColor: getAlertGlobalBackgroundColour(theme, tone),\n borderBottom: '1px solid',\n borderRadius: 0,\n borderColor: getAlertGlobalBorderColour(theme, tone),\n color: getAlertGlobalTextColour(theme, tone),\n padding: theme.spacing(3),\n paddingTop: theme.spacing(1.5),\n paddingBottom: theme.spacing(1.5),\n width: '100%',\n display: 'flex',\n position: 'relative',\n '& .MuiAlert-icon': {\n alignSelf: 'flex-start',\n },\n '& .MuiAlert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n flexGrow: 1,\n minWidth: 0,\n },\n '& .MuiAlert-action': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n marginLeft: 'auto',\n },\n '& .MuiAlert-action .MuiIconButton-root': {\n outline: 'none',\n boxShadow: 'none',\n border: 'none',\n },\n '& .MuiAlert-action .MuiIconButton-root:focus, & .MuiAlert-action .MuiIconButton-root:focus-visible': {\n outline: 'none',\n boxShadow: 'none',\n },\n // Inline actions inside message container\n '& .fd-alert-message': {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n width: '100%',\n },\n '& .fd-alert-description': {\n flexGrow: 1,\n minWidth: 0,\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 'auto',\n display: 'none',\n },\n '& .fd-alert-actions-action': {\n display: 'flex',\n },\n // Mobile layout: stack and right-align button group below description\n [theme.breakpoints.down('tablet')]: {\n '& .fd-alert-message': {\n flexDirection: 'column',\n alignItems: 'stretch',\n gap: theme.spacing(2),\n },\n '& .fd-alert-actions-inline': {\n marginLeft: 0,\n marginTop: theme.spacing(2),\n width: '100%',\n justifyContent: 'flex-end',\n display: 'flex',\n },\n '& .fd-alert-actions-action': {\n display: 'none',\n },\n '& .MuiAlert-action': {\n position: 'absolute',\n top: theme.spacing(3),\n right: theme.spacing(3),\n marginLeft: 0,\n },\n },\n}));\n\nconst ActionContainer = styled(Box)(\n ({ theme }): Record<string, unknown> => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(3),\n }),\n);\n\nconst AlertGlobalComponent = ({\n description,\n tone = 'neutral',\n onClose,\n action,\n className,\n closeAriaLabel = 'Close',\n 'data-fd': dataFd,\n}: AlertGlobalProps): ReactElement => {\n const theme = useTheme();\n const isMobile = useMediaQuery(theme.breakpoints.down('tablet'));\n\n const actionsArray = action ? (Array.isArray(action) ? action : [action]) : [];\n const actionButtons = actionsArray.map((actionItem) => {\n const uniqueKey =\n actionItem.id ?? `${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}-${actionItem.type ?? 'type'}`;\n return (\n <Button\n key={uniqueKey}\n fdKey={\n actionItem['data-fd'] ?? `action-button-${actionItem.label.replace(/\\s+/g, '-').toLowerCase()}`\n }\n onClick={actionItem.onClick}\n size=\"small\"\n tone=\"neutral\"\n variant={actionItem.type ?? 'secondary'}\n >\n {actionItem.label}\n </Button>\n );\n });\n\n const nodes: ReactNode[] = [];\n if (actionButtons.length && !isMobile) {\n nodes.push(\n <ButtonGroup\n key=\"action-group-action\"\n align=\"right\"\n className=\"fd-alert-actions-action\"\n layout=\"horizontal\"\n size=\"small\"\n >\n {actionButtons}\n </ButtonGroup>,\n );\n }\n if (onClose) {\n nodes.push(\n <IconButton\n key=\"close\"\n aria-label={closeAriaLabel}\n data-fd=\"close-button\"\n onClick={onClose}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n <CancelIcon />\n </IconButton>,\n );\n }\n\n return (\n <StyledGlobalAlert\n action={nodes.length ? <ActionContainer>{nodes}</ActionContainer> : undefined}\n className={className}\n data-fd={dataFd}\n icon={getAlertGlobalIcon(theme, tone)}\n role=\"alert\"\n tone={tone}\n >\n <Box className=\"fd-alert-message\">\n <Box className=\"fd-alert-description\">{description}</Box>\n {isMobile && actionButtons.length ? (\n <ButtonGroup align=\"right\" className=\"fd-alert-actions-inline\" layout=\"horizontal\" size=\"small\">\n {actionButtons}\n </ButtonGroup>\n ) : null}\n </Box>\n </StyledGlobalAlert>\n );\n};\n\nconst AlertGlobal = memo(AlertGlobalComponent);\nAlertGlobal.displayName = 'AlertGlobal';\n\nexport default AlertGlobal;\n"],"names":["StyledGlobalAlert","styled","MuiAlert","shouldForwardProp","prop","includes","theme","tone","alignItems","backgroundColor","getAlertGlobalBackgroundColour","borderBottom","borderRadius","borderColor","getAlertGlobalBorderColour","color","getAlertGlobalTextColour","padding","spacing","paddingTop","paddingBottom","width","display","position","alignSelf","gap","flexGrow","minWidth","marginLeft","outline","boxShadow","border","breakpoints","down","flexDirection","marginTop","justifyContent","top","right","ActionContainer","Box","AlertGlobal","memo","description","onClose","action","className","closeAriaLabel","dataFd","useTheme","isMobile","useMediaQuery","actionButtons","Array","isArray","map","actionItem","uniqueKey","id","label","replace","toLowerCase","type","_jsx","Button","fdKey","onClick","size","variant","children","nodes","length","push","ButtonGroup","align","layout","IconButton","CancelIcon","undefined","icon","getAlertGlobalIcon","role","_jsxs","displayName"],"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("react"),i=require("@mui/material/ListSubheader"),r=require("@mui/material/styles"),a=require("../../atoms/Avatar/index.cjs.js"),o=require("@mui/material/Box"),n=require("../../atoms/Button/index.cjs.js"),s=require("@mui/material/Divider"),l=require("../../atoms/IconButton/index.cjs.js"),c=require("@mui/material/ListItemText"),d=require("../../atoms/MenuItem/index.cjs.js"),u=require("@mui/material/Menu"),m=require("../../../icons/ArrowDown01/index.cjs.js"),p=require("../../../icons/ArrowUp01/index.cjs.js"),x=require("../../../icons/MoreVertical/index.cjs.js");const h=r.styled(n.Button)((({theme:e,size:t,disabled:i})=>({height:"small"===t?48:64,padding:e.spacing(1,2),textDecoration:"none","& .MuiButton-icon":{color:i?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]},"&:focus-visible, &.Mui-focusVisible":{backgroundColor:e.palette.semantic.fill["fill-weak"]}}))),b=r.styled(i)((({theme:e})=>({borderBottom:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,padding:e.spacing(1,2)})));b.muiName=i.muiName,b.muiSkipListHighlight=i.muiSkipListHighlight??!0;const g=r.styled(o,{shouldForwardProp:e=>!["disabled","size"].includes(e)})((({theme:e,disabled:t,size:i})=>({display:"flex",gap:"small"===i?e.spacing(1):e.spacing(1.5),alignItems:"center",textAlign:"left",...t&&{"& .MuiAvatar-root":{opacity:e.palette.action.disabledOpacity}," & .MuiListItemText-root, & .MuiListItemText-primary, & .MuiListItemText-secondary":{color:e.palette.semantic.text["text-disabled"]}}}))),j=({align:r="bottom-left",ariaLabel:o="",avatarSrc:j="",disabled:y=!1,fdKey:f,label:v,options:k=[],optionsType:z="text",secondaryText:M,size:q="medium",type:T="button",...C})=>{const[I,$]=t.useState(null),L=Boolean(I),O=`${f}-trigger`,w=`${f}-menu`,B=e=>{y||$(e.currentTarget)},A=()=>{$(null)},P=e=>t=>{e?.(t),A()},S=t=>e.jsxs(g,{disabled:y,size:t,children:[e.jsx(a,{"aria-hidden":!0,alt:"",size:t,src:j,type:"logo"}),e.jsx(c,{primary:v,secondary:M})]}),D=(t,i="text",r="root")=>{switch(i){case"checkboxes":return((t,i)=>t.map(((t,r)=>e.jsx(d.MenuItem,{checked:t.checked,disabled:t.disabled,label:t.label,onCheckedChange:t.onCheckedChange,secondaryText:t.secondaryText,type:"checkbox"},t.id??`${i}-checkbox-${r}`))))(t,r);case"icons":return((t,i)=>t.map(((t,r)=>e.jsx(d.MenuItem,{disabled:t.disabled,icon:t.icon,label:t.label,onClick:P(t.onClick),secondaryText:t.secondaryText,type:"icon"},t.id??`${i}-icon-${r}`))))(t,r);default:return((t,i)=>t.map(((t,r)=>e.jsx(d.MenuItem,{disabled:t.disabled,label:t.label,onClick:P(t.onClick),secondaryText:t.secondaryText,type:"text"},t.id??`${i}-text-${r}`))))(t,r)}},K=t.useMemo((()=>{return k&&0!==k.length?"groups"===z?(t=k).flatMap(((r,a)=>{const o=r.id??`group-${a}`;return[r.groupLabel?e.jsx(i,{children:r.groupLabel},`subheader-${o}`):null,...D(r.options,r.optionsType,o),a<t.length-1?e.jsx(s,{},`divider-${o}`):null]})):D(k,z):null;var t}),[k,z]),F=((e="bottom-left")=>{switch(e){case"bottom-left":default:return{anchorOrigin:{vertical:"bottom",horizontal:"left"},transformOrigin:{vertical:"top",horizontal:"left"}};case"bottom-right":return{anchorOrigin:{vertical:"bottom",horizontal:"right"},transformOrigin:{vertical:"top",horizontal:"right"}};case"top-left":return{anchorOrigin:{vertical:"top",horizontal:"left"},transformOrigin:{vertical:"bottom",horizontal:"left"}};case"top-right":return{anchorOrigin:{vertical:"top",horizontal:"right"},transformOrigin:{vertical:"bottom",horizontal:"right"}}}})(r);return e.jsxs(e.Fragment,{children:["icon-button"===T?e.jsx(l.IconButton,{"aria-controls":L?w:void 0,"aria-expanded":L,"aria-haspopup":"menu","aria-label":o,disabled:y,fdKey:f,id:O,onClick:B,size:q,variant:"secondary",children:e.jsx(x,{})}):"avatar"===T?e.jsx(h,{"aria-controls":L?w:void 0,"aria-expanded":L,"aria-haspopup":"menu",disabled:y,endIcon:L?e.jsx(p,{}):e.jsx(m,{}),fdKey:f,id:O,onClick:B,size:q,variant:"tertiary",children:S(q)}):e.jsx(n.Button,{"aria-controls":L?w:void 0,"aria-expanded":L,"aria-haspopup":"menu",disabled:y,endIcon:L?e.jsx(p,{}):e.jsx(m,{}),fdKey:f,id:O,onClick:B,size:q,variant:"secondary",children:v}),e.jsxs(u,{...C,...F,anchorEl:I,onClose:A,open:L,slotProps:{...C.slotProps,list:{...C.slotProps?.list??{},id:w,"aria-labelledby":O}},children:["avatar"===T&&e.jsx(b,{children:S("medium")}),K]})]})};exports.DropdownMenu=j,exports.default=j;
|
|
2
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/molecules/DropdownMenu/index.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\n\nimport MuiListSubheader from '@mui/material/ListSubheader';\nimport type { MenuProps as MuiMenuProps } from '@mui/material/Menu';\nimport { styled } from '@mui/material/styles';\n\nimport Avatar from '@fd/components/atoms/Avatar';\nimport Box from '@fd/components/atoms/Box';\nimport Button from '@fd/components/atoms/Button';\nimport Divider from '@fd/components/atoms/Divider';\nimport IconButton from '@fd/components/atoms/IconButton';\nimport ListItemText from '@fd/components/atoms/ListItemText';\nimport MenuItem, {\n type CheckboxMenuItemProps,\n type IconMenuItemProps,\n type MenuItemProps,\n type TextMenuItemProps,\n} from '@fd/components/atoms/MenuItem';\nimport Menu from '@fd/components/molecules/Menu';\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport MoreVerticalIcon from '@fd/icons/MoreVertical';\n\n/** Props for the DropdownMenuCheckboxOption component */\nexport type DropdownMenuCheckboxOption = Omit<CheckboxMenuItemProps, 'type'>;\n\n/** Props for the DropdownMenuIconOption component */\nexport type DropdownMenuIconOption = Omit<IconMenuItemProps, 'type'>;\n\n/** Props for the DropdownMenuTextOption component */\nexport type DropdownMenuTextOption = Omit<TextMenuItemProps, 'type'>;\n\ninterface DropdownMenuGroupOptionBase {\n /** Label of the group */\n groupLabel?: React.ReactNode;\n /** ID of the group */\n id?: string;\n}\n\ninterface DropdownMenuGroupOptionCheckbox extends DropdownMenuGroupOptionBase {\n /** Type of the menu options */\n optionsType: 'checkboxes';\n /** Options of the menu */\n options: DropdownMenuCheckboxOption[];\n}\n\ninterface DropdownMenuGroupOptionIcon extends DropdownMenuGroupOptionBase {\n /** Type of the menu options */\n optionsType: 'icons';\n /** Options of the menu */\n options: DropdownMenuIconOption[];\n}\n\ninterface DropdownMenuGroupOptionText extends DropdownMenuGroupOptionBase {\n /** Type of the menu options */\n optionsType?: 'text';\n /** Options of the menu */\n options: DropdownMenuTextOption[];\n}\n\n/** Props for the DropdownMenuGroupOption component */\nexport type DropdownMenuGroupOption =\n | DropdownMenuGroupOptionCheckbox\n | DropdownMenuGroupOptionIcon\n | DropdownMenuGroupOptionText;\n\ninterface DropdownMenuBaseCommonProps extends Omit<MuiMenuProps, 'anchorEl' | 'onClose' | 'open'> {\n /** Alignment of the menu */\n align?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';\n /** Disabled state of the menu */\n disabled?: boolean;\n /** Key of the menu */\n fdKey: string;\n /** Size of the menu */\n size?: 'medium' | 'small';\n}\n\ninterface DropdownMenuCheckboxesProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'checkboxes';\n /** Options of the menu */\n options: DropdownMenuCheckboxOption[];\n}\n\ninterface DropdownMenuIconsProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'icons';\n /** Options of the menu */\n options: DropdownMenuIconOption[];\n}\n\ninterface DropdownMenuTextProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'text';\n /** Options of the menu */\n options: DropdownMenuTextOption[];\n}\n\ntype DropdownMenuOptionsProps = DropdownMenuCheckboxesProps | DropdownMenuIconsProps | DropdownMenuTextProps;\n\ninterface DropdownMenuOptionsGroupsProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'groups';\n /** Options of the menu */\n options: DropdownMenuGroupOption[];\n}\n\ntype DropdownMenuBaseProps = DropdownMenuOptionsGroupsProps | DropdownMenuOptionsProps;\n\ntype AvatarDropdownMenuProps = DropdownMenuBaseProps & {\n /** Aria-label of the trigger */\n ariaLabel?: never;\n /** Secondary text of the menu item */\n secondaryText?: string;\n /** Source URL for the avatar image */\n avatarSrc: string;\n /** Label of the trigger */\n label: string;\n /** Type of the menu item */\n type: 'avatar';\n};\n\ntype ButtonDropdownMenuProps = DropdownMenuBaseProps & {\n /** Aria-label of the trigger */\n ariaLabel?: never;\n /** Secondary text of the menu item */\n secondaryText?: never;\n /** Source URL for the avatar image */\n avatarSrc?: never;\n /** Label of the trigger */\n label: string;\n /** Type of the menu item */\n type: 'button';\n};\n\ntype IconButtonDropdownMenuProps = DropdownMenuBaseProps & {\n /** Aria-label of the trigger */\n ariaLabel: string;\n /** Secondary text of the menu item */\n secondaryText?: never;\n /** Source URL for the avatar image */\n avatarSrc?: never;\n /** Label of the trigger */\n label?: never;\n /** Type of the menu item */\n type: 'icon-button';\n};\n\n/** Props for the DropdownMenu component */\nexport type DropdownMenuProps =\n | AvatarDropdownMenuProps\n | ButtonDropdownMenuProps\n | IconButtonDropdownMenuProps;\n\nconst StyledAvatarDropdownMenuButton = styled(Button)<{ disabled?: boolean; size: 'medium' | 'small' }>(\n ({ theme, size, disabled }) => ({\n height: size === 'small' ? 48 : 64,\n padding: theme.spacing(1, 2),\n textDecoration: 'none',\n\n '& .MuiButton-icon': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n\n '&:focus-visible, &.Mui-focusVisible': {\n backgroundColor: theme.palette.semantic.fill['fill-weak'],\n },\n }),\n);\n\nconst StyledAvatarListSubheader = styled(MuiListSubheader)(({ theme }) => ({\n borderBottom: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n padding: theme.spacing(1, 2),\n}));\n\n// Preserve MUI internals so MenuList handles it correctly\n// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n(StyledAvatarListSubheader as any).muiName = (MuiListSubheader as any).muiName;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n(StyledAvatarListSubheader as any).muiSkipListHighlight =\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (MuiListSubheader as unknown as { muiSkipListHighlight?: boolean }).muiSkipListHighlight ?? true;\n\nconst StyledAvatarLabelContainer = styled(Box, {\n shouldForwardProp: (prop) => !['disabled', 'size'].includes(prop as string),\n})<{ disabled: boolean; size: 'medium' | 'small' }>(({ theme, disabled, size }) => ({\n display: 'flex',\n gap: size === 'small' ? theme.spacing(1) : theme.spacing(1.5),\n alignItems: 'center',\n textAlign: 'left',\n\n ...(disabled && {\n '& .MuiAvatar-root': {\n opacity: theme.palette.action.disabledOpacity,\n },\n ' & .MuiListItemText-root, & .MuiListItemText-primary, & .MuiListItemText-secondary': {\n color: theme.palette.semantic.text['text-disabled'],\n },\n }),\n}));\n\nconst mapAlignToOrigins = (\n align: DropdownMenuProps['align'] = 'bottom-left',\n): Pick<MuiMenuProps, 'anchorOrigin' | 'transformOrigin'> => {\n switch (align) {\n case 'bottom-left':\n return {\n anchorOrigin: { vertical: 'bottom', horizontal: 'left' },\n transformOrigin: { vertical: 'top', horizontal: 'left' },\n };\n case 'bottom-right':\n return {\n anchorOrigin: { vertical: 'bottom', horizontal: 'right' },\n transformOrigin: { vertical: 'top', horizontal: 'right' },\n };\n case 'top-left':\n return {\n anchorOrigin: { vertical: 'top', horizontal: 'left' },\n transformOrigin: { vertical: 'bottom', horizontal: 'left' },\n };\n case 'top-right':\n return {\n anchorOrigin: { vertical: 'top', horizontal: 'right' },\n transformOrigin: { vertical: 'bottom', horizontal: 'right' },\n };\n default:\n return {\n anchorOrigin: { vertical: 'bottom', horizontal: 'left' },\n transformOrigin: { vertical: 'top', horizontal: 'left' },\n };\n }\n};\n\n/**\n * A customizable DropdownMenu component supporting button and checkbox menu items with optional groups.\n *\n * @param props - The component props\n * @returns The rendered DropdownMenu component\n */\nexport const DropdownMenu = ({\n align = 'bottom-left',\n ariaLabel = '',\n avatarSrc = '',\n disabled = false,\n fdKey,\n label,\n options = [],\n optionsType = 'text',\n secondaryText,\n size = 'medium',\n type = 'button',\n ...props\n}: DropdownMenuProps): JSX.Element => {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n\n const triggerId = `${fdKey}-trigger`;\n const menuId = `${fdKey}-menu`;\n\n const handleOpen = (event: React.MouseEvent<HTMLElement>): void => {\n if (disabled) {\n return;\n }\n\n setAnchorEl(event.currentTarget);\n };\n\n const handleClose = (): void => {\n setAnchorEl(null);\n };\n\n const handleClick =\n (onClick?: React.MouseEventHandler<HTMLLIElement>) =>\n (event: React.MouseEvent<HTMLLIElement>): void => {\n onClick?.(event);\n handleClose();\n };\n\n const renderAvatarLabelContainer = (size: 'medium' | 'small'): JSX.Element | null => (\n <StyledAvatarLabelContainer disabled={disabled} size={size}>\n <Avatar\n aria-hidden\n alt=\"\" // Avatar is described by ListItemText\n size={size}\n src={avatarSrc}\n type=\"logo\"\n />\n <ListItemText primary={label} secondary={secondaryText} />\n </StyledAvatarLabelContainer>\n );\n\n const renderTrigger = (): JSX.Element => {\n if (type === 'icon-button') {\n return (\n <IconButton\n aria-controls={open ? menuId : undefined}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n aria-label={ariaLabel}\n disabled={disabled}\n fdKey={fdKey}\n id={triggerId}\n onClick={handleOpen}\n size={size}\n variant=\"secondary\"\n >\n <MoreVerticalIcon />\n </IconButton>\n );\n }\n if (type === 'avatar') {\n return (\n <StyledAvatarDropdownMenuButton\n aria-controls={open ? menuId : undefined}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n disabled={disabled}\n endIcon={open ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n fdKey={fdKey}\n id={triggerId}\n onClick={handleOpen}\n size={size}\n variant=\"tertiary\"\n >\n {renderAvatarLabelContainer(size)}\n </StyledAvatarDropdownMenuButton>\n );\n }\n\n return (\n <Button\n aria-controls={open ? menuId : undefined}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n disabled={disabled}\n endIcon={open ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n fdKey={fdKey}\n id={triggerId}\n onClick={handleOpen}\n size={size}\n variant=\"secondary\"\n >\n {label}\n </Button>\n );\n };\n\n const renderCheckboxItems = (items: CheckboxMenuItemProps[], keyPrefix: string): JSX.Element[] =>\n items.map((item, index) => {\n return (\n <MenuItem\n key={item.id ?? `${keyPrefix}-checkbox-${index}`}\n checked={item.checked}\n disabled={item.disabled}\n label={item.label}\n onCheckedChange={item.onCheckedChange}\n secondaryText={item.secondaryText}\n type=\"checkbox\"\n />\n );\n });\n\n const renderIconItems = (items: IconMenuItemProps[], keyPrefix: string): JSX.Element[] =>\n items.map((item, index) => {\n return (\n <MenuItem\n key={item.id ?? `${keyPrefix}-icon-${index}`}\n disabled={item.disabled}\n icon={item.icon}\n label={item.label}\n onClick={handleClick(item.onClick)}\n secondaryText={item.secondaryText}\n type=\"icon\"\n />\n );\n });\n\n const renderTextItems = (items: TextMenuItemProps[], keyPrefix: string): JSX.Element[] =>\n items.map((item, index) => {\n return (\n <MenuItem\n key={item.id ?? `${keyPrefix}-text-${index}`}\n disabled={item.disabled}\n label={item.label}\n onClick={handleClick(item.onClick)}\n secondaryText={item.secondaryText}\n type=\"text\"\n />\n );\n });\n\n const renderItems = (\n items: Omit<MenuItemProps, 'type'>[],\n optionsType: DropdownMenuProps['optionsType'] = 'text',\n keyPrefix: string = 'root',\n ): JSX.Element[] => {\n switch (optionsType) {\n case 'checkboxes':\n return renderCheckboxItems(items as CheckboxMenuItemProps[], keyPrefix);\n case 'icons':\n return renderIconItems(items as IconMenuItemProps[], keyPrefix);\n case 'text':\n default:\n return renderTextItems(items as TextMenuItemProps[], keyPrefix);\n }\n };\n\n // Returns a flat array of group items (subheaders, items, dividers) needed for accessibility\n const renderGroupItems = (groups: DropdownMenuGroupOption[]): (JSX.Element | null)[] =>\n groups.flatMap((group, index) => {\n const groupKey = group.id ?? `group-${index}`;\n\n const header = group.groupLabel ? (\n <MuiListSubheader key={`subheader-${groupKey}`}>{group.groupLabel}</MuiListSubheader>\n ) : null;\n const items = renderItems(group.options, group.optionsType, groupKey);\n const divider = index < groups.length - 1 ? <Divider key={`divider-${groupKey}`} /> : null;\n\n return [header, ...items, divider];\n });\n\n const renderAvatarListSubheader = (): JSX.Element => {\n return <StyledAvatarListSubheader>{renderAvatarLabelContainer('medium')}</StyledAvatarListSubheader>;\n };\n\n const optionsItems = useMemo(() => {\n if (!options || options.length === 0) {\n return null;\n }\n\n if (optionsType === 'groups') {\n return renderGroupItems(options as DropdownMenuGroupOption[]);\n }\n\n return renderItems(options, optionsType);\n }, [options, optionsType]);\n\n const origins = mapAlignToOrigins(align);\n\n return (\n <>\n {renderTrigger()}\n\n <Menu\n {...props}\n {...origins}\n anchorEl={anchorEl}\n onClose={handleClose}\n open={open}\n slotProps={{\n ...props.slotProps,\n list: {\n ...(props.slotProps?.list ?? {}),\n id: menuId,\n 'aria-labelledby': triggerId,\n },\n }}\n >\n {type === 'avatar' && renderAvatarListSubheader()}\n {optionsItems}\n </Menu>\n </>\n );\n};\n\nexport default DropdownMenu;\n"],"names":["StyledAvatarDropdownMenuButton","styled","Button","theme","size","disabled","height","padding","spacing","textDecoration","color","palette","semantic","icon","backgroundColor","fill","StyledAvatarListSubheader","MuiListSubheader","borderBottom","stroke","muiName","muiSkipListHighlight","StyledAvatarLabelContainer","Box","shouldForwardProp","prop","includes","display","gap","alignItems","textAlign","opacity","action","disabledOpacity","text","DropdownMenu","align","ariaLabel","avatarSrc","fdKey","label","options","optionsType","secondaryText","type","props","anchorEl","setAnchorEl","useState","open","Boolean","triggerId","menuId","handleOpen","event","currentTarget","handleClose","handleClick","onClick","renderAvatarLabelContainer","_jsxs","children","_jsx","Avatar","alt","src","ListItemText","primary","secondary","renderItems","items","keyPrefix","map","item","index","MenuItem","checked","onCheckedChange","id","renderCheckboxItems","renderIconItems","renderTextItems","optionsItems","useMemo","length","groups","flatMap","group","groupKey","groupLabel","Divider","origins","anchorOrigin","vertical","horizontal","transformOrigin","mapAlignToOrigins","_Fragment","IconButton","undefined","variant","MoreVerticalIcon","endIcon","ArrowUp01Icon","ArrowDown01Icon","Menu","onClose","slotProps","list"],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import react__default from 'react';
|
|
2
|
+
import { MenuProps } from '@mui/material/Menu';
|
|
3
|
+
import { CheckboxMenuItemProps, IconMenuItemProps, TextMenuItemProps } from '@fd/components/atoms/MenuItem';
|
|
4
|
+
|
|
5
|
+
/** Props for the DropdownMenuCheckboxOption component */
|
|
6
|
+
type DropdownMenuCheckboxOption = Omit<CheckboxMenuItemProps, 'type'>;
|
|
7
|
+
/** Props for the DropdownMenuIconOption component */
|
|
8
|
+
type DropdownMenuIconOption = Omit<IconMenuItemProps, 'type'>;
|
|
9
|
+
/** Props for the DropdownMenuTextOption component */
|
|
10
|
+
type DropdownMenuTextOption = Omit<TextMenuItemProps, 'type'>;
|
|
11
|
+
interface DropdownMenuGroupOptionBase {
|
|
12
|
+
/** Label of the group */
|
|
13
|
+
groupLabel?: react__default.ReactNode;
|
|
14
|
+
/** ID of the group */
|
|
15
|
+
id?: string;
|
|
16
|
+
}
|
|
17
|
+
interface DropdownMenuGroupOptionCheckbox extends DropdownMenuGroupOptionBase {
|
|
18
|
+
/** Type of the menu options */
|
|
19
|
+
optionsType: 'checkboxes';
|
|
20
|
+
/** Options of the menu */
|
|
21
|
+
options: DropdownMenuCheckboxOption[];
|
|
22
|
+
}
|
|
23
|
+
interface DropdownMenuGroupOptionIcon extends DropdownMenuGroupOptionBase {
|
|
24
|
+
/** Type of the menu options */
|
|
25
|
+
optionsType: 'icons';
|
|
26
|
+
/** Options of the menu */
|
|
27
|
+
options: DropdownMenuIconOption[];
|
|
28
|
+
}
|
|
29
|
+
interface DropdownMenuGroupOptionText extends DropdownMenuGroupOptionBase {
|
|
30
|
+
/** Type of the menu options */
|
|
31
|
+
optionsType?: 'text';
|
|
32
|
+
/** Options of the menu */
|
|
33
|
+
options: DropdownMenuTextOption[];
|
|
34
|
+
}
|
|
35
|
+
/** Props for the DropdownMenuGroupOption component */
|
|
36
|
+
type DropdownMenuGroupOption = DropdownMenuGroupOptionCheckbox | DropdownMenuGroupOptionIcon | DropdownMenuGroupOptionText;
|
|
37
|
+
interface DropdownMenuBaseCommonProps extends Omit<MenuProps, 'anchorEl' | 'onClose' | 'open'> {
|
|
38
|
+
/** Alignment of the menu */
|
|
39
|
+
align?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
|
40
|
+
/** Disabled state of the menu */
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
/** Key of the menu */
|
|
43
|
+
fdKey: string;
|
|
44
|
+
/** Size of the menu */
|
|
45
|
+
size?: 'medium' | 'small';
|
|
46
|
+
}
|
|
47
|
+
interface DropdownMenuCheckboxesProps extends DropdownMenuBaseCommonProps {
|
|
48
|
+
/** Type of the menu options */
|
|
49
|
+
optionsType: 'checkboxes';
|
|
50
|
+
/** Options of the menu */
|
|
51
|
+
options: DropdownMenuCheckboxOption[];
|
|
52
|
+
}
|
|
53
|
+
interface DropdownMenuIconsProps extends DropdownMenuBaseCommonProps {
|
|
54
|
+
/** Type of the menu options */
|
|
55
|
+
optionsType: 'icons';
|
|
56
|
+
/** Options of the menu */
|
|
57
|
+
options: DropdownMenuIconOption[];
|
|
58
|
+
}
|
|
59
|
+
interface DropdownMenuTextProps extends DropdownMenuBaseCommonProps {
|
|
60
|
+
/** Type of the menu options */
|
|
61
|
+
optionsType: 'text';
|
|
62
|
+
/** Options of the menu */
|
|
63
|
+
options: DropdownMenuTextOption[];
|
|
64
|
+
}
|
|
65
|
+
type DropdownMenuOptionsProps = DropdownMenuCheckboxesProps | DropdownMenuIconsProps | DropdownMenuTextProps;
|
|
66
|
+
interface DropdownMenuOptionsGroupsProps extends DropdownMenuBaseCommonProps {
|
|
67
|
+
/** Type of the menu options */
|
|
68
|
+
optionsType: 'groups';
|
|
69
|
+
/** Options of the menu */
|
|
70
|
+
options: DropdownMenuGroupOption[];
|
|
71
|
+
}
|
|
72
|
+
type DropdownMenuBaseProps = DropdownMenuOptionsGroupsProps | DropdownMenuOptionsProps;
|
|
73
|
+
type AvatarDropdownMenuProps = DropdownMenuBaseProps & {
|
|
74
|
+
/** Aria-label of the trigger */
|
|
75
|
+
ariaLabel?: never;
|
|
76
|
+
/** Secondary text of the menu item */
|
|
77
|
+
secondaryText?: string;
|
|
78
|
+
/** Source URL for the avatar image */
|
|
79
|
+
avatarSrc: string;
|
|
80
|
+
/** Label of the trigger */
|
|
81
|
+
label: string;
|
|
82
|
+
/** Type of the menu item */
|
|
83
|
+
type: 'avatar';
|
|
84
|
+
};
|
|
85
|
+
type ButtonDropdownMenuProps = DropdownMenuBaseProps & {
|
|
86
|
+
/** Aria-label of the trigger */
|
|
87
|
+
ariaLabel?: never;
|
|
88
|
+
/** Secondary text of the menu item */
|
|
89
|
+
secondaryText?: never;
|
|
90
|
+
/** Source URL for the avatar image */
|
|
91
|
+
avatarSrc?: never;
|
|
92
|
+
/** Label of the trigger */
|
|
93
|
+
label: string;
|
|
94
|
+
/** Type of the menu item */
|
|
95
|
+
type: 'button';
|
|
96
|
+
};
|
|
97
|
+
type IconButtonDropdownMenuProps = DropdownMenuBaseProps & {
|
|
98
|
+
/** Aria-label of the trigger */
|
|
99
|
+
ariaLabel: string;
|
|
100
|
+
/** Secondary text of the menu item */
|
|
101
|
+
secondaryText?: never;
|
|
102
|
+
/** Source URL for the avatar image */
|
|
103
|
+
avatarSrc?: never;
|
|
104
|
+
/** Label of the trigger */
|
|
105
|
+
label?: never;
|
|
106
|
+
/** Type of the menu item */
|
|
107
|
+
type: 'icon-button';
|
|
108
|
+
};
|
|
109
|
+
/** Props for the DropdownMenu component */
|
|
110
|
+
type DropdownMenuProps = AvatarDropdownMenuProps | ButtonDropdownMenuProps | IconButtonDropdownMenuProps;
|
|
111
|
+
/**
|
|
112
|
+
* A customizable DropdownMenu component supporting button and checkbox menu items with optional groups.
|
|
113
|
+
*
|
|
114
|
+
* @param props - The component props
|
|
115
|
+
* @returns The rendered DropdownMenu component
|
|
116
|
+
*/
|
|
117
|
+
declare const DropdownMenu: ({ align, ariaLabel, avatarSrc, disabled, fdKey, label, options, optionsType, secondaryText, size, type, ...props }: DropdownMenuProps) => JSX.Element;
|
|
118
|
+
|
|
119
|
+
export { DropdownMenu, DropdownMenu as default };
|
|
120
|
+
export type { DropdownMenuCheckboxOption, DropdownMenuGroupOption, DropdownMenuIconOption, DropdownMenuProps, DropdownMenuTextOption };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jsxs as e,Fragment as t,jsx as i}from"react/jsx-runtime";import{useState as o,useMemo as a}from"react";import r from"@mui/material/ListSubheader";import{styled as n}from"@mui/material/styles";import l from"../../atoms/Avatar/index.js";import s from"@mui/material/Box";import{Button as d}from"../../atoms/Button/index.js";import c from"@mui/material/Divider";import{IconButton as m}from"../../atoms/IconButton/index.js";import p from"@mui/material/ListItemText";import{MenuItem as u}from"../../atoms/MenuItem/index.js";import h from"@mui/material/Menu";import b from"../../../icons/ArrowDown01/index.js";import g from"../../../icons/ArrowUp01/index.js";import f from"../../../icons/MoreVertical/index.js";const x=n(d)((({theme:e,size:t,disabled:i})=>({height:"small"===t?48:64,padding:e.spacing(1,2),textDecoration:"none","& .MuiButton-icon":{color:i?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]},"&:focus-visible, &.Mui-focusVisible":{backgroundColor:e.palette.semantic.fill["fill-weak"]}}))),y=n(r)((({theme:e})=>({borderBottom:`1px solid ${e.palette.semantic.stroke["stroke-weak"]}`,padding:e.spacing(1,2)})));y.muiName=r.muiName,y.muiSkipListHighlight=r.muiSkipListHighlight??!0;const v=n(s,{shouldForwardProp:e=>!["disabled","size"].includes(e)})((({theme:e,disabled:t,size:i})=>({display:"flex",gap:"small"===i?e.spacing(1):e.spacing(1.5),alignItems:"center",textAlign:"left",...t&&{"& .MuiAvatar-root":{opacity:e.palette.action.disabledOpacity}," & .MuiListItemText-root, & .MuiListItemText-primary, & .MuiListItemText-secondary":{color:e.palette.semantic.text["text-disabled"]}}}))),k=({align:n="bottom-left",ariaLabel:s="",avatarSrc:k="",disabled:z=!1,fdKey:T,label:C,options:$=[],optionsType:L="text",secondaryText:M,size:I="medium",type:O="button",...j})=>{const[w,B]=o(null),A=Boolean(w),K=`${T}-trigger`,P=`${T}-menu`,S=e=>{z||B(e.currentTarget)},D=()=>{B(null)},H=e=>t=>{e?.(t),D()},N=t=>e(v,{disabled:z,size:t,children:[i(l,{"aria-hidden":!0,alt:"",size:t,src:k,type:"logo"}),i(p,{primary:C,secondary:M})]}),V=(e,t="text",o="root")=>{switch(t){case"checkboxes":return((e,t)=>e.map(((e,o)=>i(u,{checked:e.checked,disabled:e.disabled,label:e.label,onCheckedChange:e.onCheckedChange,secondaryText:e.secondaryText,type:"checkbox"},e.id??`${t}-checkbox-${o}`))))(e,o);case"icons":return((e,t)=>e.map(((e,o)=>i(u,{disabled:e.disabled,icon:e.icon,label:e.label,onClick:H(e.onClick),secondaryText:e.secondaryText,type:"icon"},e.id??`${t}-icon-${o}`))))(e,o);default:return((e,t)=>e.map(((e,o)=>i(u,{disabled:e.disabled,label:e.label,onClick:H(e.onClick),secondaryText:e.secondaryText,type:"text"},e.id??`${t}-text-${o}`))))(e,o)}},E=a((()=>{return $&&0!==$.length?"groups"===L?(e=$).flatMap(((t,o)=>{const a=t.id??`group-${o}`;return[t.groupLabel?i(r,{children:t.groupLabel},`subheader-${a}`):null,...V(t.options,t.optionsType,a),o<e.length-1?i(c,{},`divider-${a}`):null]})):V($,L):null;var e}),[$,L]),F=((e="bottom-left")=>{switch(e){case"bottom-left":default:return{anchorOrigin:{vertical:"bottom",horizontal:"left"},transformOrigin:{vertical:"top",horizontal:"left"}};case"bottom-right":return{anchorOrigin:{vertical:"bottom",horizontal:"right"},transformOrigin:{vertical:"top",horizontal:"right"}};case"top-left":return{anchorOrigin:{vertical:"top",horizontal:"left"},transformOrigin:{vertical:"bottom",horizontal:"left"}};case"top-right":return{anchorOrigin:{vertical:"top",horizontal:"right"},transformOrigin:{vertical:"bottom",horizontal:"right"}}}})(n);return e(t,{children:["icon-button"===O?i(m,{"aria-controls":A?P:void 0,"aria-expanded":A,"aria-haspopup":"menu","aria-label":s,disabled:z,fdKey:T,id:K,onClick:S,size:I,variant:"secondary",children:i(f,{})}):"avatar"===O?i(x,{"aria-controls":A?P:void 0,"aria-expanded":A,"aria-haspopup":"menu",disabled:z,endIcon:i(A?g:b,{}),fdKey:T,id:K,onClick:S,size:I,variant:"tertiary",children:N(I)}):i(d,{"aria-controls":A?P:void 0,"aria-expanded":A,"aria-haspopup":"menu",disabled:z,endIcon:i(A?g:b,{}),fdKey:T,id:K,onClick:S,size:I,variant:"secondary",children:C}),e(h,{...j,...F,anchorEl:w,onClose:D,open:A,slotProps:{...j.slotProps,list:{...j.slotProps?.list??{},id:P,"aria-labelledby":K}},children:["avatar"===O&&i(y,{children:N("medium")}),E]})]})};export{k as DropdownMenu,k as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/molecules/DropdownMenu/index.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\n\nimport MuiListSubheader from '@mui/material/ListSubheader';\nimport type { MenuProps as MuiMenuProps } from '@mui/material/Menu';\nimport { styled } from '@mui/material/styles';\n\nimport Avatar from '@fd/components/atoms/Avatar';\nimport Box from '@fd/components/atoms/Box';\nimport Button from '@fd/components/atoms/Button';\nimport Divider from '@fd/components/atoms/Divider';\nimport IconButton from '@fd/components/atoms/IconButton';\nimport ListItemText from '@fd/components/atoms/ListItemText';\nimport MenuItem, {\n type CheckboxMenuItemProps,\n type IconMenuItemProps,\n type MenuItemProps,\n type TextMenuItemProps,\n} from '@fd/components/atoms/MenuItem';\nimport Menu from '@fd/components/molecules/Menu';\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport MoreVerticalIcon from '@fd/icons/MoreVertical';\n\n/** Props for the DropdownMenuCheckboxOption component */\nexport type DropdownMenuCheckboxOption = Omit<CheckboxMenuItemProps, 'type'>;\n\n/** Props for the DropdownMenuIconOption component */\nexport type DropdownMenuIconOption = Omit<IconMenuItemProps, 'type'>;\n\n/** Props for the DropdownMenuTextOption component */\nexport type DropdownMenuTextOption = Omit<TextMenuItemProps, 'type'>;\n\ninterface DropdownMenuGroupOptionBase {\n /** Label of the group */\n groupLabel?: React.ReactNode;\n /** ID of the group */\n id?: string;\n}\n\ninterface DropdownMenuGroupOptionCheckbox extends DropdownMenuGroupOptionBase {\n /** Type of the menu options */\n optionsType: 'checkboxes';\n /** Options of the menu */\n options: DropdownMenuCheckboxOption[];\n}\n\ninterface DropdownMenuGroupOptionIcon extends DropdownMenuGroupOptionBase {\n /** Type of the menu options */\n optionsType: 'icons';\n /** Options of the menu */\n options: DropdownMenuIconOption[];\n}\n\ninterface DropdownMenuGroupOptionText extends DropdownMenuGroupOptionBase {\n /** Type of the menu options */\n optionsType?: 'text';\n /** Options of the menu */\n options: DropdownMenuTextOption[];\n}\n\n/** Props for the DropdownMenuGroupOption component */\nexport type DropdownMenuGroupOption =\n | DropdownMenuGroupOptionCheckbox\n | DropdownMenuGroupOptionIcon\n | DropdownMenuGroupOptionText;\n\ninterface DropdownMenuBaseCommonProps extends Omit<MuiMenuProps, 'anchorEl' | 'onClose' | 'open'> {\n /** Alignment of the menu */\n align?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';\n /** Disabled state of the menu */\n disabled?: boolean;\n /** Key of the menu */\n fdKey: string;\n /** Size of the menu */\n size?: 'medium' | 'small';\n}\n\ninterface DropdownMenuCheckboxesProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'checkboxes';\n /** Options of the menu */\n options: DropdownMenuCheckboxOption[];\n}\n\ninterface DropdownMenuIconsProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'icons';\n /** Options of the menu */\n options: DropdownMenuIconOption[];\n}\n\ninterface DropdownMenuTextProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'text';\n /** Options of the menu */\n options: DropdownMenuTextOption[];\n}\n\ntype DropdownMenuOptionsProps = DropdownMenuCheckboxesProps | DropdownMenuIconsProps | DropdownMenuTextProps;\n\ninterface DropdownMenuOptionsGroupsProps extends DropdownMenuBaseCommonProps {\n /** Type of the menu options */\n optionsType: 'groups';\n /** Options of the menu */\n options: DropdownMenuGroupOption[];\n}\n\ntype DropdownMenuBaseProps = DropdownMenuOptionsGroupsProps | DropdownMenuOptionsProps;\n\ntype AvatarDropdownMenuProps = DropdownMenuBaseProps & {\n /** Aria-label of the trigger */\n ariaLabel?: never;\n /** Secondary text of the menu item */\n secondaryText?: string;\n /** Source URL for the avatar image */\n avatarSrc: string;\n /** Label of the trigger */\n label: string;\n /** Type of the menu item */\n type: 'avatar';\n};\n\ntype ButtonDropdownMenuProps = DropdownMenuBaseProps & {\n /** Aria-label of the trigger */\n ariaLabel?: never;\n /** Secondary text of the menu item */\n secondaryText?: never;\n /** Source URL for the avatar image */\n avatarSrc?: never;\n /** Label of the trigger */\n label: string;\n /** Type of the menu item */\n type: 'button';\n};\n\ntype IconButtonDropdownMenuProps = DropdownMenuBaseProps & {\n /** Aria-label of the trigger */\n ariaLabel: string;\n /** Secondary text of the menu item */\n secondaryText?: never;\n /** Source URL for the avatar image */\n avatarSrc?: never;\n /** Label of the trigger */\n label?: never;\n /** Type of the menu item */\n type: 'icon-button';\n};\n\n/** Props for the DropdownMenu component */\nexport type DropdownMenuProps =\n | AvatarDropdownMenuProps\n | ButtonDropdownMenuProps\n | IconButtonDropdownMenuProps;\n\nconst StyledAvatarDropdownMenuButton = styled(Button)<{ disabled?: boolean; size: 'medium' | 'small' }>(\n ({ theme, size, disabled }) => ({\n height: size === 'small' ? 48 : 64,\n padding: theme.spacing(1, 2),\n textDecoration: 'none',\n\n '& .MuiButton-icon': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n\n '&:focus-visible, &.Mui-focusVisible': {\n backgroundColor: theme.palette.semantic.fill['fill-weak'],\n },\n }),\n);\n\nconst StyledAvatarListSubheader = styled(MuiListSubheader)(({ theme }) => ({\n borderBottom: `1px solid ${theme.palette.semantic.stroke['stroke-weak']}`,\n padding: theme.spacing(1, 2),\n}));\n\n// Preserve MUI internals so MenuList handles it correctly\n// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n(StyledAvatarListSubheader as any).muiName = (MuiListSubheader as any).muiName;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n(StyledAvatarListSubheader as any).muiSkipListHighlight =\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (MuiListSubheader as unknown as { muiSkipListHighlight?: boolean }).muiSkipListHighlight ?? true;\n\nconst StyledAvatarLabelContainer = styled(Box, {\n shouldForwardProp: (prop) => !['disabled', 'size'].includes(prop as string),\n})<{ disabled: boolean; size: 'medium' | 'small' }>(({ theme, disabled, size }) => ({\n display: 'flex',\n gap: size === 'small' ? theme.spacing(1) : theme.spacing(1.5),\n alignItems: 'center',\n textAlign: 'left',\n\n ...(disabled && {\n '& .MuiAvatar-root': {\n opacity: theme.palette.action.disabledOpacity,\n },\n ' & .MuiListItemText-root, & .MuiListItemText-primary, & .MuiListItemText-secondary': {\n color: theme.palette.semantic.text['text-disabled'],\n },\n }),\n}));\n\nconst mapAlignToOrigins = (\n align: DropdownMenuProps['align'] = 'bottom-left',\n): Pick<MuiMenuProps, 'anchorOrigin' | 'transformOrigin'> => {\n switch (align) {\n case 'bottom-left':\n return {\n anchorOrigin: { vertical: 'bottom', horizontal: 'left' },\n transformOrigin: { vertical: 'top', horizontal: 'left' },\n };\n case 'bottom-right':\n return {\n anchorOrigin: { vertical: 'bottom', horizontal: 'right' },\n transformOrigin: { vertical: 'top', horizontal: 'right' },\n };\n case 'top-left':\n return {\n anchorOrigin: { vertical: 'top', horizontal: 'left' },\n transformOrigin: { vertical: 'bottom', horizontal: 'left' },\n };\n case 'top-right':\n return {\n anchorOrigin: { vertical: 'top', horizontal: 'right' },\n transformOrigin: { vertical: 'bottom', horizontal: 'right' },\n };\n default:\n return {\n anchorOrigin: { vertical: 'bottom', horizontal: 'left' },\n transformOrigin: { vertical: 'top', horizontal: 'left' },\n };\n }\n};\n\n/**\n * A customizable DropdownMenu component supporting button and checkbox menu items with optional groups.\n *\n * @param props - The component props\n * @returns The rendered DropdownMenu component\n */\nexport const DropdownMenu = ({\n align = 'bottom-left',\n ariaLabel = '',\n avatarSrc = '',\n disabled = false,\n fdKey,\n label,\n options = [],\n optionsType = 'text',\n secondaryText,\n size = 'medium',\n type = 'button',\n ...props\n}: DropdownMenuProps): JSX.Element => {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n\n const triggerId = `${fdKey}-trigger`;\n const menuId = `${fdKey}-menu`;\n\n const handleOpen = (event: React.MouseEvent<HTMLElement>): void => {\n if (disabled) {\n return;\n }\n\n setAnchorEl(event.currentTarget);\n };\n\n const handleClose = (): void => {\n setAnchorEl(null);\n };\n\n const handleClick =\n (onClick?: React.MouseEventHandler<HTMLLIElement>) =>\n (event: React.MouseEvent<HTMLLIElement>): void => {\n onClick?.(event);\n handleClose();\n };\n\n const renderAvatarLabelContainer = (size: 'medium' | 'small'): JSX.Element | null => (\n <StyledAvatarLabelContainer disabled={disabled} size={size}>\n <Avatar\n aria-hidden\n alt=\"\" // Avatar is described by ListItemText\n size={size}\n src={avatarSrc}\n type=\"logo\"\n />\n <ListItemText primary={label} secondary={secondaryText} />\n </StyledAvatarLabelContainer>\n );\n\n const renderTrigger = (): JSX.Element => {\n if (type === 'icon-button') {\n return (\n <IconButton\n aria-controls={open ? menuId : undefined}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n aria-label={ariaLabel}\n disabled={disabled}\n fdKey={fdKey}\n id={triggerId}\n onClick={handleOpen}\n size={size}\n variant=\"secondary\"\n >\n <MoreVerticalIcon />\n </IconButton>\n );\n }\n if (type === 'avatar') {\n return (\n <StyledAvatarDropdownMenuButton\n aria-controls={open ? menuId : undefined}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n disabled={disabled}\n endIcon={open ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n fdKey={fdKey}\n id={triggerId}\n onClick={handleOpen}\n size={size}\n variant=\"tertiary\"\n >\n {renderAvatarLabelContainer(size)}\n </StyledAvatarDropdownMenuButton>\n );\n }\n\n return (\n <Button\n aria-controls={open ? menuId : undefined}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n disabled={disabled}\n endIcon={open ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n fdKey={fdKey}\n id={triggerId}\n onClick={handleOpen}\n size={size}\n variant=\"secondary\"\n >\n {label}\n </Button>\n );\n };\n\n const renderCheckboxItems = (items: CheckboxMenuItemProps[], keyPrefix: string): JSX.Element[] =>\n items.map((item, index) => {\n return (\n <MenuItem\n key={item.id ?? `${keyPrefix}-checkbox-${index}`}\n checked={item.checked}\n disabled={item.disabled}\n label={item.label}\n onCheckedChange={item.onCheckedChange}\n secondaryText={item.secondaryText}\n type=\"checkbox\"\n />\n );\n });\n\n const renderIconItems = (items: IconMenuItemProps[], keyPrefix: string): JSX.Element[] =>\n items.map((item, index) => {\n return (\n <MenuItem\n key={item.id ?? `${keyPrefix}-icon-${index}`}\n disabled={item.disabled}\n icon={item.icon}\n label={item.label}\n onClick={handleClick(item.onClick)}\n secondaryText={item.secondaryText}\n type=\"icon\"\n />\n );\n });\n\n const renderTextItems = (items: TextMenuItemProps[], keyPrefix: string): JSX.Element[] =>\n items.map((item, index) => {\n return (\n <MenuItem\n key={item.id ?? `${keyPrefix}-text-${index}`}\n disabled={item.disabled}\n label={item.label}\n onClick={handleClick(item.onClick)}\n secondaryText={item.secondaryText}\n type=\"text\"\n />\n );\n });\n\n const renderItems = (\n items: Omit<MenuItemProps, 'type'>[],\n optionsType: DropdownMenuProps['optionsType'] = 'text',\n keyPrefix: string = 'root',\n ): JSX.Element[] => {\n switch (optionsType) {\n case 'checkboxes':\n return renderCheckboxItems(items as CheckboxMenuItemProps[], keyPrefix);\n case 'icons':\n return renderIconItems(items as IconMenuItemProps[], keyPrefix);\n case 'text':\n default:\n return renderTextItems(items as TextMenuItemProps[], keyPrefix);\n }\n };\n\n // Returns a flat array of group items (subheaders, items, dividers) needed for accessibility\n const renderGroupItems = (groups: DropdownMenuGroupOption[]): (JSX.Element | null)[] =>\n groups.flatMap((group, index) => {\n const groupKey = group.id ?? `group-${index}`;\n\n const header = group.groupLabel ? (\n <MuiListSubheader key={`subheader-${groupKey}`}>{group.groupLabel}</MuiListSubheader>\n ) : null;\n const items = renderItems(group.options, group.optionsType, groupKey);\n const divider = index < groups.length - 1 ? <Divider key={`divider-${groupKey}`} /> : null;\n\n return [header, ...items, divider];\n });\n\n const renderAvatarListSubheader = (): JSX.Element => {\n return <StyledAvatarListSubheader>{renderAvatarLabelContainer('medium')}</StyledAvatarListSubheader>;\n };\n\n const optionsItems = useMemo(() => {\n if (!options || options.length === 0) {\n return null;\n }\n\n if (optionsType === 'groups') {\n return renderGroupItems(options as DropdownMenuGroupOption[]);\n }\n\n return renderItems(options, optionsType);\n }, [options, optionsType]);\n\n const origins = mapAlignToOrigins(align);\n\n return (\n <>\n {renderTrigger()}\n\n <Menu\n {...props}\n {...origins}\n anchorEl={anchorEl}\n onClose={handleClose}\n open={open}\n slotProps={{\n ...props.slotProps,\n list: {\n ...(props.slotProps?.list ?? {}),\n id: menuId,\n 'aria-labelledby': triggerId,\n },\n }}\n >\n {type === 'avatar' && renderAvatarListSubheader()}\n {optionsItems}\n </Menu>\n </>\n );\n};\n\nexport default DropdownMenu;\n"],"names":["StyledAvatarDropdownMenuButton","styled","Button","theme","size","disabled","height","padding","spacing","textDecoration","color","palette","semantic","icon","backgroundColor","fill","StyledAvatarListSubheader","MuiListSubheader","borderBottom","stroke","muiName","muiSkipListHighlight","StyledAvatarLabelContainer","Box","shouldForwardProp","prop","includes","display","gap","alignItems","textAlign","opacity","action","disabledOpacity","text","DropdownMenu","align","ariaLabel","avatarSrc","fdKey","label","options","optionsType","secondaryText","type","props","anchorEl","setAnchorEl","useState","open","Boolean","triggerId","menuId","handleOpen","event","currentTarget","handleClose","handleClick","onClick","renderAvatarLabelContainer","_jsxs","children","_jsx","Avatar","alt","src","ListItemText","primary","secondary","renderItems","items","keyPrefix","map","item","index","MenuItem","checked","onCheckedChange","id","renderCheckboxItems","renderIconItems","renderTextItems","optionsItems","useMemo","length","groups","flatMap","group","groupKey","groupLabel","Divider","origins","anchorOrigin","vertical","horizontal","transformOrigin","mapAlignToOrigins","_Fragment","IconButton","undefined","variant","MoreVerticalIcon","endIcon","ArrowUp01Icon","ArrowDown01Icon","Menu","onClose","slotProps","list"],"mappings":"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"}
|