Skip to content

Custom time input element with customTimeInput prop #2034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs-site/src/components/Examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import RangeMonthPicker from "../../examples/rangeMonthPicker";
import QuarterPicker from "../../examples/quarterPicker";
import RangeQuarterPicker from "../../examples/rangeQuarterPicker";
import OnCalendarChangeStateCallbacks from "../../examples/onCalendarOpenStateCallbacks";
import CustomTimeInput from "../../examples/customTimeInput";

import "./style.scss";
import "react-datepicker/dist/react-datepicker.css";
Expand Down Expand Up @@ -333,6 +334,10 @@ export default class exampleComponents extends React.Component {
{
title: "Calendar open state callbacks",
component: OnCalendarChangeStateCallbacks
},
{
title: "Custom time input",
component: CustomTimeInput
}
];

Expand Down
18 changes: 18 additions & 0 deletions docs-site/src/examples/customTimeInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
() => {
const [startDate, setStartDate] = useState(new Date());
const ExampleCustomTimeInput = ({ value, onChange }) => (
<input
value={value}
onChange={e => onChange(e.target.value)}
style={{ border: "solid 1px pink" }}
/>
);
return (
<DatePicker
selected={startDate}
onChange={date => setStartDate(date)}
showTimeInput
customTimeInput={<ExampleCustomTimeInput />}
/>
);
};
209 changes: 106 additions & 103 deletions docs/index.md

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions docs/inputTime.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# `inputTime` (component)

| name | type | default value | description |
| ---------------- | -------- | ------------- | ----------- |
| `onChange` | `func` | | |
| `timeInputLabel` | `string` | | |
| `timeString` | `string` | | |
| name | type | default value | description |
| ----------------- | -------- | ------------- | ----------- |
| `onChange` | `func` | | |
| `timeInputLabel` | `string` | | |
| `timeString` | `string` | | |
| `customTimeInput` | `string` | | |
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"author": "HackerOne",
"name": "react-datepicker",
"description": "A simple and reusable datepicker component for React",
"version": "2.11.0",
"version": "2.11.1-beta",
"license": "MIT",
"homepage": "https://github.com/Hacker0x01/react-datepicker",
"main": "dist/index.js",
Expand Down
29 changes: 16 additions & 13 deletions src/calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ export default class Calendar extends React.Component {
previousYearButtonLabel: "Previous Year",
nextYearButtonLabel: "Next Year",
previousMonthButtonLabel: "Previous Month",
nextMonthButtonLabel: "Next Month"
nextMonthButtonLabel: "Next Month",
customTimeInput: null
};
}

Expand Down Expand Up @@ -146,7 +147,8 @@ export default class Calendar extends React.Component {
renderDayContents: PropTypes.func,
onDayMouseEnter: PropTypes.func,
onMonthMouseLeave: PropTypes.func,
showPopperArrow: PropTypes.bool
showPopperArrow: PropTypes.bool,
customTimeInput: PropTypes.element
};

