UNPKG

pickadate

Version:

The composable date & time picker.

1,604 lines (1,398 loc) 66.6 kB
/* pickadate v5.0.0-alpha.3, @license MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.pickadate = factory()); }(this, function () { 'use strict'; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } ///////////// // STRINGS // ///////////// var caseDash = function caseDash(string) { return string.split(/(?=[A-Z])/g).map(function (chunk) { return chunk.toLowerCase(); }).join('-'); }; ///////////// // NUMBERS // ///////////// var padZero = function padZero(number, digitsCount) { number = "".concat(number); var numberDigitsCount = number.length; var differenceInDigitsCount = digitsCount - numberDigitsCount; return differenceInDigitsCount > 0 ? '0'.repeat(differenceInDigitsCount) + number : number; }; ///////////// // OBJECTS // ///////////// var mergeUpdates = function mergeUpdates(defaults, updates) { var mergedObject = _objectSpread({}, defaults); Object.keys(defaults).forEach(function (key) { var defaultValue = defaults[key]; var updateValue = updates[key]; // If there is no default, remove the key if (defaultValue === undefined) { delete mergedObject[key]; return; } // If the default is the same as the update, do nothing if (defaultValue === updateValue) { return; } // If both values are objects, recursively merge them if (defaultValue && updateValue && defaultValue.constructor === Object && updateValue.constructor === Object) { mergedObject[key] = mergeUpdates(defaultValue, updateValue); return; } mergedObject[key] = updates.hasOwnProperty(key) ? updateValue : defaultValue; }); return mergedObject; }; var copyDefinedValues = function copyDefinedValues(object) { return Object.keys(object).reduce(function (accumulator, key) { var value = object[key]; if (value !== undefined) { accumulator[key] = value; } return accumulator; }, {}); }; //////////// // ARRAYS // //////////// var createRange = function createRange(fromIndex, toIndex) { var range = []; for (var index = fromIndex; index <= toIndex; index++) { range.push(index); } return range; }; var DAYS_IN_WEEK = 7; /** * Gets the weekday labels. */ var getWeekdayLabels = function getWeekdayLabels(weekdays, firstDayOfWeek) { return weekdays.map(function (_, dayIndex) { return weekdays[(dayIndex + firstDayOfWeek) % DAYS_IN_WEEK]; }); }; /** * Gets the dates in weeks. */ var getDatesInWeeks = function getDatesInWeeks(originDateObject, firstDayOfWeek) { var year = originDateObject.getFullYear(); var month = originDateObject.getMonth(); var monthOfLastDayInFirstWeek = getMonthOfLastDayInFirstWeek(year, month, firstDayOfWeek); var shift = monthOfLastDayInFirstWeek === month ? 0 : -1; var start = 0 + shift; var end = 5 + shift; return createRange(start, end).map(function (weekIndex) { return getDatesInWeek(year, month, weekIndex, firstDayOfWeek); }); }; /** * Gets the dates in a week. */ var getDatesInWeek = function getDatesInWeek(year, month, weekIndex, firstDayOfWeek) { var startDayOfMonth = getStartDayOfMonth(year, month); var startDayOfWeek = weekIndex * DAYS_IN_WEEK; var start = 1; var end = 7; return createRange(start, end).map(function (date) { return new Date(year, month, date + startDayOfWeek - startDayOfMonth + firstDayOfWeek); }); }; /** * Gets the month of the last day in the first week of a month. */ var getMonthOfLastDayInFirstWeek = function getMonthOfLastDayInFirstWeek(year, month, firstDayOfWeek) { var startDayOfMonth = getStartDayOfMonth(year, month) - firstDayOfWeek; var date = DAYS_IN_WEEK - startDayOfMonth; if (startDayOfMonth < 0) { return new Date(year, month, firstDayOfWeek - date).getMonth(); } return new Date(year, month, date).getMonth(); }; /** * Gets the start day of a month. */ var getStartDayOfMonth = function getStartDayOfMonth(year, month) { var startDateOfMonth = new Date(year, month, 1); return startDateOfMonth.getDay(); }; /** * Gets the start date of a month, give a date. */ var getStartDateOfMonth = function getStartDateOfMonth(dateObject) { var year = dateObject.getFullYear(); var month = dateObject.getMonth(); return new Date(year, month, 1); }; var flatten = function flatten(classNames) { var classList = Array.isArray(classNames) ? classNames : [classNames]; return classList.reduce(function (accumulator, className) { if (!className) { return accumulator; } if (Array.isArray(className)) { className.forEach(function (className) { if (typeof className === 'string') { accumulator[className] = true; } }); } else if (typeof className === 'string') { accumulator[className] = true; } else if (className.constructor === Object) { accumulator = _objectSpread({}, accumulator, className); } return accumulator; }, {}); }; var global$1 = (typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); // shim for using process in browser // based off https://github.com/defunctzombie/node-process/blob/master/browser.js function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } var cachedSetTimeout = defaultSetTimout; var cachedClearTimeout = defaultClearTimeout; if (typeof global$1.setTimeout === 'function') { cachedSetTimeout = setTimeout; } if (typeof global$1.clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } function nextTick(fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } } // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; var title = 'browser'; var platform = 'browser'; var browser = true; var env = {}; var argv = []; var version = ''; // empty string to avoid regexp issues var versions = {}; var release = {}; var config = {}; function noop() {} var on = noop; var addListener = noop; var once = noop; var off = noop; var removeListener = noop; var removeAllListeners = noop; var emit = noop; function binding(name) { throw new Error('process.binding is not supported'); } function cwd () { return '/' } function chdir (dir) { throw new Error('process.chdir is not supported'); }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance$1 = global$1.performance || {}; var performanceNow = performance$1.now || performance$1.mozNow || performance$1.msNow || performance$1.oNow || performance$1.webkitNow || function(){ return (new Date()).getTime() }; // generate timestamp or delta // see http://nodejs.org/api/process.html#process_process_hrtime function hrtime(previousTimestamp){ var clocktime = performanceNow.call(performance$1)*1e-3; var seconds = Math.floor(clocktime); var nanoseconds = Math.floor((clocktime%1)*1e9); if (previousTimestamp) { seconds = seconds - previousTimestamp[0]; nanoseconds = nanoseconds - previousTimestamp[1]; if (nanoseconds<0) { seconds--; nanoseconds += 1e9; } } return [seconds,nanoseconds] } var startTime = new Date(); function uptime() { var currentTime = new Date(); var dif = currentTime - startTime; return dif / 1000; } var process = { nextTick: nextTick, title: title, browser: browser, env: env, argv: argv, version: version, versions: versions, on: on, addListener: addListener, once: once, off: off, removeListener: removeListener, removeAllListeners: removeAllListeners, emit: emit, binding: binding, cwd: cwd, chdir: chdir, umask: umask, hrtime: hrtime, platform: platform, release: release, config: config, uptime: uptime }; // CHECKERS // ////////////// var isSameDate = function isSameDate(one, two) { return one instanceof Date && two instanceof Date && isSameMonth(one, two) && one.getDate() === two.getDate(); }; var isSameMonth = function isSameMonth(one, two) { return one instanceof Date && two instanceof Date && isSameYear(one, two) && one.getMonth() === two.getMonth(); }; var isSameYear = function isSameYear(one, two) { return one instanceof Date && two instanceof Date && one.getFullYear() === two.getFullYear(); }; var isBeforeDate = function isBeforeDate(one, two) { return one instanceof Date && two instanceof Date && (one.getFullYear() < two.getFullYear() || isSameYear(one, two) && one.getMonth() < two.getMonth() || isSameMonth(one, two) && one.getDate() < two.getDate()); }; var isSameOrBeforeDate = function isSameOrBeforeDate(one, two) { return isSameDate(one, two) || isBeforeDate(one, two); }; //////////// // FORMAT // //////////// /** * A mapping of template hooks to formatters. */ var HOOK_FORMATTER = { D: function D(dateObject) { return "".concat(dateObject.getDate()); }, DD: function DD(dateObject) { return "".concat(padZero(HOOK_FORMATTER.D(dateObject), 2)); }, DDD: function DDD(dateObject, words) { return words[dateObject.getDay()]; }, DDDD: function DDDD(dateObject, words) { return words[dateObject.getDay()]; }, M: function M(dateObject) { return "".concat(dateObject.getMonth() + 1); }, MM: function MM(dateObject) { return "".concat(padZero(HOOK_FORMATTER.M(dateObject), 2)); }, MMM: function MMM(dateObject, words) { return words[dateObject.getMonth()]; }, MMMM: function MMMM(dateObject, words) { return words[dateObject.getMonth()]; }, YYYY: function YYYY(dateObject) { return "".concat(dateObject.getFullYear()); }, H: function H(dateObject) { return "".concat(dateObject.getHours()); }, HH: function HH(dateObject) { return "".concat(padZero(HOOK_FORMATTER.H(dateObject), 2)); }, h: function h(dateObject) { return "".concat(dateObject.getHours() % 12 || 12); }, hh: function hh(dateObject) { return "".concat(padZero(HOOK_FORMATTER.h(dateObject), 2)); }, m: function m(dateObject) { return "".concat(dateObject.getMinutes()); }, mm: function mm(dateObject) { return "".concat(padZero(HOOK_FORMATTER.m(dateObject), 2)); }, a: function a(dateObject) { return dateObject.getHours() < 12 ? 'a.m.' : 'p.m.'; }, A: function A(dateObject) { return dateObject.getHours() < 12 ? 'AM' : 'PM'; }, s: function s(dateObject) { return "".concat(dateObject.getSeconds()); }, ss: function ss(dateObject) { return "".concat(padZero(HOOK_FORMATTER.s(dateObject), 2)); }, x: function x(dateObject) { return "".concat(dateObject.getTime()); } }; var getStartingDigits = function getStartingDigits(string) { return string.replace(/(^\d*)(.*)/, '$1'); }; var getStartingWord = function getStartingWord(string) { return string.replace(/(^\w*)(.*)/, '$1'); }; var getStartingLowerCaseMeridiem = function getStartingLowerCaseMeridiem(string) { return string.replace(/(^[ap]\.m\.)?(.*)/, '$1'); }; var getStartingUpperCaseMeridiem = function getStartingUpperCaseMeridiem(string) { return string.replace(/(^[AP]M)?(.*)/, '$1'); }; /** * A mapping of template hooks to parsers. */ var HOOK_PARSER = { D: getStartingDigits, DD: getStartingDigits, DDD: getStartingWord, DDDD: getStartingWord, M: getStartingDigits, MM: getStartingDigits, MMM: getStartingWord, MMMM: getStartingWord, YYYY: getStartingDigits, H: getStartingDigits, HH: getStartingDigits, h: getStartingDigits, hh: getStartingDigits, m: getStartingDigits, mm: getStartingDigits, a: getStartingLowerCaseMeridiem, A: getStartingUpperCaseMeridiem, s: getStartingDigits, ss: getStartingDigits, x: getStartingDigits }; { /* istanbul ignore next */ if (process.env.NODE_ENV === 'development') { var extraFormatterKeys = Object.keys(HOOK_FORMATTER).filter(function (key) { return !HOOK_PARSER[key]; }); console.assert(!extraFormatterKeys.length, 'Missing keys to parse with', extraFormatterKeys); var extraParserKeys = Object.keys(HOOK_PARSER).filter(function (key) { return !HOOK_FORMATTER[key]; }); console.assert(!extraParserKeys.length, 'Missing keys to format with', extraParserKeys); } } /** * A collection of the template hooks. */ var HOOKS = Object.keys(HOOK_FORMATTER); /** * A regular expression that matches all segments of a template string. */ var HOOKS_REGEXP = new RegExp([// Match any characters escaped with square brackets '(\\[.*?\\])', // Match any template hooks "(?:\\b(".concat(HOOKS.join('|'), ")\\b)"), // Match all other characters '(.)'].join('|'), 'g'); var format = function format(dateObject, template, templateHookWords) { return (// Match hooks within the template matchHooks(template) // Map through the matches while formatting template hooks // and removing the hooks of escaped characters .map(function (match) { if (match.index === 2) { var formatter = HOOK_FORMATTER[match.chunk]; return formatter(dateObject, templateHookWords[match.chunk]); } if (match.index === 1) { return match.chunk.replace(/^\[(.*)]$/, '$1'); } return match.chunk; }) // Join the chunks together into a string .join('') ); }; var matchHooks = function matchHooks(template) { return template // Split the template using the regular expression .split(HOOKS_REGEXP) // Map the chunks to keep a reference of their match group index .map(function (chunk, index) { return { chunk: chunk, index: index % 4 }; }) // Filter out false-y chunks .filter(function (match) { return !!match.chunk; }); }; var isDisabled = function isDisabled(state, dateObject) { var minimum = state.minimum, maximum = state.maximum, disabled = state.disabled; return isBeforeDate(dateObject, minimum) || isBeforeDate(maximum, dateObject) || disabled.some(function (value) { if (typeof value === 'number') { return dateObject.getDay() === value; } if (value instanceof Date) { return isSameDate(dateObject, value); } if (Array.isArray(value)) { var _value = _slicedToArray(value, 2), fromDate = _value[0], toDate = _value[1]; return isSameOrBeforeDate(fromDate, dateObject) && isSameOrBeforeDate(dateObject, toDate); } }); }; var computeInfo = function computeInfo(state, dateObject) { return { isToday: isSameDate(new Date(), dateObject), isSelected: isSameDate(state.selected, dateObject), isHighlighted: isSameDate(state.highlighted, dateObject), isSameMonth: isSameMonth(state.view, dateObject), isDisabled: isDisabled(state, dateObject) }; }; var KEY_CODE = { BACKSPACE: 8, ENTER: 13, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40 }; var ARROW_KEY_CODES = Object.values(KEY_CODE); var createOnKeyDownCalendar = function createOnKeyDownCalendar(picker) { return function onKeyDownCalendar(event) { if (event.keyCode === KEY_CODE.BACKSPACE) { event.preventDefault(); picker.clear(); } else if (event.keyCode === KEY_CODE.ENTER || event.keyCode === KEY_CODE.SPACE) { event.preventDefault(); picker.setSelected({ value: picker.store.getState().highlighted }); } else if (ARROW_KEY_CODES.includes(event.keyCode)) { event.preventDefault(); picker.setHighlighted({ keyCode: event.keyCode }); } }; }; function getValueFromMouseEvent(event) { var eventPath = getEventPath(event); var value = getValueFromMouseEventPath(eventPath, event.currentTarget); if (value == null) { return; } value = parseInt(value, 10); if (!Number.isFinite(value)) { console.error('Unable to get value from mouse event %o', event); return; } return value; } var getValueFromMouseEventPath = function getValueFromMouseEventPath(path, rootNode) { for (var i = 0; i < path.length; i += 1) { var node = path[i]; if (node === rootNode) { return; } // $FlowFixMe var value = node.dataset.value; if (value != null) { return value; } } }; var getEventPath = function getEventPath(event) { // $FlowFixMe if (event.path) { return event.path; } var path = []; var target = event.target; // $FlowFixMe while (target.parentNode) { path.push(target); // $FlowFixMe target = target.parentNode; } path.push(document, window); return path; }; // prettier-ignore var EVENT_NAME = { CHANGE: 'pickadate:change', MOUNT: 'pickadate:mount', UNMOUNT: 'pickadate:unmount', INPUT_ACTIVE: 'pickadate:input-active', INPUT_INACTIVE: 'pickadate:input-inactive', INPUT_OPEN: 'pickadate:input-open', INPUT_CLOSE: 'pickadate:input-close' }; var chevronRight = "<svg viewBox=\"0 0 32 54\"><path d=\"M7 51.02l24.04-24.01L7 3 2 7.989 21.04 27.01 2 46.03z\"/></svg>"; var chevronLeft = "<svg viewBox=\"0 0 32 54\"><path d=\"M25.04 3L1 27.01l24.04 24.01 5-4.989L11 27.01 30.04 7.99z\"/></svg>"; var chevronUp = "<svg viewBox=\"0 0 54 32\"><path d=\"M50.53 25.53L26.52 1.49 2.51 25.53l4.989 5L26.52 11.49l19.02 19.04z\"/></svg>"; var chevronDown = "<svg viewBox=\"0 0 54 32\"><path d=\"M2.51 7.49l24.01 24.04L50.53 7.49l-4.989-5L26.52 21.53 7.5 2.49z\"/></svg>"; var bullsEye = "<svg viewBox=\"0 0 54 54\"><path d=\"M27 46C16.51 46 8 37.49 8 27S16.51 8 27 8s19 8.51 19 19-8.51 19-19 19m0-45C12.64 1 1 12.64 1 27s11.64 26 26 26 26-11.64 26-26S41.36 1 27 1\"/><path d=\"M31 27c0 2.21-1.79 4-4 4s-4-1.79-4-4 1.79-4 4-4 4 1.79 4 4\"/></svg>"; // LAYOUTS // ///////////// var createLayout = function createLayout(createElement) { return function (initialize) { return function () { for (var _len = arguments.length, childLayouts = new Array(_len), _key = 0; _key < _len; _key++) { childLayouts[_key] = arguments[_key]; } return function (picker, options, rootElement) { var element = createElement(picker, rootElement); initialize(element, picker, options, rootElement); var children = childLayouts.map(function (layout) { return layout(picker, options, rootElement); }); appendChildren(element, children); return element; }; }; }; }; var createBoxLayout = createLayout(function () { return createDocumentElement({ tagName: 'div' }); }); var createButtonLayout = createLayout(function (picker, rootElement) { var buttonElement = createDocumentElement({ tagName: 'button' }); rootElement.addEventListener(EVENT_NAME.INPUT_OPEN, function () { buttonElement.disabled = false; }); rootElement.addEventListener(EVENT_NAME.INPUT_CLOSE, function () { buttonElement.disabled = true; }); return buttonElement; }); //////////////// // COMPONENTS // //////////////// var createInputRootBox = createBoxLayout(function (element, picker, options, rootElement) { if (!(rootElement instanceof HTMLInputElement)) { throw new Error('Cannot initialize an input root without the input element'); } initializeInput(rootElement, picker); element.className = options.className.inputRoot; element.addEventListener('focusin', function (event) { return event.stopPropagation(); }); element.addEventListener('click', function (event) { return event.stopPropagation(); }); element.addEventListener('mousedown', function (event) { var target = event.target; if (target instanceof HTMLInputElement || target instanceof HTMLButtonElement) { return; } event.preventDefault(); }); }); var createRootBox = createBoxLayout(function (element, picker, options, rootElement) { addAttributes(element, { className: options.className.root }); rootElement.addEventListener(EVENT_NAME.INPUT_OPEN, function () { element.classList.add(options.className.root__active); }); rootElement.addEventListener(EVENT_NAME.INPUT_CLOSE, function () { element.classList.remove(options.className.root__active); }); picker.subscribeToSelection(function () { return dispatchEvent(rootElement, EVENT_NAME.CHANGE); }); }); var createHeaderBox = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.header }); }); var createBodyBox = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.body }); }); var createFooterBox = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.footer }); }); var createTimeBox = createBoxLayout(function (element, picker, options) { // $FlowFixMe var state = picker.store.getState(); addAttributes(element, { className: options.className.time, hidden: !state.selected }); picker.store.subscribe(function () { var state = picker.store.getState(); element.hidden = !state.selected; }); }); var createMonthAndYearBox = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.monthAndYear }); var render = function render() { var state = picker.store.getState(); element.innerHTML = ''; appendChildren(element, [createDocumentElement({ children: state.templateHookWords.MMMM[state.view.getMonth()], className: options.className.monthAndYear_month }), createDocumentElement({ children: state.view.getFullYear(), className: options.className.monthAndYear_year })]); }; render(); picker.store.subscribe(render); }); var createPreviousButton = createButtonLayout(function (element, picker, options) { var onMouseDown = function onMouseDown(event) { return event.preventDefault(); }; var onClick = function onClick() { return picker.viewPrevious(); }; addAttributes(element, { className: options.className.button_previous, onMouseDown: onMouseDown, onClick: onClick }); element.innerHTML = chevronLeft; }); var createTodayButton = createButtonLayout(function (element, picker, options) { var onMouseDown = function onMouseDown(event) { return event.preventDefault(); }; var onClick = function onClick() { return picker.viewToday(); }; addAttributes(element, { className: options.className.button_today, onMouseDown: onMouseDown, onClick: onClick }); element.innerHTML = bullsEye; }); var createNextButton = createButtonLayout(function (element, picker, options) { var onMouseDown = function onMouseDown(event) { return event.preventDefault(); }; var onClick = function onClick() { return picker.viewNext(); }; addAttributes(element, { className: options.className.button_next, onMouseDown: onMouseDown, onClick: onClick }); element.innerHTML = chevronRight; }); var createGridButton = createButtonLayout(function (element, picker, options, rootElement) { rootElement.addEventListener(EVENT_NAME.INPUT_ACTIVE, function () { element.classList.add(options.className.grid__focused); }); rootElement.addEventListener(EVENT_NAME.INPUT_INACTIVE, function () { element.classList.remove(options.className.grid__focused); }); var onClick = function onClick(event) { var value = getValueFromMouseEvent(event); if (value) { picker.setSelected({ value: value }); } }; addAttributes(element, { className: options.className.grid, onClick: onClick, onKeyDown: createOnKeyDownCalendar(picker) }); var render = function render() { element.innerHTML = ''; appendChildren(element, createGridCellElements(options, picker.store.getState())); }; render(); picker.store.subscribe(render); }); var createMeridiemButton = createButtonLayout(function (element, picker, options) { var onMouseDown = function onMouseDown(event) { return event.preventDefault(); }; var onClick = function onClick() { return picker.cycleMeridiem(); }; addAttributes(element, { className: options.className.button_meridiem, onMouseDown: onMouseDown, onClick: onClick }); var updateButton = function updateButton() { var _picker$store$getStat = picker.store.getState(), selected = _picker$store$getStat.selected; element.innerHTML = ''; appendChildren(element, selected ? selected.getHours() < 12 ? 'AM' : 'PM' : 'AM'); element.tabIndex = selected ? 0 : -1; }; updateButton(); picker.store.subscribe(updateButton); }); var createHourInput = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.time_hours }); var cycleUp = function cycleUp() { return picker.cycleHourUp(); }; var cycleDown = function cycleDown() { return picker.cycleHourDown(); }; var hourInput = createTimeInputElement(options, { className: options.className.time_input__hours, onKeyCodeUp: cycleUp, onKeyCodeDown: cycleDown }); var updateHourInput = function updateHourInput() { var state = picker.store.getState(); var hours = state.selected ? padZero(state.selected.getHours() % 12 || 12, 2) : ''; hourInput.value = hours; hourInput.tabIndex = state.selected ? 0 : -1; }; updateHourInput(); picker.store.subscribe(updateHourInput); appendChildren(element, [hourInput].concat(_toConsumableArray(createTimeCounterElements(options, { onClickUp: cycleUp, onClickDown: cycleDown })))); }); var createMinuteInput = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.time_minutes }); var cycleUp = function cycleUp() { return picker.cycleMinuteUp(); }; var cycleDown = function cycleDown() { return picker.cycleMinuteDown(); }; var minuteInput = createTimeInputElement(options, { className: options.className.time_input__minutes, onKeyCodeUp: cycleUp, onKeyCodeDown: cycleDown }); var updateMinuteInput = function updateMinuteInput() { var state = picker.store.getState(); var minutes = state.selected ? padZero(state.selected.getMinutes(), 2) : ''; minuteInput.value = minutes; minuteInput.tabIndex = state.selected ? 0 : -1; }; updateMinuteInput(); picker.store.subscribe(updateMinuteInput); appendChildren(element, [minuteInput].concat(_toConsumableArray(createTimeCounterElements(options, { onClickUp: cycleUp, onClickDown: cycleDown })))); }); var createTimeSeparator = createBoxLayout(function (element, picker, options) { addAttributes(element, { className: options.className.time_separator }); element.innerHTML = ':'; }); ////////////// // ELEMENTS // ////////////// var createGridCellElements = function createGridCellElements(options, state) { var datesInWeeks = getDatesInWeeks(state.view, state.firstDayOfWeek); var elements = datesInWeeks.map(function (datesInWeek) { return createDocumentElement({ className: options.className.grid_row, children: datesInWeek.map(function (dateObject) { return createGridCellElement(options, state, dateObject); }) }); }); elements.unshift(createDocumentElement({ className: flatten([options.className.grid_row, options.className.grid_row__label]), children: getWeekdayLabels(state.templateHookWords.DDD, state.firstDayOfWeek).map(function (weekday) { return createDocumentElement({ className: options.className.grid_label, children: weekday }); }) })); return elements; }; var createGridCellElement = function createGridCellElement(options, state, dateObject) { var _ref; var cellInfo = computeInfo(state, dateObject); var parent = createDocumentElement({ className: flatten([options.className.grid_cell, (_ref = {}, _defineProperty(_ref, options.className.grid_cell__today, cellInfo.isToday), _defineProperty(_ref, options.className.grid_cell__highlighted, cellInfo.isHighlighted), _defineProperty(_ref, options.className.grid_cell__selected, cellInfo.isSelected), _defineProperty(_ref, options.className.grid_cell__outOfView, !cellInfo.isSameMonth), _defineProperty(_ref, options.className.grid_cell__disabled, cellInfo.isDisabled), _ref)]), attributes: { dataset: cellInfo.isDisabled ? undefined : { value: dateObject.getTime() } } }); var children = createDocumentElement({ children: dateObject.getDate() }); var content = options.renderCell({ dateObject: dateObject, children: children }) || children; appendChildren(parent, content); return parent; }; var createTimeInputElement = function createTimeInputElement(options, _ref2) { var className = _ref2.className, onKeyCodeUp = _ref2.onKeyCodeUp, onKeyCodeDown = _ref2.onKeyCodeDown; var onKeyDown = function onKeyDown(event) { if (event.keyCode === KEY_CODE.UP) { event.preventDefault(); onKeyCodeUp(); } else if (event.keyCode === KEY_CODE.DOWN) { event.preventDefault(); onKeyCodeDown(); } }; var onFocus = function onFocus() { return inputElement.setSelectionRange(0, 0); }; var inputElement = createDocumentElement({ tagName: 'input', className: [options.className.time_input, className], attributes: { onKeyDown: onKeyDown, onFocus: onFocus, readOnly: true } }); return inputElement; }; var createTimeCounterElements = function createTimeCounterElements(options, _ref3) { var onClickUp = _ref3.onClickUp, onClickDown = _ref3.onClickDown; var onMouseDown = function onMouseDown(event) { return event.preventDefault(); }; var upElement = createDocumentElement({ tagName: 'button', className: [options.className.time_counter, options.className.time_counter__up], attributes: { tabIndex: -1, onMouseDown: onMouseDown, onClick: onClickUp } }); upElement.innerHTML = chevronUp; var downElement = createDocumentElement({ tagName: 'button', className: [options.className.time_counter, options.className.time_counter__down], attributes: { tabIndex: -1, onMouseDown: onMouseDown, onClick: onClickDown } }); downElement.innerHTML = chevronDown; return [upElement, downElement]; }; ////////////////// // INITIALIZERS // ////////////////// var initializeInput = function initializeInput(inputElement, picker) { inputElement.readOnly = true; inputElement.value = picker.getValue(); inputElement.addEventListener('focus', function () { dispatchEvent(inputElement, EVENT_NAME.INPUT_OPEN); dispatchEvent(inputElement, EVENT_NAME.INPUT_ACTIVE); }); inputElement.addEventListener('blur', function () { dispatchEvent(inputElement, EVENT_NAME.INPUT_INACTIVE); }); inputElement.addEventListener('keydown', createOnKeyDownCalendar(picker)); var onDocumentEvent = function onDocumentEvent(event) { if (event.target !== inputElement && // $FlowFixMe: In Chrome 62+, password auto-fill simulates focusin !event.isSimulated && // In Firefox, a click on an `option` element bubbles up directly // to the document. event.target !== document && // In Firefox stopPropagation() doesn’t prevent right-click events // from bubbling. So make sure the event wasn’t a right-click. // $FlowFixMe event.which !== 3) { dispatchEvent(inputElement, EVENT_NAME.INPUT_CLOSE); } }; document.addEventListener('focusin', onDocumentEvent); document.addEventListener('click', onDocumentEvent); inputElement.addEventListener(EVENT_NAME.UNMOUNT, function () { document.removeEventListener('focusin', onDocumentEvent); document.removeEventListener('click', onDocumentEvent); }); dispatchEvent(inputElement, EVENT_NAME.INPUT_CLOSE); picker.subscribeToSelection(function (_ref4) { var value = _ref4.value; if (value === inputElement.value) { return; } inputElement.value = value; var event = new CustomEvent('change'); inputElement.dispatchEvent(event); }); }; ///////////// // HELPERS // ///////////// var createDocumentElement = function createDocumentElement(_ref5) { var _ref5$tagName = _ref5.tagName, tagName = _ref5$tagName === void 0 ? 'div' : _ref5$tagName, className = _ref5.className, attributes = _ref5.attributes, children = _ref5.children; var element = document.createElement(tagName); addAttributes(element, _objectSpread({}, attributes, { className: flatten(['pickadate--element', className]) })); appendChildren(element, children); return element; }; var appendChildren = function appendChildren(element, children) { if (children == null) { return; } children = Array.isArray(children) ? children : [children]; children.forEach(function (child) { if (!(child instanceof Node)) { child = typeof child !== 'string' ? child.toString() : child; child = document.createTextNode(child); } element.appendChild(child); }); }; var addAttributes = function addAttributes(element, attributes) { if (!attributes) { return; } Object.keys(attributes).forEach(function (attributeName) { // $FlowFixMe var attributeValue = attributes[attributeName]; if (attributeValue == null) { return; } if (typeof attributeValue === 'function') { element.addEventListener(attributeName.replace(/^on/, '').toLowerCase(), attributeValue); return; } if (attributeName === 'className') { // $FlowFixMe addClassName(element, attributeValue); return; } if (attributeName === 'dataset') { // $FlowFixMe Object.keys(attributeValue).forEach(function (datasetName) { var fullDatasetName = "data-".concat(caseDash(datasetName)); // $FlowFixMe element.setAttribute(fullDatasetName, attributeValue[datasetName]); }); return; } // $FlowFixMe element.setAttribute(attributeName, attributeValue); }); }; var addClassName = function addClassName(element, className) { if (!className) { return; } var list = Array.isArray(className) ? className : [className]; list.forEach(function (item) { if (!item) { return; } if (typeof item === 'string') { item = _defineProperty({}, item, true); } if (Array.isArray(item)) { item.forEach(function (className) { if (className && typeof className === 'string') { element.classList.add(className); } }); return; } Object.keys(item).forEach(function (className) { // $FlowFixMe if (className && typeof className === 'string' && item[className]) { element.classList.add(className); } }); }); }; var dispatchEvent = function dispatchEvent(element, eventName) { var customEvent = new CustomEvent(eventName); element.dispatchEvent(customEvent); }; var CLASS_NAME_MAP = { inputRoot: 'pickadate--input-root', root: 'pickadate--root', root__active: 'pickadate--root__active', header: 'pickadate--header', body: 'pickadate--body', footer: 'pickadate--footer', monthAndYear: 'pickadate--monthAndYear', monthAndYear_month: 'pickadate--monthAndYear_month', monthAndYear_year: 'pickadate--monthAndYear_year', grid: 'pickadate--grid', grid__focused: 'pickadate--grid__focused', grid_row: 'pickadate--grid_row', grid_row__label: 'pickadate--grid_row__label', grid_label: 'pickadate--grid_label', grid_cell: 'pickadate--grid_cell', grid_cell__today: 'pickadate--grid_cell__today', grid_cell__highlighted: 'pickadate--grid_cell__highlighted', grid_cell__selected: 'pickadate--grid_cell__selected', grid_cell__outOfView: 'pickadate--grid_cell__outOfView', grid_cell__disabled: 'pickadate--grid_cell__disabled', button_previous: ['pickadate--button', 'pickadate--button__previous'], button_today: ['pickadate--button', 'pickadate--button__today'], button_next: ['pickadate--button', 'pickadate--button__next'], button_clear: ['pickadate--button', 'pickadate--button__clear'], button_meridiem: ['pickadate--button', 'pickadate--button__meridiem'], time: 'pickadate--time', time_hours: ['pickadate--time_unit', 'pickadate--time_unit__hours'], time_minutes: ['pickadate--time_unit', 'pickadate--time_unit__minutes'], time_separator: 'pickadate--time_separator', time_input: 'pickadate--time_input', time_input__hours: 'pickadate--time_input__hours', time_input__minutes: 'pickadate--time_input__minutes', time_counter: 'pickadate--time_counter', time_counter__up: 'pickadate--time_counter__up', time_counter__down: 'pickadate--time_counter__down' }; var RENDER_OPTIONS = { mode: 'date', renderCell: function renderCell() {}, className: CLASS_NAME_MAP }; var TEMPLATE_HOOK_WORDS = { MMM: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], MMMM: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], DDD: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], DDDD: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] }; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var performanceNow$1 = createCommonjsModule(function (module) { // Generated by CoffeeScript 1.12.2 (function() { var getNanoSeconds, hrtime$$1, loadTime, moduleLoadTime, nodeLoadTime, upTime; if ((typeof performance !== "undefined" && performance !== null) && performance.now) { module.exports = function() { return performance.now(); }; } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) { module.exports = function() { return (getNanoSeconds() - nodeLoadTime) / 1e6; }; hrtime$$1 = process.hrtime; getNanoSeconds = function() { var hr; hr = hrtime$$1(); return hr[0] * 1e9 + hr[1]; }; moduleLoadTime = getNanoSeconds(); upTime = process.uptime() * 1e9; nodeLoadTime = moduleLoadTime - upTime; } else if (Date.now) { module.exports = function() { return Date.now() - loadTime; }; loadTime = Date.now(); } else { module.exports = function() { return new Date().getTime() - loadTime; }; loadTime = new Date().getTime(); } }).call(commonjsGlobal); }); var root = typeof window === 'undefined' ? commonjsGlobal : window , vendors = ['moz', 'webkit'] , suffix = 'AnimationFrame' , raf = root['request' + suffix] , caf = root['cancel' + suffix] || root['cancelRequest' + suffix]; for(var i = 0; !raf && i < vendors.length; i++) { raf = root[vendors[i] + 'Request' + suffix]; caf = root[vendors[i] + 'Cancel' + suffix] || root[vendors[i] + 'CancelRequest' + suffix]; } // Some versions of FF have rAF but not cAF if(!raf || !caf) { var last = 0 , id$1 = 0 , queue$1 = [] , frameDuration = 1000 / 60; raf = function(callback) { if(queue$1.length === 0) { var _now = performanceNow$1() , next = Math.max(0, frameDuration - (_now - last)); last = next + _now; setTimeout(function() { var cp = queue$1.slice(0); // Clear queue here to prevent // callbacks from appending listeners // to the current frame's queue queue$1.length = 0; for(var i = 0; i < cp.length; i++) { if(!cp[i].cancelled) { try{ cp[i].callback(last); } catch(e) { setTimeout(function() { throw e }, 0); } } } }, Math.round(next)); } queue$1.push({ handle: ++id$1, callback: callback, cancelled: false }); return id$1 }; caf = function(handle) { for(var i = 0; i < queue$1.length; i++) { if(queue$1[i].handle === handle) { queue$1[i].cancelled = true; } } }; } var raf_1 = function(fn) { // Wrap in a new function to prevent // `cancel` potentially being assigned // to the native rAF function return raf.call(root, fn) }; var cancel = function() { caf.apply(root, arguments); }; var polyfill = function(object) { if (!object) { object = root; } object.requestAnimationFrame = raf; object.cancelAnimationFrame = caf; }; raf_1.cancel = cancel; raf_1.polyfill = polyfill; function createStore(initialState) { var state = initialState; var addActor = function addActor(actor) { return function (payload) { /* istanbul ignore next */ if (process.env.NODE_ENV === 'development') { console.log('Updating state using %o and payload %o', actor.name, payload); } var nextPartialState = actor(state, payload); var nextState = nextPartialState ? _objectSpread({}, state, copyDefinedValues(nextPartialState)) : state; notify(nextState); }; }; var animationFrameId = null; var listeners = []; var notify = function notify(nextState) { if (state === nextState) { return; } state = nextState; if (animationFrameId) { raf_1.cancel(animationFrameId); } animationFrameId = raf_1(function () { return listeners.forEach(function (listener) { return listener(); }); }); }; var subscribe = function subscribe(listener) { listeners.push(listener); return function () {