= ({\n options,\n value,\n onChange,\n maxMenuHeight = \"250px\",\n maxValueContainerHeight = \"unset\",\n formatCreateLabel,\n placeholder = \"Search for teammates by name or email\",\n creatable = false,\n isPortal = false,\n}) => {\n const Container = creatable ? CreatableSelect : Select;\n return (\n \n null,\n IndicatorSeparator: () => null,\n MultiValueRemove,\n MultiValueLabel,\n }}\n formatOptionLabel={formatOptionLabel}\n formatCreateLabel={formatCreateLabel}\n noOptionsMessage={() => null}\n menuPosition={isPortal && \"absolute\"}\n menuPortalTarget={isPortal && document.body}\n styles={{\n multiValue: (base) => ({\n ...base,\n borderRadius: \"100px\",\n padding: \"0 3px\",\n fontSize: 14,\n }),\n multiValueRemove: (base) => ({\n ...base,\n borderRadius: \"100px\",\n \"&:hover\": {\n backgroundColor: COLORS.NEUTRAL_200,\n },\n }),\n menuPortal: (base) => ({\n ...base,\n zIndex: 9999,\n }),\n }}\n />\n
\n );\n};\n\nconst Select = styled(Select_)`\n ${DROPDOWN_STYLES};\n .Select__control {\n ${({ maxValueContainerHeight }) =>\n maxValueContainerHeight && `max-height: ${maxValueContainerHeight};`}\n overflow-y: auto;\n }\n .Select__menu-list {\n ${({ maxMenuHeight }) => `max-height: ${maxMenuHeight}`};\n }\n`;\n\nconst CreatableSelect = styled(CreatableSelect_)`\n ${DROPDOWN_STYLES};\n .Select__control {\n ${({ maxValueContainerHeight }) =>\n maxValueContainerHeight && `max-height: ${maxValueContainerHeight};`}\n overflow-y: auto;\n }\n .Select__menu-list {\n ${({ maxMenuHeight }) => `max-height: ${maxMenuHeight}`};\n }\n`;\n\nconst Option = styled.div`\n display: grid;\n grid-template-columns: 36px 1fr;\n grid-gap: 0 10px;\n align-items: flex-start;\n margin: 10px 8px;\n`;\n\nconst OptionName = styled.div`\n flex-grow: 1;\n ${FONTS.SEMIBOLD_2}\n ${STYLES.ONE_LINE}\n`;\n\nconst OptionEmail = styled.div`\n ${FONTS.REGULAR_3}\n ${STYLES.ONE_LINE}\n`;\n\nconst LabelText = styled.p`\n ${(props) => props.error && `color: ${COLORS.RED}`};\n`;\n\nconst CreateLabel = styled.span`\n ${FONTS.REGULAR_2}\n`;\n\nconst LabelContainer = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n`;\n\nconst TagContainer = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n pointer-events: none;\n`;\n\nexport default UserDropdown;\n","import { css } from \"styled-components\";\nimport { COLORS, FONTS, STYLES } from \"@constants\";\n\n// Only make changes here that are intended to be applicable to all standard dropdowns!\n// This should go first in a dropdown's styles. If a particular dropdown needs specific\n// styles, that should go into that dropdown's styles\n\nconst DROPDOWN_STYLES = css`\n .Select__control {\n border: 1px solid ${COLORS.NEUTRAL_300};\n min-height: 36px;\n transition: initial;\n &:hover {\n &:not(.Select__control--is-focused) {\n border: 1px solid ${COLORS.NEUTRAL_400};\n cursor: pointer;\n }\n &.Select__control--is-focused {\n border: 1px solid ${COLORS.HALO_BLUE};\n }\n cursor: pointer;\n }\n }\n .Select__control--is-focused {\n box-shadow: none;\n border: 1px solid ${COLORS.HALO_BLUE};\n }\n .Select__placeholder {\n color: ${COLORS.NEUTRAL_500};\n ${FONTS.REGULAR_2};\n }\n .Select__input-container {\n ${FONTS.REGULAR_2};\n }\n .Select__indicator-separator {\n display: none;\n }\n .Select__indicator {\n color: ${COLORS.BLACK};\n margin-right: 10px;\n padding: 0;\n &:hover {\n color: ${COLORS.BLACK};\n }\n }\n .Select__menu {\n white-space: nowrap;\n width: 100%;\n border-radius: 8px;\n padding: 16px 12px;\n box-shadow: ${STYLES.SHADOW_B};\n cursor: default;\n }\n .Select__menu-list {\n max-height: unset;\n }\n .Select__group {\n padding: 0;\n }\n .Select__option {\n min-width: 225px;\n margin: 0 12px;\n width: calc(100% - 24px);\n border-radius: 4px;\n background-color: ${COLORS.WHITE};\n ${FONTS.REGULAR_2};\n cursor: pointer;\n &:hover {\n background-color: ${COLORS.NEUTRAL_100};\n }\n &:active {\n background-color: ${COLORS.NEUTRAL_200};\n }\n }\n .Select__option--is-selected {\n ${FONTS.MEDIUM_2};\n color: ${COLORS.HALO_BLUE};\n }\n`;\n\nexport default DROPDOWN_STYLES;\n\nexport const MULTI_SELECT_TAG_STYLES = css`\n .Select__input-container {\n margin: 0 2px;\n }\n .Select__multi-value {\n display: flex;\n align-items: center;\n height: 24px;\n background-color: ${COLORS.NEUTRAL_100};\n padding: 0 14px;\n border-radius: 100px;\n &:not(:last-of-type) {\n margin-right: 8px;\n }\n }\n .Select__multi-value__label {\n ${FONTS.MEDIUM_3};\n padding: 0;\n }\n .Select__multi-value__remove {\n padding: 0;\n &:hover {\n opacity: 0.4;\n background-color: transparent;\n }\n }\n`;\n","// USAGE:\n// 1. Copy the medium icon SVG code from Figma and add it as a new case to the switch statement in getSvg\n// 2. The icon's name is also listed in Figma and should be added to the IconName type (camelCase)\n// 3. Replace height and width with {SIZES[size]} and instances of hex color codes with {color}\n\n// NOTES:\n// - When adding a new RFP program icon, make sure to also add it to getRfpProgramName in rfpUtils.tsx\n\nimport styled from \"styled-components\";\nimport { COLORS } from \"@constants\";\n\ninterface Props {\n name: IconName;\n color?: string;\n size?: \"xxs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"xxl\";\n margin?: string | 0;\n display?: string;\n \"data-testid\"?: string;\n}\n\nconst Icon = ({\n name,\n color = COLORS.BLACK,\n size = \"md\",\n margin = 0,\n display = \"flex\",\n \"data-testid\": dataTestId,\n}: Props) => {\n const svg = getSvg(name, color, size);\n\n if (!svg) return null;\n\n return (\n \n {svg}\n \n );\n};\n\nexport default Icon;\n\nconst SIZES = {\n xxs: 10,\n xs: 16,\n sm: 20,\n md: 24,\n lg: 32,\n xl: 40,\n xxl: 56,\n};\n\nconst IconContainer = styled.div`\n height: ${({ size }) => `${SIZES[size]}px`};\n width: ${({ size }) => `${SIZES[size]}px`};\n margin: ${({ margin }) => margin};\n display: ${({ display }) => display};\n align-items: center;\n`;\n\nexport type IconName =\n | \"3D Printing\"\n | \"Accelerator\"\n | \"Accelerator Complete\"\n | \"Add\"\n | \"Add to Collection\"\n | \"Adhesives\"\n | \"Agriculture\"\n | \"Arrow Left\"\n | \"Arrow Right\"\n | \"Arrow Up\"\n | \"Attachment\"\n | \"Attention\"\n | \"Attention Filled\"\n | \"Audio Mute\"\n | \"Audio Unmute\"\n | \"Australia\"\n | \"Bell\"\n | \"Burger\"\n | \"Calendar\"\n | \"Canada\"\n | \"Change\"\n | \"Checkup\"\n | \"Chevron Down\"\n | \"Chevron Left\"\n | \"Chevron Right\"\n | \"Chevron Up\"\n | \"China\"\n | \"Close\"\n | \"Compounds\"\n | \"Copy\"\n | \"Crown\"\n | \"Data\"\n | \"Delete\"\n | \"Download\"\n | \"Easy Apply\"\n | \"Edit\"\n | \"Employees\"\n | \"Expand\"\n | \"Expertise\"\n | \"Facebook\"\n | \"Filter\"\n | \"Followers\"\n | \"Food\"\n | \"Funding\"\n | \"Help\"\n | \"Hide\"\n | \"History\"\n | \"Hygiene\"\n | \"Idea\"\n | \"India\"\n | \"Info\"\n | \"Info Small\"\n | \"Invite\" // From a mockup, not the design system\n | \"Lead Reviewer\"\n | \"LinkedIn\"\n | \"Location\"\n | \"Lock\"\n | \"Magic\"\n | \"Malaysia\"\n | \"Materials\"\n | \"Medal\"\n | \"Medicine\"\n | \"Message\"\n | \"Messaging\"\n | \"Mexico\"\n | \"Minimize\"\n | \"More Actions\"\n | \"Notification Filled\"\n | \"Open Call\"\n | \"Open Call Paused\"\n | \"Open Call Complete\"\n | \"Open in a new tab\"\n | \"Opportunity\"\n | \"Organization\"\n | \"Packaging\"\n | \"Paused\"\n | \"Play\" // From a mockup, not the design system\n | \"Private\"\n | \"Private Company\"\n | \"Profile\"\n | \"Proposal\"\n | \"Proposal Privacy\"\n | \"Publication\"\n | \"Public\"\n | \"Quota-Based RFP\"\n | \"Reduce\"\n | \"Refresh\"\n | \"Reorder\"\n | \"RFP\"\n | \"RFP Complete\"\n | \"RFP Filled\"\n | \"Row Height\"\n | \"Row Height - Short\"\n | \"Row Height - Medium\"\n | \"Row Height - Full\"\n | \"Save\"\n | \"Search\"\n | \"Send Message\"\n | \"Share\"\n | \"Sort\"\n | \"Sort By\"\n | \"Star\"\n | \"Status\"\n | \"Success\"\n | \"Technology\"\n | \"Thumb Down\"\n | \"Thumb Down Filled\"\n | \"Thumb Up\"\n | \"Thumb Up Filled\"\n | \"Tick\"\n | \"Twitter\"\n | \"Unlocked\"\n | \"USA\"\n | \"Verified\"\n | \"View\"\n | \"Water\"\n | \"X\"\n | undefined;\n\nconst getSvg = (name: IconName, color: string, size: string) => {\n switch (name) {\n case \"Accelerator\": {\n return (\n \n );\n }\n case \"Accelerator Complete\": {\n return (\n \n );\n }\n case \"Add to Collection\": {\n return (\n \n );\n }\n case \"More Actions\": {\n return (\n \n );\n }\n case \"View\": {\n return (\n \n );\n }\n case \"Paused\": {\n return (\n \n );\n }\n case \"Play\": {\n return (\n \n );\n }\n case \"Tick\": {\n return (\n \n );\n }\n case \"Messaging\": {\n return (\n \n );\n }\n case \"Location\": {\n return (\n \n );\n }\n case \"Filter\": {\n return (\n \n );\n }\n case \"Notification Filled\": {\n return (\n \n );\n }\n case \"Open Call\": {\n return (\n \n );\n }\n case \"Open Call Paused\": {\n return (\n \n );\n }\n case \"Open Call Complete\": {\n return (\n \n );\n }\n case \"Medal\": {\n return (\n \n );\n }\n case \"Send Message\": {\n return (\n \n );\n }\n case \"X\": {\n return (\n \n );\n }\n case \"Change\": {\n return (\n \n );\n }\n case \"Twitter\": {\n return (\n \n );\n }\n case \"LinkedIn\": {\n return (\n \n );\n }\n case \"Facebook\": {\n return (\n \n );\n }\n case \"Delete\": {\n return (\n \n );\n }\n case \"Download\": {\n return (\n \n );\n }\n case \"Lead Reviewer\": {\n return (\n \n );\n }\n case \"Add\": {\n return (\n \n );\n }\n case \"Arrow Left\": {\n return (\n \n );\n }\n case \"Arrow Up\": {\n return (\n \n );\n }\n case \"Private\": {\n return (\n \n );\n }\n case \"Employees\": {\n return (\n \n );\n }\n case \"Proposal Privacy\": {\n return (\n \n );\n }\n case \"Proposal\": {\n return (\n \n );\n }\n case \"Minimize\": {\n return (\n \n );\n }\n case \"Expand\": {\n return (\n \n );\n }\n case \"Reduce\": {\n return (\n \n );\n }\n case \"Calendar\": {\n return (\n \n );\n }\n case \"Share\": {\n return (\n \n );\n }\n case \"Open in a new tab\": {\n return (\n \n );\n }\n case \"Profile\": {\n return (\n \n );\n }\n case \"Message\": {\n return (\n \n );\n }\n case \"Chevron Down\": {\n return (\n \n );\n }\n case \"Chevron Up\": {\n return (\n \n );\n }\n case \"Chevron Left\": {\n return (\n \n );\n }\n case \"Chevron Right\": {\n return (\n \n );\n }\n case \"Copy\": {\n return (\n \n );\n }\n case \"Data\": {\n return (\n \n );\n }\n case \"Refresh\": {\n return (\n \n );\n }\n case \"Close\": {\n return (\n \n );\n }\n case \"Search\": {\n return (\n \n );\n }\n case \"Verified\": {\n return (\n \n );\n }\n case \"Agriculture\": {\n return (\n \n );\n }\n case \"Hygiene\": {\n return (\n \n );\n }\n case \"Water\": {\n return (\n \n );\n }\n case \"Bell\": {\n return (\n \n );\n }\n case \"Success\": {\n return (\n \n );\n }\n case \"Opportunity\": {\n return (\n \n );\n }\n case \"3D Printing\": {\n return (\n \n );\n }\n case \"Packaging\": {\n return (\n \n );\n }\n case \"Adhesives\": {\n return (\n \n );\n }\n case \"Food\": {\n return (\n \n );\n }\n case \"Medicine\": {\n return (\n \n );\n }\n case \"Private Company\": {\n return (\n \n );\n }\n case \"Easy Apply\": {\n return (\n \n );\n }\n case \"Attention\": {\n return (\n \n );\n }\n case \"Idea\": {\n return (\n \n );\n }\n case \"Info\": {\n return (\n \n );\n }\n case \"Info Small\": {\n return (\n \n );\n }\n case \"Invite\": {\n return (\n \n );\n }\n case \"Materials\": {\n return (\n \n );\n }\n case \"Arrow Right\": {\n return (\n \n );\n }\n case \"Attachment\": {\n return (\n \n );\n }\n case \"Help\": {\n return (\n \n );\n }\n case \"History\": {\n return (\n \n );\n }\n case \"USA\": {\n return (\n \n );\n }\n case \"Australia\": {\n return (\n \n );\n }\n case \"China\": {\n return (\n \n );\n }\n case \"India\": {\n return (\n \n );\n }\n case \"Canada\": {\n return (\n \n );\n }\n case \"Malaysia\": {\n return (\n \n );\n }\n case \"Mexico\": {\n return (\n \n );\n }\n case \"Burger\": {\n return (\n \n );\n }\n case \"Technology\": {\n return (\n \n );\n }\n case \"Funding\": {\n return (\n \n );\n }\n case \"Expertise\": {\n return (\n \n );\n }\n case \"Organization\": {\n return (\n \n );\n }\n case \"Compounds\": {\n return (\n \n );\n }\n case \"Checkup\": {\n return (\n \n );\n }\n case \"Publication\": {\n // Have to use unoptimized SVG otherwise the middle bar of the book disappears at small sizes\n return (\n \n );\n }\n case \"Star\": {\n return (\n \n );\n }\n case \"Status\": {\n return (\n \n );\n }\n case \"Edit\": {\n return (\n \n );\n }\n case \"RFP\": {\n return (\n \n );\n }\n case \"RFP Complete\": {\n return (\n \n );\n }\n case \"RFP Filled\": {\n return (\n \n );\n }\n case \"Row Height\": {\n return (\n \n );\n }\n case \"Row Height - Short\": {\n return (\n \n );\n }\n case \"Row Height - Medium\": {\n return (\n \n );\n }\n case \"Row Height - Full\": {\n return (\n \n );\n }\n case \"Save\": {\n return (\n \n );\n }\n case \"Sort\": {\n return (\n \n );\n }\n case \"Public\": {\n return (\n \n );\n }\n case \"Quota-Based RFP\": {\n return (\n \n );\n }\n case \"Hide\": {\n return (\n \n );\n }\n case \"Followers\": {\n return (\n \n );\n }\n case \"Reorder\": {\n return (\n \n );\n }\n case \"Sort By\": {\n return (\n \n );\n }\n case \"Thumb Up\": {\n return (\n \n );\n }\n case \"Thumb Up Filled\": {\n return (\n \n );\n }\n case \"Thumb Down\": {\n return (\n \n );\n }\n case \"Thumb Down Filled\": {\n return (\n \n );\n }\n case \"Attention Filled\": {\n return (\n \n );\n }\n case \"Audio Mute\": {\n return (\n \n );\n }\n case \"Audio Unmute\": {\n return (\n \n );\n }\n case \"Lock\": {\n return (\n \n );\n }\n case \"Unlocked\": {\n return (\n \n );\n }\n case \"Crown\": {\n return (\n \n );\n }\n case \"Magic\": {\n return (\n \n );\n }\n default: {\n return null;\n }\n }\n};\n","import { ReactElement, ReactNode, useEffect } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport styled from \"styled-components\";\nimport { COLORS, FONTS, WINDOW_DIMENSIONS, STYLES } from \"@constants\";\nimport IconButton from \"../Buttons/IconButton\";\nimport Icon from \"@components/library/Icon\";\nimport { IconName } from \"../Icon/Icon\";\n\nexport interface BlankModalProps {\n isOpen: boolean;\n onClose: () => void;\n closeOnDimmerClick?: boolean;\n headerText?: string | ReactElement;\n headerIconName?: IconName;\n subHeaderText?: string;\n subHeaderIconName?: IconName;\n hideCloseButton?: boolean;\n disableBackgroundScroll?: boolean;\n width?: string;\n height?: string;\n children?: ReactNode;\n}\n\nconst BlankModal = ({\n isOpen,\n onClose,\n closeOnDimmerClick = true,\n headerText,\n headerIconName,\n subHeaderText,\n subHeaderIconName,\n hideCloseButton = false,\n disableBackgroundScroll = true,\n width,\n height,\n children,\n}: BlankModalProps) => {\n const handleDimmerClick = () => {\n if (closeOnDimmerClick) {\n onClose();\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.code === \"Escape\" && isOpen) {\n if (closeOnDimmerClick) {\n onClose();\n }\n }\n };\n\n useEffect(() => {\n // Close on Escape\n document.addEventListener(\"keydown\", onKeyDown, false);\n\n // Disable background scroll of anchor\n // Targets the top modal (not including the current one) if it exists\n // Targets html element otherwise\n const modals = document.querySelectorAll(\"[role=dialog]\");\n const anchor = (modals[modals.length - (isOpen ? 2 : 1)] ||\n document.querySelector(\"html\")) as HTMLElement;\n if (disableBackgroundScroll && isOpen) anchor.style.overflow = \"hidden\";\n\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown, false);\n\n if (disableBackgroundScroll) anchor.style.overflow = \"unset\";\n };\n }, [isOpen]);\n\n const modal = (\n <>\n \n \n \n {!hideCloseButton && (\n \n \n \n )}\n {headerText && (\n <>\n \n {headerIconName && }\n \n {headerText}\n {subHeaderText && (\n \n {subHeaderIconName && (\n \n )}\n {subHeaderText}
\n \n )}\n \n \n \n >\n )}\n {children}\n \n \n >\n );\n\n return isOpen ? ReactDOM.createPortal(modal, document.body) : null;\n};\n\nconst Background = styled.div`\n position: fixed;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n background-color: ${COLORS.BLACK};\n opacity: 0.7;\n z-index: 501;\n`;\n\nconst Wrapper = styled.div`\n z-index: 502;\n position: fixed;\n top: 50%;\n right: 50%;\n transform: translate(50%, -50%);\n display: flex;\n justify-content: center;\n align-items: center;\n\n ${WINDOW_DIMENSIONS.TABLET_LANDSCAPE_MEDIA_QUERY} {\n align-items: flex-start;\n }\n`;\n\nconst StyledModal = styled.div`\n z-index: 503;\n background: white;\n position: relative;\n border-radius: 12px;\n width: ${(props) => props.width};\n height: ${(props) => props.height};\n display: flex;\n flex-direction: column;\n box-shadow: ${STYLES.SHADOW_D};\n\n max-height: 90vh;\n overflow: visible;\n\n ${WINDOW_DIMENSIONS.TABLET_LANDSCAPE_MEDIA_QUERY} {\n width: 90%;\n }\n`;\n\nconst Header = styled.div`\n border-radius: 8px 8px 0 0;\n padding: 24px 20px;\n display: flex;\n align-items: center;\n`;\n\nconst HeaderContent = styled.div`\n width: 100%;\n`;\n\nconst SubHeader = styled.div`\n display: flex;\n padding-top: 4px;\n max-width: 90%;\n ${FONTS.REGULAR_3};\n align-items: center;\n gap: 8px;\n > div:last-child {\n ${STYLES.ONE_LINE_ALT};\n }\n flex-direction: row;\n`;\n\nconst HeaderText = styled.div`\n ${FONTS.HEADING_4_SEMIBOLD}\n color: ${COLORS.BLACK};\n align-self: center;\n display: flex;\n justify-content: space-between;\n`;\n\nconst Divider = styled.hr`\n margin: 0;\n border-color: ${COLORS.NEUTRAL_300};\n`;\n\nconst Content = styled.div`\n max-height: ${({ hasHeader }) => (hasHeader ? \"calc(100% - 76px)\" : \"100%\")};\n overflow-y: auto;\n overflow-x: hidden;\n`;\n\nconst CloseButton = styled.div`\n width: fit-content;\n position: absolute;\n top: 20px;\n right: 20px;\n cursor: pointer;\n`;\n\nexport default BlankModal;\n","import { ReactNode, useState, useEffect } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport styled, { css } from \"styled-components\";\nimport { IconButton } from \"@components/library\";\nimport { COLORS, STYLES } from \"@constants\";\n\nexport interface SlideModalBaseProps {\n isOpen: boolean;\n onClose: () => void;\n direction?: \"bottom\" | \"right\";\n hideCloseButton?: boolean;\n customCloseButton?: ReactNode;\n closeOnDimmerClick?: boolean;\n hideBackdrop?: boolean;\n children?: ReactNode;\n}\n\nconst SlideModalBase = ({\n isOpen,\n onClose,\n direction = \"right\",\n hideCloseButton = false,\n customCloseButton,\n closeOnDimmerClick = true,\n hideBackdrop = false,\n children,\n}: SlideModalBaseProps) => {\n // Used for the slide in/out animation\n const [shouldShowModal, setShouldShowModal] = useState(false);\n\n const handleClose = () => {\n setShouldShowModal(false);\n setTimeout(() => onClose(), 300);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.code === \"Escape\" && isOpen) {\n if (closeOnDimmerClick) {\n handleClose();\n }\n }\n };\n\n useEffect(() => {\n if (isOpen) {\n setTimeout(() => setShouldShowModal(true), 0);\n\n document.querySelector(\"html\")!.style.overflow = \"hidden\";\n }\n\n // Close on Escape\n document.addEventListener(\"keydown\", onKeyDown, false);\n\n return () => {\n document.querySelector(\"html\")!.style.overflow = \"unset\";\n\n document.removeEventListener(\"keydown\", onKeyDown, false);\n };\n }, [isOpen]);\n\n const modal = (\n <>\n {!hideBackdrop && }\n \n {!hideCloseButton && (\n \n {customCloseButton ?? (\n \n )}\n \n )}\n {children}\n \n >\n );\n\n return isOpen ? ReactDOM.createPortal(modal, document.body) : null;\n};\n\nexport default SlideModalBase;\n\nconst Background = styled.div`\n position: fixed;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n background-color: ${COLORS.BLACK};\n opacity: 0.7;\n z-index: 400;\n`;\nconst Modal = styled.div`\n position: fixed;\n ${({ direction }) =>\n direction === \"right\"\n ? css`\n top: 0;\n right: ${({ isOpen }) => (isOpen ? 0 : \"-100%\")};\n height: 100vh;\n border-radius: 12px 0px 0px 12px;\n `\n : css`\n left: 0;\n bottom: ${({ isOpen }) => (isOpen ? 0 : \"-100%\")};\n width: 100vw;\n max-height: calc(100vh - 54px);\n border-radius: 12px 12px 0px 0px;\n `};\n z-index: 401;\n background: white;\n ${({ hideBackdrop }) => hideBackdrop && `box-shadow: ${STYLES.SHADOW_D}`};\n margin: auto;\n transition: ${({ direction }) => direction} 0.25s ease-out;\n max-width: 100%;\n`;\nconst CloseButton = styled.div`\n position: absolute;\n top: 20px;\n right: 20px;\n z-index: 1;\n`;\nconst Content = styled.div`\n height: 100%;\n`;\n","import { COLORS } from \"@constants\";\n\nimport styled from \"styled-components\";\nimport Icon from \"../Icon\";\nimport { PROFILE_PICTURE_SIZE_STYLES, ProfilePictureProps } from \"./ProfilePicture\";\n\ninterface Props {\n size: ProfilePictureProps[\"size\"];\n}\n\nconst InvitedUserProfilePicture = ({ size = \"sm\" }: Props) => {\n return (\n \n \n \n \n \n );\n};\n\nexport default InvitedUserProfilePicture;\n\nconst Container = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n`;\n\nconst Outline = styled.div`\n border: 1px dashed ${COLORS.BLACK};\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n ${PROFILE_PICTURE_SIZE_STYLES}\n`;\n","import { useState } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { getInitials } from \"@utils/textUtils\";\nimport Icon from \"../Icon\";\n\nexport interface ProfilePictureProps {\n user?: {\n image: { medium: { url: string | null } };\n name: string;\n };\n size: \"xxs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n margin?: string | 0;\n forMulti?: boolean;\n hidden?: boolean;\n}\n\nconst ProfilePicture = ({\n user,\n size,\n margin = 0,\n forMulti = false,\n hidden = false,\n}: ProfilePictureProps) => {\n const [didImageError, setDidImageError] = useState(false);\n\n return (\n \n {(() => {\n if (hidden || !user) return ;\n if (user.image?.medium?.url && !didImageError)\n return (\n {\n setDidImageError(true);\n }}\n />\n );\n return getInitials(user.name);\n })()}\n \n );\n};\n\nexport default ProfilePicture;\n\nexport const PROFILE_PICTURE_SIZE_STYLES = css`\n ${({ size }) => {\n switch (size) {\n case \"xxs\": {\n return css`\n font-size: 10px;\n height: 20px;\n width: 20px;\n `;\n }\n case \"xs\": {\n return css`\n font-size: 12px;\n height: 28px;\n width: 28px;\n `;\n }\n case \"sm\": {\n return css`\n font-size: 16px;\n height: 36px;\n width: 36px;\n `;\n }\n case \"md\": {\n return css`\n font-size: 23px;\n height: 50px;\n width: 50px;\n `;\n }\n case \"lg\": {\n return css`\n font-size: 23px;\n font-weight: 600;\n height: 68px;\n width: 68px;\n `;\n }\n case \"xl\": {\n return css`\n font-size: 32px;\n font-weight: 600;\n height: 96px;\n width: 96px;\n `;\n }\n }\n }};\n`;\n\nconst Container = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n border-radius: 50%;\n background-color: ${({ size }) => (size === \"lg\" ? COLORS.NEUTRAL_100 : COLORS.NEUTRAL_200)};\n color: ${COLORS.BLACK};\n border: ${({ forMulti }) => (forMulti ? `1px solid ${COLORS.WHITE}` : \"none\")};\n margin: ${({ margin }) => margin};\n font-weight: 500;\n ${PROFILE_PICTURE_SIZE_STYLES}\n`;\n\nconst Picture = styled.img`\n height: 100%;\n width: 100%;\n ${FONTS.REGULAR_4};\n border-radius: 50%;\n`;\n","// Note: SearchBar and MultiSelectDropdown are not using this component, though are styled\n// to look the same, due to the way React-Select handles multi-select tags\n\nimport { ReactNode } from \"react\";\nimport styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { Icon } from \"@components/library\";\nimport { IconName } from \"../Icon/Icon\";\n\nexport type TagTheme = \"light\" | \"dark\" | \"neutral\";\n\nexport interface TagProps {\n content: ReactNode;\n iconName?: IconName;\n size?: \"xs\" | \"sm\" | \"md\";\n font?: string;\n theme?: TagTheme;\n isValid?: boolean;\n onRemove?: (...args: any[]) => any;\n id?: string;\n \"data-testid\"?: string;\n // Style override props\n backgroundColor?: string;\n color?: string;\n margin?: string | 0;\n border?: string;\n}\n\nconst ICON_SIZE = {\n xs: \"xxs\",\n sm: \"xs\",\n md: \"sm\",\n};\n\nconst ICON_MARGIN = {\n xs: \"0 3px 0 0\",\n sm: \"0 4px 0 0\",\n md: \"0 6px 0 0\",\n};\n\nconst Tag = ({\n content,\n iconName,\n size = \"sm\",\n font,\n theme = \"neutral\",\n isValid = true,\n onRemove,\n id,\n \"data-testid\": dataTestId,\n backgroundColor,\n color,\n margin = 0,\n border,\n}: Props) => (\n \n {iconName && (\n \n )}\n {content}\n {onRemove && (\n \n \n
\n )}\n \n);\n\nconst BACKGROUND_TYPE = {\n light: COLORS.WHITE,\n dark: COLORS.NEUTRAL_200,\n neutral: COLORS.NEUTRAL_100,\n};\n\nconst XS_STYLES = `\n height: 16px;\n padding: 0 8px;\n ${FONTS.TAG_MEDIUM_3}\n`;\n\nconst SM_STYLES = `\n height: 24px;\n padding: 0 14px;\n ${FONTS.TAG_MEDIUM_2}\n`;\n\nconst MD_STYLES = `\n height: 36px;\n padding: 0 16px;\n ${FONTS.TAG_SEMIBOLD_1}\n`;\n\nconst StyledTag = styled.div`\n display: inline-flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n width: fit-content;\n border: none;\n border-radius: 100px;\n background-color: ${({ backgroundColor, theme, isValid }) =>\n (!isValid && COLORS.RED_100) || backgroundColor || BACKGROUND_TYPE[theme]};\n color: ${({ color, isValid }) => (!isValid && COLORS.RED) || color || COLORS.BLACK};\n ${({ size }) => {\n switch (size) {\n case \"xs\":\n return XS_STYLES;\n case \"sm\":\n return SM_STYLES;\n case \"md\":\n return MD_STYLES;\n }\n }}\n white-space: nowrap;\n margin: ${({ margin }) => margin};\n border: ${({ border }) => border};\n ${({ font }) => font && font};\n\n &:not(:last-of-type) {\n margin-right: 8px;\n }\n`;\n\nexport default Tag;\n","import Tooltip from \"@components/library/Tooltips/Tooltip\";\nimport { COLORS, LINKS } from \"@constants\";\nimport { t } from \"@utils/i18n\";\nimport { ReactNode } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport styled from \"styled-components\";\n\ninterface Props {\n children: ReactNode;\n}\nexport function PremiumTagTooltip({ children }: Props) {\n return (\n \n {t(\"components.premium_tag_tooltip.text\")} >}\n >\n {children}\n \n
\n );\n}\n\nexport const WhiteLink = styled(Link)`\n color: ${COLORS.WHITE};\n text-decoration: underline;\n\n &:hover,\n &:focus,\n &:active {\n color: ${COLORS.WHITE};\n }\n`;\n","import { COLORS } from \"@constants\";\nimport Tag from \"../Tag\";\nimport { PremiumTagTooltip } from \"./PremiumTagTooltip\";\nimport { useSelector } from \"react-redux\";\nimport { RootState } from \"@redux/store\";\n\nexport function PremiumTag() {\n const subscription = useSelector((state: RootState) => state.company.subscription);\n\n if (subscription?.plan === \"rfp_based\") return null;\n\n return (\n \n \n \n );\n}\n","import { COLORS } from \"@constants\";\nimport Tag from \"../Tag\";\n\nexport function AdminTag() {\n return (\n \n );\n}\n","import { COLORS, LINKS } from \"@constants\";\nimport { Icon, Tooltip } from \"@components/library\";\nimport { WhiteLink } from \"./PremiumTagTooltip\";\nimport { t } from \"@utils/i18n\";\n\ninterface Props {\n size?: \"xs\" | \"sm\";\n}\n\nexport function SuperAdminTag({ size = \"xs\" }: Props) {\n return (\n \n {t(\"components.super_admin_tag.text\")} >} tooltipWidth=\"290px\">\n \n \n
\n );\n}\n","import { useState, useEffect, useRef, ReactElement, cloneElement } from \"react\";\nimport styled from \"styled-components\";\nimport { COLORS, STYLES } from \"@constants\";\n\ninterface Props {\n // The element(s) over which the tooltip should show when hovered\n children: ReactElement | ReactElement[];\n tags: ReactElement[];\n}\n\nconst TooltipWrapper = ({ children, tags }: Props) => {\n const [isHovered, setIsHovered] = useState(false);\n const [displayedTags, setDisplayedTags] = useState([]);\n\n // Make sure the proper tag theme is used\n useEffect(() => {\n const updatedTags: ReactElement[] = [];\n\n for (const tag of tags) {\n const updatedTag = cloneElement(tag, {\n theme: \"neutral\",\n });\n\n updatedTags.push(updatedTag);\n\n setDisplayedTags(updatedTags);\n }\n }, [tags]);\n\n // This is used to prevent the tooltip from flashing if a user passes over the child element(s)\n const timeoutRef = useRef>();\n const toggleShow = (newState) => {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => setIsHovered(newState), 100);\n };\n\n const size = tags[0]?.props?.size;\n\n return (\n toggleShow(true)} onMouseLeave={() => toggleShow(false)}>\n {children}\n \n {displayedTags.map((tag) => (\n \n {tag}\n \n ))}\n \n \n );\n};\n\nexport default TooltipWrapper;\n\nconst Wrapper = styled.div`\n position: relative;\n`;\nconst Container = styled.div`\n display: ${({ isHovered }) => (isHovered ? \"initial\" : \"none\")};\n position: absolute;\n top: 5%;\n left: 50%;\n transform: translate(-50%, -100%);\n padding: 10px 22px 18px;\n padding: ${({ size }) => (size === \"xs\" ? \"5px 11px 9px\" : \"10px 22px 18px\")};\n border-radius: 8px;\n box-shadow: ${STYLES.SHADOW_B};\n background-color: ${COLORS.WHITE};\n z-index: 1;\n`;\nconst TagContainer = styled.div`\n margin-top: ${({ size }) => (size === \"xs\" ? \"0\" : \"8px\")};\n`;\n","import { useState, useRef, ReactNode, useEffect } from \"react\";\nimport styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\n\ninterface Props {\n children: ReactNode;\n content: string | ReactNode;\n tooltipWidth?: string;\n contentWidth?: string;\n position?: \"top\" | \"bottom\" | \"left\" | \"right\";\n arrowOffsetTop?: string | 0;\n remainOnHover?: boolean;\n shouldWrap?: boolean;\n isActive?: boolean;\n shouldFlex?: boolean;\n \"data-testid\"?: string;\n}\n\nconst Tooltip = ({\n children,\n content,\n tooltipWidth,\n contentWidth,\n position = \"top\",\n arrowOffsetTop,\n remainOnHover = true,\n shouldWrap = true,\n isActive = true,\n shouldFlex = false,\n \"data-testid\": dataTestId,\n}: Props) => {\n const [showTooltip, setShowTooltip] = useState(false);\n\n const childrenRef = useRef(null);\n const timeoutRef = useRef>();\n const toggleShow = (newState) => {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => setShowTooltip(newState), 100);\n };\n\n useEffect(() => {\n return () => {\n clearTimeout(timeoutRef.current);\n };\n }, []);\n\n const childrenHeight = childrenRef.current?.clientHeight ?? 0;\n const childrenVerticalCenter = `${childrenHeight / 2 - 8}px`;\n const top = arrowOffsetTop ?? childrenVerticalCenter;\n\n return (\n \n toggleShow(true)}\n onMouseLeave={() => toggleShow(false)}\n ref={childrenRef}\n shouldFlex={shouldFlex}\n >\n {children}\n \n {\n e.stopPropagation();\n e.preventDefault();\n }}\n onMouseEnter={() => remainOnHover && toggleShow(true)}\n onMouseLeave={() => toggleShow(false)}\n data-testid={dataTestId}\n >\n {content}\n \n \n \n );\n};\n\nexport default Tooltip;\n\nconst Container = styled.div`\n position: relative;\n display: flex;\n justify-content: center;\n align-items: center;\n height: fit-content;\n ${({ contentWidth }) => `width: ${contentWidth}`}\n`;\nconst ChildrenContainer = styled.div`\n width: 100%;\n ${({ shouldFlex }) => shouldFlex && \"display: flex;\"}\n`;\nconst StyledTooltip = styled.div`\n display: ${({ showTooltip }) => (showTooltip ? \"flex\" : \"none\")};\n flex-direction: column;\n align-items: center;\n gap: 4px;\n position: absolute;\n ${({ position }) => {\n switch (position) {\n case \"top\":\n return `\n bottom: calc(100% + 12px);\n `;\n case \"bottom\":\n return `\n top: calc(100% + 12px);\n `;\n case \"left\":\n return `\n right: calc(100% + 12px);\n `;\n case \"right\":\n return `\n left: calc(100% + 12px);\n `;\n }\n }}\n background-color: ${COLORS.BLACK};\n color: ${COLORS.WHITE};\n ${({ width }) => width && `width: ${width};`}\n ${({ shouldWrap }) => !shouldWrap && `white-space: nowrap;`}\n border-radius: 6px;\n padding: 12px;\n text-align: left;\n ${FONTS.REGULAR_3};\n z-index: 1;\n cursor: auto;\n`;\nconst ContentContainer = styled.div`\n width: 100%;\n white-space: ${({ shouldWrap }) => (shouldWrap ? \"normal\" : \"no-wrap\")};\n`;\nconst Arrow = styled.div`\n width: 0;\n height: 0;\n position: absolute;\n ${({ position, top }) => {\n switch (position) {\n case \"top\":\n return `\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid ${COLORS.BLACK};\n bottom: -8px;\n `;\n case \"bottom\":\n return `\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid ${COLORS.BLACK};\n top: -8px;\n `;\n case \"left\":\n return `\n border-top: 8px solid transparent;\n border-bottom: 8px solid transparent;\n border-left: 8px solid ${COLORS.BLACK};\n right: -8px;\n top: ${top};\n `;\n case \"right\":\n return `\n border-top: 8px solid transparent;\n border-bottom: 8px solid transparent;\n border-right: 8px solid ${COLORS.BLACK};\n left: -8px;\n top: ${top};\n `;\n }\n }}\n`;\n","import { ReactElement } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { BaseButtonProps } from \"./Button\";\nimport { Link } from \"react-router-dom\";\n\ninterface Props extends BaseButtonProps {\n size?: \"md\" | \"lg\";\n // This sets a min-width in case the button is intended to extend past its contents. A minimum padding will be maintained\n width?: string;\n maxHeight?: string;\n icon?: HTMLImageElement | ReactElement | null;\n iconPosition?: \"left\" | \"right\";\n children: any;\n to?: string;\n className?: string;\n}\n\nconst GradientButton = ({\n size = \"lg\",\n width,\n maxHeight,\n to,\n margin = 0,\n icon,\n iconPosition = \"left\",\n children,\n id,\n disabled,\n type = \"button\",\n onClick,\n \"data-testid\": dataTestId,\n className,\n}: Props) => {\n const StyledComponent = to ? StyledLink : StyledButton;\n\n return (\n \n {icon ? {icon} : null}\n {children}\n \n );\n};\n\nexport default GradientButton;\n\nconst BaseStyles = css`\n display: flex;\n flex-direction: ${({ iconPosition }) => (iconPosition === \"left\" ? \"row\" : \"row-reverse\")};\n justify-content: center;\n align-items: center;\n height: ${({ size }) => (size === \"md\" ? \"42px\" : \"64px\")};\n min-width: ${({ width }) => width ?? \"initial\"};\n max-height: ${({ maxHeight }) => maxHeight ?? \"initial\"};\n background: ${COLORS.BLUE_GRADIENT};\n color: ${COLORS.WHITE};\n font-size: ${({ size }) => (size === \"md\" ? \"16px\" : \"18px\")};\n font-weight: 500;\n line-height: ${({ size }) => (size === \"md\" ? \"16px\" : \"18px\")};\n border: none;\n border-radius: ${({ size }) => (size === \"md\" ? \"4px\" : \"6px\")};\n box-shadow: 0px 10px ${({ size }) => (size === \"md\" ? 16 : 32)}px -4px #016aaa54;\n padding: 0 24px;\n margin: ${({ margin }) => margin};\n &:hover {\n background: linear-gradient(92.65deg, #004980 0%, #0085cc 92%);\n }\n &:focus:not(:active) {\n outline: none;\n }\n &:disabled {\n opacity: 0.4;\n pointer-events: none;\n }\n`;\n\nconst StyledLink = styled(Link)`\n display: inline-block;\n ${BaseStyles}\n ${FONTS.HEADING_5_MEDIUM}\n &:hover {\n color: white;\n text-decoration: none;\n }\n`;\n\nconst StyledButton = styled.button`\n ${BaseStyles}\n`;\nconst IconContainer = styled.div`\n margin: ${({ iconPosition }) => (iconPosition === \"left\" ? \"0 4px 0 0\" : \"0 0 0 4px\")};\n width: 24px;\n height: 24px;\n`;\n","import styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { Link } from \"react-router-dom\";\n\ninterface Props {\n to: string | { pathname: string };\n children: any;\n color?: string;\n font?: string;\n underline?: boolean;\n newTab?: boolean;\n}\n\nconst TextLink = ({\n to,\n children,\n color = COLORS.BLACK,\n font = FONTS.MEDIUM_2,\n underline = false,\n newTab = false,\n}: Props) => {\n return (\n \n {children}\n \n );\n};\n\nexport default TextLink;\n\nconst StyledLink = styled(Link)`\n display: inline-flex;\n align-items: center;\n color: ${({ color }) => color};\n ${({ font }) => font};\n ${({ $underline }) => $underline && `text-decoration: underline;`};\n &:hover,\n &:focus {\n color: ${({ color }) => color};\n }\n`;\n","import styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport Icon, { IconName } from \"@components/library/Icon/Icon\";\nimport { BaseButtonProps } from \"./Button\";\n\ninterface Props extends BaseButtonProps {\n text: string;\n size?: \"xs\" | \"sm\" | \"md\";\n color?: string;\n iconName?: IconName | null;\n iconPosition?: \"right\" | \"left\";\n}\n\nconst TextButton = ({\n text,\n size = \"md\",\n color = COLORS.HALO_BLUE,\n iconName = \"Chevron Down\",\n iconPosition = \"right\",\n margin,\n id,\n name,\n type = \"button\",\n disabled,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onFocus,\n onBlur,\n \"data-testid\": dataTestId,\n}: Props) => {\n return (\n \n );\n};\n\nexport default TextButton;\n\nconst Button = styled.button`\n display: flex;\n flex-direction: ${({ iconPosition }) => (iconPosition === \"right\" ? \"row\" : \"row-reverse\")};\n align-items: center;\n height: ${({ size }) => (size === \"sm\" ? 16 : 24)}px;\n width: fit-content;\n ${({ margin }) => margin && `margin: ${margin}`};\n padding: 0;\n ${({ size }) => {\n if (size === \"xs\") return FONTS.BUTTON_4;\n if (size === \"sm\") return FONTS.BUTTON_3;\n return FONTS.BUTTON_2;\n }};\n color: ${({ color }) => (color ? color : COLORS.HALO_BLUE)};\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 4px;\n &:focus {\n outline: none;\n }\n &:disabled {\n opacity: 0.4;\n }\n`;\n","import styled from \"styled-components\";\nimport { COLORS } from \"@constants\";\nimport Icon from \"../Icon/Icon\";\n\nexport type SortDirection = \"NONE\" | \"DESC\" | \"ASC\";\n\ninterface SortState {\n color: string;\n inverted: boolean;\n next: SortDirection;\n}\n\nconst SORT_STATES = new Map([\n [\n \"NONE\",\n {\n color: COLORS.NEUTRAL_300,\n inverted: false,\n next: \"DESC\",\n },\n ],\n [\n \"DESC\",\n {\n color: COLORS.BLACK,\n inverted: false,\n next: \"ASC\",\n },\n ],\n [\n \"ASC\",\n {\n color: COLORS.BLACK,\n inverted: true,\n next: \"NONE\",\n },\n ],\n]);\n\ninterface SortButtonProps {\n sortDirection: SortDirection;\n setSortDirection: (newSortDirection: SortDirection) => any;\n margin?: string;\n}\n\nconst SortButton = ({ sortDirection = \"NONE\", setSortDirection, margin }: SortButtonProps) => {\n const state = SORT_STATES.get(sortDirection);\n return (\n setSortDirection(state!.next)}\n title=\"Change Sort\"\n >\n \n \n );\n};\n\nexport default SortButton;\n\nconst IconContainer = styled.button`\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: inherit;\n ${({ inverted }) => inverted && \"transform: scaleY(-1);\"}\n`;\n","import styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\n\ninterface Props {\n children: number | string;\n marginLeft?: string;\n accent?: boolean;\n backgroundColor?: string;\n}\n\nconst InfoTag = ({ children, marginLeft = \"12px\", accent = false, backgroundColor }: Props) => {\n return (\n \n {children}\n \n );\n};\n\nexport default InfoTag;\n\nconst Container = styled.div`\n display: inline-flex;\n justify-content: center;\n align-items: center;\n height: 18px;\n min-width: 20px;\n width: auto;\n background: ${({ accent, backgroundColor }) =>\n backgroundColor || (accent && COLORS.BLUE_GRADIENT) || COLORS.NEUTRAL_400};\n color: ${COLORS.WHITE};\n border-radius: 100px;\n padding: ${({ accent }) => (accent ? \"2px 8px\" : \"2px 6px\")};\n margin-left: ${({ marginLeft }) => marginLeft};\n ${({ accent }) => (accent ? FONTS.TAG_ACCENT : FONTS.TAG_BOLD_2)};\n`;\n","import { COLORS, FONTS } from \"@constants\";\n\nimport styled from \"styled-components\";\nimport Icon from \"../Icon\";\nimport InfoTag from \"../Tags/InfoTag\";\n\ninterface Props {\n variant: \"ghost\" | \"fourth\";\n count: number;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n}\n\nfunction FiltersButton({ variant, count, isOpen, setIsOpen }: Props) {\n const hasFilters = count > 0;\n\n let iconColor: string;\n let countTagBackgroundColor: string;\n switch (variant) {\n case \"ghost\": {\n iconColor = COLORS.HALO_BLUE;\n countTagBackgroundColor = COLORS.BLUE_650;\n break;\n }\n case \"fourth\": {\n iconColor = COLORS.NEUTRAL_800;\n countTagBackgroundColor = COLORS.BLACK;\n break;\n }\n }\n\n return (\n \n );\n}\n\nexport default FiltersButton;\n\nconst Button = styled.button`\n height: 36px;\n border: none;\n border-radius: 4px;\n padding: 0;\n background-color: ${({ hasFilters, variant }) => {\n if (!hasFilters) return \"transparent\";\n switch (variant) {\n case \"ghost\": {\n return COLORS.BLUE_LIGHT_300;\n }\n case \"fourth\": {\n return COLORS.NEUTRAL_200;\n }\n }\n }};\n outline: 1px solid\n ${({ hasFilters, isOpen, variant }) => {\n if (!(hasFilters || isOpen)) return \"transparent\";\n switch (variant) {\n case \"ghost\": {\n return COLORS.HALO_BLUE;\n }\n case \"fourth\": {\n return COLORS.NEUTRAL_800;\n }\n }\n }};\n\n &:hover > div {\n background-color: ${({ variant, hasFilters }) => {\n switch (variant) {\n case \"ghost\": {\n return hasFilters ? COLORS.BLUE_LIGHT_500 : COLORS.BLUE_LIGHT_300;\n }\n case \"fourth\": {\n return hasFilters ? COLORS.NEUTRAL_350 : COLORS.NEUTRAL_200;\n }\n }\n }};\n }\n\n &:active {\n & > div {\n background-color: ${({ variant, hasFilters }) => {\n switch (variant) {\n case \"ghost\": {\n return hasFilters ? COLORS.BLUE_LIGHT_600 : COLORS.BLUE_LIGHT_400;\n }\n case \"fourth\": {\n return hasFilters ? COLORS.NEUTRAL_400 : COLORS.NEUTRAL_300;\n }\n }\n }};\n }\n }\n`;\n\nconst Content = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 4px;\n\n width: 100%;\n height: 100%;\n\n ${FONTS.BUTTON_2}\n border-radius: 4px;\n color: ${({ variant }) => {\n switch (variant) {\n case \"ghost\": {\n return COLORS.HALO_BLUE;\n }\n case \"fourth\": {\n return COLORS.NEUTRAL_800;\n }\n }\n }};\n padding: 0 20px 0 12px;\n transition: background-color 0.1s ease;\n`;\n","import { ReactNode } from \"react\";\nimport styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport DROPDOWN_STYLES from \"./dropdownStyles\";\nimport Select, { components } from \"react-select\";\nimport { TextButton } from \"@components/library\";\nimport { DropdownOption, ExtendedDropdownOption, OptionLabel } from \"./DropdownOption\";\n\ninterface Props {\n children?: ReactNode; // Trigger component. Defaults to a TextButton with the value label\n options: ExtendedDropdownOption[];\n value: DropdownOption;\n onChange: (...args: any[]) => any;\n isSearchable?: boolean;\n menuWidth?: string;\n maxMenuHeight?: string;\n menuHorizontalPosition?: \"right\" | \"left\";\n // Portal the menu with width if using within a scrollable overflow\n isPortal?: boolean;\n portalMenuWidth?: string;\n}\n\nconst DropdownIndicator = (props) => {\n const { children, value } = props.selectProps;\n\n return (\n // eslint-disable-next-line react/jsx-props-no-spreading\n \n {children ?? }\n \n );\n};\n\n// This dropdown is used when a selected option becomes the value of the dropdown. Often times, the\n// display will directly reflect the selected option. A typical use case would be a \"sort by\" menu\nconst SelectableDropdown = ({\n children,\n options,\n value,\n onChange,\n isSearchable = false,\n menuWidth,\n maxMenuHeight,\n menuHorizontalPosition,\n isPortal,\n portalMenuWidth = \"300px\",\n}: Props) => {\n return (\n onChange(e)}\n isSearchable={isSearchable}\n menuWidth={menuWidth}\n maxMenuHeight={maxMenuHeight}\n menuHorizontalPosition={menuHorizontalPosition}\n menuPosition={isPortal ? \"fixed\" : \"absolute\"}\n menuPortalTarget={isPortal && document.body}\n styles={{\n menuPortal: (base) => ({\n ...base,\n zIndex: 9999,\n width: portalMenuWidth,\n }),\n option: (base, { isSelected }) => {\n return {\n ...base,\n color: COLORS.BLACK,\n ...(isSelected && { backgroundColor: COLORS.BLUE_LIGHT_400 }),\n };\n },\n }}\n menuShouldBlockScroll={isPortal}\n >\n {children}\n \n );\n};\n\nexport default SelectableDropdown;\n\nconst Dropdown = styled(Select)`\n ${DROPDOWN_STYLES};\n\n ${({ menuWidth }) =>\n menuWidth &&\n `\n .Select__menu {\n white-space: normal;\n width: ${menuWidth};\n\n position: absolute;\n right: 0;\n }\n `}\n .Select__control {\n padding: 0 2px 0 4px;\n min-height: unset;\n border: none;\n &:hover {\n &:not(.Select__control--is-focused) {\n border: none;\n }\n &.Select__control--is-focused {\n border: none;\n }\n }\n }\n .Select__placeholder {\n color: ${COLORS.BLACK};\n ${FONTS.MEDIUM_2};\n }\n .Select__value-container {\n height: 0;\n width: 0;\n padding: 0;\n }\n .Select__indicator {\n margin: 0px;\n }\n .Select__option {\n min-width: unset;\n }\n .Select__menu {\n min-width: fit-content;\n ${({ menuHorizontalPosition }) =>\n menuHorizontalPosition &&\n `\n position: absolute;\n ${menuHorizontalPosition}: 0;\n `}\n }\n .Select__menu-list {\n max-height: ${({ maxMenuHeight }) => maxMenuHeight};\n }\n .Select__control:hover:not(.Select__control--is-focused) {\n border: none;\n }\n`;\n","import MultiSelectDropdown, { SingleSelectProps } from \"./MultiSelectDropdown\";\n\nconst SingleSelectDropdown = ({ placeholder = \"None\", ...props }: SingleSelectProps) => (\n // eslint-disable-next-line react/jsx-props-no-spreading\n \n);\n\nexport default SingleSelectDropdown;\n","import { ReactNode } from \"react\";\nimport styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { Icon } from \"@components/library\";\nimport DROPDOWN_STYLES from \"./dropdownStyles\";\nimport type { DropdownOption } from \"@components/library/Dropdowns/DropdownOption\";\nimport { MultiSelectDropdownBaseStyles, LabelText, Optional } from \"./MultiSelectDropdown\";\nimport Select from \"react-select\";\n\ninterface Props {\n value: DropdownOption | null;\n options: DropdownOption[];\n onChange: (...args: any[]) => any;\n placeholder: string;\n label?: string;\n labelFont?: string;\n isOptional?: boolean;\n createOptionComponent?: ReactNode;\n onCreate?: (...args: any[]) => any;\n menuPlacement?: \"bottom\" | \"auto\" | \"top\";\n maxValueContainerHeight?: string;\n maxMenuHeight?: string;\n helpText?: string;\n errors?: { hasError: boolean; errorMessage: string }[];\n}\n\nconst SelectOrCreateDropdown = ({\n value,\n options,\n onChange,\n placeholder,\n label,\n labelFont = FONTS.SEMIBOLD_2,\n isOptional = false,\n createOptionComponent = (\n \n \n Create new\n \n ),\n onCreate,\n menuPlacement = \"auto\",\n maxValueContainerHeight = \"unset\",\n maxMenuHeight = \"250px\",\n helpText,\n errors,\n}: Props) => {\n const handleChange = (option) => {\n if (option.value === \"_CREATE\" && onCreate) {\n onCreate();\n }\n onChange(option);\n };\n\n const hasAnyError = errors?.map((error) => error.hasError).includes(true);\n\n const optionsWithCreate = onCreate\n ? [\n ...options,\n {\n value: \"_CREATE\",\n label: createOptionComponent,\n },\n ]\n : options;\n\n const dropdown = (\n \n );\n\n return (\n \n {label ? (\n \n \n {label}\n {isOptional && Optional}\n \n {dropdown}\n \n ) : (\n dropdown\n )}\n {Number(helpText?.length) > 0 && {helpText}}\n {hasAnyError &&\n errors?.map(\n (error) =>\n error.hasError && (\n \n \n {error.errorMessage}\n \n )\n )}\n
\n );\n};\n\nexport default SelectOrCreateDropdown;\n\nconst CreateLabel = styled.div`\n display: flex;\n align-items: center;\n`;\nconst Dropdown = styled(Select)`\n ${DROPDOWN_STYLES};\n ${MultiSelectDropdownBaseStyles};\n\n .Select__control {\n margin-top: 0;\n }\n ${({ hasCreateOption }) =>\n hasCreateOption &&\n `\n .Select__option:last-of-type {\n color: ${COLORS.HALO_BLUE};\n ${FONTS.MEDIUM_2};\n }\n `}\n`;\nconst DropdownLabel = styled.label`\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n ${({ labelFont }) => labelFont};\n`;\nconst HelpText = styled.div`\n margin-top: 8px;\n ${FONTS.REGULAR_3};\n`;\nconst ErrorMessage = styled.div`\n display: flex;\n margin-top: 8px;\n ${FONTS.MEDIUM_3};\n color: ${COLORS.RED_600};\n`;\n","import { getValueFromOption } from \"@utils/dropdownUtils\";\nimport { useUniversityOptions } from \"src/views/Onboarding/Hooks\";\n\nimport { DropdownOption } from \"./DropdownOption\";\nimport MultiSelectDropdown from \"./MultiSelectDropdown\";\nimport Fuse from \"fuse.js\";\n\ninterface Props {\n value: DropdownOption | null;\n onChange: (newValue: DropdownOption | null) => void;\n}\n\nexport default function UniversityDropdown({ value, onChange }: Props) {\n const universityOptions = useUniversityOptions();\n\n const searchUniversities = async (query: string): Promise => {\n const fuse = new Fuse(universityOptions, {\n keys: [\"value\"],\n });\n const result = fuse.search(query);\n const values = result.map((r: any) => r.item).slice(0, 500);\n return values;\n };\n\n return (\n \n );\n}\n","import { useState } from \"react\";\nimport styled from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { Icon } from \"@components/library\";\nimport DROPDOWN_STYLES, { MULTI_SELECT_TAG_STYLES } from \"../Dropdowns/dropdownStyles\";\nimport CreatableSelect from \"react-select/creatable\";\nimport { components } from \"react-select\";\nimport type { DropdownOption } from \"@components/library/Dropdowns/DropdownOption\";\nimport { getValueFromOption } from \"@utils/dropdownUtils\";\n\ninterface Props {\n value: DropdownOption[];\n onChange: (...args: any[]) => any;\n placeholder: string;\n createOptionText?: string; // e.g. \"Search proposals for\"\n suggestedOptions?: DropdownOption[];\n}\n\nconst CreateOptionLabel = (input: string, createOptionText?: string) => {\n return (\n \n \n {`${createOptionText ?? \"Search for\"} \"${input}\"`}\n \n );\n};\n\nconst NoOptionsMessage = ({\n children,\n getValue,\n selectOption,\n}: {\n children: DropdownOption[];\n getValue: () => DropdownOption[];\n selectOption: (newValue: DropdownOption) => void;\n}) => {\n const values: string[] = getValue().map(getValueFromOption);\n const filteredChildren = children?.filter(({ value }: DropdownOption) => !values.includes(value));\n\n if (!filteredChildren?.length)\n return (\n \n \n Search by title, content, keywords, researcher, or organization\n \n );\n\n return (\n \n Try searching for\n {children\n .filter(({ value }: DropdownOption) => !values.includes(value))\n .map(({ value, label }: DropdownOption) => (\n selectOption({ label, value })}>\n \n {value}\n \n ))}\n
\n );\n};\n\nexport const ClearIndicator = (props) => {\n const {\n getStyles,\n innerProps: { ref, ...restInnerProps },\n } = props;\n\n return (\n \n \n
\n );\n};\n\nconst MultiValueRemove = ({ ...props }) => {\n return (\n // From the React-Select docs\n /* eslint-disable-next-line */ //@ts-ignore\n \n \n \n );\n};\n\nconst SearchBar = ({ value, placeholder, onChange, createOptionText, suggestedOptions }: Props) => {\n const [inputValue, setInputValue] = useState(\"\");\n\n return (\n \n \n \n \n CreateOptionLabel(input, createOptionText)}\n noOptionsMessage={() => suggestedOptions}\n inputValue={inputValue}\n onInputChange={(e) => setInputValue(e)}\n isMulti\n openMenuOnFocus={true}\n />\n \n );\n};\n\nexport default SearchBar;\n\nconst CreateLabel = styled.div`\n display: flex;\n align-items: center;\n`;\nconst NoOptionsLabel = styled.div`\n display: flex;\n align-items: center;\n color: ${COLORS.NEUTRAL_500};\n`;\nconst SuggestedOptionsHeader = styled.div`\n display: flex;\n align-items: center;\n height: 30px;\n`;\nconst SuggestedOptionLabel = styled.div`\n display: flex;\n align-items: center;\n ${({ isSelected }) => (isSelected ? FONTS.MEDIUM_2 : FONTS.REGULAR_2)};\n color: ${({ isSelected }) => (isSelected ? COLORS.HALO_BLUE : COLORS.BLACK)};\n margin: 0;\n padding: 10px 14px;\n border-radius: 4px;\n cursor: pointer;\n &:hover {\n background-color: ${COLORS.NEUTRAL_100};\n }\n`;\nconst SuggestedOptionText = styled.span`\n overflow-wrap: break-word;\n white-space: normal;\n`;\nexport const Container = styled.div`\n display: flex;\n align-items: center;\n width: 100%;\n`;\nexport const IconContainer = styled.div`\n position: absolute;\n z-index: 1;\n`;\nexport const Dropdown = styled(CreatableSelect)`\n ${DROPDOWN_STYLES};\n ${MULTI_SELECT_TAG_STYLES};\n width: 100%;\n\n .Select__control {\n min-height: 54px;\n }\n .Select__value-container {\n padding-left: 42px;\n cursor: text;\n }\n .Select__dropdown-indicator {\n display: none;\n }\n .Select__indicators {\n height: 52px;\n &:hover {\n opacity: 0.5;\n }\n }\n .Select__menu {\n padding: 8px 12px;\n }\n .Select__option {\n color: ${COLORS.HALO_BLUE};\n ${FONTS.MEDIUM_2};\n padding-right: 16px;\n }\n`;\n","import { ChangeEvent, ForwardedRef, forwardRef, ReactNode } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { COLORS, FONTS } from \"@constants\";\nimport { Icon } from \"@components/library\";\nimport resizeGrabber from \"@images/icons/resize_grabber.svg\";\n\ninterface Props {\n id?: string;\n value: string;\n onChange: (e: ChangeEvent) => void;\n label?: ReactNode;\n labelFont?: string;\n placeholder?: string;\n placeholderColor?: string;\n onBlur?: (...args: any[]) => void;\n optional?: boolean;\n characterLimit?: number;\n warningLimit?: number;\n errors?: { hasError: boolean; errorMessage: string }[];\n textarea?: boolean;\n type?: string;\n hideClearButton?: boolean;\n resize?: string;\n startingHeight?: string;\n min?: number;\n max?: number;\n \"data-testid\"?: string;\n}\n\nconst TextInput = (\n {\n id,\n value,\n onChange,\n label,\n labelFont,\n placeholder,\n placeholderColor,\n type = \"text\",\n onBlur,\n optional = false,\n characterLimit,\n warningLimit,\n errors,\n hideClearButton = false,\n textarea = false,\n resize = \"vertical\",\n startingHeight,\n min,\n max,\n \"data-testid\": dataTestId,\n }: Props,\n ref: ForwardedRef\n) => {\n const hasExceededCharacterLimit = characterLimit && value.length > characterLimit;\n const hasExceededWarningLimit = warningLimit && value.length > warningLimit;\n const hasAnyError =\n // If the other error conditions are all false, we still want to check the character limit\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n errors?.map((error) => error.hasError).includes(true) || hasExceededCharacterLimit;\n\n const handleClear = (e) => {\n const newEvent = {\n ...e,\n target: {\n ...e.target,\n value: type === \"number\" ? undefined : \"\",\n },\n };\n\n onChange(newEvent);\n };\n\n const input = textarea ? (\n