lucid-ui
Version:
A UI component library from Xandr.
326 lines • 17 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateSelectDumb = void 0;
/* eslint-disable react/prop-types */
var lodash_1 = __importStar(require("lodash"));
var prop_types_1 = __importDefault(require("prop-types"));
var react_1 = __importDefault(require("react"));
var react_day_picker_1 = __importDefault(require("react-day-picker"));
var state_management_1 = require("../../util/state-management");
var style_helpers_1 = require("../../util/style-helpers");
var component_types_1 = require("../../util/component-types");
var reducers = __importStar(require("./DateSelect.reducers"));
var InfiniteSlidePanel_1 = __importDefault(require("../InfiniteSlidePanel/InfiniteSlidePanel"));
var CalendarMonth_1 = __importDefault(require("../CalendarMonth/CalendarMonth"));
var ChevronIcon_1 = __importDefault(require("../Icon/ChevronIcon/ChevronIcon"));
var cx = style_helpers_1.lucidClassNames.bind('&-DateSelect');
var DateUtils = react_day_picker_1.default.DateUtils;
var NAV_BUTTON_SIZE = 32;
var clampMonthsShown = function (monthsShown) { return lodash_1.default.clamp(monthsShown, 1, 6); };
var any = prop_types_1.default.any, bool = prop_types_1.default.bool, node = prop_types_1.default.node, func = prop_types_1.default.func, instanceOf = prop_types_1.default.instanceOf, number = prop_types_1.default.number, oneOf = prop_types_1.default.oneOf, string = prop_types_1.default.string;
var DateSelectCalendarMonth = function (_props) {
return null;
};
DateSelectCalendarMonth.displayName = 'DateSelect.CalendarMonth';
DateSelectCalendarMonth.peek = {
description: "Child component to pass thru props to underlying CalendarMonth.",
};
DateSelectCalendarMonth.propName = 'CalendarMonth';
var nonPassThroughs = [
'className',
'monthsShown',
'calendarsRendered',
'offset',
'from',
'to',
'selectMode',
'initialMonth',
'selectedDays',
'disabledDays',
'showDivider',
'onSwipe',
'onPrev',
'onNext',
'onSelectDate',
'isFontSizeRelative',
'showCursorHighlight',
'useSlidePanel',
'CalendarMonth',
'callbackId',
'initialState',
];
var DateSelect = /** @class */ (function (_super) {
__extends(DateSelect, _super);
function DateSelect(props) {
var _this = _super.call(this, props) || this;
_this.rootRef = null;
_this.handleDayClick = function (day, _a, event) {
var disabled = _a.disabled;
var onSelectDate = _this.props.onSelectDate;
if (!disabled) {
onSelectDate(day, { event: event, props: _this.props });
}
};
_this.handleDayMouseEnter = function (day, _a) {
var disabled = _a.disabled;
if (disabled) {
_this.setState({
cursor: null,
});
}
else {
_this.setState({
cursor: day,
});
}
};
_this.handleDayMouseLeave = function () {
_this.setState({
cursor: null,
});
};
_this.handlePrev = function (_a) {
var event = _a.event;
_this.props.onPrev({ event: event, props: _this.props });
};
_this.handleNext = function (_a) {
var event = _a.event;
_this.props.onNext({ event: event, props: _this.props });
};
_this.componentDidMount = function () {
var _a = _this.props, isFontSizeRelative = _a.isFontSizeRelative, monthsShownRaw = _a.monthsShown;
var monthsShown = clampMonthsShown(monthsShownRaw);
if (isFontSizeRelative && _this.rootRef) {
var rootElement = _this.rootRef;
var _b = rootElement.getBoundingClientRect(), width = _b.width, height = _b.height;
var navButtonsWidth = NAV_BUTTON_SIZE * 2;
var oneMonthShownWidth = (width - navButtonsWidth) / monthsShown + navButtonsWidth;
var size = Math.sqrt(oneMonthShownWidth * height);
var relativeFontSize = Math.round(size / 24);
var relativeMinWidth = ((((width - navButtonsWidth) / monthsShown) * 10.1075) /
relativeFontSize) *
monthsShown +
navButtonsWidth;
rootElement.style.fontSize = "".concat(relativeFontSize, "px");
rootElement.style.minWidth = "".concat(relativeMinWidth, "px");
}
};
_this.renderCalendarMonth = function (monthOffset, isRangeSameDay, selectedDays, _a) {
var key = _a.key, initialMonth = _a.initialMonth, cursor = _a.cursor, from = _a.from, to = _a.to, disabledDays = _a.disabledDays, selectMode = _a.selectMode, onDayClick = _a.onDayClick, showCursorHighlight = _a.showCursorHighlight, onDayMouseEnter = _a.onDayMouseEnter, onDayMouseLeave = _a.onDayMouseLeave, rest = __rest(_a, ["key", "initialMonth", "cursor", "from", "to", "disabledDays", "selectMode", "onDayClick", "showCursorHighlight", "onDayMouseEnter", "onDayMouseLeave"]);
return (react_1.default.createElement(CalendarMonth_1.default, __assign({ key: key, className: cx('&-CalendarMonth'), monthOffset: monthOffset, initialMonth: initialMonth, cursor: cursor, from: isRangeSameDay ? null : from, to: isRangeSameDay ? null : to, selectedDays: isRangeSameDay ? from : selectedDays, disabledDays: disabledDays, selectMode: selectMode, onDayClick: onDayClick, onDayMouseEnter: showCursorHighlight ? onDayMouseEnter : lodash_1.default.noop, onDayMouseLeave: showCursorHighlight ? onDayMouseLeave : lodash_1.default.noop }, rest)));
};
_this.initialMonth = new Date(_this.props.initialMonth);
_this.state = {
offset: 0,
cursor: null,
};
return _this;
}
DateSelect.prototype.render = function () {
var _this = this;
var _a = this.props, className = _a.className, monthsShownRaw = _a.monthsShown, calendarsRendered = _a.calendarsRendered, offset = _a.offset, from = _a.from, to = _a.to, selectMode = _a.selectMode, selectedDays = _a.selectedDays, disabledDays = _a.disabledDays, showDivider = _a.showDivider, onSwipe = _a.onSwipe, showCursorHighlight = _a.showCursorHighlight, useSlidePanel = _a.useSlidePanel, passThroughs = __rest(_a, ["className", "monthsShown", "calendarsRendered", "offset", "from", "to", "selectMode", "selectedDays", "disabledDays", "showDivider", "onSwipe", "showCursorHighlight", "useSlidePanel"]);
var cursor = this.state.cursor;
//@ts-ignore
// For some reason react-day-pickers type doesn't allow `null` values but
// we seem to be passing them in and it seems to "work" at least in that
// the code doesn't blow up.
var isRangeSameDay = DateUtils.isSameDay(from, to);
var calendarMonthProps = lodash_1.default.get((0, component_types_1.getFirst)(this.props, DateSelect.CalendarMonth), 'props');
var monthsShown = clampMonthsShown(monthsShownRaw);
/* istanbul ignore next */
return (react_1.default.createElement("section", __assign({ ref: function (ref) { return (_this.rootRef = ref); }, className: cx('&', className, {
'&-show-divider': showDivider,
}), style: __assign({ minWidth: NAV_BUTTON_SIZE * 2 + 185 * monthsShown }, passThroughs.style) }, (0, lodash_1.omit)(passThroughs, nonPassThroughs)),
react_1.default.createElement("div", null,
react_1.default.createElement(ChevronIcon_1.default, { className: cx('&-chevron'), size: NAV_BUTTON_SIZE, isClickable: true, direction: 'left', onClick: this.handlePrev })),
useSlidePanel ? (react_1.default.createElement(InfiniteSlidePanel_1.default, { className: cx('&-InfiniteSlidePanel', '&-slidePanel'), totalSlides: calendarsRendered, slidesToShow: monthsShown, offset: offset, onSwipe: onSwipe },
react_1.default.createElement(InfiniteSlidePanel_1.default.Slide, { className: cx('&-slide') }, function (slideOffset) { return (react_1.default.createElement("div", { className: cx('&-slide-content') }, _this.renderCalendarMonth(offset + slideOffset - offset, isRangeSameDay, selectedDays, __assign({ key: slideOffset, initialMonth: _this.initialMonth, cursor: cursor, from: from, to: to, disabledDays: disabledDays, selectMode: selectMode, onDayClick: _this.handleDayClick, showCursorHighlight: showCursorHighlight, onDayMouseEnter: _this.handleDayMouseEnter, onDayMouseLeave: _this.handleDayMouseLeave }, calendarMonthProps)))); }))) : (react_1.default.createElement("div", { className: cx('&-slidePanel', '&-slidePanel-simple') }, lodash_1.default.times(monthsShown, function (calendarIndex) { return (react_1.default.createElement("div", { className: cx('&-slide', '&-slide-simple'), key: calendarIndex },
react_1.default.createElement("div", { className: cx('&-slide-content') }, _this.renderCalendarMonth(offset + calendarIndex, isRangeSameDay, selectedDays, __assign({ initialMonth: _this.initialMonth, cursor: cursor, from: from, to: to, disabledDays: disabledDays, selectMode: selectMode, onDayClick: _this.handleDayClick, showCursorHighlight: showCursorHighlight, onDayMouseEnter: _this.handleDayMouseEnter, onDayMouseLeave: _this.handleDayMouseLeave }, calendarMonthProps))))); }))),
react_1.default.createElement("div", null,
react_1.default.createElement(ChevronIcon_1.default, { className: cx('&-chevron'), size: NAV_BUTTON_SIZE, isClickable: true, direction: 'right', onClick: this.handleNext }))));
};
DateSelect.displayName = 'DateSelect';
DateSelect.CalendarMonth = DateSelectCalendarMonth;
DateSelect.peek = {
description: "A date selection component capabaple of supporting single date and date range selections.",
categories: ['controls', 'selectors'],
madeFrom: ['InfiniteSlidePanel', 'CalendarMonth'],
};
DateSelect.propTypes = {
/**
Appended to the component-specific class names set on the root element.
*/
className: string,
/**
Number of calendar months to show. Min 1, suggested max 3. Actual max is 6.
*/
monthsShown: number,
calendarsRendered: number /**
Number of calendar months rendered at any given time (including those out
of view). In practice it should be at least (2 * monthsShown) + 2. It's
got some issues that still need to be ironed out but it works.
*/,
/**
The offset of the leftmost month in view, where 0 is the
\`initialMonth\`. Negative values will show previous months.
*/
offset: number,
/**
Sets the start date in a date range.
*/
from: instanceOf(Date),
/**
Sets the end date in a date range.
*/
to: instanceOf(Date),
/**
The next selection that is expected. Primarily used to preview expected
ranges when the cursor is on a target date.
*/
selectMode: oneOf(['day', 'from', 'to']),
/**
Sets first month in view on render. The 0 value for the \`offset\` prop
refers to this month.
*/
initialMonth: instanceOf(Date),
/**
Sets selected days. Passed through to \`CalendarMonth\` ->
\`react-day-picker\`. Can be a \`Date\`, array of \`Date\`s or a function
with the signature \`(date) => Boolean\`.
*/
selectedDays: any,
/**
Sets disabled days. Passed through to \`CalendarMonth\` ->
\`react-day-picker\`. Can be a \`Date\`, array of \`Date\`s or a function
with the signature \`(date) => Boolean\`.
*/
disabledDays: any,
/**
Display a divider between each month.
*/
showDivider: bool,
/**
Called when user's swipe would change the month \`offset\`. Callback
passes number of months swiped by the user (positive for forward swipes,
negative for backwards swipes). Signature:
\`(monthsSwiped, { event, props }) => {}\`
*/
onSwipe: func,
/**
Called when user clicks the previous button. Signature:
\`({ event, props }) => {}\`
*/
onPrev: func,
/**
Called when user clicks the next button. Signature:
\`({ event, props }) => {}\`
*/
onNext: func,
/**
Called when user selects a date. Callback passes a Date object as the
first argument. Signature: \`(selectedDate, { event, props }) => {}\`
*/
onSelectDate: func,
/**
Render initial font size relative to size of the component so it scales
with the calendar size.
*/
isFontSizeRelative: bool,
/**
Highlight dates and ranges based on cursor position.
*/
showCursorHighlight: bool,
/**
Render the calendar months in a touch-friendly slider with some being
rendered out-of-view. Set to \`false\` to disable this feature and gain a
performance boost.
*/
useSlidePanel: bool,
/**
Child component to pass thru props to underlying CalendarMonth.
*/
CalendarMonth: node,
};
DateSelect.defaultProps = {
monthsShown: 1,
calendarsRendered: 6,
offset: 0,
from: null,
to: null,
initialMonth: new Date(),
selectedDays: function () { return false; },
disabledDays: function () { return false; },
showDivider: false,
onSwipe: lodash_1.default.noop,
onPrev: lodash_1.default.noop,
onNext: lodash_1.default.noop,
onSelectDate: lodash_1.default.noop,
isFontSizeRelative: false,
showCursorHighlight: true,
useSlidePanel: true,
};
DateSelect.reducers = reducers;
return DateSelect;
}(react_1.default.Component));
exports.DateSelectDumb = DateSelect;
exports.default = (0, state_management_1.buildModernHybridComponent)(DateSelect, { reducers: reducers });
//# sourceMappingURL=DateSelect.js.map