Shared:Components:DatePicker: rewrite to typescript

This commit is contained in:
Timofey Boyko 2023-12-25 11:08:54 +03:00
parent 1e47de32ff
commit 37e09ba0ee
10 changed files with 540 additions and 559 deletions

View File

@ -1,300 +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 DatePicker from "./";
import NewCalendar from "../calendar";
import InputBlock from "../input-block";
import moment from "moment";
const selectedDate = new Date("09/12/2019");
const minDate = new Date("01/01/1970");
const maxDate = new Date("01/01/2020");
// @ts-expect-error TS(2582): Cannot find name 'describe'. Do you need to instal... Remove this comment to see the full error message
describe("DatePicker tests", () => {
// @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("DatePicker renders without error", () => {
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{}' but re... Remove this comment to see the full error message
const wrapper = mount(<DatePicker />);
// @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("DatePicker disabled when isDisabled is passed", () => {
// @ts-expect-error TS(2322): Type '{ isDisabled: boolean; }' is not assignable ... Remove this comment to see the full error message
const wrapper = mount(<DatePicker isDisabled={true} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("isDisabled")).toEqual(true);
});
// @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("DatePicker opened when inOpen is passed", () => {
// @ts-expect-error TS(2322): Type '{ inOpen: boolean; }' is not assignable to t... Remove this comment to see the full error message
const wrapper = mount(<DatePicker inOpen={true} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("inOpen")).toEqual(true);
});
// @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("DatePicker has rendered content NewCalendar", () => {
// @ts-expect-error TS(2322): Type '{ inOpen: boolean; }' is not assignable to t... Remove this comment to see the full error message
const wrapper = mount(<DatePicker inOpen={true} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper).toExist(<NewCalendar />);
});
// @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("DatePicker has rendered content InputBlock", () => {
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{}' but re... Remove this comment to see the full error message
const wrapper = mount(<DatePicker />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper).toExist(<InputBlock />);
});
// @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("DatePicker hasError is passed", () => {
// @ts-expect-error TS(2322): Type '{ hasError: boolean; }' is not assignable to... Remove this comment to see the full error message
const wrapper = mount(<DatePicker hasError={true} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("hasError")).toEqual(true);
});
// @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("DatePicker disabled when isReadOnly is passed", () => {
// @ts-expect-error TS(2322): Type '{ isReadOnly: boolean; }' is not assignable ... Remove this comment to see the full error message
const wrapper = mount(<DatePicker isReadOnly={true} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("isReadOnly")).toEqual(true);
});
// @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("DatePicker minDate test", () => {
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ minDate:... Remove this comment to see the full error message
const wrapper = mount(<DatePicker minDate={minDate} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().minDate).toEqual(minDate);
});
// @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("DatePicker maxDate test", () => {
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ maxDate:... Remove this comment to see the full error message
const wrapper = mount(<DatePicker maxDate={maxDate} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().maxDate).toEqual(maxDate);
});
// @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("DatePicker selectedDate test", () => {
// @ts-expect-error TS(2322): Type '{ selectedDate: Date; }' is not assignable t... Remove this comment to see the full error message
const wrapper = mount(<DatePicker selectedDate={selectedDate} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().selectedDate).toEqual(selectedDate);
});
// @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("DatePicker themeColor test", () => {
// @ts-expect-error TS(2322): Type '{ themeColor: string; }' is not assignable t... Remove this comment to see the full error message
const wrapper = mount(<DatePicker themeColor={"#fff"} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().themeColor).toEqual("#fff");
});
// @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("DatePicker input mask test", () => {
const mask = [/\d/, /\d/, "/", /\d/, /\d/, "/", /\d/, /\d/, /\d/, /\d/];
// @ts-expect-error TS(2322): Type '{ mask: (string | RegExp)[]; }' is not assig... Remove this comment to see the full error message
const wrapper = mount(<InputBlock mask={mask} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().mask).toBe(mask);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().mask).toEqual(mask);
});
// @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("DatePicker locale test", () => {
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ locale: ... Remove this comment to see the full error message
const wrapper = mount(<DatePicker locale={"en-GB"} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("locale")).toEqual("en-GB");
});
// @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("DatePicker input value with locale test", () => {
moment.locale("ru");
const value = moment(selectedDate).format("L");
// @ts-expect-error TS(2322): Type '{ value: string; }' is not assignable to typ... Remove this comment to see the full error message
const wrapper = mount(<DatePicker value={value} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props().value).toEqual("12.09.2019");
});
// @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("DatePicker check the onChange callback", () => {
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
const onChange = jest.fn();
const props = {
value: "03/03/2000",
onChange,
};
const wrapper = mount(<DatePicker {...props} />).find("input");
wrapper.simulate("change", { target: { value: "09/09/2019" } });
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(onChange).toHaveBeenCalledWith(new Date("09/09/2019"));
});
/*it("check DatePicker popup open", () => {
const onFocus = jest.fn(() => true);
const wrapper = mount(<DatePicker onFocus={onFocus} isOpen={false} />);
const input = wrapper.find("input");
input.simulate("focus");
const instance = wrapper.instance();
expect(instance.state.isOpen).toEqual(true);
});*/
// @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("DatePicker check the Calendar onChange callback", () => {
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
const onChange = jest.fn();
const props = {
value: "03/03/2000",
isOpen: true,
onChange,
};
const wrapper = mount(<DatePicker {...props} />);
const days = wrapper.find(".calendar-month");
days.first().simulate("click", { target: { value: 1 } });
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(onChange).toHaveBeenCalled();
});
// @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("DatePicker check Compare date function", () => {
const date = new Date();
const errorDate = new Date("01/01/3000");
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{}' but re... Remove this comment to see the full error message
const wrapper = shallow(<DatePicker />).instance();
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.compareDate(date)).toEqual(true);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.compareDate(errorDate)).toEqual(false);
});
// @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("DatePicker check Compare dates function", () => {
const date = new Date();
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{}' but re... Remove this comment to see the full error message
const wrapper = shallow(<DatePicker />).instance();
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.compareDates(date, date) === 0).toEqual(true);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.compareDates(date, new Date("01/01/2000")) === 0).toEqual(
false
);
});
// @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("DatePicker check is valid dates function", () => {
var date = new Date();
date.setFullYear(1);
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{}' but re... Remove this comment to see the full error message
const wrapper = shallow(<DatePicker />).instance();
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.isValidDate(selectedDate, maxDate, minDate, false)).toEqual(
false
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.isValidDate(date, maxDate, minDate, false)).toEqual(true);
});
// @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("DatePicker componentDidUpdate() lifecycle test", () => {
const props = {
selectedDate: new Date(),
minDate: new Date("01/01/1970"),
maxDate: new Date("01/01/2030"),
isOpen: true,
isDisabled: false,
isReadOnly: false,
hasError: false,
themeColor: "#ED7309",
locale: "en",
};
var date = new Date();
date.setFullYear(1);
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ selected... Remove this comment to see the full error message
const wrapper = mount(<DatePicker {...props} />).instance();
wrapper.componentDidUpdate(wrapper.props, wrapper.state);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props).toBe(wrapper.props);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.state).toBe(wrapper.state);
const wrapper2 = mount(
<DatePicker
{...props}
// @ts-expect-error TS(2322): Type '{ selectedDate: Date; hasError: boolean; siz... Remove this comment to see the full error message
selectedDate={date}
hasError={false}
size="big"
isDisabled={false}
/>
).instance();
wrapper2.componentDidUpdate(wrapper2.props, wrapper2.state);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper2.props).toBe(wrapper2.props);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper2.state).toBe(wrapper2.state);
});
// @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("componentWillUnmount() lifecycle test", () => {
// @ts-expect-error TS(2322): Type '{ isOpen: boolean; }' is not assignable to t... Remove this comment to see the full error message
const wrapper = mount(<DatePicker isOpen={true} />);
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
const componentWillUnmount = jest.spyOn(
wrapper.instance(),
"componentWillUnmount"
);
wrapper.unmount();
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(componentWillUnmount).toHaveBeenCalled();
});
// @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 '{ isOpen: boolean; id: string; }' is not ass... Remove this comment to see the full error message
const wrapper = mount(<DatePicker isOpen={true} 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 '{ isOpen: boolean; className: string; }' is ... Remove this comment to see the full error message
const wrapper = mount(<DatePicker isOpen={true} 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 '{ isOpen: boolean; style: { color: string; }... Remove this comment to see the full error message
<DatePicker isOpen={true} style={{ color: "red" }} />
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
});
});

