chore: Move Input to functional component (#4629)

* chore: Remove ReactHookWrappedInput workaround
Move Input to functional component

* I love Typescript
This commit is contained in:
Tom Moor
2023-01-01 18:35:02 +00:00
committed by GitHub
parent 2494ca39c1
commit 205f7d2a7e
7 changed files with 78 additions and 90 deletions

View File

@@ -1,5 +1,3 @@
import { observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { VisuallyHidden } from "reakit/VisuallyHidden";
import styled from "styled-components";
@@ -123,93 +121,89 @@ export type Props = React.InputHTMLAttributes<
margin?: string | number;
error?: string;
icon?: React.ReactNode;
innerRef?: React.Ref<any>;
onFocus?: (ev: React.SyntheticEvent) => unknown;
onBlur?: (ev: React.SyntheticEvent) => unknown;
};
@observer
class Input extends React.Component<Props> {
input = this.props.innerRef;
function Input(
props: Props,
ref: React.RefObject<HTMLInputElement | HTMLTextAreaElement>
) {
const [focused, setFocused] = React.useState(false);
@observable
focused = false;
const handleBlur = (ev: React.SyntheticEvent) => {
setFocused(false);
handleBlur = (ev: React.SyntheticEvent) => {
this.focused = false;
if (this.props.onBlur) {
this.props.onBlur(ev);
if (props.onBlur) {
props.onBlur(ev);
}
};
handleFocus = (ev: React.SyntheticEvent) => {
this.focused = true;
const handleFocus = (ev: React.SyntheticEvent) => {
setFocused(true);
if (this.props.onFocus) {
this.props.onFocus(ev);
if (props.onFocus) {
props.onFocus(ev);
}
};
render() {
const {
type = "text",
icon,
label,
margin,
error,
className,
short,
flex,
labelHidden,
onFocus,
onBlur,
...rest
} = this.props;
const {
type = "text",
icon,
label,
margin,
error,
className,
short,
flex,
labelHidden,
onFocus,
onBlur,
...rest
} = props;
const wrappedLabel = <LabelText>{label}</LabelText>;
const wrappedLabel = <LabelText>{label}</LabelText>;
return (
<Wrapper className={className} short={short} flex={flex}>
<label>
{label &&
(labelHidden ? (
<VisuallyHidden>{wrappedLabel}</VisuallyHidden>
) : (
wrappedLabel
))}
<Outline focused={this.focused} margin={margin}>
{icon && <IconWrapper>{icon}</IconWrapper>}
{type === "textarea" ? (
<RealTextarea
ref={this.props.innerRef}
onBlur={this.handleBlur}
onFocus={this.handleFocus}
hasIcon={!!icon}
{...rest}
/>
) : (
<RealInput
ref={this.props.innerRef}
onBlur={this.handleBlur}
onFocus={this.handleFocus}
hasIcon={!!icon}
type={type}
{...rest}
/>
)}
</Outline>
</label>
{error && (
<TextWrapper>
<StyledText type="danger" size="xsmall">
{error}
</StyledText>
</TextWrapper>
)}
</Wrapper>
);
}
return (
<Wrapper className={className} short={short} flex={flex}>
<label>
{label &&
(labelHidden ? (
<VisuallyHidden>{wrappedLabel}</VisuallyHidden>
) : (
wrappedLabel
))}
<Outline focused={focused} margin={margin}>
{icon && <IconWrapper>{icon}</IconWrapper>}
{type === "textarea" ? (
<RealTextarea
ref={ref as React.RefObject<HTMLTextAreaElement>}
onBlur={handleBlur}
onFocus={handleFocus}
hasIcon={!!icon}
{...rest}
/>
) : (
<RealInput
ref={ref as React.RefObject<HTMLInputElement>}
onBlur={handleBlur}
onFocus={handleFocus}
hasIcon={!!icon}
type={type}
{...rest}
/>
)}
</Outline>
</label>
{error && (
<TextWrapper>
<StyledText type="danger" size="xsmall">
{error}
</StyledText>
</TextWrapper>
)}
</Wrapper>
);
}
export const TextWrapper = styled.span`
@@ -222,10 +216,4 @@ export const StyledText = styled(Text)`
margin-bottom: 0;
`;
export const ReactHookWrappedInput = React.forwardRef(
(props: Omit<Props, "innerRef">, ref: React.Ref<any>) => {
return <Input {...{ ...props, innerRef: ref }} />;
}
);
export default Input;
export default React.forwardRef(Input);

View File

@@ -42,7 +42,7 @@ function InputSearch(
onBlur={handleBlur}
margin={0}
labelHidden
innerRef={ref}
ref={ref}
{...rest}
/>
);

View File

@@ -68,7 +68,7 @@ function InputSearchPage({
return (
<InputMaxWidth
innerRef={inputRef}
ref={inputRef}
type="search"
placeholder={placeholder || `${t("Search")}`}
value={value}

View File

@@ -8,7 +8,7 @@ import Integration from "~/models/Integration";
import Button from "~/components/Button";
import Heading from "~/components/Heading";
import GoogleIcon from "~/components/Icons/GoogleIcon";
import { ReactHookWrappedInput as Input } from "~/components/Input";
import Input from "~/components/Input";
import Scene from "~/components/Scene";
import Text from "~/components/Text";
import useStores from "~/hooks/useStores";

View File

@@ -8,7 +8,7 @@ import { IntegrationService, IntegrationType } from "@shared/types";
import Integration from "~/models/Integration";
import Button from "~/components/Button";
import Heading from "~/components/Heading";
import { ReactHookWrappedInput as Input } from "~/components/Input";
import Input from "~/components/Input";
import Scene from "~/components/Scene";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";

View File

@@ -7,7 +7,7 @@ import { useTranslation, Trans } from "react-i18next";
import styled from "styled-components";
import WebhookSubscription from "~/models/WebhookSubscription";
import Button from "~/components/Button";
import { ReactHookWrappedInput } from "~/components/Input";
import Input from "~/components/Input";
import Text from "~/components/Text";
import useMobile from "~/hooks/useMobile";
@@ -230,7 +230,7 @@ function WebhookSubscriptionForm({ handleSubmit, webhookSubscription }: Props) {
</Trans>
</Text>
<TextFields>
<ReactHookWrappedInput
<Input
required
autoFocus
flex
@@ -240,7 +240,7 @@ function WebhookSubscriptionForm({ handleSubmit, webhookSubscription }: Props) {
required: true,
})}
/>
<ReactHookWrappedInput
<Input
required
autoFocus
flex
@@ -249,7 +249,7 @@ function WebhookSubscriptionForm({ handleSubmit, webhookSubscription }: Props) {
label={t("URL")}
{...register("url", { required: true })}
/>
<ReactHookWrappedInput
<Input
flex
spellCheck={false}
label={t("Signing secret")}

View File

@@ -4,7 +4,7 @@ import { useForm } from "react-hook-form";
import { useTranslation, Trans } from "react-i18next";
import Button from "~/components/Button";
import Flex from "~/components/Flex";
import { ReactHookWrappedInput as Input } from "~/components/Input";
import Input from "~/components/Input";
import Text from "~/components/Text";
import env from "~/env";
import useStores from "~/hooks/useStores";