UNPKG

lucid-ui

Version:

A UI component library from Xandr.

326 lines 17 kB
"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