View File

@ -1,240 +0,0 @@
import React, { useRef, useState, useEffect } from "react";
import moment from "moment";
import styled, { css } from "styled-components";
import PropTypes from "prop-types";
import Text from "../text";
import SelectorAddButton from "../selector-add-button";
import SelectedItem from "../selected-item";
import Calendar from "../calendar";
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/calendar.rea... Remove this comment to see the full error message
import CalendarIconUrl from "PUBLIC_DIR/images/calendar.react.svg?url";
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/calendar.rea... Remove this comment to see the full error message
import CalendarIcon from "PUBLIC_DIR/images/calendar.react.svg";
import { mobile } from "../utils/device";
const Wrapper = styled.div`
.selectedItem {
cursor: pointer;
.calendarIcon {
width: 12px;
height: 12px;
padding: 0 10px 0 2px;
path {
fill: #657077;
}
}
}
`;
const DateSelector = styled.div`
width: fit-content;
cursor: pointer;
display: flex;
align-items: center;
.mr-8 {
margin-right: 8px;
${(props) =>
props.theme.interfaceDirection === "rtl" &&
css`
margin-right: 0px;
margin-left: 8px;
`}
}
`;
const SelectedLabel = styled.span`
display: flex;
align-items: center;
`;
const StyledCalendar = styled(Calendar)`
position: absolute;
@media ${mobile} {
position: fixed;
bottom: 0;
left: 0;
}
`;
const DatePicker = (props: any) => {
const {
initialDate,
onChange,
selectDateText,
className,
id,
minDate,
maxDate,
locale,
showCalendarIcon,
outerDate,
openDate,
isMobile,
} = props;
const calendarRef = useRef();
const selectorRef = useRef();
const selectedItemRef = useRef();
const [date, setDate] = useState(initialDate ? moment(initialDate) : null);
const [isCalendarOpen, setIsCalendarOpen] = useState(false);
const toggleCalendar = () =>
setIsCalendarOpen((prevIsCalendarOpen) => !prevIsCalendarOpen);
const closeCalendar = () => {
setIsCalendarOpen(false);
};
const handleChange = (date: any) => {
onChange && onChange(date);
setDate(date);
closeCalendar();
};
const deleteSelectedDate = (propKey: any, label: any, group: any, e: any) => {
e.stopPropagation();
handleChange(null);
setIsCalendarOpen(false);
};
const CalendarElement = () => (
<StyledCalendar
isMobile={isMobile}
selectedDate={date}
setSelectedDate={handleChange}
onChange={closeCalendar}
forwardedRef={calendarRef}
minDate={minDate}
maxDate={maxDate}
locale={locale}
initialDate={openDate}
/>
);
const handleClick = (e: any) => {
if (
e.target.classList.contains("nav-thumb-vertical") ||
e.target.classList.contains("nav-thumb-horizontal")
) {
return;
}
// @ts-expect-error TS(2339): Property 'contains' does not exist on type 'never'... Remove this comment to see the full error message
!selectorRef?.current?.contains(e.target) &&
// @ts-expect-error TS(2339): Property 'contains' does not exist on type 'never'... Remove this comment to see the full error message
!calendarRef?.current?.contains(e.target) &&
// @ts-expect-error TS(2339): Property 'contains' does not exist on type 'never'... Remove this comment to see the full error message
!selectedItemRef?.current?.contains(e.target) &&
setIsCalendarOpen(false);
};
useEffect(() => {
document.addEventListener("mousedown", handleClick, { capture: true });
return () =>
document.removeEventListener("mousedown", handleClick, { capture: true });
}, []);
useEffect(() => {
if (
outerDate &&
moment(outerDate).format("YYYY-MM-D HH:mm") !==
moment(date).format("YYYY-MM-D HH:mm")
) {
setDate(outerDate);
}
}, [outerDate]);
return (
<Wrapper className={className} id={id}>
{!date ? (
<>
// @ts-expect-error TS(2769): No overload matches this call.
<DateSelector onClick={toggleCalendar} ref={selectorRef}>
<SelectorAddButton
title={selectDateText}
className="mr-8 add-delivery-date-button"
iconName={CalendarIconUrl}
/>
// @ts-expect-error TS(2322): Type '{ children: any; isInline: true; fontWeight:... Remove this comment to see the full error message
<Text isInline fontWeight={600} color="#A3A9AE">
{selectDateText}
</Text>
</DateSelector>
</>
) : (
<SelectedItem
className="selectedItem"
onClose={deleteSelectedDate}
label={
showCalendarIcon ? (
<SelectedLabel>
<CalendarIcon className="calendarIcon" />
{date.format("DD MMM YYYY")}
</SelectedLabel>
) : (
date.format("DD MMM YYYY")
)
}
onClick={toggleCalendar}
forwardedRef={selectedItemRef}
/>
)}
{isCalendarOpen && <CalendarElement />}
</Wrapper>
);
};
DatePicker.propTypes = {
/** Allows to change select date text */
selectDateText: PropTypes.string,
/** Selected date */
initialDate: PropTypes.oneOfType([
PropTypes.object,
PropTypes.string,
PropTypes.number,
]),
/** Allow you to handle changing events of component */
onChange: PropTypes.func.isRequired,
/** Allows to set classname */
className: PropTypes.string,
/** Allows to set id */
id: PropTypes.string,
/** Specifies min choosable calendar date */
minDate: PropTypes.oneOfType([
PropTypes.object,
PropTypes.string,
PropTypes.number,
]),
/** Specifies max choosable calendar date */
maxDate: PropTypes.oneOfType([
PropTypes.object,
PropTypes.string,
PropTypes.number,
]),
/** Specifies calendar locale */
locale: PropTypes.string,
/** Shows calendar icon in selected item */
showCalendarIcon: PropTypes.bool,
/** Allows to track date outside the component */
outerDate: PropTypes.object,
/** Allows to set first shown date in calendar */
openDate: PropTypes.oneOfType([
PropTypes.object,
PropTypes.string,
PropTypes.number,
]),
};
DatePicker.defaultProps = {
selectDateText: "Select date",
showCalendarIcon: true,
};
export default DatePicker;

