chore: Move Input to functional component (#4629)
* chore: Remove ReactHookWrappedInput workaround Move Input to functional component * I love Typescript
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -42,7 +42,7 @@ function InputSearch(
|
||||
onBlur={handleBlur}
|
||||
margin={0}
|
||||
labelHidden
|
||||
innerRef={ref}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -68,7 +68,7 @@ function InputSearchPage({
|
||||
|
||||
return (
|
||||
<InputMaxWidth
|
||||
innerRef={inputRef}
|
||||
ref={inputRef}
|
||||
type="search"
|
||||
placeholder={placeholder || `${t("Search")}…`}
|
||||
value={value}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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")}
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user