backpack-ui
Version:
Lonely Planet's Components
573 lines (469 loc) • 17.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof2 = require("babel-runtime/helpers/typeof");
var _typeof3 = _interopRequireDefault(_typeof2);
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn");
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require("babel-runtime/helpers/inherits");
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
var _radium = require("radium");
var _radium2 = _interopRequireDefault(_radium);
var _moment = require("moment");
var _moment2 = _interopRequireDefault(_moment);
var _reactTether = require("react-tether");
var _reactTether2 = _interopRequireDefault(_reactTether);
var _zIndex = require("../../styles/zIndex");
var _zIndex2 = _interopRequireDefault(_zIndex);
var _createQAHook = require("../../utils/createQAHook");
var _createQAHook2 = _interopRequireDefault(_createQAHook);
var _select = require("./select");
var _select2 = _interopRequireDefault(_select);
var _styles = require("./styles");
var _styles2 = _interopRequireDefault(_styles);
var _calendar = require("../calendar");
var _calendar2 = _interopRequireDefault(_calendar);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var DateInput = function (_React$Component) {
(0, _inherits3.default)(DateInput, _React$Component);
function DateInput(props) {
(0, _classCallCheck3.default)(this, DateInput);
var _this = (0, _possibleConstructorReturn3.default)(this, (DateInput.__proto__ || (0, _getPrototypeOf2.default)(DateInput)).call(this, props));
_this.state = {
isCalendarOpen: false,
startDate: props.startDate,
endDate: props.endDate
};
_this.timeOptionPresets = {
default: ["12:00 AM", "1:00 AM", "2:00 AM", "3:00 AM", "4:00 AM", "5:00 AM", "6:00 AM", "7:00 AM", "8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM", "5:00 PM", "6:00 PM", "7:00 PM", "8:00 PM", "9:00 PM", "10:00 PM", "11:00 PM"],
openTable: ["1:30 PM", "2:00 PM", "2:30 PM", "3:00 PM", "3:30 PM", "4:00 PM", "4:30 PM", "5:00 PM", "5:30 PM", "6:00 PM", "6:30 PM", "7:00 PM", "7:30 PM", "8:00 PM", "8:30 PM", "9:00 PM", "9:30 PM", "10:00 PM", "10:30 PM", "11:00 PM", "11:30 PM"]
};
_this.openCalendar = _this.openCalendar.bind(_this);
_this.closeCalendar = _this.closeCalendar.bind(_this);
_this.calendarOnChange = _this.calendarOnChange.bind(_this);
_this.updateInputValue = _this.updateInputValue.bind(_this);
_this.updateRangeValues = _this.updateRangeValues.bind(_this);
_this.handleClickOutside = _this.handleClickOutside.bind(_this);
_this.handleKeydown = _this.handleKeydown.bind(_this);
_this.startRangeOnClick = _this.startRangeOnClick.bind(_this);
_this.endRangeOnClick = _this.endRangeOnClick.bind(_this);
return _this;
}
(0, _createClass3.default)(DateInput, [{
key: "componentDidMount",
value: function componentDidMount() {
document.addEventListener("click", this.handleClickOutside);
document.addEventListener("keydown", this.handleKeydown);
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
document.removeEventListener("click", this.handleClickOutside);
document.removeEventListener("keydown", this.handleKeydown);
}
}, {
key: "openCalendar",
value: function openCalendar() {
if (!this.state.isCalendarOpen) {
this.setState({
isCalendarOpen: true
});
}
}
}, {
key: "closeCalendar",
value: function closeCalendar() {
if (this.state.isCalendarOpen) {
this.setState({
isCalendarOpen: false
});
}
}
}, {
key: "updateInputValue",
value: function updateInputValue(date) {
this.setState({
isCalendarOpen: false,
startDate: date
});
}
}, {
key: "updateRangeValues",
value: function updateRangeValues(newDates) {
var _state = this.state,
clicked = _state.clicked,
startDate = _state.startDate,
endDate = _state.endDate;
var fromDateOpen = clicked === "start";
var toDateOpen = clicked === "end";
if (fromDateOpen) {
if (newDates.startDate > endDate) {
this.setState({
startDate: newDates.startDate,
endDate: newDates.endDate
});
} else {
this.setState({
startDate: newDates.startDate
});
}
this.inputEnd.focus();
}
if (toDateOpen) {
if (startDate > newDates.endDate) {
this.setState({
startDate: newDates.startDate,
endDate: newDates.endDate
});
} else {
this.setState({
endDate: newDates.endDate
});
}
}
}
}, {
key: "calendarOnChange",
value: function calendarOnChange(date) {
if (!this.props.range) {
this.updateInputValue(date);
}
if (this.props.range) {
this.updateRangeValues(date);
}
if (this.props.onClose) {
this.props.onClose({
startDate: date.startDate,
endDate: date.endDate
});
}
}
}, {
key: "handleClickOutside",
value: function handleClickOutside(event) {
var isCalendarOpen = this.state.isCalendarOpen;
var input = this.input;
var calendar = this.calendar;
if (input.contains(event.target)) {
return;
} else if (calendar && !calendar.contains(event.target) && isCalendarOpen) {
this.closeCalendar();
}
}
}, {
key: "handleKeydown",
value: function handleKeydown(event) {
var isCalendarOpen = this.state.isCalendarOpen;
if (event.keyCode === 27 && isCalendarOpen) {
this.closeCalendar();
}
}
}, {
key: "startRangeOnClick",
value: function startRangeOnClick() {
var clicked = this.state.clicked;
this.openCalendar();
if (clicked !== "start") {
this.setState({
clicked: "start"
});
}
}
}, {
key: "endRangeOnClick",
value: function endRangeOnClick() {
var clicked = this.state.clicked;
this.openCalendar();
if (clicked !== "end") {
this.setState({
clicked: "end"
});
}
}
}, {
key: "render",
value: function render() {
var _this2 = this;
var _props = this.props,
id = _props.id,
label = _props.label,
name = _props.name,
format = _props.format,
placeholder = _props.placeholder,
required = _props.required,
size = _props.size,
theme = _props.theme,
fill = _props.fill,
noBorder = _props.noBorder,
range = _props.range,
time = _props.time,
timeOptions = _props.timeOptions,
defaultTime = _props.defaultTime,
qaHook = _props.qaHook;
var _state2 = this.state,
isCalendarOpen = _state2.isCalendarOpen,
startDate = _state2.startDate,
endDate = _state2.endDate;
var style = [_styles2.default.base, _styles2.default.element.input.base, _styles2.default.element.dateInput.base];
if (size) {
style.push(_styles2.default.size[size]);
style.push(_styles2.default.element.input.size[size]);
}
if (theme) {
style.push(_styles2.default.theme[theme]);
style.push(_styles2.default.element.input.theme[theme]);
style.push(_styles2.default.element.dateInput.theme[theme]);
}
if (fill) {
style.push(_styles2.default.fill);
}
if (noBorder) {
style.push(_styles2.default.noBorder);
}
if (range || time) {
style.push({
float: "left",
width: "50%"
});
}
var tetherComponentStyles = {
position: "relative",
zIndex: _zIndex2.default.modal
};
return _react2.default.createElement(
_reactTether2.default,
{
className: "DateInput-calendar",
style: tetherComponentStyles,
attachment: "top left",
targetAttachment: "bottom left",
constraints: [{
to: "window",
attachment: "together"
}]
},
_react2.default.createElement(
"div",
{ ref: function ref(node) {
_this2.input = node;
} },
!range && !time && _react2.default.createElement("input", {
id: id,
"data-testid": qaHook ? (0, _createQAHook2.default)(name, id, "input") : null,
name: name || id,
style: [style],
value: startDate.format(format),
onClick: this.openCalendar,
onFocus: this.openCalendar,
onBlur: this.closeCalendar,
placeholder: (typeof placeholder === "undefined" ? "undefined" : (0, _typeof3.default)(placeholder)) === "object" ? placeholder[0] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[0] : label,
title: (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[0] : label,
readOnly: true
}),
(range && time || !range && time) && _react2.default.createElement(
"div",
{ style: { overflow: "hidden" } },
_react2.default.createElement("input", {
id: id + "-date",
"data-testid": qaHook ? (0, _createQAHook2.default)(name + "-date", id + "-date", "input") : null,
name: (name || id) + "-date",
style: [style],
value: startDate.format(format),
onClick: this.openCalendar,
onFocus: this.openCalendar,
onBlur: this.closeCalendar,
placeholder: (typeof placeholder === "undefined" ? "undefined" : (0, _typeof3.default)(placeholder)) === "object" ? placeholder[0] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[0] : label,
title: (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[0] : label,
readOnly: true
}),
_react2.default.createElement(_select2.default, {
id: id + "-time",
defaultValue: defaultTime,
options: typeof timeOptions === "string" ? this.timeOptionPresets[timeOptions] : timeOptions,
size: size,
theme: theme,
label: (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[1] : label,
style: {
borderLeft: 0,
float: "left",
width: "50%"
},
required: true
})
),
range && !time && _react2.default.createElement(
"div",
{ style: { overflow: "hidden" } },
_react2.default.createElement("input", {
id: id + "-start",
name: (name || id) + "-start",
"data-testid": qaHook ? (0, _createQAHook2.default)(name + "-start", id + "-start", "input") : null,
style: [style, noBorder && {
width: "calc(50% - 1px)"
}],
value: startDate.format(format),
onClick: this.startRangeOnClick,
onFocus: this.startRangeOnClick,
placeholder: (typeof placeholder === "undefined" ? "undefined" : (0, _typeof3.default)(placeholder)) === "object" ? placeholder[0] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[0] : label,
title: (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[0] : label,
ref: function ref(node) {
_this2.inputStart = node;
},
key: "inputStart",
readOnly: true
}),
_react2.default.createElement("input", {
id: id + "-end",
name: (name || id) + "-end",
"data-testid": qaHook ? (0, _createQAHook2.default)(name + "-end", id + "-end", "input") : null,
style: [style, { borderLeft: 0 }, noBorder && {
float: "right",
width: "calc(50% - 1px)"
}],
value: endDate.format(format),
onClick: this.endRangeOnClick,
onFocus: this.endRangeOnClick,
placeholder: (typeof placeholder === "undefined" ? "undefined" : (0, _typeof3.default)(placeholder)) === "object" ? placeholder[1] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[1] : label,
title: (typeof label === "undefined" ? "undefined" : (0, _typeof3.default)(label)) === "object" ? label[1] : label,
ref: function ref(node) {
_this2.inputEnd = node;
},
key: "inputEnd",
readOnly: true
})
)
),
isCalendarOpen && _react2.default.createElement(
"div",
{ ref: function ref(node) {
_this2.calendar = node;
} },
_react2.default.createElement(_calendar2.default, {
startDate: startDate,
endDate: endDate,
format: format,
minDate: (0, _moment2.default)(),
onChange: this.calendarOnChange,
useRange: range
})
)
);
}
}]);
return DateInput;
}(_react2.default.Component);
DateInput.propTypes = {
/**
* ID of the input
*/
id: _propTypes2.default.string.isRequired,
/**
* Label for the input; will not create a `label` element but instead add
* `title` and `aria-label` attributes; this is a design decision to not
* show labels
*/
label: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]).isRequired,
/**
* Name of the input
*/
name: _propTypes2.default.string,
/**
* Start date value
*/
startDate: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object, // Moment.js object
_propTypes2.default.func]),
/**
* End date value; range only
*/
endDate: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object, // Moment.js object
_propTypes2.default.func]),
/**
* Moment.js date format
*/
format: _propTypes2.default.string,
/**
* Placeholder text for the input
*/
placeholder: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
/**
* Whether or not the input is required
*/
required: _propTypes2.default.bool,
/**
* Size of the input; sizes are defined in styles.js
*/
size: _propTypes2.default.oneOf(["tiny", "small", "medium", "large", "huge"]),
/**
* Theme of the input; themes are defined in styles.js
*/
theme: _propTypes2.default.oneOf(["base", "light", "dark", "inputGroup"]),
/**
* Fills the width of the parent
*/
fill: _propTypes2.default.bool,
/**
* Remove border
*/
noBorder: _propTypes2.default.bool,
/**
* Whether or not to use the range calendar
*/
range: _propTypes2.default.bool,
/**
* Whether or not to show a "time" drop down
*/
time: _propTypes2.default.bool,
/**
* An array of time options or a keyword to use a preset
*/
timeOptions: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.oneOf(["default", "openTable"])]),
/**
* A string to set the default value (time)
*/
defaultTime: _propTypes2.default.string,
onClose: _propTypes2.default.func,
/**
* A boolean value to turn on qa hooks or not
*/
qaHook: _propTypes2.default.bool
};
DateInput.defaultProps = {
id: "",
label: "",
name: "",
startDate: (0, _moment2.default)(),
endDate: (0, _moment2.default)().add(1, "week"),
format: "M/D/YYYY",
placeholder: "",
required: false,
size: "medium",
theme: "base",
fill: false,
noBorder: false,
range: false,
time: false,
timeOptions: "default",
defaultTime: "7:00 PM",
qaHook: false
};
DateInput.styles = _styles2.default;
exports.default = (0, _radium2.default)(DateInput);