View File

@ -1,7 +1,11 @@
import React from "react";
import DatePicker from "./";
import moment from "moment";
import { StoryObj, Meta } from "@storybook/react";
import styled from "styled-components";
import { DatePicker } from "./DatePicker";
import { DatePickerProps } from "./DatePicker.types";
const locales = [
"az",
"ar-SA",
@ -31,7 +35,7 @@ const locales = [
"vi",
];
export default {
const meta = {
title: "Components/DatePicker",
component: DatePicker,
@ -54,27 +58,31 @@ export default {
url: "https://www.figma.com/file/9AtdOHnhjhZCIRDrj4Unta/Public-room?type=design&node-id=1846-218508&mode=design&t=xSsXehQdoxpp5o7F-4",
},
},
};
} satisfies Meta<typeof DatePicker>;
type Story = StoryObj<typeof meta>;
export default meta;
const Wrapper = styled.div`
height: 500px;
`;
const Template = ({ ...args }) => {
const Template = ({ ...args }: DatePickerProps) => {
return (
<Wrapper>
// @ts-expect-error TS(2741): Property 'onChange' is missing in type '{}' but re... Remove this comment to see the full error message
<DatePicker {...args} />
</Wrapper>
);
};
export const Default = Template.bind({});
// @ts-expect-error TS(2339): Property 'args' does not exist on type '({ ...args... Remove this comment to see the full error message
Default.args = {
maxDate: new Date(new Date().getFullYear() + 10 + "/01/01"),
export const Default: Story = {
render: (args) => <Template {...args} />,
args: {
maxDate: new Date(`${new Date().getFullYear() + 10}/01/01`),
minDate: new Date("1970/01/01"),
openDate: new Date(),
initialDate: null,
openDate: moment(),
initialDate: moment(),
onChange: () => {},
locale: "en",
},
};

View File

@ -1,6 +1,8 @@
import styled from "styled-components";
import Base from "../themes/base";
import { mobile } from "../utils/device";
import styled, { css } from "styled-components";
import { Base } from "../../themes";
import { mobile } from "../../utils";
import { Calendar } from "../calendar";
const DateInputStyle = styled.div`
width: ${(props) => props.theme.datePicker.width};
@ -70,4 +72,61 @@ const Body = styled.div`
`;
Body.defaultProps = { theme: Base };
export { Body, Header, Content, DropDownStyle, DateInputStyle };
const Wrapper = styled.div`
.selectedItem {
cursor: pointer;
.calendarIcon {
width: 12px;
height: 12px;
padding: 0 10px 0 2px;
path {
fill: #657077;
}
}
}
`;
const DateSelector = styled.div`
width: fit-content;
cursor: pointer;
display: flex;
align-items: center;
.mr-8 {
margin-right: 8px;
${(props) =>
props.theme.interfaceDirection === "rtl" &&
css`
margin-right: 0px;
margin-left: 8px;
`}
}
`;
const SelectedLabel = styled.span`
display: flex;
align-items: center;
`;
const StyledCalendar = styled(Calendar)`
position: absolute;
@media ${mobile} {
position: fixed;
bottom: 0;
left: 0;
}
`;
export {
Body,
Header,
Content,
DropDownStyle,
DateInputStyle,
Wrapper,
SelectedLabel,
StyledCalendar,
DateSelector,
};

View File

@ -0,0 +1,275 @@
import React from "react";
import moment from "moment";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { DatePicker } from "./DatePicker";
// import { Calendar } from "../calendar";
// import { InputBlock } from "../input-block";
const selectedDate = new Date("09/12/2019");
const minDate = new Date("01/01/1970");
const maxDate = new Date("01/01/2020");
describe("DatePicker tests", () => {
it("DatePicker renders without error", () => {
render(
<DatePicker
minDate={minDate}
maxDate={maxDate}
selectDateText="Select date"
initialDate={selectedDate}
onChange={() => {}}
locale="en"
openDate={moment()}
/>,
);
expect(screen.getByTestId("date-picker")).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("DatePicker disabled when isDisabled is passed", () => {
// // @ts-expect-error TS(2322): Type '{ isDisabled: boolean; }' is not assignable ... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker isDisabled={true} />);
// expect(wrapper.prop("isDisabled")).toEqual(true);
// });
// // @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("DatePicker opened when inOpen is passed", () => {
// // @ts-expect-error TS(2322): Type '{ inOpen: boolean; }' is not assignable to t... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker inOpen={true} />);
// expect(wrapper.prop("inOpen")).toEqual(true);
// });
// // @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("DatePicker has rendered content NewCalendar", () => {
// // @ts-expect-error TS(2322): Type '{ inOpen: boolean; }' is not assignable to t... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker inOpen={true} />);
// expect(wrapper).toExist(<NewCalendar />);
// });
// // @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("DatePicker has rendered content InputBlock", () => {
// const wrapper = mount(<DatePicker />);
// expect(wrapper).toExist(<InputBlock />);
// });
// // @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("DatePicker hasError is passed", () => {
// // @ts-expect-error TS(2322): Type '{ hasError: boolean; }' is not assignable to... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker hasError={true} />);
// expect(wrapper.prop("hasError")).toEqual(true);
// });
// // @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("DatePicker disabled when isReadOnly is passed", () => {
// // @ts-expect-error TS(2322): Type '{ isReadOnly: boolean; }' is not assignable ... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker isReadOnly={true} />);
// expect(wrapper.prop("isReadOnly")).toEqual(true);
// });
// // @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("DatePicker minDate test", () => {
// // @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ minDate:... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker minDate={minDate} />);
// expect(wrapper.props().minDate).toEqual(minDate);
// });
// // @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("DatePicker maxDate test", () => {
// // @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ maxDate:... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker maxDate={maxDate} />);
// expect(wrapper.props().maxDate).toEqual(maxDate);
// });
// // @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("DatePicker selectedDate test", () => {
// // @ts-expect-error TS(2322): Type '{ selectedDate: Date; }' is not assignable t... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker selectedDate={selectedDate} />);
// expect(wrapper.props().selectedDate).toEqual(selectedDate);
// });
// // @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("DatePicker themeColor test", () => {
// // @ts-expect-error TS(2322): Type '{ themeColor: string; }' is not assignable t... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker themeColor={"#fff"} />);
// expect(wrapper.props().themeColor).toEqual("#fff");
// });
// // @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("DatePicker input mask test", () => {
// const mask = [/\d/, /\d/, "/", /\d/, /\d/, "/", /\d/, /\d/, /\d/, /\d/];
// // @ts-expect-error TS(2322): Type '{ mask: (string | RegExp)[]; }' is not assig... Remove this comment to see the full error message
// const wrapper = mount(<InputBlock mask={mask} />);
// expect(wrapper.props().mask).toBe(mask);
// expect(wrapper.props().mask).toEqual(mask);
// });
// // @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("DatePicker locale test", () => {
// // @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ locale: ... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker locale={"en-GB"} />);
// expect(wrapper.prop("locale")).toEqual("en-GB");
// });
// // @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("DatePicker input value with locale test", () => {
// moment.locale("ru");
// const value = moment(selectedDate).format("L");
// // @ts-expect-error TS(2322): Type '{ value: string; }' is not assignable to typ... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker value={value} />);
// expect(wrapper.props().value).toEqual("12.09.2019");
// });
// // @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("DatePicker check the onChange callback", () => {
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// const onChange = jest.fn();
// const props = {
// value: "03/03/2000",
// onChange,
// };
// const wrapper = mount(<DatePicker {...props} />).find("input");
// wrapper.simulate("change", { target: { value: "09/09/2019" } });
// expect(onChange).toHaveBeenCalledWith(new Date("09/09/2019"));
// });
// /*it("check DatePicker popup open", () => {
// const onFocus = jest.fn(() => true);
// const wrapper = mount(<DatePicker onFocus={onFocus} isOpen={false} />);
// const input = wrapper.find("input");
// input.simulate("focus");
// const instance = wrapper.instance();
// expect(instance.state.isOpen).toEqual(true);
// });*/
// // @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("DatePicker check the Calendar onChange callback", () => {
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// const onChange = jest.fn();
// const props = {
// value: "03/03/2000",
// isOpen: true,
// onChange,
// };
// const wrapper = mount(<DatePicker {...props} />);
// const days = wrapper.find(".calendar-month");
// days.first().simulate("click", { target: { value: 1 } });
// expect(onChange).toHaveBeenCalled();
// });
// // @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("DatePicker check Compare date function", () => {
// const date = new Date();
// const errorDate = new Date("01/01/3000");
// const wrapper = shallow(<DatePicker />).instance();
// expect(wrapper.compareDate(date)).toEqual(true);
// expect(wrapper.compareDate(errorDate)).toEqual(false);
// });
// // @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("DatePicker check Compare dates function", () => {
// const date = new Date();
// const wrapper = shallow(<DatePicker />).instance();
// expect(wrapper.compareDates(date, date) === 0).toEqual(true);
// expect(wrapper.compareDates(date, new Date("01/01/2000")) === 0).toEqual(
// false,
// );
// });
// // @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("DatePicker check is valid dates function", () => {
// var date = new Date();
// date.setFullYear(1);
// const wrapper = shallow(<DatePicker />).instance();
// expect(wrapper.isValidDate(selectedDate, maxDate, minDate, false)).toEqual(
// false,
// );
// expect(wrapper.isValidDate(date, maxDate, minDate, false)).toEqual(true);
// });
// // @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("DatePicker componentDidUpdate() lifecycle test", () => {
// const props = {
// selectedDate: new Date(),
// minDate: new Date("01/01/1970"),
// maxDate: new Date("01/01/2030"),
// isOpen: true,
// isDisabled: false,
// isReadOnly: false,
// hasError: false,
// themeColor: "#ED7309",
// locale: "en",
// };
// var date = new Date();
// date.setFullYear(1);
// // @ts-expect-error TS(2741): Property 'onChange' is missing in type '{ selected... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker {...props} />).instance();
// wrapper.componentDidUpdate(wrapper.props, wrapper.state);
// expect(wrapper.props).toBe(wrapper.props);
// expect(wrapper.state).toBe(wrapper.state);
// const wrapper2 = mount(
// <DatePicker
// {...props}
// // @ts-expect-error TS(2322): Type '{ selectedDate: Date; hasError: boolean; siz... Remove this comment to see the full error message
// selectedDate={date}
// hasError={false}
// size="big"
// isDisabled={false}
// />,
// ).instance();
// wrapper2.componentDidUpdate(wrapper2.props, wrapper2.state);
// expect(wrapper2.props).toBe(wrapper2.props);
// expect(wrapper2.state).toBe(wrapper2.state);
// });
// // @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("componentWillUnmount() lifecycle test", () => {
// // @ts-expect-error TS(2322): Type '{ isOpen: boolean; }' is not assignable to t... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker isOpen={true} />);
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// const componentWillUnmount = jest.spyOn(
// wrapper.instance(),
// "componentWillUnmount",
// );
// wrapper.unmount();
// expect(componentWillUnmount).toHaveBeenCalled();
// });
// // @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 '{ isOpen: boolean; id: string; }' is not ass... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker isOpen={true} id="testId" />);
// 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 '{ isOpen: boolean; className: string; }' is ... Remove this comment to see the full error message
// const wrapper = mount(<DatePicker isOpen={true} className="test" />);
// 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 '{ isOpen: boolean; style: { color: string; }... Remove this comment to see the full error message
// <DatePicker isOpen={true} style={{ color: "red" }} />,
// );
// expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
// });
});

View File

@ -0,0 +1,152 @@
import React, { useRef, useState, useEffect } from "react";
import moment from "moment";
import CalendarIconUrl from "PUBLIC_DIR/images/calendar.react.svg?url";
import CalendarIcon from "PUBLIC_DIR/images/calendar.react.svg";
import { Text } from "../text";
import { SelectorAddButton } from "../selector-add-button";
import { SelectedItem } from "../selected-item";
import {
DateSelector,
SelectedLabel,
StyledCalendar,
Wrapper,
} from "./DatePicker.styled";
import { DatePickerProps } from "./DatePicker.types";
const DatePicker = (props: DatePickerProps) => {
const {
initialDate,
onChange,
selectDateText = "Select date",
className,
id,
minDate,
maxDate,
locale,
showCalendarIcon = true,
outerDate,
openDate,
isMobile,
} = props;
const calendarRef = useRef<HTMLDivElement | null>(null);
const selectorRef = useRef<HTMLDivElement | null>(null);
const selectedItemRef = useRef<HTMLDivElement | null>(null);
const [date, setDate] = useState<moment.Moment>(
initialDate ? moment(initialDate) : moment(),
);
const [isCalendarOpen, setIsCalendarOpen] = useState(false);
const toggleCalendar = () =>
setIsCalendarOpen((prevIsCalendarOpen) => !prevIsCalendarOpen);
const closeCalendar = () => {
setIsCalendarOpen(false);
};
const handleChange = (d: null | moment.Moment) => {
onChange?.(d);
setDate(date);
closeCalendar();
};
const deleteSelectedDate = (
propKey: string,
label: string | React.ReactNode,
group: string | undefined,
e: React.MouseEvent | undefined,
) => {
if (e) e.stopPropagation();
handleChange(null);
setIsCalendarOpen(false);
};
const handleClick = (e: MouseEvent) => {
const target = e.target as HTMLElement;
if (
target.classList.contains("nav-thumb-vertical") ||
target.classList.contains("nav-thumb-horizontal")
) {
return;
}
if (
!selectorRef?.current?.contains(target) &&
!calendarRef?.current?.contains(target) &&
!selectedItemRef?.current?.contains(target)
)
setIsCalendarOpen(false);
};
useEffect(() => {
document.addEventListener("mousedown", handleClick, { capture: true });
return () =>
document.removeEventListener("mousedown", handleClick, { capture: true });
}, []);
useEffect(() => {
if (
outerDate &&
moment(outerDate).format("YYYY-MM-D HH:mm") !==
moment(date).format("YYYY-MM-D HH:mm")
) {
setDate(outerDate);
}
}, [date, outerDate]);
return (
<Wrapper className={className} id={id} data-testid="date-picker">
{!date ? (
<DateSelector onClick={toggleCalendar} ref={selectorRef}>
<SelectorAddButton
title={selectDateText}
className="mr-8 add-delivery-date-button"
iconName={CalendarIconUrl}
/>
<Text isInline fontWeight={600} color="#A3A9AE">
{selectDateText}
</Text>
</DateSelector>
) : (
<SelectedItem
className="selectedItem"
propKey=""
onClose={deleteSelectedDate}
label={
showCalendarIcon ? (
<SelectedLabel>
<CalendarIcon className="calendarIcon" />
{date.format("DD MMM YYYY")}
</SelectedLabel>
) : (
date.format("DD MMM YYYY")
)
}
onClick={toggleCalendar}
forwardedRef={selectedItemRef}
/>
)}
{isCalendarOpen && (
<StyledCalendar
isMobile={isMobile}
selectedDate={date}
setSelectedDate={handleChange}
onChange={closeCalendar}
forwardedRef={calendarRef}
minDate={minDate || moment()}
maxDate={maxDate || moment()}
locale={locale}
initialDate={openDate}
/>
)}
</Wrapper>
);
};
export { DatePicker };

View File

@ -0,0 +1,27 @@
import moment from "moment";
export interface DatePickerProps {
/** Allows to change select date text */
selectDateText?: string;
/** Selected date */
initialDate?: moment.Moment | Date;
/** Allow you to handle changing events of component */
onChange: (d: null | moment.Moment) => void;
/** Allows to set classname */
className?: string;
/** Allows to set id */
id?: string;
/** Specifies min choosable calendar date */
minDate?: moment.Moment | Date;
/** Specifies max choosable calendar date */
maxDate?: moment.Moment | Date;
/** Specifies calendar locale */
locale: string;
/** Shows calendar icon in selected item */
showCalendarIcon?: boolean;
/** Allows to track date outside the component */
outerDate?: moment.Moment;
/** Allows to set first shown date in calendar */
openDate: moment.Moment;
isMobile?: boolean;
}

View File

@ -5,7 +5,7 @@ Base DatePicker component
### Usage
```js
import DatePicker from "@docspace/components/date-picker";
import { DatePicker } from "@docspace/shared/components";
```
```jsx

View File

@ -1,6 +1,6 @@
export interface SelectorAddButtonProps {
/** Title text */
title: string;
title?: string;
/** Sets a callback function that is triggered when the button is clicked */
onClick?: (e: React.MouseEvent) => void;
/** Sets the button to present a disabled state */