@flipdish/portal-library 7.0.0 → 7.2.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/Badge/index.cjs.js +1 -1
- package/dist/components/atoms/Badge/index.cjs.js.map +1 -1
- package/dist/components/atoms/Badge/index.d.ts +12 -14
- package/dist/components/atoms/Badge/index.js +1 -1
- package/dist/components/atoms/Badge/index.js.map +1 -1
- package/dist/components/atoms/Card/index.cjs.js +1 -1
- package/dist/components/atoms/Card/index.cjs.js.map +1 -1
- package/dist/components/atoms/Card/index.js +1 -1
- package/dist/components/atoms/Card/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.d.ts +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.js +1 -1
- package/dist/components/atoms/MenuItem/index.js.map +1 -1
- package/dist/components/atoms/Select/index.cjs.js +1 -1
- package/dist/components/atoms/Select/index.cjs.js.map +1 -1
- package/dist/components/atoms/Select/index.js +1 -1
- package/dist/components/atoms/Select/index.js.map +1 -1
- package/dist/components/atoms/Tag/index.cjs.js +2 -0
- package/dist/components/atoms/Tag/index.cjs.js.map +1 -0
- package/dist/components/atoms/Tag/index.d.ts +47 -0
- package/dist/components/atoms/Tag/index.js +2 -0
- package/dist/components/atoms/Tag/index.js.map +1 -0
- package/dist/components/atoms/TextField/index.cjs.js +1 -1
- package/dist/components/atoms/TextField/index.cjs.js.map +1 -1
- package/dist/components/atoms/TextField/index.js +1 -1
- package/dist/components/atoms/TextField/index.js.map +1 -1
- package/dist/components/molecules/Autocomplete/hooks/useDynamicLimitTags.cjs.js +2 -0
- package/dist/components/molecules/Autocomplete/hooks/useDynamicLimitTags.cjs.js.map +1 -0
- package/dist/components/molecules/Autocomplete/hooks/useDynamicLimitTags.d.ts +14 -0
- package/dist/components/molecules/Autocomplete/hooks/useDynamicLimitTags.js +2 -0
- package/dist/components/molecules/Autocomplete/hooks/useDynamicLimitTags.js.map +1 -0
- package/dist/components/molecules/Autocomplete/index.cjs.js +1 -1
- package/dist/components/molecules/Autocomplete/index.cjs.js.map +1 -1
- package/dist/components/molecules/Autocomplete/index.d.ts +57 -2
- package/dist/components/molecules/Autocomplete/index.js +1 -1
- package/dist/components/molecules/Autocomplete/index.js.map +1 -1
- package/dist/components/molecules/CheckboxGroup/index.cjs.js +1 -1
- package/dist/components/molecules/CheckboxGroup/index.cjs.js.map +1 -1
- package/dist/components/molecules/CheckboxGroup/index.d.ts +1 -1
- package/dist/components/molecules/CheckboxGroup/index.js +1 -1
- package/dist/components/molecules/CheckboxGroup/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/autocompleteOverrides.cjs.js +2 -0
- package/dist/themes/overrides/autocompleteOverrides.cjs.js.map +1 -0
- package/dist/themes/overrides/autocompleteOverrides.d.ts +5 -0
- package/dist/themes/overrides/autocompleteOverrides.js +2 -0
- package/dist/themes/overrides/autocompleteOverrides.js.map +1 -0
- package/dist/themes/overrides/buttonBaseOverrides.cjs.js +2 -0
- package/dist/themes/overrides/buttonBaseOverrides.cjs.js.map +1 -0
- package/dist/themes/overrides/buttonBaseOverrides.d.ts +5 -0
- package/dist/themes/overrides/buttonBaseOverrides.js +2 -0
- package/dist/themes/overrides/buttonBaseOverrides.js.map +1 -0
- package/dist/themes/overrides/chipOverrides.cjs.js +2 -0
- package/dist/themes/overrides/chipOverrides.cjs.js.map +1 -0
- package/dist/themes/overrides/chipOverrides.d.ts +5 -0
- package/dist/themes/overrides/chipOverrides.js +2 -0
- package/dist/themes/overrides/chipOverrides.js.map +1 -0
- package/dist/themes/overrides/inputBaseOverrides.cjs.js +1 -1
- package/dist/themes/overrides/inputBaseOverrides.cjs.js.map +1 -1
- package/dist/themes/overrides/inputBaseOverrides.js +1 -1
- package/dist/themes/overrides/inputBaseOverrides.js.map +1 -1
- 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/dist/themes/overrides/selectOverrides.cjs.js +1 -1
- package/dist/themes/overrides/selectOverrides.cjs.js.map +1 -1
- package/dist/themes/overrides/selectOverrides.js +1 -1
- package/dist/themes/overrides/selectOverrides.js.map +1 -1
- package/dist/utilities/stringUtilities.cjs.js +2 -0
- package/dist/utilities/stringUtilities.cjs.js.map +1 -0
- package/dist/utilities/stringUtilities.d.ts +7 -0
- package/dist/utilities/stringUtilities.js +2 -0
- package/dist/utilities/stringUtilities.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/MenuItem/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport ListItemText from '@mui/material/ListItemText';\nimport MuiMenuItem, { type MenuItemProps as MuiMenuItemProps } from '@mui/material/MenuItem';\nimport { styled } from '@mui/material/styles';\n\nimport Checkbox from '../Checkbox';\n\ntype BaseProps = Omit<MuiMenuItemProps, 'children'> & {\n children?: React.ReactNode;\n label?: React.ReactNode;\n secondaryText?: React.ReactNode;\n type?: 'avatar' | 'checkbox' | 'icon' | 'text';\n};\n\ntype AvatarMenuItemProps = BaseProps & {\n avatar: React.ReactNode;\n checkbox?: never;\n icon?: never;\n type: 'avatar';\n};\n\ntype CheckboxMenuItemProps = BaseProps & {\n avatar?: never;\n checked?: boolean;\n icon?: never;\n onCheckedChange?: (\n checked: boolean,\n e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLLIElement>,\n ) => void;\n type: 'checkbox';\n};\n\ntype IconMenuItemProps = BaseProps & {\n avatar?: never;\n checkbox?: never;\n icon: React.ReactNode;\n type: 'icon';\n};\n\ntype TextMenuItemProps = BaseProps & {\n avatar?: never;\n checkbox?: never;\n icon?: never;\n type?: 'text';\n};\n\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
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/MenuItem/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport ListItemText from '@mui/material/ListItemText';\nimport MuiMenuItem, { type MenuItemProps as MuiMenuItemProps } from '@mui/material/MenuItem';\nimport { styled } from '@mui/material/styles';\n\nimport Checkbox from '../Checkbox';\n\ntype BaseProps = Omit<MuiMenuItemProps, 'children'> & {\n children?: React.ReactNode;\n label?: React.ReactNode;\n secondaryText?: React.ReactNode;\n type?: 'avatar' | 'checkbox' | 'icon' | 'text';\n};\n\ntype AvatarMenuItemProps = BaseProps & {\n avatar: React.ReactNode;\n checkbox?: never;\n icon?: never;\n type: 'avatar';\n};\n\ntype CheckboxMenuItemProps = BaseProps & {\n avatar?: never;\n checked?: boolean;\n icon?: never;\n onCheckedChange?: (\n checked: boolean,\n e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLLIElement>,\n ) => void;\n type: 'checkbox';\n};\n\ntype IconMenuItemProps = BaseProps & {\n avatar?: never;\n checkbox?: never;\n icon: React.ReactNode;\n type: 'icon';\n};\n\ntype TextMenuItemProps = BaseProps & {\n avatar?: never;\n checkbox?: never;\n icon?: never;\n type?: 'text';\n};\n\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\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 { avatar: _a, ...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 { avatar } = props as AvatarMenuItemProps;\n return <StyledStartAdornment disabled={disabled}>{avatar}</StyledStartAdornment>;\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>{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","avatar","_a","icon","_i","_jsxs","MuiMenuItem","onClick","event","preventDefault","stopPropagation","isChecked","Boolean","selected","_jsx","renderAvatar","fdKey","size","tabIndex","renderCheckbox","renderIcon","renderStartAdornment","ListItemText","primary","secondary"],"mappings":"qPAoDA,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,WAGJC,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,OAAQC,KAAOF,GAASN,EAChC,OAAOM,CACT,CACA,IAAK,OAAQ,CACX,MAAQG,KAAMC,KAAOJ,GAASN,EAC9B,OAAOM,CACT,CACA,QACE,OAAON,EAEZ,EAjBkC,GAuFnC,OACEW,EAACC,EAAW,IAAKX,EAAUjB,SAAUA,EAAU6B,QArE5BC,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,aA+B2B,MAC3B,OAAQf,GACN,IAAK,SACH,MA7Be,MACnB,MAAMQ,OAAEA,GAAWP,EACnB,OAAOoB,EAAC1C,EAAoB,CAACM,SAAUA,EAAQY,SAAGW,KA2BvCc,GACT,IAAK,WACH,MA1BiB,MACrB,MAAMnB,QAAEA,GAAYF,EACdiB,EAA+B,kBAAZf,EAAwBA,EAAUgB,QAASlB,EAA2BmB,UAE/F,OACEC,EAAC5B,EAAc,CAAA,eAAA,EAEbU,QAASe,EACTjC,SAAUA,EACVsC,MAAM,qBACNC,KAAK,QACLC,UAAU,KAeHC,GACT,IAAK,OACH,MAZa,MACjB,MAAMhB,KAAEA,GAAST,EACjB,OAAOoB,EAAC1C,EAAoB,CAAAkB,SAAEa,KAUnBiB,GACT,QACE,OAAO,OAcRC,GATC9B,GAASC,EACJsB,EAACQ,EAAY,CAACC,QAAShC,EAAOiC,UAAWhC,IAG3CF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),r=require("react"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),r=require("react"),i=require("@mui/material/Box"),l=require("@mui/material/FormHelperText"),t=require("@mui/material/InputLabel"),s=require("@mui/material/Select"),d=require("@mui/material/styles"),o=require("../../../icons/ArrowDown01/index.cjs.js"),a=require("../../../icons/ArrowUp01/index.cjs.js"),n=require("../../../icons/CancelCircle/index.cjs.js"),u=require("../MenuItem/index.cjs.js");const c=d.styled(i,{shouldForwardProp:e=>"fullWidth"!==e})((({theme:e,fullWidth:r=!1})=>({display:"flex",flexDirection:"column",gap:e.spacing(.5),width:r?"100%":"min(364px, 100%)"}))),p=d.styled(s,{shouldForwardProp:e=>!["fullWidth","showPlaceholder"].includes(e)})((({theme:e,fullWidth:r=!1,showPlaceholder:i=!1})=>({display:"flex",width:r?"100%":"auto","& .MuiSelect-select":{color:i?e.palette.semantic.text["text-weak"]:e.palette.semantic.text["text-strong"]}}))),h=d.styled(i,{shouldForwardProp:e=>"disabled"!==e})((({theme:e,disabled:r=!1})=>({alignItems:"center",cursor:r?"not-allowed":"pointer",display:"flex",justifyContent:"center",paddingRight:e.spacing(2),pointerEvents:"auto","& svg":{color:r?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),x=d.styled(u.MenuItem)((()=>({display:"none"}))),m=({children:s,disabled:d=!1,errorText:m,fdKey:j,fullWidth:b=!1,helperText:f,label:v,onChange:g,options:q=[],placeholder:y,required:w=!1,value:P,...C})=>{const[I,W]=r.useState(!1),M=f?`${j}-helper-text`:void 0,F=m?`${j}-error-message`:void 0,S=[M,F].filter(Boolean).join(" ")||void 0,D=!!m&&!d,T=!(!y||P&&""!==P);r.useEffect((()=>{d&&W(!1)}),[d]);const k=e=>{d||W(void 0===e?e=>!e:e)},A=r.useMemo((()=>q.map((r=>e.jsx(u.MenuItem,{disabled:r.disabled,value:r.value,children:r.label},r.value)))),[q]);return e.jsxs(c,{fullWidth:b,children:[e.jsxs(i,{children:[v&&e.jsx(t,{disabled:d,htmlFor:j,required:w,children:v}),f&&e.jsx(l,{disabled:d,id:M,children:f})]}),D&&e.jsxs(l,{error:!0,id:F,children:[e.jsx(n,{}),m]}),e.jsx(p,{"data-fd":j,disabled:d,error:D,fullWidth:b,IconComponent:()=>e.jsx(h,{disabled:d,onClick:e=>{d||(e.stopPropagation(),k())},children:I?e.jsx(a,{}):e.jsx(o,{})}),id:j,inputProps:{"aria-describedby":S},label:"",onChange:(e,r)=>{!(r&&"object"==typeof r&&"props"in r&&r.props?.disabled)?g&&g(e,r):e.preventDefault()},onClose:()=>k(!1),onOpen:()=>k(!0),open:I,required:w,showPlaceholder:T,value:T?y:String(P),variant:"outlined",...C,children:(()=>{const r=[];return T&&r.push(e.jsx(x,{disabled:!0,"aria-hidden":"true",tabIndex:-1,value:y,children:y},"placeholder")),q?.length>0?r.push(...A):r.push(s),r})()})]})};exports.Select=m,exports.default=m;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/Select/index.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport MuiSelect, { type SelectChangeEvent, type SelectProps as MuiSelectProps } from '@mui/material/Select';\nimport { styled } from '@mui/material/styles';\n\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\n\nimport MenuItem from '../MenuItem';\n\nexport interface SelectOption {\n value: number | string;\n label: string;\n disabled?: boolean;\n}\n\nexport type SelectProps = Omit<MuiSelectProps, 'error' | 'id' | 'value' | 'variant'> & {\n errorText?: string;\n fdKey: string;\n helperText?: string;\n options?: SelectOption[];\n placeholder?: string;\n value?: number | string;\n};\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain minWidth to a maximum of 100% of the container width\n}));\n\nconst StyledSelect = styled(MuiSelect, {\n shouldForwardProp: (prop) => !['fullWidth', 'showPlaceholder'].includes(prop as string),\n})<{ fullWidth?: boolean; showPlaceholder?: boolean }>(\n ({ theme, fullWidth = false, showPlaceholder = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n\n '& .MuiSelect-select': {\n color: showPlaceholder\n ? theme.palette.semantic.text['text-weak']\n : theme.palette.semantic.text['text-strong'],\n },\n }),\n);\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ theme, disabled = false }) => ({\n alignItems: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n display: 'flex',\n justifyContent: 'center',\n pointerEvents: 'auto',\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n}));\n\nconst StyledHiddenPlaceholderMenuItem = styled(MenuItem)(() => ({\n display: 'none',\n}));\n\nexport const Select = ({\n children,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n onChange,\n options = [],\n placeholder,\n required = false,\n value,\n ...props\n}: SelectProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const showPlaceholder = !!placeholder && (!value || value === '');\n\n const handleOpen = (): void => {\n if (disabled) {\n return;\n }\n\n setIsOpen((open) => !open);\n };\n\n const handleChange = (event: SelectChangeEvent<unknown>, child?: React.ReactNode): void => {\n // Check if the child is disabled\n const isMenuItemDisabled = !!(\n child &&\n typeof child === 'object' &&\n 'props' in (child as React.ReactElement) &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (child as React.ReactElement).props?.disabled\n );\n if (isMenuItemDisabled) {\n event.preventDefault();\n return;\n }\n\n // Call the original onChange handler if provided\n if (onChange) {\n onChange(event, child);\n }\n };\n\n const getDisplayValue = (): string => {\n if (showPlaceholder) {\n return placeholder;\n }\n\n return String(value);\n };\n\n const renderIcon = (): JSX.Element => {\n const handleIconClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n handleOpen();\n };\n\n return (\n <StyledIconContainer disabled={disabled} onClick={handleIconClick}>\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledIconContainer>\n );\n };\n\n const optionsMenuItems = useMemo((): React.ReactNode[] => {\n return options.map((option) => (\n <MenuItem key={option.value} disabled={option.disabled} value={option.value}>\n {option.label}\n </MenuItem>\n ));\n }, [options]);\n\n const renderMenuItems = (): React.ReactNode => {\n const menuItems = [];\n\n // Workaround to get the placeholder to show up when no value is selected\n // Placeholder must be a menu item to be displayed\n if (showPlaceholder) {\n menuItems.push(\n <StyledHiddenPlaceholderMenuItem\n key=\"placeholder\"\n disabled\n aria-hidden=\"true\"\n tabIndex={-1}\n value={placeholder}\n >\n {placeholder}\n </StyledHiddenPlaceholderMenuItem>,\n );\n }\n\n // Add either options or children\n if (options?.length > 0) {\n menuItems.push(...optionsMenuItems);\n } else {\n // If no options are provided, use the children\n menuItems.push(children);\n }\n\n return menuItems;\n };\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledSelect\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n IconComponent={renderIcon}\n id={fdKey}\n inputProps={{\n 'aria-describedby': ariaDescribedBy,\n }}\n label=\"\" // Remove label from Select since we're rendering it separately\n onChange={handleChange}\n onClick={handleOpen}\n open={isOpen}\n required={required}\n showPlaceholder={showPlaceholder}\n value={getDisplayValue()}\n variant=\"outlined\"\n {...props}\n >\n {renderMenuItems()}\n </StyledSelect>\n </StyledContainer>\n );\n};\n\nexport type { SelectChangeEvent };\nexport default Select;\n"],"names":["StyledContainer","styled","Box","shouldForwardProp","prop","theme","fullWidth","display","flexDirection","gap","spacing","width","StyledSelect","MuiSelect","includes","showPlaceholder","color","palette","semantic","text","StyledIconContainer","disabled","alignItems","cursor","justifyContent","pointerEvents","icon","StyledHiddenPlaceholderMenuItem","MenuItem","Select","children","errorText","fdKey","helperText","label","onChange","options","placeholder","required","value","props","isOpen","setIsOpen","useState","helperTextId","undefined","errorMessageId","ariaDescribedBy","filter","Boolean","join","isError","handleOpen","open","optionsMenuItems","useMemo","map","option","_jsx","_jsxs","MuiInputLabel","htmlFor","MuiFormHelperText","id","error","CancelCircleIcon","IconComponent","onClick","event","stopPropagation","ArrowUp01Icon","ArrowDown01Icon","inputProps","child","preventDefault","String","variant","menuItems","push","tabIndex","length","renderMenuItems"],"mappings":"ifA6BA,MAAMA,EAAkBC,EAAAA,OAAOC,EAAK,CAClCC,kBAAoBC,GAAkB,cAATA,GADPH,EAEI,EAAGI,QAAOC,aAAY,MAAO,CACvDC,QAAS,OACTC,cAAe,SACfC,IAAKJ,EAAMK,QAAQ,IACnBC,MAAOL,EAAY,OAAS,uBAGxBM,EAAeX,EAAAA,OAAOY,EAAW,CACrCV,kBAAoBC,IAAU,CAAC,YAAa,mBAAmBU,SAASV,IADrDH,EAGnB,EAAGI,QAAOC,aAAY,EAAOS,mBAAkB,MAAO,CACpDR,QAAS,OACTI,MAAOL,EAAY,OAAS,OAE5B,sBAAuB,CACrBU,MAAOD,EACHV,EAAMY,QAAQC,SAASC,KAAK,aAC5Bd,EAAMY,QAAQC,SAASC,KAAK,oBAKhCC,EAAsBnB,EAAAA,OAAOC,EAAK,CACtCC,kBAAoBC,GAAkB,aAATA,GADHH,EAED,EAAGI,QAAOgB,YAAW,MAAO,CACrDC,WAAY,SACZC,OAAQF,EAAW,cAAgB,UACnCd,QAAS,OACTiB,eAAgB,SAChBC,cAAe,OAEf,QAAS,CACPT,MAAOK,EACHhB,EAAMY,QAAQC,SAASQ,KAAK,iBAC5BrB,EAAMY,QAAQC,SAASQ,KAAK,oBAI9BC,EAAkC1B,EAAAA,OAAO2B,EAAAA,SAAP3B,EAAiB,KAAA,CACvDM,QAAS,WAGEsB,EAAS,EACpBC,WACAT,YAAW,EACXU,YACAC,QACA1B,aAAY,EACZ2B,aACAC,QACAC,WACAC,UAAU,GACVC,cACAC,YAAW,EACXC,WACGC,MAEH,MAAOC,EAAQC,GAAaC,EAAAA,UAAkB,GAExCC,EAAeX,EAAa,GAAGD,qBAAsBa,EACrDC,EAAiBf,EAAY,GAAGC,uBAAwBa,EAGxDE,EAAkB,CAACH,EAAcE,GAAgBE,OAAOC,SAASC,KAAK,WAAQL,EAE9EM,IAAYpB,IAAcV,EAC1BN,KAAoBsB,GAAiBE,GAAmB,KAAVA,GAE9Ca,EAAa,KACb/B,GAIJqB,GAAWW,IAAUA,KAgDjBC,EAAmBC,EAAAA,SAAQ,IACxBnB,EAAQoB,KAAKC,GAClBC,EAAAA,IAAC9B,WAAQ,CAAoBP,SAAUoC,EAAOpC,SAAUkB,MAAOkB,EAAOlB,eACnEkB,EAAOvB,OADKuB,EAAOlB,UAIvB,CAACH,IAgCJ,OACEuB,EAAAA,KAAC3D,EAAe,CAACM,UAAWA,YAC1BqD,EAAAA,KAACzD,aACEgC,GACCwB,EAAAA,IAACE,GAAcvC,SAAUA,EAAUwC,QAAS7B,EAAOM,SAAUA,EAAQR,SAClEI,IAIJD,GACCyB,EAAAA,IAACI,EAAiB,CAACzC,SAAUA,EAAU0C,GAAInB,EAAYd,SACpDG,OAKNkB,GACCQ,EAAAA,KAACG,EAAiB,CAACE,OAAK,EAACD,GAAIjB,EAAchB,SAAA,CACzC4B,EAAAA,IAACO,EAAgB,CAAA,GAEhBlC,KAIL2B,EAAAA,IAAC9C,aACUoB,EACTX,SAAUA,EACV2C,MAAOb,EACP7C,UAAWA,EACX4D,cApFa,IAWfR,EAAAA,IAACtC,EAAmB,CAACC,SAAUA,EAAU8C,QAVlBC,IACnB/C,IAIJ+C,EAAMC,kBACNjB,MAIiEtB,SAC9DW,EAASiB,EAAAA,IAACY,EAAa,IAAMZ,EAAAA,IAACa,EAAe,CAAA,KAyE9CR,GAAI/B,EACJwC,WAAY,CACV,mBAAoBzB,GAEtBb,MAAM,GACNC,SAtHe,CAACiC,EAAmCK,OAGrDA,GACiB,iBAAVA,GACP,UAAYA,GAEXA,EAA6BjC,OAAOnB,UAQnCc,GACFA,EAASiC,EAAOK,GANhBL,EAAMM,kBA6GJP,QAASf,EACTC,KAAMZ,EACNH,SAAUA,EACVvB,gBAAiBA,EACjBwB,MAtGAxB,EACKsB,EAGFsC,OAAOpC,GAmGVqC,QAAQ,cACJpC,WAxEc,MACtB,MAAMqC,EAAY,GA0BlB,OAtBI9D,GACF8D,EAAUC,KACRpB,MAAC/B,GAECN,UAAQ,EAAA,cACI,OACZ0D,UAAU,EACVxC,MAAOF,EAAWP,SAEjBO,GANG,gBAYND,GAAS4C,OAAS,EACpBH,EAAUC,QAAQxB,GAGlBuB,EAAUC,KAAKhD,GAGV+C,GA+CFI"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/Select/index.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport MuiSelect, { type SelectChangeEvent, type SelectProps as MuiSelectProps } from '@mui/material/Select';\nimport { styled } from '@mui/material/styles';\n\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\n\nimport MenuItem from '../MenuItem';\n\nexport interface SelectOption {\n value: number | string;\n label: string;\n disabled?: boolean;\n}\n\nexport type SelectProps = Omit<MuiSelectProps, 'error' | 'id' | 'value' | 'variant'> & {\n errorText?: string;\n fdKey: string;\n helperText?: string;\n options?: SelectOption[];\n placeholder?: string;\n value?: number | string;\n};\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain minWidth to a maximum of 100% of the container width\n}));\n\nconst StyledSelect = styled(MuiSelect, {\n shouldForwardProp: (prop) => !['fullWidth', 'showPlaceholder'].includes(prop as string),\n})<{ fullWidth?: boolean; showPlaceholder?: boolean }>(\n ({ theme, fullWidth = false, showPlaceholder = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n\n '& .MuiSelect-select': {\n color: showPlaceholder\n ? theme.palette.semantic.text['text-weak']\n : theme.palette.semantic.text['text-strong'],\n },\n }),\n);\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ theme, disabled = false }) => ({\n alignItems: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n display: 'flex',\n justifyContent: 'center',\n paddingRight: theme.spacing(2),\n pointerEvents: 'auto',\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n}));\n\nconst StyledHiddenPlaceholderMenuItem = styled(MenuItem)(() => ({\n display: 'none',\n}));\n\nexport const Select = ({\n children,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n onChange,\n options = [],\n placeholder,\n required = false,\n value,\n ...props\n}: SelectProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const showPlaceholder = !!placeholder && (!value || value === '');\n\n // Close the dropdown (if open) when the component is dynamically disabled\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n /**\n * Toggles or sets the dropdown open state.\n * Does nothing when the component is disabled.\n *\n * @param open - Optional boolean to explicitly set open state; if undefined, toggles current state\n */\n const toggleOpen = (open?: boolean): void => {\n if (disabled) {\n return;\n }\n\n if (open !== undefined) {\n setIsOpen(open);\n return;\n }\n\n setIsOpen((prevOpen) => !prevOpen);\n };\n\n const handleChange = (event: SelectChangeEvent<unknown>, child?: React.ReactNode): void => {\n // Check if the child is disabled\n const isMenuItemDisabled = !!(\n child &&\n typeof child === 'object' &&\n 'props' in (child as React.ReactElement) &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (child as React.ReactElement).props?.disabled\n );\n if (isMenuItemDisabled) {\n event.preventDefault();\n return;\n }\n\n // Call the original onChange handler if provided\n if (onChange) {\n onChange(event, child);\n }\n };\n\n const getDisplayValue = (): string => {\n if (showPlaceholder) {\n return placeholder;\n }\n\n return String(value);\n };\n\n const renderIcon = (): JSX.Element => {\n const handleIconClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n toggleOpen();\n };\n\n return (\n <StyledIconContainer disabled={disabled} onClick={handleIconClick}>\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledIconContainer>\n );\n };\n\n const optionsMenuItems = useMemo((): React.ReactNode[] => {\n return options.map((option) => (\n <MenuItem key={option.value} disabled={option.disabled} value={option.value}>\n {option.label}\n </MenuItem>\n ));\n }, [options]);\n\n const renderMenuItems = (): React.ReactNode => {\n const menuItems = [];\n\n // Workaround to get the placeholder to show up when no value is selected\n // Placeholder must be a menu item to be displayed\n if (showPlaceholder) {\n menuItems.push(\n <StyledHiddenPlaceholderMenuItem\n key=\"placeholder\"\n disabled\n aria-hidden=\"true\"\n tabIndex={-1}\n value={placeholder}\n >\n {placeholder}\n </StyledHiddenPlaceholderMenuItem>,\n );\n }\n\n // Add either options or children\n if (options?.length > 0) {\n menuItems.push(...optionsMenuItems);\n } else {\n // If no options are provided, use the children\n menuItems.push(children);\n }\n\n return menuItems;\n };\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledSelect\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n IconComponent={renderIcon}\n id={fdKey}\n inputProps={{\n 'aria-describedby': ariaDescribedBy,\n }}\n label=\"\" // Remove label from Select since we're rendering it separately\n onChange={handleChange}\n onClose={() => toggleOpen(false)}\n onOpen={() => toggleOpen(true)}\n open={isOpen}\n required={required}\n showPlaceholder={showPlaceholder}\n value={getDisplayValue()}\n variant=\"outlined\"\n {...props}\n >\n {renderMenuItems()}\n </StyledSelect>\n </StyledContainer>\n );\n};\n\nexport type { SelectChangeEvent };\nexport default Select;\n"],"names":["StyledContainer","styled","Box","shouldForwardProp","prop","theme","fullWidth","display","flexDirection","gap","spacing","width","StyledSelect","MuiSelect","includes","showPlaceholder","color","palette","semantic","text","StyledIconContainer","disabled","alignItems","cursor","justifyContent","paddingRight","pointerEvents","icon","StyledHiddenPlaceholderMenuItem","MenuItem","Select","children","errorText","fdKey","helperText","label","onChange","options","placeholder","required","value","props","isOpen","setIsOpen","useState","helperTextId","undefined","errorMessageId","ariaDescribedBy","filter","Boolean","join","isError","useEffect","toggleOpen","open","prevOpen","optionsMenuItems","useMemo","map","option","_jsx","_jsxs","MuiInputLabel","htmlFor","MuiFormHelperText","id","error","CancelCircleIcon","IconComponent","onClick","event","stopPropagation","ArrowUp01Icon","ArrowDown01Icon","inputProps","child","preventDefault","onClose","onOpen","String","variant","menuItems","push","tabIndex","length","renderMenuItems"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as
|
|
1
|
+
import{jsx as e,jsxs as i}from"react/jsx-runtime";import{useState as r,useEffect as o,useMemo as l}from"react";import t from"@mui/material/Box";import d from"@mui/material/FormHelperText";import a from"@mui/material/InputLabel";import n from"@mui/material/Select";import{styled as s}from"@mui/material/styles";import p from"../../../icons/ArrowDown01/index.js";import c from"../../../icons/ArrowUp01/index.js";import m from"../../../icons/CancelCircle/index.js";import{MenuItem as h}from"../MenuItem/index.js";const u=s(t,{shouldForwardProp:e=>"fullWidth"!==e})((({theme:e,fullWidth:i=!1})=>({display:"flex",flexDirection:"column",gap:e.spacing(.5),width:i?"100%":"min(364px, 100%)"}))),f=s(n,{shouldForwardProp:e=>!["fullWidth","showPlaceholder"].includes(e)})((({theme:e,fullWidth:i=!1,showPlaceholder:r=!1})=>({display:"flex",width:i?"100%":"auto","& .MuiSelect-select":{color:r?e.palette.semantic.text["text-weak"]:e.palette.semantic.text["text-strong"]}}))),x=s(t,{shouldForwardProp:e=>"disabled"!==e})((({theme:e,disabled:i=!1})=>({alignItems:"center",cursor:i?"not-allowed":"pointer",display:"flex",justifyContent:"center",paddingRight:e.spacing(2),pointerEvents:"auto","& svg":{color:i?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),b=s(h)((()=>({display:"none"}))),g=({children:n,disabled:s=!1,errorText:g,fdKey:v,fullWidth:w=!1,helperText:y,label:j,onChange:C,options:P=[],placeholder:W,required:F=!1,value:I,...q})=>{const[D,S]=r(!1),T=y?`${v}-helper-text`:void 0,k=g?`${v}-error-message`:void 0,A=[T,k].filter(Boolean).join(" ")||void 0,B=!!g&&!s,M=!(!W||I&&""!==I);o((()=>{s&&S(!1)}),[s]);const $=e=>{s||S(void 0===e?e=>!e:e)},E=l((()=>P.map((i=>e(h,{disabled:i.disabled,value:i.value,children:i.label},i.value)))),[P]);return i(u,{fullWidth:w,children:[i(t,{children:[j&&e(a,{disabled:s,htmlFor:v,required:F,children:j}),y&&e(d,{disabled:s,id:T,children:y})]}),B&&i(d,{error:!0,id:k,children:[e(m,{}),g]}),e(f,{"data-fd":v,disabled:s,error:B,fullWidth:w,IconComponent:()=>e(x,{disabled:s,onClick:e=>{s||(e.stopPropagation(),$())},children:e(D?c:p,{})}),id:v,inputProps:{"aria-describedby":A},label:"",onChange:(e,i)=>{!(i&&"object"==typeof i&&"props"in i&&i.props?.disabled)?C&&C(e,i):e.preventDefault()},onClose:()=>$(!1),onOpen:()=>$(!0),open:D,required:F,showPlaceholder:M,value:M?W:String(I),variant:"outlined",...q,children:(()=>{const i=[];return M&&i.push(e(b,{disabled:!0,"aria-hidden":"true",tabIndex:-1,value:W,children:W},"placeholder")),P?.length>0?i.push(...E):i.push(n),i})()})]})};export{g as Select,g as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/Select/index.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport MuiSelect, { type SelectChangeEvent, type SelectProps as MuiSelectProps } from '@mui/material/Select';\nimport { styled } from '@mui/material/styles';\n\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\n\nimport MenuItem from '../MenuItem';\n\nexport interface SelectOption {\n value: number | string;\n label: string;\n disabled?: boolean;\n}\n\nexport type SelectProps = Omit<MuiSelectProps, 'error' | 'id' | 'value' | 'variant'> & {\n errorText?: string;\n fdKey: string;\n helperText?: string;\n options?: SelectOption[];\n placeholder?: string;\n value?: number | string;\n};\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain minWidth to a maximum of 100% of the container width\n}));\n\nconst StyledSelect = styled(MuiSelect, {\n shouldForwardProp: (prop) => !['fullWidth', 'showPlaceholder'].includes(prop as string),\n})<{ fullWidth?: boolean; showPlaceholder?: boolean }>(\n ({ theme, fullWidth = false, showPlaceholder = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n\n '& .MuiSelect-select': {\n color: showPlaceholder\n ? theme.palette.semantic.text['text-weak']\n : theme.palette.semantic.text['text-strong'],\n },\n }),\n);\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ theme, disabled = false }) => ({\n alignItems: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n display: 'flex',\n justifyContent: 'center',\n pointerEvents: 'auto',\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n}));\n\nconst StyledHiddenPlaceholderMenuItem = styled(MenuItem)(() => ({\n display: 'none',\n}));\n\nexport const Select = ({\n children,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n onChange,\n options = [],\n placeholder,\n required = false,\n value,\n ...props\n}: SelectProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const showPlaceholder = !!placeholder && (!value || value === '');\n\n const handleOpen = (): void => {\n if (disabled) {\n return;\n }\n\n setIsOpen((open) => !open);\n };\n\n const handleChange = (event: SelectChangeEvent<unknown>, child?: React.ReactNode): void => {\n // Check if the child is disabled\n const isMenuItemDisabled = !!(\n child &&\n typeof child === 'object' &&\n 'props' in (child as React.ReactElement) &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (child as React.ReactElement).props?.disabled\n );\n if (isMenuItemDisabled) {\n event.preventDefault();\n return;\n }\n\n // Call the original onChange handler if provided\n if (onChange) {\n onChange(event, child);\n }\n };\n\n const getDisplayValue = (): string => {\n if (showPlaceholder) {\n return placeholder;\n }\n\n return String(value);\n };\n\n const renderIcon = (): JSX.Element => {\n const handleIconClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n handleOpen();\n };\n\n return (\n <StyledIconContainer disabled={disabled} onClick={handleIconClick}>\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledIconContainer>\n );\n };\n\n const optionsMenuItems = useMemo((): React.ReactNode[] => {\n return options.map((option) => (\n <MenuItem key={option.value} disabled={option.disabled} value={option.value}>\n {option.label}\n </MenuItem>\n ));\n }, [options]);\n\n const renderMenuItems = (): React.ReactNode => {\n const menuItems = [];\n\n // Workaround to get the placeholder to show up when no value is selected\n // Placeholder must be a menu item to be displayed\n if (showPlaceholder) {\n menuItems.push(\n <StyledHiddenPlaceholderMenuItem\n key=\"placeholder\"\n disabled\n aria-hidden=\"true\"\n tabIndex={-1}\n value={placeholder}\n >\n {placeholder}\n </StyledHiddenPlaceholderMenuItem>,\n );\n }\n\n // Add either options or children\n if (options?.length > 0) {\n menuItems.push(...optionsMenuItems);\n } else {\n // If no options are provided, use the children\n menuItems.push(children);\n }\n\n return menuItems;\n };\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledSelect\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n IconComponent={renderIcon}\n id={fdKey}\n inputProps={{\n 'aria-describedby': ariaDescribedBy,\n }}\n label=\"\" // Remove label from Select since we're rendering it separately\n onChange={handleChange}\n onClick={handleOpen}\n open={isOpen}\n required={required}\n showPlaceholder={showPlaceholder}\n value={getDisplayValue()}\n variant=\"outlined\"\n {...props}\n >\n {renderMenuItems()}\n </StyledSelect>\n </StyledContainer>\n );\n};\n\nexport type { SelectChangeEvent };\nexport default Select;\n"],"names":["StyledContainer","styled","Box","shouldForwardProp","prop","theme","fullWidth","display","flexDirection","gap","spacing","width","StyledSelect","MuiSelect","includes","showPlaceholder","color","palette","semantic","text","StyledIconContainer","disabled","alignItems","cursor","justifyContent","pointerEvents","icon","StyledHiddenPlaceholderMenuItem","MenuItem","Select","children","errorText","fdKey","helperText","label","onChange","options","placeholder","required","value","props","isOpen","setIsOpen","useState","helperTextId","undefined","errorMessageId","ariaDescribedBy","filter","Boolean","join","isError","handleOpen","open","optionsMenuItems","useMemo","map","option","_jsx","_jsxs","MuiInputLabel","htmlFor","MuiFormHelperText","id","error","CancelCircleIcon","IconComponent","onClick","event","stopPropagation","ArrowUp01Icon","ArrowDown01Icon","inputProps","child","preventDefault","String","variant","menuItems","push","tabIndex","length","renderMenuItems"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/Select/index.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport MuiSelect, { type SelectChangeEvent, type SelectProps as MuiSelectProps } from '@mui/material/Select';\nimport { styled } from '@mui/material/styles';\n\nimport ArrowDown01Icon from '@fd/icons/ArrowDown01';\nimport ArrowUp01Icon from '@fd/icons/ArrowUp01';\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\n\nimport MenuItem from '../MenuItem';\n\nexport interface SelectOption {\n value: number | string;\n label: string;\n disabled?: boolean;\n}\n\nexport type SelectProps = Omit<MuiSelectProps, 'error' | 'id' | 'value' | 'variant'> & {\n errorText?: string;\n fdKey: string;\n helperText?: string;\n options?: SelectOption[];\n placeholder?: string;\n value?: number | string;\n};\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain minWidth to a maximum of 100% of the container width\n}));\n\nconst StyledSelect = styled(MuiSelect, {\n shouldForwardProp: (prop) => !['fullWidth', 'showPlaceholder'].includes(prop as string),\n})<{ fullWidth?: boolean; showPlaceholder?: boolean }>(\n ({ theme, fullWidth = false, showPlaceholder = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n\n '& .MuiSelect-select': {\n color: showPlaceholder\n ? theme.palette.semantic.text['text-weak']\n : theme.palette.semantic.text['text-strong'],\n },\n }),\n);\n\nconst StyledIconContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ theme, disabled = false }) => ({\n alignItems: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n display: 'flex',\n justifyContent: 'center',\n paddingRight: theme.spacing(2),\n pointerEvents: 'auto',\n\n '& svg': {\n color: disabled\n ? theme.palette.semantic.icon['icon-disabled']\n : theme.palette.semantic.icon['icon-strong'],\n },\n}));\n\nconst StyledHiddenPlaceholderMenuItem = styled(MenuItem)(() => ({\n display: 'none',\n}));\n\nexport const Select = ({\n children,\n disabled = false,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n label,\n onChange,\n options = [],\n placeholder,\n required = false,\n value,\n ...props\n}: SelectProps): JSX.Element => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const showPlaceholder = !!placeholder && (!value || value === '');\n\n // Close the dropdown (if open) when the component is dynamically disabled\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n /**\n * Toggles or sets the dropdown open state.\n * Does nothing when the component is disabled.\n *\n * @param open - Optional boolean to explicitly set open state; if undefined, toggles current state\n */\n const toggleOpen = (open?: boolean): void => {\n if (disabled) {\n return;\n }\n\n if (open !== undefined) {\n setIsOpen(open);\n return;\n }\n\n setIsOpen((prevOpen) => !prevOpen);\n };\n\n const handleChange = (event: SelectChangeEvent<unknown>, child?: React.ReactNode): void => {\n // Check if the child is disabled\n const isMenuItemDisabled = !!(\n child &&\n typeof child === 'object' &&\n 'props' in (child as React.ReactElement) &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (child as React.ReactElement).props?.disabled\n );\n if (isMenuItemDisabled) {\n event.preventDefault();\n return;\n }\n\n // Call the original onChange handler if provided\n if (onChange) {\n onChange(event, child);\n }\n };\n\n const getDisplayValue = (): string => {\n if (showPlaceholder) {\n return placeholder;\n }\n\n return String(value);\n };\n\n const renderIcon = (): JSX.Element => {\n const handleIconClick = (event: React.MouseEvent): void => {\n if (disabled) {\n return;\n }\n\n event.stopPropagation();\n toggleOpen();\n };\n\n return (\n <StyledIconContainer disabled={disabled} onClick={handleIconClick}>\n {isOpen ? <ArrowUp01Icon /> : <ArrowDown01Icon />}\n </StyledIconContainer>\n );\n };\n\n const optionsMenuItems = useMemo((): React.ReactNode[] => {\n return options.map((option) => (\n <MenuItem key={option.value} disabled={option.disabled} value={option.value}>\n {option.label}\n </MenuItem>\n ));\n }, [options]);\n\n const renderMenuItems = (): React.ReactNode => {\n const menuItems = [];\n\n // Workaround to get the placeholder to show up when no value is selected\n // Placeholder must be a menu item to be displayed\n if (showPlaceholder) {\n menuItems.push(\n <StyledHiddenPlaceholderMenuItem\n key=\"placeholder\"\n disabled\n aria-hidden=\"true\"\n tabIndex={-1}\n value={placeholder}\n >\n {placeholder}\n </StyledHiddenPlaceholderMenuItem>,\n );\n }\n\n // Add either options or children\n if (options?.length > 0) {\n menuItems.push(...optionsMenuItems);\n } else {\n // If no options are provided, use the children\n menuItems.push(children);\n }\n\n return menuItems;\n };\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledSelect\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n IconComponent={renderIcon}\n id={fdKey}\n inputProps={{\n 'aria-describedby': ariaDescribedBy,\n }}\n label=\"\" // Remove label from Select since we're rendering it separately\n onChange={handleChange}\n onClose={() => toggleOpen(false)}\n onOpen={() => toggleOpen(true)}\n open={isOpen}\n required={required}\n showPlaceholder={showPlaceholder}\n value={getDisplayValue()}\n variant=\"outlined\"\n {...props}\n >\n {renderMenuItems()}\n </StyledSelect>\n </StyledContainer>\n );\n};\n\nexport type { SelectChangeEvent };\nexport default Select;\n"],"names":["StyledContainer","styled","Box","shouldForwardProp","prop","theme","fullWidth","display","flexDirection","gap","spacing","width","StyledSelect","MuiSelect","includes","showPlaceholder","color","palette","semantic","text","StyledIconContainer","disabled","alignItems","cursor","justifyContent","paddingRight","pointerEvents","icon","StyledHiddenPlaceholderMenuItem","MenuItem","Select","children","errorText","fdKey","helperText","label","onChange","options","placeholder","required","value","props","isOpen","setIsOpen","useState","helperTextId","undefined","errorMessageId","ariaDescribedBy","filter","Boolean","join","isError","useEffect","toggleOpen","open","prevOpen","optionsMenuItems","useMemo","map","option","_jsx","_jsxs","MuiInputLabel","htmlFor","MuiFormHelperText","id","error","CancelCircleIcon","IconComponent","onClick","event","stopPropagation","ArrowUp01Icon","ArrowDown01Icon","inputProps","child","preventDefault","onClose","onOpen","String","variant","menuItems","push","tabIndex","length","renderMenuItems"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),t=require("@mui/material/Box"),l=require("@mui/material/Chip"),i=require("@mui/material/styles"),s=require("../../../icons/Cancel/index.cjs.js");const o=i.styled(t,{shouldForwardProp:e=>"disabled"!==e})((({disabled:e})=>({cursor:e?"not-allowed":void 0}))),r=i.styled(l,{shouldForwardProp:e=>"selected"!==e})((({theme:e,selected:t})=>({...t&&{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"],"& .MuiChip-deleteIcon, & .MuiChip-icon":{color:e.palette.semantic.icon["icon-inverse-strong"],"&:hover:not(.Mui-disabled)":{color:e.palette.semantic.text["text-inverse-strong"]}},"&:hover:not(.Mui-disabled)":{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"]},"&:active:not(.Mui-disabled)":{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"]},"&:focus-visible, &.Mui-focusVisible":{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"]},"&.Mui-disabled":{backgroundColor:e.palette.semantic.fill["fill-disabled"],borderColor:e.palette.semantic.fill["fill-disabled"],color:e.palette.semantic.text["text-inverse-strong"],"& .MuiChip-deleteIcon, & .MuiChip-icon":{color:e.palette.semantic.icon["icon-inverse-strong"]}}}}))),a=({className:t,disabled:l=!1,fdKey:i,label:a,onClick:d,onDismiss:n,selected:c=!1,size:m="medium",dismissAriaLabel:u})=>e.jsx(o,{disabled:l,children:e.jsx(r,{"aria-label":d?`${a}`:n?`${u} ${a}`:void 0,className:t,clickable:!l&&!!d,"data-fd":i,"data-fd-variant":"tag",deleteIcon:(()=>{if(n)return e.jsx(s,{"aria-hidden":!0,"data-testid":"tag-dismiss-icon",size:"sm"})})(),disabled:l,label:a,onClick:l?void 0:d,onDelete:l?void 0:n,onKeyDown:e=>{l||"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),e.stopPropagation(),n?n(e):d&&d(e))},selected:c,size:m})});a.displayName="Tag",exports.Tag=a,exports.default=a;
|
|
2
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/Tag/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport MuiChip, { type ChipProps as MuiChipProps } from '@mui/material/Chip';\nimport { styled } from '@mui/material/styles';\n\nimport CancelIcon from '@fd/icons/Cancel';\n\n/** Props for the Tag component */\ninterface TagBaseProps {\n /** Additional CSS class names */\n className?: string;\n /** Whether the tag is disabled */\n disabled?: boolean;\n /** Test ID for testing and automation */\n fdKey?: string;\n /** Text label displayed in the tag */\n label: string;\n /** Whether the tag is selected */\n selected?: boolean;\n /** Size of the tag */\n size?: MuiChipProps['size'];\n}\n\ninterface TagDismissibleProps extends TagBaseProps {\n /** Callback function when the tag is clicked */\n onClick?: undefined;\n /** Callback function when the tag is dismissed */\n onDismiss: NonNullable<MuiChipProps['onDelete']>;\n /** Aria-label prefix for the dismiss button; the tag label is appended automatically */\n dismissAriaLabel: string;\n}\n\ninterface TagNonDismissibleProps extends TagBaseProps {\n /** Callback function when the tag is clicked */\n onClick?: MuiChipProps['onClick'];\n /** No dismiss handler in this variant */\n onDismiss?: undefined;\n /** No aria label when there is no dismiss */\n dismissAriaLabel?: undefined;\n}\n\n/** Props for the Tag component */\nexport type TagProps = TagDismissibleProps | TagNonDismissibleProps;\n\nconst StyledTagContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ disabled }) => ({\n cursor: disabled ? 'not-allowed' : undefined,\n}));\n\nconst StyledTag = styled(MuiChip, {\n shouldForwardProp: (prop) => prop !== 'selected',\n})<{ selected?: boolean }>(({ theme, selected }) => ({\n ...(selected && {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n\n '& .MuiChip-deleteIcon, & .MuiChip-icon': {\n color: theme.palette.semantic.icon['icon-inverse-strong'],\n\n '&:hover:not(.Mui-disabled)': {\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n },\n '&:hover:not(.Mui-disabled)': {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n '&:active:not(.Mui-disabled)': {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n '&:focus-visible, &.Mui-focusVisible': {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n '&.Mui-disabled': {\n backgroundColor: theme.palette.semantic.fill['fill-disabled'],\n borderColor: theme.palette.semantic.fill['fill-disabled'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n\n '& .MuiChip-deleteIcon, & .MuiChip-icon': {\n color: theme.palette.semantic.icon['icon-inverse-strong'],\n },\n },\n }),\n}));\n\n/**\n * Tag component used for categorization and filtering.\n * It supports two variants: dismissible (with delete icon) and clickable (entire tag is interactive).\n * Both variants support a selected state.\n */\nexport const Tag = ({\n className,\n disabled = false,\n fdKey,\n label,\n onClick,\n onDismiss,\n selected = false,\n size = 'medium',\n dismissAriaLabel,\n}: TagProps): JSX.Element => {\n const getAriaLabel = (): string | undefined => {\n if (onClick) {\n return `${label}`;\n }\n if (onDismiss) {\n return `${dismissAriaLabel} ${label}`;\n }\n\n return undefined;\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (disabled) {\n return;\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n\n if (onDismiss) {\n onDismiss(event as unknown as React.MouseEvent<HTMLDivElement>);\n } else if (onClick) {\n onClick(event as unknown as React.MouseEvent<HTMLDivElement>);\n }\n }\n };\n\n const renderDismissIcon = (): React.ReactElement<unknown> | undefined => {\n if (!onDismiss) {\n return undefined;\n }\n\n return <CancelIcon aria-hidden={true} data-testid=\"tag-dismiss-icon\" size=\"sm\" />;\n };\n\n return (\n <StyledTagContainer disabled={disabled}>\n <StyledTag\n aria-label={getAriaLabel()}\n className={className}\n clickable={disabled ? false : !!onClick}\n data-fd={fdKey}\n data-fd-variant=\"tag\"\n deleteIcon={renderDismissIcon()}\n disabled={disabled}\n label={label}\n onClick={disabled ? undefined : onClick}\n onDelete={disabled ? undefined : onDismiss}\n onKeyDown={handleKeyDown}\n selected={selected}\n size={size}\n />\n </StyledTagContainer>\n );\n};\n\nTag.displayName = 'Tag';\n\nexport default Tag;\n"],"names":["StyledTagContainer","styled","Box","shouldForwardProp","prop","disabled","cursor","undefined","StyledTag","MuiChip","theme","selected","backgroundColor","palette","semantic","fill","borderColor","stroke","color","text","icon","Tag","className","fdKey","label","onClick","onDismiss","size","dismissAriaLabel","_jsx","children","clickable","deleteIcon","CancelIcon","renderDismissIcon","onDelete","onKeyDown","event","key","preventDefault","stopPropagation","displayName"],"mappings":"wPA2CA,MAAMA,EAAqBC,EAAAA,OAAOC,EAAK,CACrCC,kBAAoBC,GAAkB,aAATA,GADJH,EAEA,EAAGI,eAAU,CACtCC,OAAQD,EAAW,mBAAgBE,MAG/BC,EAAYP,EAAAA,OAAOQ,EAAS,CAChCN,kBAAoBC,GAAkB,aAATA,GADbH,EAES,EAAGS,QAAOC,eAAU,IACzCA,GAAY,CACdC,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,uBAEnC,yCAA0C,CACxCD,MAAOR,EAAMG,QAAQC,SAASM,KAAK,uBAEnC,6BAA8B,CAC5BF,MAAOR,EAAMG,QAAQC,SAASK,KAAK,yBAGvC,6BAA8B,CAC5BP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,wBAErC,8BAA+B,CAC7BP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,wBAErC,sCAAuC,CACrCP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,wBAErC,iBAAkB,CAChBP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASC,KAAK,iBACzCG,MAAOR,EAAMG,QAAQC,SAASK,KAAK,uBAEnC,yCAA0C,CACxCD,MAAOR,EAAMG,QAAQC,SAASM,KAAK,8BAW9BC,EAAM,EACjBC,YACAjB,YAAW,EACXkB,QACAC,QACAC,UACAC,YACAf,YAAW,EACXgB,OAAO,SACPC,sBAuCEC,EAAAA,IAAC7B,GAAmBK,SAAUA,EAAQyB,SACpCD,EAAAA,IAACrB,EAAS,CAAA,aArCRiB,EACK,GAAGD,IAERE,EACK,GAAGE,KAAoBJ,SADhC,EAoCIF,UAAWA,EACXS,WAAW1B,KAAqBoB,YACvBF,EAAK,kBACE,MAChBS,WAhBoB,MACxB,GAAKN,EAIL,OAAOG,EAAAA,IAACI,EAAU,CAAA,eAAc,EAAI,cAAc,mBAAmBN,KAAK,QAW1DO,GACZ7B,SAAUA,EACVmB,MAAOA,EACPC,QAASpB,OAAWE,EAAYkB,EAChCU,SAAU9B,OAAWE,EAAYmB,EACjCU,UAtCiBC,IACjBhC,GAIc,UAAdgC,EAAMC,KAAiC,MAAdD,EAAMC,MACjCD,EAAME,iBACNF,EAAMG,kBAEFd,EACFA,EAAUW,GACDZ,GACTA,EAAQY,KA2BR1B,SAAUA,EACVgB,KAAMA,MAMdN,EAAIoB,YAAc"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ChipProps } from '@mui/material/Chip';
|
|
2
|
+
|
|
3
|
+
/** Props for the Tag component */
|
|
4
|
+
interface TagBaseProps {
|
|
5
|
+
/** Additional CSS class names */
|
|
6
|
+
className?: string;
|
|
7
|
+
/** Whether the tag is disabled */
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
/** Test ID for testing and automation */
|
|
10
|
+
fdKey?: string;
|
|
11
|
+
/** Text label displayed in the tag */
|
|
12
|
+
label: string;
|
|
13
|
+
/** Whether the tag is selected */
|
|
14
|
+
selected?: boolean;
|
|
15
|
+
/** Size of the tag */
|
|
16
|
+
size?: ChipProps['size'];
|
|
17
|
+
}
|
|
18
|
+
interface TagDismissibleProps extends TagBaseProps {
|
|
19
|
+
/** Callback function when the tag is clicked */
|
|
20
|
+
onClick?: undefined;
|
|
21
|
+
/** Callback function when the tag is dismissed */
|
|
22
|
+
onDismiss: NonNullable<ChipProps['onDelete']>;
|
|
23
|
+
/** Aria-label prefix for the dismiss button; the tag label is appended automatically */
|
|
24
|
+
dismissAriaLabel: string;
|
|
25
|
+
}
|
|
26
|
+
interface TagNonDismissibleProps extends TagBaseProps {
|
|
27
|
+
/** Callback function when the tag is clicked */
|
|
28
|
+
onClick?: ChipProps['onClick'];
|
|
29
|
+
/** No dismiss handler in this variant */
|
|
30
|
+
onDismiss?: undefined;
|
|
31
|
+
/** No aria label when there is no dismiss */
|
|
32
|
+
dismissAriaLabel?: undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Props for the Tag component */
|
|
35
|
+
type TagProps = TagDismissibleProps | TagNonDismissibleProps;
|
|
36
|
+
/**
|
|
37
|
+
* Tag component used for categorization and filtering.
|
|
38
|
+
* It supports two variants: dismissible (with delete icon) and clickable (entire tag is interactive).
|
|
39
|
+
* Both variants support a selected state.
|
|
40
|
+
*/
|
|
41
|
+
declare const Tag: {
|
|
42
|
+
({ className, disabled, fdKey, label, onClick, onDismiss, selected, size, dismissAriaLabel, }: TagProps): JSX.Element;
|
|
43
|
+
displayName: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { Tag, Tag as default };
|
|
47
|
+
export type { TagProps };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import t from"@mui/material/Box";import i from"@mui/material/Chip";import{styled as l}from"@mui/material/styles";import o from"../../../icons/Cancel/index.js";const s=l(t,{shouldForwardProp:e=>"disabled"!==e})((({disabled:e})=>({cursor:e?"not-allowed":void 0}))),a=l(i,{shouldForwardProp:e=>"selected"!==e})((({theme:e,selected:t})=>({...t&&{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"],"& .MuiChip-deleteIcon, & .MuiChip-icon":{color:e.palette.semantic.icon["icon-inverse-strong"],"&:hover:not(.Mui-disabled)":{color:e.palette.semantic.text["text-inverse-strong"]}},"&:hover:not(.Mui-disabled)":{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"]},"&:active:not(.Mui-disabled)":{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"]},"&:focus-visible, &.Mui-focusVisible":{backgroundColor:e.palette.semantic.fill["fill-selected"],borderColor:e.palette.semantic.stroke["stroke-selected"],color:e.palette.semantic.text["text-inverse-strong"]},"&.Mui-disabled":{backgroundColor:e.palette.semantic.fill["fill-disabled"],borderColor:e.palette.semantic.fill["fill-disabled"],color:e.palette.semantic.text["text-inverse-strong"],"& .MuiChip-deleteIcon, & .MuiChip-icon":{color:e.palette.semantic.icon["icon-inverse-strong"]}}}}))),r=({className:t,disabled:i=!1,fdKey:l,label:r,onClick:d,onDismiss:n,selected:c=!1,size:m="medium",dismissAriaLabel:p})=>e(s,{disabled:i,children:e(a,{"aria-label":d?`${r}`:n?`${p} ${r}`:void 0,className:t,clickable:!i&&!!d,"data-fd":l,"data-fd-variant":"tag",deleteIcon:(()=>{if(n)return e(o,{"aria-hidden":!0,"data-testid":"tag-dismiss-icon",size:"sm"})})(),disabled:i,label:r,onClick:i?void 0:d,onDelete:i?void 0:n,onKeyDown:e=>{i||"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),e.stopPropagation(),n?n(e):d&&d(e))},selected:c,size:m})});r.displayName="Tag";export{r as Tag,r as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/Tag/index.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport MuiChip, { type ChipProps as MuiChipProps } from '@mui/material/Chip';\nimport { styled } from '@mui/material/styles';\n\nimport CancelIcon from '@fd/icons/Cancel';\n\n/** Props for the Tag component */\ninterface TagBaseProps {\n /** Additional CSS class names */\n className?: string;\n /** Whether the tag is disabled */\n disabled?: boolean;\n /** Test ID for testing and automation */\n fdKey?: string;\n /** Text label displayed in the tag */\n label: string;\n /** Whether the tag is selected */\n selected?: boolean;\n /** Size of the tag */\n size?: MuiChipProps['size'];\n}\n\ninterface TagDismissibleProps extends TagBaseProps {\n /** Callback function when the tag is clicked */\n onClick?: undefined;\n /** Callback function when the tag is dismissed */\n onDismiss: NonNullable<MuiChipProps['onDelete']>;\n /** Aria-label prefix for the dismiss button; the tag label is appended automatically */\n dismissAriaLabel: string;\n}\n\ninterface TagNonDismissibleProps extends TagBaseProps {\n /** Callback function when the tag is clicked */\n onClick?: MuiChipProps['onClick'];\n /** No dismiss handler in this variant */\n onDismiss?: undefined;\n /** No aria label when there is no dismiss */\n dismissAriaLabel?: undefined;\n}\n\n/** Props for the Tag component */\nexport type TagProps = TagDismissibleProps | TagNonDismissibleProps;\n\nconst StyledTagContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'disabled',\n})<{ disabled?: boolean }>(({ disabled }) => ({\n cursor: disabled ? 'not-allowed' : undefined,\n}));\n\nconst StyledTag = styled(MuiChip, {\n shouldForwardProp: (prop) => prop !== 'selected',\n})<{ selected?: boolean }>(({ theme, selected }) => ({\n ...(selected && {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n\n '& .MuiChip-deleteIcon, & .MuiChip-icon': {\n color: theme.palette.semantic.icon['icon-inverse-strong'],\n\n '&:hover:not(.Mui-disabled)': {\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n },\n '&:hover:not(.Mui-disabled)': {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n '&:active:not(.Mui-disabled)': {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n '&:focus-visible, &.Mui-focusVisible': {\n backgroundColor: theme.palette.semantic.fill['fill-selected'],\n borderColor: theme.palette.semantic.stroke['stroke-selected'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n },\n '&.Mui-disabled': {\n backgroundColor: theme.palette.semantic.fill['fill-disabled'],\n borderColor: theme.palette.semantic.fill['fill-disabled'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n\n '& .MuiChip-deleteIcon, & .MuiChip-icon': {\n color: theme.palette.semantic.icon['icon-inverse-strong'],\n },\n },\n }),\n}));\n\n/**\n * Tag component used for categorization and filtering.\n * It supports two variants: dismissible (with delete icon) and clickable (entire tag is interactive).\n * Both variants support a selected state.\n */\nexport const Tag = ({\n className,\n disabled = false,\n fdKey,\n label,\n onClick,\n onDismiss,\n selected = false,\n size = 'medium',\n dismissAriaLabel,\n}: TagProps): JSX.Element => {\n const getAriaLabel = (): string | undefined => {\n if (onClick) {\n return `${label}`;\n }\n if (onDismiss) {\n return `${dismissAriaLabel} ${label}`;\n }\n\n return undefined;\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (disabled) {\n return;\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n\n if (onDismiss) {\n onDismiss(event as unknown as React.MouseEvent<HTMLDivElement>);\n } else if (onClick) {\n onClick(event as unknown as React.MouseEvent<HTMLDivElement>);\n }\n }\n };\n\n const renderDismissIcon = (): React.ReactElement<unknown> | undefined => {\n if (!onDismiss) {\n return undefined;\n }\n\n return <CancelIcon aria-hidden={true} data-testid=\"tag-dismiss-icon\" size=\"sm\" />;\n };\n\n return (\n <StyledTagContainer disabled={disabled}>\n <StyledTag\n aria-label={getAriaLabel()}\n className={className}\n clickable={disabled ? false : !!onClick}\n data-fd={fdKey}\n data-fd-variant=\"tag\"\n deleteIcon={renderDismissIcon()}\n disabled={disabled}\n label={label}\n onClick={disabled ? undefined : onClick}\n onDelete={disabled ? undefined : onDismiss}\n onKeyDown={handleKeyDown}\n selected={selected}\n size={size}\n />\n </StyledTagContainer>\n );\n};\n\nTag.displayName = 'Tag';\n\nexport default Tag;\n"],"names":["StyledTagContainer","styled","Box","shouldForwardProp","prop","disabled","cursor","undefined","StyledTag","MuiChip","theme","selected","backgroundColor","palette","semantic","fill","borderColor","stroke","color","text","icon","Tag","className","fdKey","label","onClick","onDismiss","size","dismissAriaLabel","_jsx","children","clickable","deleteIcon","CancelIcon","renderDismissIcon","onDelete","onKeyDown","event","key","preventDefault","stopPropagation","displayName"],"mappings":"uMA2CA,MAAMA,EAAqBC,EAAOC,EAAK,CACrCC,kBAAoBC,GAAkB,aAATA,GADJH,EAEA,EAAGI,eAAU,CACtCC,OAAQD,EAAW,mBAAgBE,MAG/BC,EAAYP,EAAOQ,EAAS,CAChCN,kBAAoBC,GAAkB,aAATA,GADbH,EAES,EAAGS,QAAOC,eAAU,IACzCA,GAAY,CACdC,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,uBAEnC,yCAA0C,CACxCD,MAAOR,EAAMG,QAAQC,SAASM,KAAK,uBAEnC,6BAA8B,CAC5BF,MAAOR,EAAMG,QAAQC,SAASK,KAAK,yBAGvC,6BAA8B,CAC5BP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,wBAErC,8BAA+B,CAC7BP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,wBAErC,sCAAuC,CACrCP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASG,OAAO,mBAC3CC,MAAOR,EAAMG,QAAQC,SAASK,KAAK,wBAErC,iBAAkB,CAChBP,gBAAiBF,EAAMG,QAAQC,SAASC,KAAK,iBAC7CC,YAAaN,EAAMG,QAAQC,SAASC,KAAK,iBACzCG,MAAOR,EAAMG,QAAQC,SAASK,KAAK,uBAEnC,yCAA0C,CACxCD,MAAOR,EAAMG,QAAQC,SAASM,KAAK,8BAW9BC,EAAM,EACjBC,YACAjB,YAAW,EACXkB,QACAC,QACAC,UACAC,YACAf,YAAW,EACXgB,OAAO,SACPC,sBAuCEC,EAAC7B,GAAmBK,SAAUA,EAAQyB,SACpCD,EAACrB,EAAS,CAAA,aArCRiB,EACK,GAAGD,IAERE,EACK,GAAGE,KAAoBJ,SADhC,EAoCIF,UAAWA,EACXS,WAAW1B,KAAqBoB,YACvBF,EAAK,kBACE,MAChBS,WAhBoB,MACxB,GAAKN,EAIL,OAAOG,EAACI,EAAU,CAAA,eAAc,EAAI,cAAc,mBAAmBN,KAAK,QAW1DO,GACZ7B,SAAUA,EACVmB,MAAOA,EACPC,QAASpB,OAAWE,EAAYkB,EAChCU,SAAU9B,OAAWE,EAAYmB,EACjCU,UAtCiBC,IACjBhC,GAIc,UAAdgC,EAAMC,KAAiC,MAAdD,EAAMC,MACjCD,EAAME,iBACNF,EAAMG,kBAEFd,EACFA,EAAUW,GACDZ,GACTA,EAAQY,KA2BR1B,SAAUA,EACVgB,KAAMA,MAMdN,EAAIoB,YAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),r=require("react"),i=require("@mui/material/Box"),t=require("@mui/material/FormHelperText"),l=require("@mui/material/InputAdornment"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),r=require("react"),i=require("@mui/material/Box"),t=require("@mui/material/FormHelperText"),l=require("@mui/material/InputAdornment"),s=require("@mui/material/InputLabel"),d=require("@mui/material/styles"),n=require("@mui/material/TextField"),a=require("../../../icons/CancelCircle/index.cjs.js"),o=require("../../../icons/View/index.cjs.js"),u=require("../../../icons/ViewOff/index.cjs.js"),x=require("../IconButton/index.cjs.js");const c=d.styled(i,{shouldForwardProp:e=>"fullWidth"!==e})((({theme:e,fullWidth:r=!1})=>({display:"flex",flexDirection:"column",gap:e.spacing(.5),width:r?"100%":"min(364px, 100%)"}))),p=d.styled(n,{shouldForwardProp:e=>"fullWidth"!==e})((({fullWidth:e=!1})=>({display:"flex",width:e?"100%":"auto"}))),m=({disabled:d=!1,endAdornment:n,errorText:m,fdKey:h,fullWidth:j=!1,helperText:f,hidePasswordAriaLabel:q,label:b,multiline:w=!1,required:y=!1,showPasswordAriaLabel:P,startAdornment:v,type:A="text",...W})=>{const[F,I]=r.useState(!1),T=f?`${h}-helper-text`:void 0,B=m?`${h}-error-message`:void 0,g=[T,B].filter(Boolean).join(" ")||void 0,C=!!m&&!d,L="password"===A,O=()=>I((e=>!e)),V=(()=>{if(L){if(!P||!q)return;return e.jsx(l,{position:"end",children:e.jsx(x.IconButton,{"aria-label":F?q:P,disabled:d,onClick:O,size:"small",tone:"neutral",variant:"tertiary",children:F?e.jsx(u,{}):e.jsx(o,{})})})}if(n)return e.jsx(l,{position:"end",children:n})})(),$=(()=>{if(v)return e.jsx(l,{position:"start",children:v})})();return e.jsxs(c,{fullWidth:j,children:[e.jsxs(i,{children:[b&&e.jsx(s,{disabled:d,htmlFor:h,required:y,children:b}),f&&e.jsx(t,{disabled:d,id:T,children:f})]}),C&&e.jsxs(t,{error:!0,id:B,children:[e.jsx(a,{}),m]}),e.jsx(p,{"data-fd":h,disabled:d,error:C,fullWidth:j,id:h,label:"",multiline:w,required:y,slotProps:{input:{...W.slotProps?.input??{},...$&&{startAdornment:$},...V&&{endAdornment:V}},htmlInput:{...W.slotProps?.htmlInput??{},"aria-describedby":g}},type:L?F?"text":"password":A,variant:"outlined",...W})]})};exports.TextField=m,exports.default=m;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/TextField/index.tsx"],"sourcesContent":["import { type ReactNode, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputAdornment from '@mui/material/InputAdornment';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport { styled } from '@mui/material/styles';\nimport MuiTextField, { type TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField';\n\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport ViewIcon from '@fd/icons/View';\nimport ViewOffIcon from '@fd/icons/ViewOff';\n\nimport IconButton from '../IconButton';\n\n// Common props for all TextField variants\ntype BaseTextFieldProps = Omit<MuiTextFieldProps, 'error' | 'id' | 'type' | 'variant'> & {\n endAdornment?: ReactNode;\n errorText?: string;\n fdKey: string;\n startAdornment?: ReactNode;\n};\n\n// Password TextField variant - requires aria labels\ntype PasswordTextFieldProps = BaseTextFieldProps & {\n type: 'password';\n hidePasswordAriaLabel: string;\n showPasswordAriaLabel: string;\n};\n\n// Generic TextField variant - for all other input types\ntype GenericTextFieldProps = BaseTextFieldProps & {\n type?: Exclude<MuiTextFieldProps['type'], 'password'>;\n hidePasswordAriaLabel?: never;\n showPasswordAriaLabel?: never;\n};\n\nexport type TextFieldProps = GenericTextFieldProps | PasswordTextFieldProps;\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain width to a maximum of 100% of the container width\n}));\n\nconst StyledTextField = styled(MuiTextField, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n}));\n\nexport const TextField = ({\n disabled = false,\n endAdornment = undefined,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n hidePasswordAriaLabel,\n label,\n multiline = false,\n required = false,\n showPasswordAriaLabel,\n startAdornment = undefined,\n type = 'text',\n ...props\n}: TextFieldProps): JSX.Element => {\n const [showPassword, setShowPassword] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const isPassword = type === 'password';\n\n const handleClickShowPassword = (): void => setShowPassword((show) => !show);\n\n const getFieldType = (): MuiTextFieldProps['type'] => {\n if (isPassword) {\n return showPassword ? 'text' : 'password';\n }\n\n return type;\n };\n\n const renderEndAdornment = (): React.ReactNode => {\n if (isPassword) {\n if (!showPasswordAriaLabel || !hidePasswordAriaLabel) {\n return undefined;\n }\n\n return (\n <MuiInputAdornment position=\"end\">\n <IconButton\n aria-label={showPassword ? hidePasswordAriaLabel : showPasswordAriaLabel}\n disabled={disabled}\n onClick={handleClickShowPassword}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n {showPassword ? <ViewOffIcon /> : <ViewIcon />}\n </IconButton>\n </MuiInputAdornment>\n );\n }\n if (endAdornment) {\n return <MuiInputAdornment position=\"end\">{endAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n const renderStartAdornment = (): React.ReactNode => {\n if (startAdornment) {\n return <MuiInputAdornment position=\"start\">{startAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledTextField\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n id={fdKey}\n label=\"\" // Remove label from TextField since we're rendering it separately\n multiline={multiline}\n required={required}\n slotProps={{\n input: {\n endAdornment:
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../src/components/atoms/TextField/index.tsx"],"sourcesContent":["import { type ReactNode, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputAdornment from '@mui/material/InputAdornment';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport { styled } from '@mui/material/styles';\nimport MuiTextField, { type TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField';\n\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport ViewIcon from '@fd/icons/View';\nimport ViewOffIcon from '@fd/icons/ViewOff';\n\nimport IconButton from '../IconButton';\n\n// Common props for all TextField variants\ntype BaseTextFieldProps = Omit<MuiTextFieldProps, 'error' | 'id' | 'type' | 'variant'> & {\n endAdornment?: ReactNode;\n errorText?: string;\n fdKey: string;\n startAdornment?: ReactNode;\n};\n\n// Password TextField variant - requires aria labels\ntype PasswordTextFieldProps = BaseTextFieldProps & {\n type: 'password';\n hidePasswordAriaLabel: string;\n showPasswordAriaLabel: string;\n};\n\n// Generic TextField variant - for all other input types\ntype GenericTextFieldProps = BaseTextFieldProps & {\n type?: Exclude<MuiTextFieldProps['type'], 'password'>;\n hidePasswordAriaLabel?: never;\n showPasswordAriaLabel?: never;\n};\n\nexport type TextFieldProps = GenericTextFieldProps | PasswordTextFieldProps;\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain width to a maximum of 100% of the container width\n}));\n\nconst StyledTextField = styled(MuiTextField, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n}));\n\nexport const TextField = ({\n disabled = false,\n endAdornment = undefined,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n hidePasswordAriaLabel,\n label,\n multiline = false,\n required = false,\n showPasswordAriaLabel,\n startAdornment = undefined,\n type = 'text',\n ...props\n}: TextFieldProps): JSX.Element => {\n const [showPassword, setShowPassword] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const isPassword = type === 'password';\n\n const handleClickShowPassword = (): void => setShowPassword((show) => !show);\n\n const getFieldType = (): MuiTextFieldProps['type'] => {\n if (isPassword) {\n return showPassword ? 'text' : 'password';\n }\n\n return type;\n };\n\n const renderEndAdornment = (): React.ReactNode => {\n if (isPassword) {\n if (!showPasswordAriaLabel || !hidePasswordAriaLabel) {\n return undefined;\n }\n\n return (\n <MuiInputAdornment position=\"end\">\n <IconButton\n aria-label={showPassword ? hidePasswordAriaLabel : showPasswordAriaLabel}\n disabled={disabled}\n onClick={handleClickShowPassword}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n {showPassword ? <ViewOffIcon /> : <ViewIcon />}\n </IconButton>\n </MuiInputAdornment>\n );\n }\n if (endAdornment) {\n return <MuiInputAdornment position=\"end\">{endAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n const renderStartAdornment = (): React.ReactNode => {\n if (startAdornment) {\n return <MuiInputAdornment position=\"start\">{startAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n const renderedEndAdornment = renderEndAdornment();\n const renderedStartAdornment = renderStartAdornment();\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledTextField\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n id={fdKey}\n label=\"\" // Remove label from TextField since we're rendering it separately\n multiline={multiline}\n required={required}\n slotProps={{\n input: {\n ...(props.slotProps?.input ?? {}),\n // Only pass startAdornment and endAdornment if they are defined\n ...(renderedStartAdornment && { startAdornment: renderedStartAdornment }),\n ...(renderedEndAdornment && { endAdornment: renderedEndAdornment }),\n },\n htmlInput: {\n ...(props.slotProps?.htmlInput ?? {}),\n 'aria-describedby': ariaDescribedBy,\n },\n }}\n type={getFieldType()}\n variant=\"outlined\"\n {...props}\n />\n </StyledContainer>\n );\n};\n\nexport default TextField;\n"],"names":["StyledContainer","styled","Box","shouldForwardProp","prop","theme","fullWidth","display","flexDirection","gap","spacing","width","StyledTextField","MuiTextField","TextField","disabled","endAdornment","errorText","fdKey","helperText","hidePasswordAriaLabel","label","multiline","required","showPasswordAriaLabel","startAdornment","type","props","showPassword","setShowPassword","useState","helperTextId","undefined","errorMessageId","ariaDescribedBy","filter","Boolean","join","isError","isPassword","handleClickShowPassword","show","renderedEndAdornment","_jsx","MuiInputAdornment","position","children","IconButton","onClick","size","tone","variant","ViewOffIcon","ViewIcon","renderEndAdornment","renderedStartAdornment","renderStartAdornment","_jsxs","MuiInputLabel","htmlFor","MuiFormHelperText","id","error","CancelCircleIcon","slotProps","input","htmlInput"],"mappings":"uhBAuCA,MAAMA,EAAkBC,EAAAA,OAAOC,EAAK,CAClCC,kBAAoBC,GAAkB,cAATA,GADPH,EAEI,EAAGI,QAAOC,aAAY,MAAO,CACvDC,QAAS,OACTC,cAAe,SACfC,IAAKJ,EAAMK,QAAQ,IACnBC,MAAOL,EAAY,OAAS,uBAGxBM,EAAkBX,EAAAA,OAAOY,EAAc,CAC3CV,kBAAoBC,GAAkB,cAATA,GADPH,EAEI,EAAGK,aAAY,MAAO,CAChDC,QAAS,OACTI,MAAOL,EAAY,OAAS,WAGjBQ,EAAY,EACvBC,YAAW,EACXC,eACAC,YACAC,QACAZ,aAAY,EACZa,aACAC,wBACAC,QACAC,aAAY,EACZC,YAAW,EACXC,wBACAC,iBACAC,OAAO,UACJC,MAEH,MAAOC,EAAcC,GAAmBC,EAAAA,UAAkB,GAEpDC,EAAeZ,EAAa,GAAGD,qBAAsBc,EACrDC,EAAiBhB,EAAY,GAAGC,uBAAwBc,EAGxDE,EAAkB,CAACH,EAAcE,GAAgBE,OAAOC,SAASC,KAAK,WAAQL,EAE9EM,IAAYrB,IAAcF,EAC1BwB,EAAsB,aAATb,EAEbc,EAA0B,IAAYX,GAAiBY,IAAUA,IA8CjEC,EApCqB,MACzB,GAAIH,EAAY,CACd,IAAKf,IAA0BJ,EAC7B,OAGF,OACEuB,EAAAA,IAACC,EAAiB,CAACC,SAAS,MAAKC,SAC/BH,MAACI,EAAAA,WAAU,CAAA,aACGnB,EAAeR,EAAwBI,EACnDT,SAAUA,EACViC,QAASR,EACTS,KAAK,QACLC,KAAK,UACLC,QAAQ,WAAUL,SAEjBlB,EAAee,EAAAA,IAACS,EAAW,CAAA,GAAMT,EAAAA,IAACU,EAAQ,CAAA,MAInD,CACA,GAAIrC,EACF,OAAO2B,EAAAA,IAACC,EAAiB,CAACC,SAAS,MAAKC,SAAE9B,KAcjBsC,GACvBC,EATuB,MAC3B,GAAI9B,EACF,OAAOkB,EAAAA,IAACC,EAAiB,CAACC,SAAS,QAAOC,SAAErB,KAOjB+B,GAE/B,OACEC,EAAAA,KAACzD,EAAe,CAACM,UAAWA,YAC1BmD,EAAAA,KAACvD,aACEmB,GACCsB,EAAAA,IAACe,GAAc3C,SAAUA,EAAU4C,QAASzC,EAAOK,SAAUA,EAAQuB,SAClEzB,IAIJF,GACCwB,EAAAA,IAACiB,GAAkB7C,SAAUA,EAAU8C,GAAI9B,EAAYe,SACpD3B,OAKNmB,GACCmB,EAAAA,KAACG,GAAkBE,OAAK,EAACD,GAAI5B,YAC3BU,EAAAA,IAACoB,MAEA9C,KAIL0B,EAAAA,IAAC/B,EAAe,CAAA,UACLM,EACTH,SAAUA,EACV+C,MAAOxB,EACPhC,UAAWA,EACXuD,GAAI3C,EACJG,MAAM,GACNC,UAAWA,EACXC,SAAUA,EACVyC,UAAW,CACTC,MAAO,IACDtC,EAAMqC,WAAWC,OAAS,MAE1BV,GAA0B,CAAE9B,eAAgB8B,MAC5Cb,GAAwB,CAAE1B,aAAc0B,IAE9CwB,UAAW,IACLvC,EAAMqC,WAAWE,WAAa,GAClC,mBAAoBhC,IAGxBR,KA3FAa,EACKX,EAAe,OAAS,WAG1BF,EAwFHyB,QAAQ,cACJxB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as r,jsx as i}from"react/jsx-runtime";import{useState as e}from"react";import t from"@mui/material/Box";import o from"@mui/material/FormHelperText";import l from"@mui/material/InputAdornment";import d from"@mui/material/InputLabel";import{styled as n}from"@mui/material/styles";import a from"@mui/material/TextField";import m from"../../../icons/CancelCircle/index.js";import s from"../../../icons/View/index.js";import
|
|
1
|
+
import{jsxs as r,jsx as i}from"react/jsx-runtime";import{useState as e}from"react";import t from"@mui/material/Box";import o from"@mui/material/FormHelperText";import l from"@mui/material/InputAdornment";import d from"@mui/material/InputLabel";import{styled as n}from"@mui/material/styles";import a from"@mui/material/TextField";import m from"../../../icons/CancelCircle/index.js";import s from"../../../icons/View/index.js";import p from"../../../icons/ViewOff/index.js";import{IconButton as u}from"../IconButton/index.js";const f=n(t,{shouldForwardProp:r=>"fullWidth"!==r})((({theme:r,fullWidth:i=!1})=>({display:"flex",flexDirection:"column",gap:r.spacing(.5),width:i?"100%":"min(364px, 100%)"}))),h=n(a,{shouldForwardProp:r=>"fullWidth"!==r})((({fullWidth:r=!1})=>({display:"flex",width:r?"100%":"auto"}))),c=({disabled:n=!1,endAdornment:a,errorText:c,fdKey:x,fullWidth:b=!1,helperText:w,hidePasswordAriaLabel:y,label:A,multiline:P=!1,required:W=!1,showPasswordAriaLabel:j,startAdornment:v,type:F="text",...I})=>{const[T,g]=e(!1),q=w?`${x}-helper-text`:void 0,B=c?`${x}-error-message`:void 0,C=[q,B].filter(Boolean).join(" ")||void 0,L=!!c&&!n,V="password"===F,$=()=>g((r=>!r)),k=(()=>{if(V){if(!j||!y)return;return i(l,{position:"end",children:i(u,{"aria-label":T?y:j,disabled:n,onClick:$,size:"small",tone:"neutral",variant:"tertiary",children:i(T?p:s,{})})})}if(a)return i(l,{position:"end",children:a})})(),z=(()=>{if(v)return i(l,{position:"start",children:v})})();return r(f,{fullWidth:b,children:[r(t,{children:[A&&i(d,{disabled:n,htmlFor:x,required:W,children:A}),w&&i(o,{disabled:n,id:q,children:w})]}),L&&r(o,{error:!0,id:B,children:[i(m,{}),c]}),i(h,{"data-fd":x,disabled:n,error:L,fullWidth:b,id:x,label:"",multiline:P,required:W,slotProps:{input:{...I.slotProps?.input??{},...z&&{startAdornment:z},...k&&{endAdornment:k}},htmlInput:{...I.slotProps?.htmlInput??{},"aria-describedby":C}},type:V?T?"text":"password":F,variant:"outlined",...I})]})};export{c as TextField,c as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/TextField/index.tsx"],"sourcesContent":["import { type ReactNode, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputAdornment from '@mui/material/InputAdornment';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport { styled } from '@mui/material/styles';\nimport MuiTextField, { type TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField';\n\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport ViewIcon from '@fd/icons/View';\nimport ViewOffIcon from '@fd/icons/ViewOff';\n\nimport IconButton from '../IconButton';\n\n// Common props for all TextField variants\ntype BaseTextFieldProps = Omit<MuiTextFieldProps, 'error' | 'id' | 'type' | 'variant'> & {\n endAdornment?: ReactNode;\n errorText?: string;\n fdKey: string;\n startAdornment?: ReactNode;\n};\n\n// Password TextField variant - requires aria labels\ntype PasswordTextFieldProps = BaseTextFieldProps & {\n type: 'password';\n hidePasswordAriaLabel: string;\n showPasswordAriaLabel: string;\n};\n\n// Generic TextField variant - for all other input types\ntype GenericTextFieldProps = BaseTextFieldProps & {\n type?: Exclude<MuiTextFieldProps['type'], 'password'>;\n hidePasswordAriaLabel?: never;\n showPasswordAriaLabel?: never;\n};\n\nexport type TextFieldProps = GenericTextFieldProps | PasswordTextFieldProps;\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain width to a maximum of 100% of the container width\n}));\n\nconst StyledTextField = styled(MuiTextField, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n}));\n\nexport const TextField = ({\n disabled = false,\n endAdornment = undefined,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n hidePasswordAriaLabel,\n label,\n multiline = false,\n required = false,\n showPasswordAriaLabel,\n startAdornment = undefined,\n type = 'text',\n ...props\n}: TextFieldProps): JSX.Element => {\n const [showPassword, setShowPassword] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const isPassword = type === 'password';\n\n const handleClickShowPassword = (): void => setShowPassword((show) => !show);\n\n const getFieldType = (): MuiTextFieldProps['type'] => {\n if (isPassword) {\n return showPassword ? 'text' : 'password';\n }\n\n return type;\n };\n\n const renderEndAdornment = (): React.ReactNode => {\n if (isPassword) {\n if (!showPasswordAriaLabel || !hidePasswordAriaLabel) {\n return undefined;\n }\n\n return (\n <MuiInputAdornment position=\"end\">\n <IconButton\n aria-label={showPassword ? hidePasswordAriaLabel : showPasswordAriaLabel}\n disabled={disabled}\n onClick={handleClickShowPassword}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n {showPassword ? <ViewOffIcon /> : <ViewIcon />}\n </IconButton>\n </MuiInputAdornment>\n );\n }\n if (endAdornment) {\n return <MuiInputAdornment position=\"end\">{endAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n const renderStartAdornment = (): React.ReactNode => {\n if (startAdornment) {\n return <MuiInputAdornment position=\"start\">{startAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledTextField\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n id={fdKey}\n label=\"\" // Remove label from TextField since we're rendering it separately\n multiline={multiline}\n required={required}\n slotProps={{\n input: {\n endAdornment:
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/TextField/index.tsx"],"sourcesContent":["import { type ReactNode, useState } from 'react';\n\nimport Box from '@mui/material/Box';\nimport MuiFormHelperText from '@mui/material/FormHelperText';\nimport MuiInputAdornment from '@mui/material/InputAdornment';\nimport MuiInputLabel from '@mui/material/InputLabel';\nimport { styled } from '@mui/material/styles';\nimport MuiTextField, { type TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField';\n\nimport CancelCircleIcon from '@fd/icons/CancelCircle';\nimport ViewIcon from '@fd/icons/View';\nimport ViewOffIcon from '@fd/icons/ViewOff';\n\nimport IconButton from '../IconButton';\n\n// Common props for all TextField variants\ntype BaseTextFieldProps = Omit<MuiTextFieldProps, 'error' | 'id' | 'type' | 'variant'> & {\n endAdornment?: ReactNode;\n errorText?: string;\n fdKey: string;\n startAdornment?: ReactNode;\n};\n\n// Password TextField variant - requires aria labels\ntype PasswordTextFieldProps = BaseTextFieldProps & {\n type: 'password';\n hidePasswordAriaLabel: string;\n showPasswordAriaLabel: string;\n};\n\n// Generic TextField variant - for all other input types\ntype GenericTextFieldProps = BaseTextFieldProps & {\n type?: Exclude<MuiTextFieldProps['type'], 'password'>;\n hidePasswordAriaLabel?: never;\n showPasswordAriaLabel?: never;\n};\n\nexport type TextFieldProps = GenericTextFieldProps | PasswordTextFieldProps;\n\nconst StyledContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ theme, fullWidth = false }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(0.5),\n width: fullWidth ? '100%' : 'min(364px, 100%)', // Constrain width to a maximum of 100% of the container width\n}));\n\nconst StyledTextField = styled(MuiTextField, {\n shouldForwardProp: (prop) => prop !== 'fullWidth',\n})<{ fullWidth?: boolean }>(({ fullWidth = false }) => ({\n display: 'flex',\n width: fullWidth ? '100%' : 'auto',\n}));\n\nexport const TextField = ({\n disabled = false,\n endAdornment = undefined,\n errorText,\n fdKey,\n fullWidth = false,\n helperText,\n hidePasswordAriaLabel,\n label,\n multiline = false,\n required = false,\n showPasswordAriaLabel,\n startAdornment = undefined,\n type = 'text',\n ...props\n}: TextFieldProps): JSX.Element => {\n const [showPassword, setShowPassword] = useState<boolean>(false);\n\n const helperTextId = helperText ? `${fdKey}-helper-text` : undefined;\n const errorMessageId = errorText ? `${fdKey}-error-message` : undefined;\n\n // Combine helper text and error message IDs for aria-describedby\n const ariaDescribedBy = [helperTextId, errorMessageId].filter(Boolean).join(' ') || undefined;\n\n const isError = !!errorText && !disabled;\n const isPassword = type === 'password';\n\n const handleClickShowPassword = (): void => setShowPassword((show) => !show);\n\n const getFieldType = (): MuiTextFieldProps['type'] => {\n if (isPassword) {\n return showPassword ? 'text' : 'password';\n }\n\n return type;\n };\n\n const renderEndAdornment = (): React.ReactNode => {\n if (isPassword) {\n if (!showPasswordAriaLabel || !hidePasswordAriaLabel) {\n return undefined;\n }\n\n return (\n <MuiInputAdornment position=\"end\">\n <IconButton\n aria-label={showPassword ? hidePasswordAriaLabel : showPasswordAriaLabel}\n disabled={disabled}\n onClick={handleClickShowPassword}\n size=\"small\"\n tone=\"neutral\"\n variant=\"tertiary\"\n >\n {showPassword ? <ViewOffIcon /> : <ViewIcon />}\n </IconButton>\n </MuiInputAdornment>\n );\n }\n if (endAdornment) {\n return <MuiInputAdornment position=\"end\">{endAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n const renderStartAdornment = (): React.ReactNode => {\n if (startAdornment) {\n return <MuiInputAdornment position=\"start\">{startAdornment}</MuiInputAdornment>;\n }\n\n return undefined;\n };\n\n const renderedEndAdornment = renderEndAdornment();\n const renderedStartAdornment = renderStartAdornment();\n\n return (\n <StyledContainer fullWidth={fullWidth}>\n <Box>\n {label && (\n <MuiInputLabel disabled={disabled} htmlFor={fdKey} required={required}>\n {label}\n </MuiInputLabel>\n )}\n\n {helperText && (\n <MuiFormHelperText disabled={disabled} id={helperTextId}>\n {helperText}\n </MuiFormHelperText>\n )}\n </Box>\n\n {isError && (\n <MuiFormHelperText error id={errorMessageId}>\n <CancelCircleIcon />\n\n {errorText}\n </MuiFormHelperText>\n )}\n\n <StyledTextField\n data-fd={fdKey}\n disabled={disabled}\n error={isError}\n fullWidth={fullWidth}\n id={fdKey}\n label=\"\" // Remove label from TextField since we're rendering it separately\n multiline={multiline}\n required={required}\n slotProps={{\n input: {\n ...(props.slotProps?.input ?? {}),\n // Only pass startAdornment and endAdornment if they are defined\n ...(renderedStartAdornment && { startAdornment: renderedStartAdornment }),\n ...(renderedEndAdornment && { endAdornment: renderedEndAdornment }),\n },\n htmlInput: {\n ...(props.slotProps?.htmlInput ?? {}),\n 'aria-describedby': ariaDescribedBy,\n },\n }}\n type={getFieldType()}\n variant=\"outlined\"\n {...props}\n />\n </StyledContainer>\n );\n};\n\nexport default TextField;\n"],"names":["StyledContainer","styled","Box","shouldForwardProp","prop","theme","fullWidth","display","flexDirection","gap","spacing","width","StyledTextField","MuiTextField","TextField","disabled","endAdornment","errorText","fdKey","helperText","hidePasswordAriaLabel","label","multiline","required","showPasswordAriaLabel","startAdornment","type","props","showPassword","setShowPassword","useState","helperTextId","undefined","errorMessageId","ariaDescribedBy","filter","Boolean","join","isError","isPassword","handleClickShowPassword","show","renderedEndAdornment","_jsx","MuiInputAdornment","position","children","IconButton","onClick","size","tone","variant","ViewOffIcon","ViewIcon","renderEndAdornment","renderedStartAdornment","renderStartAdornment","_jsxs","MuiInputLabel","htmlFor","MuiFormHelperText","id","error","CancelCircleIcon","slotProps","input","htmlInput"],"mappings":"4gBAuCA,MAAMA,EAAkBC,EAAOC,EAAK,CAClCC,kBAAoBC,GAAkB,cAATA,GADPH,EAEI,EAAGI,QAAOC,aAAY,MAAO,CACvDC,QAAS,OACTC,cAAe,SACfC,IAAKJ,EAAMK,QAAQ,IACnBC,MAAOL,EAAY,OAAS,uBAGxBM,EAAkBX,EAAOY,EAAc,CAC3CV,kBAAoBC,GAAkB,cAATA,GADPH,EAEI,EAAGK,aAAY,MAAO,CAChDC,QAAS,OACTI,MAAOL,EAAY,OAAS,WAGjBQ,EAAY,EACvBC,YAAW,EACXC,eACAC,YACAC,QACAZ,aAAY,EACZa,aACAC,wBACAC,QACAC,aAAY,EACZC,YAAW,EACXC,wBACAC,iBACAC,OAAO,UACJC,MAEH,MAAOC,EAAcC,GAAmBC,GAAkB,GAEpDC,EAAeZ,EAAa,GAAGD,qBAAsBc,EACrDC,EAAiBhB,EAAY,GAAGC,uBAAwBc,EAGxDE,EAAkB,CAACH,EAAcE,GAAgBE,OAAOC,SAASC,KAAK,WAAQL,EAE9EM,IAAYrB,IAAcF,EAC1BwB,EAAsB,aAATb,EAEbc,EAA0B,IAAYX,GAAiBY,IAAUA,IA8CjEC,EApCqB,MACzB,GAAIH,EAAY,CACd,IAAKf,IAA0BJ,EAC7B,OAGF,OACEuB,EAACC,EAAiB,CAACC,SAAS,MAAKC,SAC/BH,EAACI,EAAU,CAAA,aACGnB,EAAeR,EAAwBI,EACnDT,SAAUA,EACViC,QAASR,EACTS,KAAK,QACLC,KAAK,UACLC,QAAQ,WAAUL,SAEFH,EAAff,EAAgBwB,EAAkBC,EAAP,CAAA,MAIpC,CACA,GAAIrC,EACF,OAAO2B,EAACC,EAAiB,CAACC,SAAS,MAAKC,SAAE9B,KAcjBsC,GACvBC,EATuB,MAC3B,GAAI9B,EACF,OAAOkB,EAACC,EAAiB,CAACC,SAAS,QAAOC,SAAErB,KAOjB+B,GAE/B,OACEC,EAACzD,EAAe,CAACM,UAAWA,YAC1BmD,EAACvD,aACEmB,GACCsB,EAACe,GAAc3C,SAAUA,EAAU4C,QAASzC,EAAOK,SAAUA,EAAQuB,SAClEzB,IAIJF,GACCwB,EAACiB,GAAkB7C,SAAUA,EAAU8C,GAAI9B,EAAYe,SACpD3B,OAKNmB,GACCmB,EAACG,GAAkBE,OAAK,EAACD,GAAI5B,YAC3BU,EAACoB,MAEA9C,KAIL0B,EAAC/B,EAAe,CAAA,UACLM,EACTH,SAAUA,EACV+C,MAAOxB,EACPhC,UAAWA,EACXuD,GAAI3C,EACJG,MAAM,GACNC,UAAWA,EACXC,SAAUA,EACVyC,UAAW,CACTC,MAAO,IACDtC,EAAMqC,WAAWC,OAAS,MAE1BV,GAA0B,CAAE9B,eAAgB8B,MAC5Cb,GAAwB,CAAE1B,aAAc0B,IAE9CwB,UAAW,IACLvC,EAAMqC,WAAWE,WAAa,GAClC,mBAAoBhC,IAGxBR,KA3FAa,EACKX,EAAe,OAAS,WAG1BF,EAwFHyB,QAAQ,cACJxB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("react");exports.useDynamicLimitTags=function(t){const{chipMax:r=130,gap:n=4,horizontalPadding:s=32,reservedPx:a=0}=t??{},i=e.useRef(null),[o,c]=e.useState(1);return e.useLayoutEffect((()=>{const e=i.current;if(!e)return;const t=()=>{const t=e.clientWidth,i=Math.max(0,t-s-a),o=r+n,u=Math.max(1,Math.floor(i/o));c(u)};t();const o=new ResizeObserver(t);return o.observe(e),()=>o.disconnect()}),[r,n,s,a]),{rootRef:i,limitTags:o}};
|
|
2
|
+
//# sourceMappingURL=useDynamicLimitTags.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDynamicLimitTags.cjs.js","sources":["../../../../../src/components/molecules/Autocomplete/hooks/useDynamicLimitTags.ts"],"sourcesContent":["import { useLayoutEffect, useRef, useState } from 'react';\n\nexport interface UseDynamicLimitTagsProps {\n chipMax?: number; // px\n gap?: number; // px, matches theme gap between tags\n horizontalPadding?: number; // px, inputRoot left+right padding\n reservedPx?: number; // px, start/end adornments (icons) and search input width you want to reserve\n}\n\nexport interface UseDynamicLimitTagsReturn {\n rootRef: React.RefObject<HTMLDivElement | null>;\n limitTags: number;\n}\n\nexport function useDynamicLimitTags(props?: UseDynamicLimitTagsProps): UseDynamicLimitTagsReturn {\n const {\n chipMax = 130,\n gap = 4,\n horizontalPadding = 32, // matches padding: theme.spacing(0.5, 2) → 16px each side\n reservedPx = 0, // tweak if you have more adornments or larger search input\n } = props ?? {};\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [limitTags, setLimitTags] = useState<number>(1);\n\n useLayoutEffect(() => {\n const el = rootRef.current;\n if (!el) return;\n\n const update = (): void => {\n const width = el.clientWidth;\n const usable = Math.max(0, width - horizontalPadding - reservedPx);\n const perChip = chipMax + gap;\n const count = Math.max(1, Math.floor(usable / perChip));\n setLimitTags(count);\n };\n\n update();\n const ro = new ResizeObserver(update);\n ro.observe(el);\n return (): void => ro.disconnect();\n }, [chipMax, gap, horizontalPadding, reservedPx]);\n\n return { rootRef, limitTags };\n}\n"],"names":["props","chipMax","gap","horizontalPadding","reservedPx","rootRef","useRef","limitTags","setLimitTags","useState","useLayoutEffect","el","current","update","width","clientWidth","usable","Math","max","perChip","count","floor","ro","ResizeObserver","observe","disconnect"],"mappings":"gEAcM,SAA8BA,GAClC,MAAMC,QACJA,EAAU,IAAGC,IACbA,EAAM,EAACC,kBACPA,EAAoB,GAAEC,WACtBA,EAAa,GACXJ,GAAS,CAAA,EAEPK,EAAUC,EAAAA,OAA8B,OACvCC,EAAWC,GAAgBC,EAAAA,SAAiB,GAoBnD,OAlBAC,EAAAA,iBAAgB,KACd,MAAMC,EAAKN,EAAQO,QACnB,IAAKD,EAAI,OAET,MAAME,EAAS,KACb,MAAMC,EAAQH,EAAGI,YACXC,EAASC,KAAKC,IAAI,EAAGJ,EAAQX,EAAoBC,GACjDe,EAAUlB,EAAUC,EACpBkB,EAAQH,KAAKC,IAAI,EAAGD,KAAKI,MAAML,EAASG,IAC9CX,EAAaY,IAGfP,IACA,MAAMS,EAAK,IAAIC,eAAeV,GAE9B,OADAS,EAAGE,QAAQb,GACJ,IAAYW,EAAGG,eACrB,CAACxB,EAASC,EAAKC,EAAmBC,IAE9B,CAAEC,UAASE,YACpB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface UseDynamicLimitTagsProps {
|
|
2
|
+
chipMax?: number;
|
|
3
|
+
gap?: number;
|
|
4
|
+
horizontalPadding?: number;
|
|
5
|
+
reservedPx?: number;
|
|
6
|
+
}
|
|
7
|
+
interface UseDynamicLimitTagsReturn {
|
|
8
|
+
rootRef: React.RefObject<HTMLDivElement | null>;
|
|
9
|
+
limitTags: number;
|
|
10
|
+
}
|
|
11
|
+
declare function useDynamicLimitTags(props?: UseDynamicLimitTagsProps): UseDynamicLimitTagsReturn;
|
|
12
|
+
|
|
13
|
+
export { useDynamicLimitTags };
|
|
14
|
+
export type { UseDynamicLimitTagsProps, UseDynamicLimitTagsReturn };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{useRef as t,useState as r,useLayoutEffect as e}from"react";function n(n){const{chipMax:o=130,gap:c=4,horizontalPadding:i=32,reservedPx:a=0}=n??{},s=t(null),[h,l]=r(1);return e((()=>{const t=s.current;if(!t)return;const r=()=>{const r=t.clientWidth,e=Math.max(0,r-i-a),n=o+c,s=Math.max(1,Math.floor(e/n));l(s)};r();const e=new ResizeObserver(r);return e.observe(t),()=>e.disconnect()}),[o,c,i,a]),{rootRef:s,limitTags:h}}export{n as useDynamicLimitTags};
|
|
2
|
+
//# sourceMappingURL=useDynamicLimitTags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDynamicLimitTags.js","sources":["../../../../../src/components/molecules/Autocomplete/hooks/useDynamicLimitTags.ts"],"sourcesContent":["import { useLayoutEffect, useRef, useState } from 'react';\n\nexport interface UseDynamicLimitTagsProps {\n chipMax?: number; // px\n gap?: number; // px, matches theme gap between tags\n horizontalPadding?: number; // px, inputRoot left+right padding\n reservedPx?: number; // px, start/end adornments (icons) and search input width you want to reserve\n}\n\nexport interface UseDynamicLimitTagsReturn {\n rootRef: React.RefObject<HTMLDivElement | null>;\n limitTags: number;\n}\n\nexport function useDynamicLimitTags(props?: UseDynamicLimitTagsProps): UseDynamicLimitTagsReturn {\n const {\n chipMax = 130,\n gap = 4,\n horizontalPadding = 32, // matches padding: theme.spacing(0.5, 2) → 16px each side\n reservedPx = 0, // tweak if you have more adornments or larger search input\n } = props ?? {};\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [limitTags, setLimitTags] = useState<number>(1);\n\n useLayoutEffect(() => {\n const el = rootRef.current;\n if (!el) return;\n\n const update = (): void => {\n const width = el.clientWidth;\n const usable = Math.max(0, width - horizontalPadding - reservedPx);\n const perChip = chipMax + gap;\n const count = Math.max(1, Math.floor(usable / perChip));\n setLimitTags(count);\n };\n\n update();\n const ro = new ResizeObserver(update);\n ro.observe(el);\n return (): void => ro.disconnect();\n }, [chipMax, gap, horizontalPadding, reservedPx]);\n\n return { rootRef, limitTags };\n}\n"],"names":["useDynamicLimitTags","props","chipMax","gap","horizontalPadding","reservedPx","rootRef","useRef","limitTags","setLimitTags","useState","useLayoutEffect","el","current","update","width","clientWidth","usable","Math","max","perChip","count","floor","ro","ResizeObserver","observe","disconnect"],"mappings":"kEAcM,SAAUA,EAAoBC,GAClC,MAAMC,QACJA,EAAU,IAAGC,IACbA,EAAM,EAACC,kBACPA,EAAoB,GAAEC,WACtBA,EAAa,GACXJ,GAAS,CAAA,EAEPK,EAAUC,EAA8B,OACvCC,EAAWC,GAAgBC,EAAiB,GAoBnD,OAlBAC,GAAgB,KACd,MAAMC,EAAKN,EAAQO,QACnB,IAAKD,EAAI,OAET,MAAME,EAAS,KACb,MAAMC,EAAQH,EAAGI,YACXC,EAASC,KAAKC,IAAI,EAAGJ,EAAQX,EAAoBC,GACjDe,EAAUlB,EAAUC,EACpBkB,EAAQH,KAAKC,IAAI,EAAGD,KAAKI,MAAML,EAASG,IAC9CX,EAAaY,IAGfP,IACA,MAAMS,EAAK,IAAIC,eAAeV,GAE9B,OADAS,EAAGE,QAAQb,GACJ,IAAYW,EAAGG,eACrB,CAACxB,EAASC,EAAKC,EAAmBC,IAE9B,CAAEC,UAASE,YACpB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("@mui/material/Autocomplete");
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),i=require("react/jsx-runtime"),t=require("@mui/material/Autocomplete"),l=require("@mui/material/Box"),s=require("@mui/material/styles"),n=require("@mui/material/Tooltip"),r=require("../../../icons/ArrowDown01/index.cjs.js"),a=require("../../../icons/ArrowUp01/index.cjs.js"),o=require("../../../icons/Cancel/index.cjs.js"),d=require("../../../icons/Search/index.cjs.js"),c=require("../../../utilities/stringUtilities.cjs.js"),p=require("../../atoms/CircularProgress/index.cjs.js"),u=require("../../atoms/MenuItem/index.cjs.js"),m=require("../../atoms/Tag/index.cjs.js"),g=require("../../atoms/TextField/index.cjs.js"),x=require("./hooks/useDynamicLimitTags.cjs.js");const h=t,j=s.styled(h,{shouldForwardProp:e=>"fullWidth"!==e})((({fullWidth:e=!1})=>({width:e?"100%":"min(364px, 100%)"}))),b=s.styled(l,{shouldForwardProp:e=>!["clickable","disabled","placement"].includes(e)})((({theme:e,clickable:i=!1,disabled:t=!1,placement:l})=>({alignItems:"center",cursor:i?t?"not-allowed":"pointer":"default",display:"flex",justifyContent:"center",padding:0,pointerEvents:i?"auto":"none",..."start"===l&&{paddingRight:e.spacing(1)},..."middle"===l&&{padding:e.spacing(0,1)},"& svg":{color:t?e.palette.semantic.icon["icon-disabled"]:e.palette.semantic.icon["icon-strong"]}}))),y=s.styled(l,{shouldForwardProp:e=>"placement"!==e})((({theme:e,placement:i})=>({alignItems:"center",display:"flex",justifyContent:"center",padding:0,..."start"===i&&{paddingRight:e.spacing(1)},..."middle"===i&&{padding:e.spacing(0,1)}}))),f=({className:t,disabled:l=!1,errorText:s,fdKey:h,fullWidth:f=!1,helperText:T,label:q,loading:A=!1,multiple:C=!1,placeholder:I,onChange:P,onInputChange:k,options:v=[],required:L=!1,translations:O,type:w="search",value:E})=>{const[F,W]=e.useState(!1),D="search"===w,S="combobox"===w,{rootRef:M,limitTags:z}=x.useDynamicLimitTags({chipMax:130,gap:4,horizontalPadding:32,reservedPx:D?120:90});e.useEffect((()=>{l&&W(!1)}),[l]);const K=e=>{l||W(void 0===e?e=>!e:e)};return i.jsx(j,{ref:M,className:t,clearIcon:i.jsx(o,{size:"md"}),clearText:O.clearTextAriaLabel,disableClearable:l||A,disableCloseOnSelect:C,disabled:l,filterOptions:D?e=>e:void 0,forcePopupIcon:S,freeSolo:D,fullWidth:f,getOptionKey:e=>"string"==typeof e?e:String(e.value),getOptionLabel:e=>"string"==typeof e?e:e.label,isOptionEqualToValue:(e,i)=>null!=i&&("string"==typeof i?e.label===i||String(e.value)===i:e.value===i.value),limitTags:z,loading:A,loadingText:O.loadingText,multiple:C,noOptionsText:O.noOptionsText,onChange:(e,i,t,l)=>{P&&P(e,i,t,l)},onClose:()=>K(!1),onInputChange:(e,i,t)=>{k&&k(e,i,t)},onOpen:()=>K(!0),open:F,openText:O.openPopupAriaLabel,options:v,popupIcon:D?null:i.jsx(b,{clickable:!0,disabled:l,placement:"end",children:F?i.jsx(a,{}):i.jsx(r,{})}),renderInput:e=>i.jsx(g.TextField,{disabled:l,errorText:s,fdKey:h,fullWidth:f,helperText:T,label:q,placeholder:I,required:L,slotProps:{input:{...e.InputProps,endAdornment:i.jsxs(i.Fragment,{children:[A?i.jsx(y,{placement:D?"end":"middle",children:i.jsx(p.CircularProgress,{size:"small"})}):null,e.InputProps.endAdornment]}),startAdornment:i.jsxs(i.Fragment,{children:[D?i.jsx(b,{disabled:l,placement:"start",children:i.jsx(d,{"aria-hidden":"true"})}):null,e.InputProps.startAdornment]})},htmlInput:{...e.inputProps}}}),renderOption:(i,t,l)=>{const{key:s,onClick:n,...r}=i;return C?e.createElement(u.MenuItem,{...r,key:s,checked:l.selected,label:t.label,onCheckedChange:(e,i)=>{n?.(i)},type:"checkbox"}):e.createElement(u.MenuItem,{...r,key:s,label:t.label,onClick:n,selected:l.selected,type:"text"})},renderTags:(e,t)=>e.map(((e,l)=>{const{key:s,onDelete:r,...a}=t({index:l}),o="string"==typeof e?e:e.label,d=c.truncateWithEllipsis(o,13,{includeEllipsisInLimit:!0}),p=d.endsWith("..."),u=s??`tag-${"string"==typeof e?e:e.value}`;return p?i.jsx(n,{arrow:!0,placement:"top",title:o,children:i.jsx("span",{...a,children:i.jsx(m.Tag,{dismissAriaLabel:O.dismissTagAriaLabel,label:d,onDismiss:r})})},u):i.jsx("span",{...a,children:i.jsx(m.Tag,{dismissAriaLabel:O.dismissTagAriaLabel,label:d,onDismiss:r})},u)})),slotProps:{popupIndicator:{onClick:e=>{l||(e.stopPropagation(),K())}}},value:C?Array.isArray(E)?E:null==E?[]:[E]:Array.isArray(E)?E.length>0?E[0]:null:E??null})};exports.Autocomplete=f,exports.default=f;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|