backpack-ui
Version:
Lonely Planet's Components
538 lines (447 loc) • 17.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
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 _settings = require("../../../settings.json");
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 }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var DateInput = function (_React$Component) {
_inherits(DateInput, _React$Component);
function DateInput(props) {
_classCallCheck(this, DateInput);
var _this = _possibleConstructorReturn(this, (DateInput.__proto__ || Object.getPrototypeOf(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;
}
_createClass(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;
var clicked = _state.clicked;
var startDate = _state.startDate;
var 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;
var id = _props.id;
var label = _props.label;
var name = _props.name;
var format = _props.format;
var placeholder = _props.placeholder;
var required = _props.required;
var size = _props.size;
var theme = _props.theme;
var fill = _props.fill;
var noBorder = _props.noBorder;
var range = _props.range;
var time = _props.time;
var timeOptions = _props.timeOptions;
var defaultTime = _props.defaultTime;
var _state2 = this.state;
var isCalendarOpen = _state2.isCalendarOpen;
var startDate = _state2.startDate;
var 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: _settings.zIndex.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,
name: name || id,
style: [style],
value: startDate.format(format),
onClick: this.openCalendar,
onFocus: this.openCalendar,
onBlur: this.closeCalendar,
placeholder: (typeof placeholder === "undefined" ? "undefined" : _typeof(placeholder)) === "object" ? placeholder[0] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : _typeof(label)) === "object" ? label[0] : label,
title: (typeof label === "undefined" ? "undefined" : _typeof(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",
name: (name || id) + "-date",
style: [style],
value: startDate.format(format),
onClick: this.openCalendar,
onFocus: this.openCalendar,
onBlur: this.closeCalendar,
placeholder: (typeof placeholder === "undefined" ? "undefined" : _typeof(placeholder)) === "object" ? placeholder[0] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : _typeof(label)) === "object" ? label[0] : label,
title: (typeof label === "undefined" ? "undefined" : _typeof(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" : _typeof(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",
style: [style, noBorder && {
width: "calc(50% - 1px)"
}],
value: startDate.format(format),
onClick: this.startRangeOnClick,
onFocus: this.startRangeOnClick,
placeholder: (typeof placeholder === "undefined" ? "undefined" : _typeof(placeholder)) === "object" ? placeholder[0] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : _typeof(label)) === "object" ? label[0] : label,
title: (typeof label === "undefined" ? "undefined" : _typeof(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",
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" : _typeof(placeholder)) === "object" ? placeholder[1] : placeholder,
required: required,
"aria-label": (typeof label === "undefined" ? "undefined" : _typeof(label)) === "object" ? label[1] : label,
title: (typeof label === "undefined" ? "undefined" : _typeof(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: _react2.default.PropTypes.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: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.array]).isRequired,
/**
* Name of the input
*/
name: _react2.default.PropTypes.string,
/**
* Start date value
*/
startDate: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.object, // Moment.js object
_react2.default.PropTypes.func]),
/**
* End date value; range only
*/
endDate: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.object, // Moment.js object
_react2.default.PropTypes.func]),
/**
* Moment.js date format
*/
format: _react2.default.PropTypes.string,
/**
* Placeholder text for the input
*/
placeholder: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.array]),
/**
* Whether or not the input is required
*/
required: _react2.default.PropTypes.bool,
/**
* Size of the input; sizes are defined in styles.js
*/
size: _react2.default.PropTypes.oneOf(["tiny", "small", "medium", "large", "huge"]),
/**
* Theme of the input; themes are defined in styles.js
*/
theme: _react2.default.PropTypes.oneOf(["base", "light", "dark", "inputGroup"]),
/**
* Fills the width of the parent
*/
fill: _react2.default.PropTypes.bool,
/**
* Remove border
*/
noBorder: _react2.default.PropTypes.bool,
/**
* Whether or not to use the range calendar
*/
range: _react2.default.PropTypes.bool,
/**
* Whether or not to show a "time" drop down
*/
time: _react2.default.PropTypes.bool,
/**
* An array of time options or a keyword to use a preset
*/
timeOptions: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.array, _react2.default.PropTypes.oneOf(["default", "openTable"])]),
/**
* A string to set the default value (time)
*/
defaultTime: _react2.default.PropTypes.string,
onClose: _react2.default.PropTypes.func
};
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"
};
DateInput.styles = _styles2.default;
exports.default = (0, _radium2.default)(DateInput);