idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 1 | import { Stack, TextField } from "@mui/material" |
idillon | fb2af5b | 2022-09-16 13:40:08 -0400 | [diff] [blame] | 2 | import { styled } from "@mui/material/styles" |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 3 | import { useState, useCallback, useEffect } from "react"; |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 4 | import { InfoButton, ToggleVisibilityButton } from "./buttons" |
idillon | 927b759 | 2022-09-15 12:56:45 -0400 | [diff] [blame] | 5 | import { CheckedIcon, RoundSaltireIcon, LockIcon, PenIcon, PersonIcon } from "./svgIcons" |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 6 | |
| 7 | const iconsHeight = "16px" |
| 8 | const StyledCheckedIconSuccess = styled(CheckedIcon)(({theme}) => ({height: iconsHeight, color: theme.palette.success.main})) |
idillon | 927b759 | 2022-09-15 12:56:45 -0400 | [diff] [blame] | 9 | const StyledRoundSaltireIconError = styled(RoundSaltireIcon)(({theme}) => ({height: iconsHeight, color: theme.palette.error.main})) |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 10 | const StyledPenIconLight = styled(PenIcon)({height: iconsHeight, color: "#03B9E9"}) |
| 11 | const StyledPenIconDark = styled(PenIcon)(({theme}) => ({height: iconsHeight, color: theme.palette.primary.dark})) |
| 12 | const StyledPersonIconLight = styled(PersonIcon)({height: iconsHeight, color: "#03B9E9"}) |
| 13 | const StyledLockIcon = styled(LockIcon)({height: iconsHeight, color: "#03B9E9"}) |
| 14 | |
| 15 | export const UsernameInput = ({infoButtonProps, ...props}) => { |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 16 | const [isSelected, setIsSelected] = useState(false); |
| 17 | const [input, setInput] = useState(props.defaultValue); |
| 18 | const [startAdornment, setStartAdornment] = useState() |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 19 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 20 | const onChange = useCallback((event) => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 21 | setInput(event.target.value) |
| 22 | props.onChange?.(event) |
| 23 | }, [props.onChange]) |
| 24 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 25 | useEffect(() => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 26 | /* Handle startAdornment */ |
| 27 | let Icon = StyledPersonIconLight |
| 28 | let visibility = "visible" |
| 29 | if (props.error) { |
idillon | 927b759 | 2022-09-15 12:56:45 -0400 | [diff] [blame] | 30 | Icon = StyledRoundSaltireIconError |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 31 | } |
| 32 | else if (props.success) { |
| 33 | Icon = StyledCheckedIconSuccess |
| 34 | } |
| 35 | else if (!isSelected && !input) { |
| 36 | visibility = "hidden" // keep icon's space so text does not move |
| 37 | } |
| 38 | setStartAdornment(<Icon sx={{visibility}}/>) |
| 39 | }, [props.error, props.success, isSelected, input]) |
| 40 | |
| 41 | return ( |
| 42 | <TextField |
| 43 | {...props} |
| 44 | label="Choose an identifier" |
| 45 | variant="standard" |
| 46 | InputLabelProps={{ shrink: !!(isSelected || input) }} |
| 47 | onChange={onChange} |
| 48 | InputProps={{ |
| 49 | startAdornment, |
| 50 | endAdornment: <InfoButton {...infoButtonProps}/>, |
| 51 | }} |
| 52 | onFocus={() => setIsSelected(true)} |
| 53 | onBlur={() => setIsSelected(false)} |
| 54 | /> |
| 55 | ) |
| 56 | } |
| 57 | |
| 58 | export const PasswordInput = ({infoButtonProps, ...props}) => { |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 59 | const [showPassword, setShowPassword] = useState(false); |
| 60 | const [isSelected, setIsSelected] = useState(false); |
| 61 | const [input, setInput] = useState(props.defaultValue); |
| 62 | const [startAdornment, setStartAdornment] = useState() |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 63 | |
| 64 | const toggleShowPassword = () => { |
| 65 | setShowPassword((showPassword) => !showPassword); |
| 66 | } |
| 67 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 68 | const onChange = useCallback((event) => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 69 | setInput(event.target.value) |
| 70 | props.onChange?.(event) |
| 71 | }, [props.onChange]) |
| 72 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 73 | useEffect(() => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 74 | /* Handle startAdornment */ |
| 75 | let Icon = StyledLockIcon |
| 76 | let visibility = "visible" |
| 77 | if (props.error) { |
idillon | 927b759 | 2022-09-15 12:56:45 -0400 | [diff] [blame] | 78 | Icon = StyledRoundSaltireIconError |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 79 | } |
| 80 | else if (props.success) { |
| 81 | Icon = StyledCheckedIconSuccess |
| 82 | } |
| 83 | else if (!isSelected && !input) { |
| 84 | visibility = "hidden" // keep icon's space so text does not move |
| 85 | } |
| 86 | setStartAdornment(<Icon sx={{visibility}}/>) |
| 87 | }, [props.error, props.success, isSelected, input]) |
| 88 | |
| 89 | return ( |
| 90 | <TextField |
| 91 | {...props} |
| 92 | label="Password" |
| 93 | type={showPassword ? "text" : "password"} |
| 94 | variant="standard" |
| 95 | autoComplete="current-password" |
| 96 | InputLabelProps={{ shrink: !!(isSelected || input) }} |
| 97 | onChange={onChange} |
| 98 | InputProps={{ |
| 99 | startAdornment, |
| 100 | endAdornment: <Stack direction="row" spacing="14px"> |
| 101 | <InfoButton {...infoButtonProps}/> |
| 102 | <ToggleVisibilityButton |
| 103 | visible={showPassword} |
| 104 | onClick={toggleShowPassword} |
| 105 | /> |
| 106 | </Stack>, |
| 107 | }} |
| 108 | onFocus={() => setIsSelected(true)} |
| 109 | onBlur={() => setIsSelected(false)} |
| 110 | /> |
| 111 | ) |
| 112 | } |
| 113 | |
| 114 | export const NickNameInput = (props) => { |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 115 | const [isSelected, setIsSelected] = useState(false); |
| 116 | const [input, setInput] = useState(props.defaultValue); |
| 117 | const [startAdornmentVisibility, setStartAdornmentVisibility] = useState() |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 118 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 119 | const onChange = useCallback((event) => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 120 | setInput(event.target.value) |
| 121 | props.onChange?.(event) |
| 122 | }, [props.onChange]) |
| 123 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 124 | useEffect(() => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 125 | setStartAdornmentVisibility((isSelected || input) ? "visible" : "hidden") |
| 126 | }, [isSelected, input]) |
| 127 | |
| 128 | return ( |
| 129 | <TextField |
| 130 | {...props} |
| 131 | label="Nickname, surname..." |
| 132 | variant="standard" |
| 133 | InputLabelProps={{ shrink: !!(isSelected || input) }} |
| 134 | onChange={onChange} |
| 135 | InputProps={{ |
| 136 | startAdornment: <StyledPenIconLight sx={{visibility: startAdornmentVisibility}}/>, |
| 137 | }} |
| 138 | onFocus={() => setIsSelected(true)} |
| 139 | onBlur={() => setIsSelected(false)} |
| 140 | /> |
| 141 | ) |
| 142 | } |
| 143 | |
| 144 | export const RegularInput = (props) => { |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 145 | const [isSelected, setIsSelected] = useState(false); |
| 146 | const [input, setInput] = useState(props.defaultValue); |
| 147 | const [startAdornmentVisibility, setStartAdornmentVisibility] = useState() |
| 148 | const [endAdornmentVisibility, setEndAdornmentVisibility] = useState() |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 149 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 150 | const onChange = useCallback((event) => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 151 | setInput(event.target.value) |
| 152 | props.onChange?.(event) |
| 153 | }, [props.onChange]) |
| 154 | |
Adrien Béraud | 023f7cf | 2022-09-18 14:57:53 -0400 | [diff] [blame] | 155 | useEffect(() => { |
idillon-sfl | 37c18df | 2022-08-26 18:44:27 -0400 | [diff] [blame] | 156 | setStartAdornmentVisibility((isSelected || input) ? "visible" : "hidden") |
| 157 | setEndAdornmentVisibility((isSelected || input) ? "hidden" : "visible") |
| 158 | }, [isSelected, input]) |
| 159 | |
| 160 | return ( |
| 161 | <TextField |
| 162 | {...props} |
| 163 | variant="standard" |
| 164 | InputLabelProps={{ shrink: !!(isSelected || input) }} |
| 165 | onChange={onChange} |
| 166 | InputProps={{ |
| 167 | startAdornment: <StyledPenIconLight sx={{visibility: startAdornmentVisibility}}/>, |
| 168 | endAdornment: <StyledPenIconDark sx={{visibility: endAdornmentVisibility}}/>, |
| 169 | }} |
| 170 | onFocus={() => setIsSelected(true)} |
| 171 | onBlur={() => setIsSelected(false)} |
| 172 | /> |
| 173 | ) |
| 174 | } |