constructor(props) {
Expand Down Expand Up @@ -380,8 +382,9 @@ export default class Calendar extends React.Component {
classes.push("react-datepicker__navigation--previous--disabled");
clickHandler = null;
}

const isForYear = this.props.showMonthYearPicker || this.props.showQuarterYearPicker;

const isForYear =
this.props.showMonthYearPicker || this.props.showQuarterYearPicker;

return (
<button
Expand All @@ -390,7 +393,7 @@ export default class Calendar extends React.Component {
onClick={clickHandler}
aria-label={isForYear ? "Previous Year" : "Previous Month"}
>
{isForYear
{isForYear
? this.props.previousYearButtonLabel
: this.props.previousMonthButtonLabel}
</button>
Expand Down Expand Up @@ -445,17 +448,18 @@ export default class Calendar extends React.Component {
classes.push("react-datepicker__navigation--next--disabled");
clickHandler = null;
}

const isForYear = this.props.showMonthYearPicker || this.props.showQuarterYearPicker;


const isForYear =
this.props.showMonthYearPicker || this.props.showQuarterYearPicker;

return (
<button
type="button"
className={classes.join(" ")}
onClick={clickHandler}
aria-label={isForYear ? "Next Year" : "Next Month"}
aria-label={isForYear ? "Next Year" : "Next Month"}
>
{ isForYear
{isForYear
? this.props.nextYearButtonLabel
: this.props.nextMonthButtonLabel}
</button>
Expand Down Expand Up @@ -553,9 +557,7 @@ export default class Calendar extends React.Component {
<div className="react-datepicker__header">
{this.renderCurrentMonth(monthDate)}
<div
className={`react-datepicker__header__dropdown react-datepicker__header__dropdown--${
this.props.dropdownMode
}`}
className={`react-datepicker__header__dropdown react-datepicker__header__dropdown--${this.props.dropdownMode}`}
onFocus={this.handleDropdownFocus}
>
{this.renderMonthDropdown(i !== 0)}
Expand Down Expand Up @@ -743,6 +745,7 @@ export default class Calendar extends React.Component {
timeString={timeString}
timeInputLabel={this.props.timeInputLabel}
onChange={this.props.onTimeChange}
customTimeInput={this.props.customTimeInput}
/>
);
}
Expand Down
7 changes: 5 additions & 2 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ export default class DatePicker extends React.Component {
return date;
},
inlineFocusSelectedMonth: false,
showPopperArrow: true
showPopperArrow: true,
customTimeInput: null
};
}

Expand Down Expand Up @@ -222,7 +223,8 @@ export default class DatePicker extends React.Component {
inlineFocusSelectedMonth: PropTypes.bool,
onDayMouseEnter: PropTypes.func,
onMonthMouseLeave: PropTypes.func,
showPopperArrow: PropTypes.bool
showPopperArrow: PropTypes.bool,
customTimeInput: PropTypes.element
};

constructor(props) {
Expand Down Expand Up @@ -720,6 +722,7 @@ export default class DatePicker extends React.Component {
showMonthYearPicker={this.props.showMonthYearPicker}
showQuarterYearPicker={this.props.showQuarterYearPicker}
showPopperArrow={this.props.showPopperArrow}
customTimeInput={this.props.customTimeInput}
>
{this.props.children}
</WrappedCalendar>
Expand Down
43 changes: 29 additions & 14 deletions src/inputTime.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export default class inputTime extends React.Component {
static propTypes = {
onChange: PropTypes.func,
timeString: PropTypes.string,
timeInputLabel: PropTypes.string
timeInputLabel: PropTypes.string,
customTimeInput: PropTypes.element
};

constructor(props) {
Expand All @@ -24,27 +25,41 @@ export default class inputTime extends React.Component {
this.props.onChange(date);
};

render() {
renderTimeInput = () => {
const { time } = this.state;
const { timeString } = this.props;
const { timeString, customTimeInput } = this.props;

if (customTimeInput) {
return React.cloneElement(customTimeInput, {
value: time,
onChange: this.onTimeChange
});
}

return (
<input
type="time"
className="react-datepicker-time__input"
placeholder="Time"
name="time-input"
required
value={time}
onChange={ev => {
this.onTimeChange(ev.target.value || timeString);
}}
/>
);
};

render() {
return (
<div className="react-datepicker__input-time-container">
<div className="react-datepicker-time__caption">
{this.props.timeInputLabel}
</div>
<div className="react-datepicker-time__input-container">
<div className="react-datepicker-time__input">
<input
type="time"
className="react-datepicker-time__input"
placeholder="Time"
name="time-input"
required
value={time}
onChange={ev => {
this.onTimeChange(ev.target.value || timeString);
}}
/>
{this.renderTimeInput()}
</div>
</div>
</div>
Expand Down
28 changes: 28 additions & 0 deletions test/time_input_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { mount, shallow } from "enzyme";
import DatePicker from "../src/index.jsx";
import InputTimeComponent from "../src/inputTime";
import PropTypes from "prop-types";

describe("DatePicker", () => {
let sandbox;
Expand Down Expand Up @@ -45,4 +46,31 @@ describe("DatePicker", () => {
input.simulate("change", { target: { value: "" } });
expect(timeComponent.state("time")).to.equal("13:00");
});

it("should trigger onChange event on a custom time input without using the last valid timeString", () => {
const CustomTimeInputComponent = ({ onChange, value }) => (
<input
value={value}
onChange={e => onChange(e.target.value)}
style={{ border: "solid 1px pink" }}
/>
);

CustomTimeInputComponent.propTypes = {
onChange: PropTypes.func,
value: PropTypes.string
};

const timeComponent = shallow(
<InputTimeComponent
timeString="13:00"
onChange={console.log}
customTimeInput={<CustomTimeInputComponent />}
/>
);

const input = timeComponent.find("CustomTimeInputComponent");
input.simulate("change", "14:00");
expect(timeComponent.state("time")).to.equal("14:00");
});
});