Shared:Components:SearchInput: rewrite to typescript
This commit is contained in:
parent
1d7d92818d
commit
70c2adfc85
@ -32,8 +32,12 @@ import { Textarea } from "./textarea";
|
||||
import { TextInput, InputSize, InputType } from "./text-input";
|
||||
import { EmailInput } from "./email-input";
|
||||
import { Heading, HeadingLevel, HeadingSize } from "./heading";
|
||||
import { InputBlock } from "./input-block";
|
||||
import { SearchInput } from "./search-input";
|
||||
|
||||
export {
|
||||
SearchInput,
|
||||
InputBlock,
|
||||
Heading,
|
||||
HeadingLevel,
|
||||
HeadingSize,
|
||||
|
@ -5,7 +5,7 @@ SearchInput description
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import SearchInput from "@docspace/components/search-input";
|
||||
import { SearchInput } from "@docspace/shared/components";
|
||||
```
|
||||
|
||||
```jsx
|
||||
|
@ -0,0 +1,52 @@
|
||||
import React, { useState } from "react";
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
import { InputSize } from "../text-input";
|
||||
|
||||
import { SearchInput } from "./SearchInput";
|
||||
import { SearchInputProps } from "./SearchInput.types";
|
||||
|
||||
const meta = {
|
||||
title: "Components/SearchInput",
|
||||
component: SearchInput,
|
||||
parameters: {
|
||||
design: {
|
||||
type: "figma",
|
||||
url: "https://www.figma.com/file/ZiW5KSwb4t7Tj6Nz5TducC/UI-Kit-DocSpace-1.0.0?type=design&node-id=58-2238&mode=design&t=TBNCKMQKQMxr44IZ-0",
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
onChange: { action: "onChange" },
|
||||
},
|
||||
} satisfies Meta<typeof SearchInput>;
|
||||
type Story = StoryObj<typeof SearchInput>;
|
||||
|
||||
export default meta;
|
||||
|
||||
const Template = ({ value, onChange, ...args }: SearchInputProps) => {
|
||||
const [searchValue, setSearchValue] = useState(value);
|
||||
|
||||
return (
|
||||
<SearchInput
|
||||
{...args}
|
||||
style={{ width: "20%" }}
|
||||
value={searchValue}
|
||||
onChange={(v: string) => {
|
||||
onChange?.(v);
|
||||
setSearchValue(v);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default: Story = {
|
||||
render: (args) => <Template {...args} />,
|
||||
args: {
|
||||
id: "",
|
||||
isDisabled: false,
|
||||
size: InputSize.base,
|
||||
scale: false,
|
||||
placeholder: "Search",
|
||||
value: "",
|
||||
},
|
||||
};
|
@ -1,11 +1,11 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import Base from "../themes/base";
|
||||
|
||||
const StyledSearchInput = styled.div`
|
||||
import { Base } from "../../themes";
|
||||
|
||||
const StyledSearchInput = styled.div<{ isScale?: boolean }>`
|
||||
font-family: Open Sans;
|
||||
font-style: normal;
|
||||
|
||||
// @ts-expect-error TS(2339): Property 'isScale' does not exist on type 'Omit<De... Remove this comment to see the full error message
|
||||
${({ isScale }) =>
|
||||
isScale &&
|
||||
css`
|
207
packages/shared/components/search-input/SearchInput.test.tsx
Normal file
207
packages/shared/components/search-input/SearchInput.test.tsx
Normal file
@ -0,0 +1,207 @@
|
||||
import React from "react";
|
||||
|
||||
import { screen, render } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
|
||||
import { InputSize } from "../text-input";
|
||||
|
||||
import { SearchInput } from "./SearchInput";
|
||||
|
||||
const baseProps = {
|
||||
value: "",
|
||||
size: InputSize.base,
|
||||
// getFilterData: () => [
|
||||
// {
|
||||
// key: "filter-example",
|
||||
// group: "filter-example",
|
||||
// label: "example group",
|
||||
// isHeader: true,
|
||||
// },
|
||||
// { key: "filter-example-test", group: "filter-example", label: "Test" },
|
||||
// ],
|
||||
};
|
||||
|
||||
describe("<SearchInput />", () => {
|
||||
it("renders without error", () => {
|
||||
render(<SearchInput {...baseProps} />);
|
||||
|
||||
expect(screen.getByTestId("search-input")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
// it("middle size prop", () => {
|
||||
// // @ts-expect-error TS(2322): Type '{ size: string; isNeedFilter: boolean; value... Remove this comment to see the full error message
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="middle" />);
|
||||
|
||||
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
// expect(wrapper.prop("size")).toEqual("middle");
|
||||
// });
|
||||
|
||||
// // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
// it("big size prop", () => {
|
||||
// // @ts-expect-error TS(2322): Type '{ size: string; isNeedFilter: boolean; value... Remove this comment to see the full error message
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="big" />);
|
||||
|
||||
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
// expect(wrapper.prop("size")).toEqual("big");
|
||||
// });
|
||||
|
||||
// // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
// it("huge size prop", () => {
|
||||
// // @ts-expect-error TS(2322): Type '{ size: string; isNeedFilter: boolean; value... Remove this comment to see the full error message
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="huge" />);
|
||||
|
||||
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
// expect(wrapper.prop("size")).toEqual("huge");
|
||||
// });
|
||||
|
||||
// // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
// it("accepts id", () => {
|
||||
// // @ts-expect-error TS(2322): Type '{ id: string; isNeedFilter: boolean; value: ... Remove this comment to see the full error message
|
||||
// const wrapper = mount(<SearchInput {...baseProps} id="testId" />);
|
||||
|
||||
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
// expect(wrapper.prop("id")).toEqual("testId");
|
||||
// });
|
||||
|
||||
// // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
// it("accepts className", () => {
|
||||
// // @ts-expect-error TS(2322): Type '{ className: string; isNeedFilter: boolean; ... Remove this comment to see the full error message
|
||||
// const wrapper = mount(<SearchInput {...baseProps} className="test" />);
|
||||
|
||||
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
// expect(wrapper.prop("className")).toEqual("test");
|
||||
// });
|
||||
|
||||
// // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
// it("accepts style", () => {
|
||||
// const wrapper = mount(
|
||||
// // @ts-expect-error TS(2322): Type '{ style: { color: string; }; isNeedFilter: b... Remove this comment to see the full error message
|
||||
// <SearchInput {...baseProps} style={{ color: "red" }} />,
|
||||
// );
|
||||
|
||||
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
// expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
|
||||
// });
|
||||
// // TODO: Fix icons tests
|
||||
// /*it("call onClearSearch", () => {
|
||||
// const onClearSearch = jest.fn();
|
||||
// const onChange = jest.fn();
|
||||
// const wrapper = mount(
|
||||
// <SearchInput
|
||||
// {...baseProps}
|
||||
// onClearSearch={onClearSearch}
|
||||
// onChange={onChange}
|
||||
// />
|
||||
// );
|
||||
|
||||
// wrapper
|
||||
// .find("input")
|
||||
// .first()
|
||||
// .simulate("change", { target: { value: "test" } });
|
||||
|
||||
// const icon = wrapper.find(".append div");
|
||||
// icon.first().simulate("click");
|
||||
// expect(onClearSearch).toHaveBeenCalled();
|
||||
// });
|
||||
// it("not call onClearSearch", () => {
|
||||
// const onClearSearch = jest.fn();
|
||||
// const onChange = jest.fn();
|
||||
// const wrapper = mount(<SearchInput {...baseProps} onChange={onChange} />);
|
||||
|
||||
// wrapper
|
||||
// .find("input")
|
||||
// .first()
|
||||
// .simulate("change", { target: { value: "test" } });
|
||||
|
||||
// const icon = wrapper.find(".append div");
|
||||
// icon.first().simulate("click");
|
||||
// expect(onClearSearch).not.toHaveBeenCalled();
|
||||
// });
|
||||
// it("componentDidUpdate() props lifecycle test", () => {
|
||||
// const wrapper = shallow(<SearchInput {...baseProps} />);
|
||||
// const instance = wrapper.instance();
|
||||
|
||||
// instance.componentDidUpdate(
|
||||
// {
|
||||
// opened: true,
|
||||
// selectedOption: {
|
||||
// value: "test",
|
||||
// },
|
||||
// },
|
||||
// wrapper.state()
|
||||
// );
|
||||
|
||||
// expect(wrapper.props()).toBe(wrapper.props());
|
||||
// });
|
||||
// it("not call setSearchTimer", (done) => {
|
||||
// const onChange = jest.fn();
|
||||
// const wrapper = mount(
|
||||
// <SearchInput {...baseProps} autoRefresh={false} onChange={onChange} />
|
||||
// );
|
||||
|
||||
// const input = wrapper.find("input");
|
||||
// input.first().simulate("change", { target: { value: "test" } });
|
||||
|
||||
// setTimeout(() => {
|
||||
// expect(onChange).not.toHaveBeenCalled();
|
||||
// done();
|
||||
// }, 1000);
|
||||
// });
|
||||
// it("call setSearchTimer", (done) => {
|
||||
// const onChange = jest.fn();
|
||||
// const wrapper = mount(<SearchInput {...baseProps} onChange={onChange} />);
|
||||
|
||||
// const instance = wrapper.instance();
|
||||
// instance.setSearchTimer("test");
|
||||
|
||||
// setTimeout(() => {
|
||||
// expect(onChange).toHaveBeenCalled();
|
||||
// done();
|
||||
// }, 1000);
|
||||
// });
|
||||
// it("test icon button size. base size prop", () => {
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="base" />);
|
||||
|
||||
// wrapper
|
||||
// .find("input")
|
||||
// .first()
|
||||
// .simulate("change", { target: { value: "test" } });
|
||||
|
||||
// const inputBlock = wrapper.find(InputBlock);
|
||||
// expect(inputBlock.prop("iconSize")).toEqual(12);
|
||||
// });
|
||||
// it("test icon button size. middle size prop", () => {
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="middle" />);
|
||||
|
||||
// wrapper
|
||||
// .find("input")
|
||||
// .first()
|
||||
// .simulate("change", { target: { value: "test" } });
|
||||
|
||||
// const inputBlock = wrapper.find(InputBlock);
|
||||
// expect(inputBlock.prop("iconSize")).toEqual(16);
|
||||
// });
|
||||
// it("test icon button size. big size prop", () => {
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="big" />);
|
||||
|
||||
// wrapper
|
||||
// .find("input")
|
||||
// .first()
|
||||
// .simulate("change", { target: { value: "test" } });
|
||||
|
||||
// const inputBlock = wrapper.find(InputBlock);
|
||||
// expect(inputBlock.prop("iconSize")).toEqual(19);
|
||||
// });
|
||||
// it("test icon button size. huge size prop", () => {
|
||||
// const wrapper = mount(<SearchInput {...baseProps} size="huge" />);
|
||||
|
||||
// wrapper
|
||||
// .find("input")
|
||||
// .first()
|
||||
// .simulate("change", { target: { value: "test" } });
|
||||
|
||||
// const inputBlock = wrapper.find(InputBlock);
|
||||
// expect(inputBlock.prop("iconSize")).toEqual(22);
|
||||
// });*/
|
||||
});
|
155
packages/shared/components/search-input/SearchInput.tsx
Normal file
155
packages/shared/components/search-input/SearchInput.tsx
Normal file
@ -0,0 +1,155 @@
|
||||
import React from "react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import CrossIconReactSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
|
||||
import SearchIconReactSvgUrl from "PUBLIC_DIR/images/search.react.svg?url";
|
||||
|
||||
import { InputBlock } from "../input-block";
|
||||
import { InputSize, InputType } from "../text-input";
|
||||
|
||||
import StyledSearchInput from "./SearchInput.styled";
|
||||
import { SearchInputProps } from "./SearchInput.types";
|
||||
|
||||
const SearchInput = ({
|
||||
forwardedRef,
|
||||
value,
|
||||
autoRefresh,
|
||||
refreshTimeout,
|
||||
showClearButton,
|
||||
onClearSearch,
|
||||
onChange,
|
||||
size,
|
||||
className,
|
||||
style,
|
||||
scale,
|
||||
onClick,
|
||||
id,
|
||||
name,
|
||||
isDisabled,
|
||||
placeholder,
|
||||
children,
|
||||
}: SearchInputProps) => {
|
||||
const timerId = React.useRef<null | ReturnType<typeof setTimeout>>(null);
|
||||
|
||||
const prevValue = React.useRef(value);
|
||||
|
||||
const [inputValue, setInputValue] = React.useState(value);
|
||||
|
||||
const onClearSearchAction = React.useCallback(() => {
|
||||
setInputValue("");
|
||||
onClearSearch?.();
|
||||
}, [onClearSearch]);
|
||||
|
||||
const setSearchTimer = React.useCallback(
|
||||
(v: string) => {
|
||||
if (timerId.current) clearTimeout(timerId.current);
|
||||
|
||||
timerId.current = setTimeout(() => {
|
||||
onChange?.(v);
|
||||
if (timerId.current) clearTimeout(timerId.current);
|
||||
timerId.current = null;
|
||||
}, refreshTimeout);
|
||||
},
|
||||
[onChange, refreshTimeout],
|
||||
);
|
||||
|
||||
const onInputChange = React.useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value);
|
||||
if (autoRefresh) setSearchTimer(e.target.value);
|
||||
},
|
||||
[autoRefresh, setSearchTimer],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (prevValue.current !== value) {
|
||||
prevValue.current = value;
|
||||
setInputValue(value);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
const getClearButtonSize = () => {
|
||||
let clearButtonSize = 16;
|
||||
|
||||
switch (size) {
|
||||
case InputSize.base:
|
||||
clearButtonSize = !!inputValue || showClearButton ? 12 : 16;
|
||||
break;
|
||||
case InputSize.middle:
|
||||
clearButtonSize = !!inputValue || showClearButton ? 16 : 18;
|
||||
break;
|
||||
case InputSize.big:
|
||||
clearButtonSize = !!inputValue || showClearButton ? 18 : 22;
|
||||
break;
|
||||
case InputSize.huge:
|
||||
clearButtonSize = !!inputValue || showClearButton ? 22 : 24;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return clearButtonSize;
|
||||
};
|
||||
|
||||
const getIconNode = () => {
|
||||
const showCrossIcon = !!inputValue || showClearButton;
|
||||
const iconNode = (
|
||||
<ReactSVG
|
||||
className="icon-button_svg not-selectable"
|
||||
src={showCrossIcon ? CrossIconReactSvgUrl : SearchIconReactSvgUrl}
|
||||
/>
|
||||
);
|
||||
|
||||
return iconNode;
|
||||
};
|
||||
|
||||
const clearButtonSize = getClearButtonSize();
|
||||
const iconNode = getIconNode();
|
||||
|
||||
return (
|
||||
<StyledSearchInput
|
||||
className={className}
|
||||
style={style}
|
||||
isScale={scale}
|
||||
data-testid="search-input"
|
||||
>
|
||||
<InputBlock
|
||||
className="search-input-block"
|
||||
forwardedRef={forwardedRef}
|
||||
onClick={onClick}
|
||||
id={id}
|
||||
name={name}
|
||||
isDisabled={isDisabled}
|
||||
type={InputType.text}
|
||||
iconNode={iconNode}
|
||||
iconButtonClassName={
|
||||
!!inputValue || showClearButton ? "search-cross" : "search-loupe"
|
||||
}
|
||||
isIconFill
|
||||
iconSize={clearButtonSize}
|
||||
onIconClick={
|
||||
!!inputValue || showClearButton ? onClearSearchAction : undefined
|
||||
}
|
||||
size={size}
|
||||
scale
|
||||
value={inputValue}
|
||||
placeholder={placeholder}
|
||||
onChange={onInputChange}
|
||||
>
|
||||
{children}
|
||||
</InputBlock>
|
||||
</StyledSearchInput>
|
||||
);
|
||||
};
|
||||
|
||||
SearchInput.defaultProps = {
|
||||
autoRefresh: true,
|
||||
value: "",
|
||||
scale: false,
|
||||
isDisabled: false,
|
||||
refreshTimeout: 1000,
|
||||
showClearButton: false,
|
||||
};
|
||||
|
||||
export { SearchInput };
|
39
packages/shared/components/search-input/SearchInput.types.ts
Normal file
39
packages/shared/components/search-input/SearchInput.types.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import React from "react";
|
||||
|
||||
import { InputSize } from "components/text-input";
|
||||
|
||||
export interface SearchInputProps {
|
||||
/** Used as HTML `id` property */
|
||||
id?: string;
|
||||
/** Forwarded ref */
|
||||
forwardedRef?: React.Ref<HTMLInputElement>;
|
||||
/** Sets the unique element name */
|
||||
name?: string;
|
||||
/** Accepts class */
|
||||
className?: string;
|
||||
/** Supported size of the input fields. */
|
||||
size: InputSize;
|
||||
/** Input value */
|
||||
value: string;
|
||||
/** Indicates that the input field has scale */
|
||||
scale?: boolean;
|
||||
/** Placeholder text for the input */
|
||||
placeholder?: string;
|
||||
/** Sets a callback function that allows handling the component's changing events */
|
||||
onChange?: (value: string) => void;
|
||||
/** Sets a callback function that is triggered when the clear icon of the search input is clicked */
|
||||
onClearSearch?: () => void;
|
||||
onClick?: (e: React.MouseEvent<HTMLInputElement>) => void;
|
||||
/** Indicates that the field cannot be used (e.g not authorized, or the changes have not been saved) */
|
||||
isDisabled?: boolean;
|
||||
/** Displays the Clear Button */
|
||||
showClearButton?: boolean;
|
||||
/** Sets the refresh timeout of the input */
|
||||
refreshTimeout?: number;
|
||||
/** Sets the input to refresh automatically */
|
||||
autoRefresh?: boolean;
|
||||
/** Child elements */
|
||||
children?: React.ReactNode;
|
||||
/** Accepts css style */
|
||||
style?: React.CSSProperties;
|
||||
}
|
@ -1,214 +1 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/cross.react.... Remove this comment to see the full error message
|
||||
import CrossIconReactSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
|
||||
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/search.react... Remove this comment to see the full error message
|
||||
import SearchIconReactSvgUrl from "PUBLIC_DIR/images/search.react.svg?url";
|
||||
import InputBlock from "../input-block";
|
||||
import StyledSearchInput from "./styled-search-input";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
class SearchInput extends React.Component {
|
||||
forwardedRef: any;
|
||||
timerId: any;
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.forwardedRef = props.forwardedRef || React.createRef();
|
||||
this.timerId = null;
|
||||
|
||||
this.state = {
|
||||
inputValue: props.value,
|
||||
};
|
||||
}
|
||||
|
||||
clearSearch = () => {
|
||||
this.setState({
|
||||
inputValue: "",
|
||||
});
|
||||
// @ts-expect-error TS(2339): Property 'onClearSearch' does not exist on type 'R... Remove this comment to see the full error message
|
||||
typeof this.props.onClearSearch === "function" &&
|
||||
// @ts-expect-error TS(2339): Property 'onClearSearch' does not exist on type 'R... Remove this comment to see the full error message
|
||||
this.props.onClearSearch();
|
||||
};
|
||||
|
||||
onInputChange = (e: any) => {
|
||||
this.setState({
|
||||
inputValue: e.target.value,
|
||||
});
|
||||
// @ts-expect-error TS(2339): Property 'autoRefresh' does not exist on type 'Rea... Remove this comment to see the full error message
|
||||
if (this.props.autoRefresh) this.setSearchTimer(e.target.value);
|
||||
};
|
||||
|
||||
setSearchTimer = (value: any) => {
|
||||
clearTimeout(this.timerId);
|
||||
this.timerId = setTimeout(() => {
|
||||
// @ts-expect-error TS(2339): Property 'onChange' does not exist on type 'Readon... Remove this comment to see the full error message
|
||||
this.props.onChange(value);
|
||||
clearTimeout(this.timerId);
|
||||
this.timerId = null;
|
||||
// @ts-expect-error TS(2339): Property 'refreshTimeout' does not exist on type '... Remove this comment to see the full error message
|
||||
}, this.props.refreshTimeout);
|
||||
};
|
||||
componentDidUpdate(prevProps: any) {
|
||||
// @ts-expect-error TS(2339): Property 'value' does not exist on type 'Readonly<... Remove this comment to see the full error message
|
||||
if (this.props.value != prevProps.value) {
|
||||
// @ts-expect-error TS(2339): Property 'value' does not exist on type 'Readonly<... Remove this comment to see the full error message
|
||||
this.setState({ inputValue: this.props.value });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
//console.log("Search input render");
|
||||
let clearButtonSize = 16;
|
||||
// @ts-expect-error TS(2339): Property 'size' does not exist on type 'Readonly<{... Remove this comment to see the full error message
|
||||
switch (this.props.size) {
|
||||
case "base":
|
||||
clearButtonSize =
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
!!this.state.inputValue || this.props.showClearButton ? 12 : 16;
|
||||
break;
|
||||
case "middle":
|
||||
clearButtonSize =
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
!!this.state.inputValue || this.props.showClearButton ? 16 : 18;
|
||||
break;
|
||||
case "big":
|
||||
clearButtonSize =
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
!!this.state.inputValue || this.props.showClearButton ? 18 : 22;
|
||||
break;
|
||||
case "huge":
|
||||
clearButtonSize =
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
!!this.state.inputValue || this.props.showClearButton ? 22 : 24;
|
||||
break;
|
||||
}
|
||||
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
const showCrossIcon = !!this.state.inputValue || this.props.showClearButton;
|
||||
|
||||
const iconNode = (
|
||||
<>
|
||||
{showCrossIcon && (
|
||||
<ReactSVG
|
||||
className="icon-button_svg not-selectable"
|
||||
src={CrossIconReactSvgUrl}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!showCrossIcon && (
|
||||
<ReactSVG
|
||||
className="icon-button_svg not-selectable"
|
||||
src={SearchIconReactSvgUrl}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledSearchInput
|
||||
// @ts-expect-error TS(2339): Property 'theme' does not exist on type 'Readonly<... Remove this comment to see the full error message
|
||||
theme={this.props.theme}
|
||||
// @ts-expect-error TS(2339): Property 'className' does not exist on type 'Reado... Remove this comment to see the full error message
|
||||
className={this.props.className}
|
||||
// @ts-expect-error TS(2339): Property 'style' does not exist on type 'Readonly<... Remove this comment to see the full error message
|
||||
style={this.props.style}
|
||||
// @ts-expect-error TS(2769): No overload matches this call.
|
||||
isScale={this.props.scale}
|
||||
>
|
||||
// @ts-expect-error TS(2322): Type '{ children: any; theme: any; className: stri... Remove this comment to see the full error message
|
||||
<InputBlock
|
||||
// @ts-expect-error TS(2339): Property 'theme' does not exist on type 'Readonly<... Remove this comment to see the full error message
|
||||
theme={this.props.theme}
|
||||
className="search-input-block"
|
||||
forwardedRef={this.forwardedRef}
|
||||
// @ts-expect-error TS(2339): Property 'onClick' does not exist on type 'Readonl... Remove this comment to see the full error message
|
||||
onClick={this.props.onClick}
|
||||
// @ts-expect-error TS(2339): Property 'id' does not exist on type 'Readonly<{}>... Remove this comment to see the full error message
|
||||
id={this.props.id}
|
||||
// @ts-expect-error TS(2339): Property 'name' does not exist on type 'Readonly<{... Remove this comment to see the full error message
|
||||
name={this.props.name}
|
||||
// @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
isDisabled={this.props.isDisabled}
|
||||
iconNode={iconNode}
|
||||
iconButtonClassName={
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
!!this.state.inputValue || this.props.showClearButton
|
||||
? "search-cross"
|
||||
: "search-loupe"
|
||||
}
|
||||
isIconFill={true}
|
||||
iconSize={clearButtonSize}
|
||||
onIconClick={
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
!!this.state.inputValue || this.props.showClearButton
|
||||
? this.clearSearch
|
||||
: undefined
|
||||
}
|
||||
// @ts-expect-error TS(2339): Property 'size' does not exist on type 'Readonly<{... Remove this comment to see the full error message
|
||||
size={this.props.size}
|
||||
scale={true}
|
||||
// @ts-expect-error TS(2339): Property 'inputValue' does not exist on type 'Read... Remove this comment to see the full error message
|
||||
value={this.state.inputValue}
|
||||
// @ts-expect-error TS(2339): Property 'placeholder' does not exist on type 'Rea... Remove this comment to see the full error message
|
||||
placeholder={this.props.placeholder}
|
||||
onChange={this.onInputChange}
|
||||
>
|
||||
// @ts-expect-error TS(2339): Property 'children' does not exist on type 'Readon... Remove this comment to see the full error message
|
||||
{this.props.children}
|
||||
</InputBlock>
|
||||
</StyledSearchInput>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error TS(2339): Property 'propTypes' does not exist on type 'typeo... Remove this comment to see the full error message
|
||||
SearchInput.propTypes = {
|
||||
/** Used as HTML `id` property */
|
||||
id: PropTypes.string,
|
||||
/** Forwarded ref */
|
||||
forwardedRef: PropTypes.object,
|
||||
/** Sets the unique element name */
|
||||
name: PropTypes.string,
|
||||
/** Accepts class */
|
||||
className: PropTypes.string,
|
||||
/** Supported size of the input fields. */
|
||||
size: PropTypes.oneOf(["base", "middle", "big", "huge"]),
|
||||
/** Input value */
|
||||
value: PropTypes.string,
|
||||
/** Indicates that the input field has scale */
|
||||
scale: PropTypes.bool,
|
||||
/** Placeholder text for the input */
|
||||
placeholder: PropTypes.string,
|
||||
/** Sets a callback function that allows handling the component's changing events */
|
||||
onChange: PropTypes.func,
|
||||
/** Sets a callback function that is triggered when the clear icon of the search input is clicked */
|
||||
onClearSearch: PropTypes.func,
|
||||
/** Indicates that the field cannot be used (e.g not authorized, or the changes have not been saved) */
|
||||
isDisabled: PropTypes.bool,
|
||||
/** Displays the Clear Button */
|
||||
showClearButton: PropTypes.bool,
|
||||
/** Sets the refresh timeout of the input */
|
||||
refreshTimeout: PropTypes.number,
|
||||
/** Sets the input to refresh automatically */
|
||||
autoRefresh: PropTypes.bool,
|
||||
/** Child elements */
|
||||
children: PropTypes.any,
|
||||
/** Accepts css style */
|
||||
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||
};
|
||||
|
||||
// @ts-expect-error TS(2339): Property 'defaultProps' does not exist on type 'ty... Remove this comment to see the full error message
|
||||
SearchInput.defaultProps = {
|
||||
autoRefresh: true,
|
||||
size: "base",
|
||||
value: "",
|
||||
scale: false,
|
||||
isDisabled: false,
|
||||
refreshTimeout: 1000,
|
||||
showClearButton: false,
|
||||
};
|
||||
|
||||
export default SearchInput;
|
||||
export { SearchInput } from "./SearchInput";
|
||||
|
@ -1,48 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import SearchInput from ".";
|
||||
import Button from "../button";
|
||||
|
||||
export default {
|
||||
title: "Components/SearchInput",
|
||||
component: SearchInput,
|
||||
parameters: {
|
||||
design: {
|
||||
type: "figma",
|
||||
url: "https://www.figma.com/file/ZiW5KSwb4t7Tj6Nz5TducC/UI-Kit-DocSpace-1.0.0?type=design&node-id=58-2238&mode=design&t=TBNCKMQKQMxr44IZ-0",
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
onChange: { action: "onChange" },
|
||||
},
|
||||
};
|
||||
|
||||
const Template = ({
|
||||
value,
|
||||
onChange,
|
||||
...args
|
||||
}: any) => {
|
||||
const [searchValue, setSearchValue] = useState(value);
|
||||
|
||||
return <>
|
||||
<SearchInput
|
||||
{...args}
|
||||
style={{ width: "20%" }}
|
||||
value={searchValue}
|
||||
onChange={(value: any) => {
|
||||
onChange(value);
|
||||
setSearchValue(value);
|
||||
}}
|
||||
/>
|
||||
</>;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
// @ts-expect-error TS(2339): Property 'args' does not exist on type '({ value, ... Remove this comment to see the full error message
|
||||
Default.args = {
|
||||
id: "",
|
||||
isDisabled: false,
|
||||
size: "base",
|
||||
scale: false,
|
||||
placeholder: "Search",
|
||||
value: "",
|
||||
};
|
@ -1,207 +0,0 @@
|
||||
import React from "react";
|
||||
// @ts-expect-error TS(7016): Could not find a declaration file for module 'enzy... Remove this comment to see the full error message
|
||||
import { mount, shallow } from "enzyme";
|
||||
import SearchInput from ".";
|
||||
import InputBlock from "../input-block";
|
||||
|
||||
const baseProps = {
|
||||
isNeedFilter: true,
|
||||
value: "",
|
||||
getFilterData: () => [
|
||||
{
|
||||
key: "filter-example",
|
||||
group: "filter-example",
|
||||
label: "example group",
|
||||
isHeader: true,
|
||||
},
|
||||
{ key: "filter-example-test", group: "filter-example", label: "Test" },
|
||||
],
|
||||
};
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'describe'. Do you need to instal... Remove this comment to see the full error message
|
||||
describe("<SearchInput />", () => {
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("renders without error", () => {
|
||||
const wrapper = mount(<SearchInput {...baseProps} />);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper).toExist();
|
||||
});
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("middle size prop", () => {
|
||||
// @ts-expect-error TS(2322): Type '{ size: string; isNeedFilter: boolean; value... Remove this comment to see the full error message
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="middle" />);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper.prop("size")).toEqual("middle");
|
||||
});
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("big size prop", () => {
|
||||
// @ts-expect-error TS(2322): Type '{ size: string; isNeedFilter: boolean; value... Remove this comment to see the full error message
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="big" />);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper.prop("size")).toEqual("big");
|
||||
});
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("huge size prop", () => {
|
||||
// @ts-expect-error TS(2322): Type '{ size: string; isNeedFilter: boolean; value... Remove this comment to see the full error message
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="huge" />);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper.prop("size")).toEqual("huge");
|
||||
});
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("accepts id", () => {
|
||||
// @ts-expect-error TS(2322): Type '{ id: string; isNeedFilter: boolean; value: ... Remove this comment to see the full error message
|
||||
const wrapper = mount(<SearchInput {...baseProps} id="testId" />);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper.prop("id")).toEqual("testId");
|
||||
});
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("accepts className", () => {
|
||||
// @ts-expect-error TS(2322): Type '{ className: string; isNeedFilter: boolean; ... Remove this comment to see the full error message
|
||||
const wrapper = mount(<SearchInput {...baseProps} className="test" />);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper.prop("className")).toEqual("test");
|
||||
});
|
||||
|
||||
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
|
||||
it("accepts style", () => {
|
||||
const wrapper = mount(
|
||||
// @ts-expect-error TS(2322): Type '{ style: { color: string; }; isNeedFilter: b... Remove this comment to see the full error message
|
||||
<SearchInput {...baseProps} style={{ color: "red" }} />
|
||||
);
|
||||
|
||||
// @ts-expect-error TS(2304): Cannot find name 'expect'.
|
||||
expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
|
||||
});
|
||||
// TODO: Fix icons tests
|
||||
/*it("call onClearSearch", () => {
|
||||
const onClearSearch = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<SearchInput
|
||||
{...baseProps}
|
||||
onClearSearch={onClearSearch}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find("input")
|
||||
.first()
|
||||
.simulate("change", { target: { value: "test" } });
|
||||
|
||||
const icon = wrapper.find(".append div");
|
||||
icon.first().simulate("click");
|
||||
expect(onClearSearch).toHaveBeenCalled();
|
||||
});
|
||||
it("not call onClearSearch", () => {
|
||||
const onClearSearch = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<SearchInput {...baseProps} onChange={onChange} />);
|
||||
|
||||
wrapper
|
||||
.find("input")
|
||||
.first()
|
||||
.simulate("change", { target: { value: "test" } });
|
||||
|
||||
const icon = wrapper.find(".append div");
|
||||
icon.first().simulate("click");
|
||||
expect(onClearSearch).not.toHaveBeenCalled();
|
||||
});
|
||||
it("componentDidUpdate() props lifecycle test", () => {
|
||||
const wrapper = shallow(<SearchInput {...baseProps} />);
|
||||
const instance = wrapper.instance();
|
||||
|
||||
instance.componentDidUpdate(
|
||||
{
|
||||
opened: true,
|
||||
selectedOption: {
|
||||
value: "test",
|
||||
},
|
||||
},
|
||||
wrapper.state()
|
||||
);
|
||||
|
||||
expect(wrapper.props()).toBe(wrapper.props());
|
||||
});
|
||||
it("not call setSearchTimer", (done) => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<SearchInput {...baseProps} autoRefresh={false} onChange={onChange} />
|
||||
);
|
||||
|
||||
const input = wrapper.find("input");
|
||||
input.first().simulate("change", { target: { value: "test" } });
|
||||
|
||||
setTimeout(() => {
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
it("call setSearchTimer", (done) => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<SearchInput {...baseProps} onChange={onChange} />);
|
||||
|
||||
const instance = wrapper.instance();
|
||||
instance.setSearchTimer("test");
|
||||
|
||||
setTimeout(() => {
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
it("test icon button size. base size prop", () => {
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="base" />);
|
||||
|
||||
wrapper
|
||||
.find("input")
|
||||
.first()
|
||||
.simulate("change", { target: { value: "test" } });
|
||||
|
||||
const inputBlock = wrapper.find(InputBlock);
|
||||
expect(inputBlock.prop("iconSize")).toEqual(12);
|
||||
});
|
||||
it("test icon button size. middle size prop", () => {
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="middle" />);
|
||||
|
||||
wrapper
|
||||
.find("input")
|
||||
.first()
|
||||
.simulate("change", { target: { value: "test" } });
|
||||
|
||||
const inputBlock = wrapper.find(InputBlock);
|
||||
expect(inputBlock.prop("iconSize")).toEqual(16);
|
||||
});
|
||||
it("test icon button size. big size prop", () => {
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="big" />);
|
||||
|
||||
wrapper
|
||||
.find("input")
|
||||
.first()
|
||||
.simulate("change", { target: { value: "test" } });
|
||||
|
||||
const inputBlock = wrapper.find(InputBlock);
|
||||
expect(inputBlock.prop("iconSize")).toEqual(19);
|
||||
});
|
||||
it("test icon button size. huge size prop", () => {
|
||||
const wrapper = mount(<SearchInput {...baseProps} size="huge" />);
|
||||
|
||||
wrapper
|
||||
.find("input")
|
||||
.first()
|
||||
.simulate("change", { target: { value: "test" } });
|
||||
|
||||
const inputBlock = wrapper.find(InputBlock);
|
||||
expect(inputBlock.prop("iconSize")).toEqual(22);
|
||||
});*/
|
||||
});
|
Loading…
Reference in New Issue
Block a user