{"version":3,"sources":["webpack://switch-website/./src/components/common/Forms.js"],"names":["baseInputPlaceholderStyle","css","fonts","colors","baseInputStyles","StyledFormError","P2Mono","fontWeights","FormError","messages","length","formattedMessages","map","message","key","Math","random","toString","substring","className","defaultProps","Input","TextArea","FileFieldAttachment","p2BaseStyle","TextAreaResizer","StyledSelect","P2","hexToRgba","Select","options","defaultOption","id","onSelect","initialOption","useState","selectedOption","setSelectedOption","open","setOpen","inputOptionsWrapper","useDetectOutsideClick","inputOptionsCss","arrowClasses","inputOptionsWrapperClasses","push","maxHeight","current","scrollHeight","selectOptions","concat","option","onClick","value","label","type","placeholder","role","readOnly","join","ref","DefaultForm","PrimaryButton","breakpoints"],"mappings":"6XAqBMA,GAA4BC,QAAH,eACZC,eADY,UAElBC,gBAFkB,2CAOzBC,GAAkBH,QAAH,iDAGUE,WAHV,wGASFD,eATE,qGAiBcC,WAjBd,6EAwBXH,EAxBW,sDAgCGG,SAhCH,mBAwCfE,GAAe,mDAGfC,KAHe,UAIJH,SAJI,gDAOEI,cAPF,eAYfC,EAAY,SAAC,GAAuB,IAAD,IAArBC,gBAAqB,MAAV,KAAU,EACrC,IAAKA,IAAaA,EAASC,OACvB,OAAO,KAGX,IAAMC,EAAoBF,EAASG,KAAI,SAAAC,GAAO,OAC1C,QAAC,KAAD,CAAQC,IAAKC,KAAKC,SAASC,SAAS,IAAIC,UAAU,IAAKL,MAE3D,OAAO,QAACR,EAAD,CAAiBc,UAAU,cAAcR,IAOpDH,EAAUY,aAAe,CACrBX,SAAU,MAId,IAAMY,GAAK,mCACLjB,EADK,KA4LLkB,IAvLe,mCACflB,EADe,sDAQXJ,EARW,oBAWCuB,IAXD,sHA+FC,iCAChBnB,EADgB,yKAiBRoB,KAjBQ,yBAwFR,sCACRpB,EADQ,sCAIYqB,IAJZ,kBASRC,GAAY,qEAIRL,EAJQ,uDAOclB,iBAPd,oHAsBYA,gBAtBZ,0GAkCUA,WAlCV,UAmCDA,cAnCC,wHA8CJwB,KA9CI,kGAoD0BC,QAAUzB,gBAAmB,IApDvD,UAqDeA,gBArDf,gBAsDqBI,YAtDrB,6BA2DWJ,gBA3DX,2BA4EZ0B,EAAS,SAAC,GAAkF,IAAjFC,EAAgF,EAAhFA,QAASC,EAAuE,EAAvEA,cAAuE,IAAxDC,UAAwD,MAAnD,KAAmD,MAA7CC,gBAA6C,MAAlC,aAAkC,MAAxBC,qBAAwB,MAAR,GAAQ,EAC7F,GAA4CC,cAASD,GAA9CE,EAAP,KAAuBC,EAAvB,KACA,GAAwBF,eAAS,GAA1BG,EAAP,KAAaC,EAAb,KACMC,GAAsBC,QAAsB,kBAAOH,GAAQC,GAAQ,MAarEG,EAAkB,KAChBC,EAAe,CAAC,SAChBC,EAA6B,CAAC,yBAEhCN,IACAK,EAAaE,KAAK,QAClBD,EAA2BC,KAAK,QAIhCH,EAAkB,CACdI,UAAWN,EAAoBO,QAAQC,eAK/C,IAEMC,EAAgB,EAFM,QAAC,EAAAtB,GAAD,CAAIR,UAAU,iBAAiBL,IAAI,kBAAkBiB,IAErCmB,OAAOpB,EAAQlB,KAAI,SAAAuC,GAAM,OACjE,QAAC,EAAAxB,GAAD,CAAIyB,SAzBaC,EAyBSF,EAzBA,WAC1Bd,EAAkBgB,GAClBd,GAAQ,GACRN,EAASoB,KAsB0BvC,IAAKqC,EAAOE,OAAQF,EAAOG,OAzB7C,IAAAD,MA6BrB,OACI,QAAC3B,EAAD,CAAcP,UAAU,iBACpB,eAAKA,UAAU,kBACX,QAACE,EAAD,CACIkC,KAAK,OACLpC,UAAU,eACVqC,YAAazB,EACbsB,MAAOjB,EAAeiB,OAAS,GAC/BD,QAAS,kBAAMb,GAASD,IACxBmB,KAAK,UACLC,UAAQ,KAEZ,iBAAOH,KAAK,SAASvB,GAAIA,EAAIqB,MAAOjB,EAAetB,KAAO,MAC1D,QAAC,IAAD,CAAWK,UAAWwB,EAAagB,KAAK,KAAMP,QAAS,kBAAMb,GAASD,QAG1E,eAAKnB,UAAWyB,EAA2Be,KAAK,KAAMC,IAAKpB,EAAqBvC,IAAKyC,IACjF,eAAKvB,UAAU,yBAAyB8B,MAcxDpB,EAAOT,aAAe,CAClBY,GAAI,KACJC,SAAU,aACVC,cAAe,IAInB,IAAM2B,GAAW,sFAKU3D,eALV,sEAaAC,gBAbA,wDAkBUD,eAlBV,mFA4BX4D,KA5BW,wCAgCQC,QAhCR,KAiCPD,KAjCO","file":"e50829f1-5c103575ca6453530697.js","sourcesContent":["/** @jsx jsx */\n/* eslint-disable i18next/no-literal-string */\nimport React, {useRef, useState} from 'react';\nimport PropTypes from 'prop-types';\n\nimport {css, jsx} from '@emotion/react';\nimport styled from '@emotion/styled';\n\nimport {PrimaryButton} from './Clickables';\nimport {P2, p2BaseStyle, P2Mono} from './Typography';\nimport FileFieldAttachment from '../../images/forms/file-field-attachment.no-inline.svg';\nimport TextAreaResizer from '../../images/forms/textarea-resizer.no-inline.svg';\nimport ArrowDown from '../../images/clickables/arrow_down.svg';\nimport useDetectOutsideClick from '../../helpers/hooks/useDetectOutsideClick';\nimport {hexToRgba} from '../../helpers/utils';\nimport {breakpoints, colors, fonts, fontWeights} from '../../styles/theme';\n\n\n/*\n * Private Elements\n */\nconst baseInputPlaceholderStyle = css`\n font-family: ${fonts.sansSerif};\n color: ${colors.mediumGrey};\n font-size: 0.75rem;\n line-height: 40px;\n`;\n\nconst baseInputStyles = css`\n padding: 0;\n border: none;\n border-bottom: 2px solid ${colors.white};\n border-radius: 0;\n background-color: inherit;\n color: inherit;\n line-height: 35px;\n min-height: 42px;\n font-family: ${fonts.sansSerif};\n font-size: 14px;\n width: 100%;\n\n &:focus {\n color: inherit;\n outline: none;\n border: none;\n border-bottom: 2px solid ${colors.white};\n transition: none;\n box-shadow: none;\n background-color: inherit;\n }\n\n &::placeholder {\n ${baseInputPlaceholderStyle}\n }\n\n &.form-control {\n height: 42px;\n }\n\n &.error {\n border-color: ${colors.red} !important;\n }\n`;\n\n\n/*\n * Public Elements\n */\nconst StyledFormError = styled.div`\n margin-top: 5px;\n\n ${P2Mono} {\n color: ${colors.red};\n font-size: 12px;\n line-height: 18px;\n font-weight: ${fontWeights.semiBold};\n margin: 0;\n }\n`;\n\nconst FormError = ({messages = null}) => {\n if (!messages || !messages.length) {\n return null;\n }\n\n const formattedMessages = messages.map(message => (\n {message}\n ));\n return {formattedMessages};\n};\n\nFormError.propTypes = {\n messages: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.node])),\n};\n\nFormError.defaultProps = {\n messages: null,\n};\n\n\nconst Input = styled.input`\n ${baseInputStyles};\n`;\n\n\nconst StyledInputFile = styled.label`\n ${baseInputStyles};\n\n &.disabled {\n background-color: #E9ECEF;\n }\n\n .placeholder {\n ${baseInputPlaceholderStyle};\n }\n\n background: url(${FileFieldAttachment}) no-repeat right center;\n\n input {\n width: 0.1px;\n height: 0.1px;\n opacity: 0;\n overflow: hidden;\n position: absolute;\n z-index: -10;\n }\n`;\n\n/**\n * Custom input file\n *\n * @param {string} value - The value of the input\n * @param {function} onChange - The callback to run when the input changes\n * @param {string} id - The ID of the input\n * @param {string} placeholder - The placeholder to show in the input\n * @param {string} name - The name of the input\n * @param {string} className - The extra classes to add to the input\n * @param {boolean = false} disabled - Whether the form input is disabled or not\n * @param {boolean = false} required - Whether the form input is required or not\n * @param {string} acceptedFileExtensions - Comma-separated list of accepted file extensions (e.g.: \".pdf,.png\")\n */\nconst InputFile = ({\n onChange = () => {},\n id = '',\n placeholder = '',\n name = '',\n className = '',\n disabled = false,\n required = false,\n acceptedFileExtensions = '',\n}) => {\n const inputRef = useRef(null);\n const [placeholderText, setPlaceholderText] = useState(placeholder);\n const disabledClass = disabled ? 'disabled' : '';\n\n const _onChange = event => {\n setPlaceholderText(inputRef.current?.files[0]?.name || placeholder);\n onChange(event);\n };\n\n return (\n \n \n {placeholderText}\n \n );\n};\n\nInputFile.propTypes = {\n onChange: PropTypes.func,\n id: PropTypes.string,\n placeholder: PropTypes.string,\n name: PropTypes.string,\n className: PropTypes.string,\n disabled: PropTypes.bool,\n required: PropTypes.bool,\n acceptedFileExtensions: PropTypes.string,\n};\n\nInputFile.defaultProps = {\n id: '',\n onChange: () => {},\n placeholder: '',\n name: '',\n className: '',\n disabled: false,\n required: false,\n acceptedFileExtensions: '',\n};\n\n\nconst StyledInputRadio = styled.div`\n ${baseInputStyles};\n border: 0;\n height: auto;\n\n &.form-control {\n height: auto;\n }\n\n .radio-option {\n display: flex;\n flex-direction: row;\n margin-top: 15px;\n justify-content: flex-start;\n align-items: baseline;\n\n label {\n ${p2BaseStyle};\n\n margin-left: 15px;\n }\n }\n`;\n\n/**\n * Custom input radio\n *\n * @param {string} id - The ID of the input\n * @param {string} name - The name of the input\n * @param {[{}]} options - The input options\n * @param {string} value - The value of the input\n * @param {function} onChange - The callback to run when the input changes\n * @param {string} className - The extra classes to add to the input\n * @param {boolean = false} disabled - Whether the form input is disabled or not\n * @param {boolean = false} required - Whether the form input is required or not\n */\nconst InputRadio = ({\n id,\n name,\n options,\n onChange = () => {},\n className = '',\n disabled = false,\n required = false,\n}) => {\n const radioOptions = options.map((option, idx) => {\n const optionId = `${name}-${idx}`;\n return (\n \n { if (option.value.toString() === event.target.value) onChange(event); }}\n required={required}\n disabled={disabled}\n />\n \n \n );\n });\n\n return (\n \n {radioOptions}\n \n );\n};\n\nInputRadio.propTypes = {\n id: PropTypes.string.isRequired,\n name: PropTypes.string.isRequired,\n options: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,\n onChange: PropTypes.func,\n className: PropTypes.string,\n disabled: PropTypes.bool,\n required: PropTypes.bool,\n};\n\nInputRadio.defaultProps = {\n onChange: () => {},\n className: '',\n disabled: false,\n required: false,\n};\n\n\nconst TextArea = styled.textarea`\n ${baseInputStyles};\n\n &::-webkit-resizer {\n background: url(${TextAreaResizer}) no-repeat;\n }\n`;\n\n\nconst StyledSelect = styled.div`\n position: relative;\n\n .input-wrapper {\n ${Input} {\n cursor: inherit;\n padding-right: 35px;\n background-color: ${colors.transparent};\n }\n\n .caret {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 10px;\n margin: auto;\n z-index: 11;\n\n &.open {\n transform: scaleY(-1);\n\n * {\n stroke: ${colors.darkPurple};\n }\n }\n }\n }\n\n .input-options-wrapper {\n position: absolute;\n top: 0;\n left: 0;\n overflow: hidden;\n width: 100%;\n background-color: ${colors.white};\n color: ${colors.darkGrey};\n transition: max-height 0.3s ease-out;\n z-index: 10;\n\n &:not(.open) {\n max-height: 0;\n }\n\n .input-options-content {\n margin: 10px 0 15px;\n\n ${P2} {\n padding: 2.5px 35px 2.5px 20px;\n cursor: default;\n\n &:hover {\n &:not(.default-option) {\n background-color: ${hexToRgba(colors.darkPurple, 0.1)};\n color: ${colors.darkPurple};\n font-weight: ${fontWeights.medium};\n }\n }\n\n &.default-option {\n color: ${colors.darkPurple};\n margin-bottom: 5px;\n }\n }\n }\n }\n`;\n\n/**\n * Custom select box\n *\n * @param {[{}]} options - List of the options to show in the select box\n * @param {string} defaultOption - The default, already selected, option in the select box (which can't be used)\n * @param {string} id - The ID of the element holding the value\n * @param {function} onSelect - Callback to run when an element is selected\n * @param {{}} initialOption - Initial selection option to display\n */\nconst Select = ({options, defaultOption, id = null, onSelect = () => {}, initialOption = {}}) => {\n const [selectedOption, setSelectedOption] = useState(initialOption);\n const [open, setOpen] = useState(false);\n const inputOptionsWrapper = useDetectOutsideClick(() => (open && setOpen(false)));\n\n /**\n * Set an option of the dropdown as selected\n *\n * @param {object} value - The option to set as selected when the function is called\n */\n const selectOption = value => () => {\n setSelectedOption(value);\n setOpen(false);\n onSelect(value);\n };\n\n let inputOptionsCss = null;\n const arrowClasses = ['caret'];\n const inputOptionsWrapperClasses = ['input-options-wrapper'];\n\n if (open) {\n arrowClasses.push('open');\n inputOptionsWrapperClasses.push('open');\n\n // Set the dropdown's max height to the \"rendered\" height of the element (the open/close animation is done with\n // this property)\n inputOptionsCss = {\n maxHeight: inputOptionsWrapper.current.scrollHeight,\n };\n }\n\n // Define the default element\n const styledDefaultOption = {defaultOption};\n // Define the existing options\n const selectOptions = [styledDefaultOption].concat(options.map(option => (\n {option.label}\n )));\n\n // Render the thing!\n return (\n \n
\n setOpen(!open)}\n role=\"listbox\"\n readOnly\n />\n \n setOpen(!open)} />\n
\n\n
\n
{selectOptions}
\n
\n
\n );\n};\n\nSelect.propTypes = {\n id: PropTypes.string,\n options: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,\n defaultOption: PropTypes.string.isRequired,\n onSelect: PropTypes.func,\n initialOption: PropTypes.object,\n};\n\nSelect.defaultProps = {\n id: null,\n onSelect: () => {},\n initialOption: {},\n};\n\n\nconst DefaultForm = styled.form`\n .form-group {\n margin-bottom: 32px;\n\n label {\n font-family: ${fonts.monospace};\n font-size: 16px;\n line-height: 24px;\n margin-bottom: 0;\n }\n }\n\n .required {\n color: ${colors.darkPurple};\n\n &.small {\n font-size: 10px;\n line-height: 15px;\n font-family: ${fonts.monospace};\n }\n }\n\n .submit-group {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n ${PrimaryButton} {\n margin-top: 25px;\n }\n\n @media (min-width: ${breakpoints.md}) {\n ${PrimaryButton} {\n margin-top: 10px;\n }\n }\n`;\n\nexport {\n FormError,\n DefaultForm,\n Input,\n InputFile,\n InputRadio,\n Select,\n TextArea,\n};\n"],"sourceRoot":""}