Improve types and add more examples for refs

This commit is contained in:
Andrey Okonetchnikov committed 2022-09-21 11:49:49 +02:00
1 parent ebd952492a
commit 2a4cd84e10
2 files changed
+82 -53

No files matched your search

@@ -1,6 +1,7 @@
import React from "react";
import { ComponentStory } from "@storybook/react";
import { BrushIcon, ChevronDownIcon } from "@webstudio-is/icons";
import { Button } from "./button";
import { Flex } from "./flex";
import { IconButton } from "./icon-button";
import { TextField } from "./text-field";
@@ -94,3 +95,30 @@ export const PrefixSuffix: ComponentStory<typeof TextField> = () => {
</Flex>
);
};
export const Interactive: ComponentStory<typeof TextField> = () => {
const [value, setValue] = React.useState("");
const wrapperRef = React.useRef<HTMLDivElement>(null);
const inputRef = React.useRef<HTMLInputElement>(null);
return (
<Flex direction="column" gap={3}>
<TextField ref={wrapperRef} inputRef={inputRef} value={value} readOnly />
<Button
onClick={() => {
// eslint-disable-next-line no-console
setValue(JSON.stringify(wrapperRef.current?.getBoundingClientRect()));
}}
>
Measure TextField
</Button>
<Button
onClick={() => {
inputRef.current?.focus();
}}
>
Focus TextField
</Button>
</Flex>
);
};
@@ -146,67 +146,68 @@ const TextFieldBase = styled("div", {
},
});
type TextFieldProps = Omit<
type TextFieldProps = Pick<
React.ComponentProps<typeof TextFieldBase>,
"onChange" | "onFocus" | "onBlur" | "prefix"
"size" | "variant" | "state" | "css"
> &
React.ComponentProps<"input"> & {
Omit<React.ComponentProps<"input">, "prefix" | "children"> & {
inputRef?: React.Ref<HTMLInputElement>;
prefix?: React.ReactNode;
suffix?: React.ReactNode;
};
export const TextField = React.forwardRef<
React.ElementRef<typeof TextFieldBase>,
TextFieldProps
>((props, forwardedRef) => {
const {
prefix,
suffix,
css,
disabled,
inputRef,
size,
state,
variant,
...textFieldProps
} = props;
return (
<TextFieldBase
aria-disabled={disabled}
ref={forwardedRef}
size={size}
state={state}
variant={variant}
css={css}
>
{prefix && (
<Flex
css={{
alignItems: "center",
flexShrink: 0,
order: 0,
}}
>
{prefix}
</Flex>
)}
export const TextField = React.forwardRef<HTMLDivElement, TextFieldProps>(
(props, forwardedRef) => {
const {
prefix,
suffix,
css,
disabled,
inputRef,
size,
state,
variant,
...textFieldProps
} = props;
<InputBase disabled={disabled} {...textFieldProps} ref={inputRef} />
return (
<TextFieldBase
aria-disabled={disabled}
ref={forwardedRef}
size={size}
state={state}
variant={variant}
css={css}
>
{/* We want input to be the first element in DOM so it receives the focus first */}
<InputBase disabled={disabled} {...textFieldProps} ref={inputRef} />
{suffix && (
<Flex
css={{
alignItems: "center",
flexShrink: 0,
order: 2,
}}
>
{suffix}
</Flex>
)}
</TextFieldBase>
);
});
{prefix && (
<Flex
css={{
alignItems: "center",
flexShrink: 0,
order: 0,
}}
>
{prefix}
</Flex>
)}
{suffix && (
<Flex
css={{
alignItems: "center",
flexShrink: 0,
order: 2,
}}
>
{suffix}
</Flex>
)}
</TextFieldBase>
);
}
);
TextField.displayName = "TextField";