JSFiddle - React, Tailwind, and code Playground

by levchenko_d

HTML

<input type="text">

CSS

.dp-modal{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.25)}.dp{position:relative;border:1px solid #DDD;background:#FFF;line-height:1.4;border-radius:4px;max-height:400px;z-index:1000;overflow:auto !important}.dp-cal{min-height:300px}.dp-below{position:absolute;font-size:.8em;width:400px;max-width:100vw}.dp-modal .dp{position:absolute;top:50%;left:50%;max-width:600px;width:calc(100% - 4em);transform:translate(-50%,-50%);box-shadow:0 0 5em rgba(0,0,0,0.45);animation:slide-up .3s forwards}.dp-months{padding:1em}.dp-cal-month,.dp-cal-year,.dp-day,.dp-month,.dp-year{box-sizing:border-box;text-align:center;text-decoration:none;position:relative;color:#3b404d}.dp-cal-header{position:relative;text-align:center;margin-bottom:.5em}.dp-next,.dp-prev{position:absolute;width:30px;height:30px;overflow:hidden;top:1em;color:#777;transition:color .2s}.dp-next:focus,.dp-prev:focus,.dp-next:hover,.dp-prev:hover{outline:0;color:inherit}.dp-prev{left:1.4em}.dp-next{right:1.4em}.dp-prev:before,.dp-next:before{content:'';border:2px solid;width:10px;height:10px;display:inline-block;transform:rotate(-45deg);transition:border-color .2s;margin:.5em 0 4em}.dp-prev:before{border-right:0;border-bottom:0}.dp-next:before{border-left:0;border-top:0}.dp-cal-month,.dp-cal-year{display:inline-block;font-size:1.4em;padding:.75em .25em .5em;outline:0}.dp-cal-footer{text-align:center}.dp-day-today:after{content:'';height:0;width:0;border:7px solid...

JavaScript

// Beginning of module definition /////////////////////////////////////////////////////////////////
var TinyDatePicker = (function() {

// Indenting all the way over, since the rest of the source is really one module
'use strict';

// Constants...
var left = 37;
var up = 38;
var right = 39;
var down = 40;
var CustomEvent = getCustomEventConstructor();

// The module export...
return TinyDatePicker;

// Constructs a new instance of the tiny date picker
function TinyDatePicker(input, opts) {
  var context = buildContext(input, opts || {});

  if (context.isModal) {
    input.readOnly = true;
  } else {
    // For the dropdown calendar, we need to hide when the input loses focus
    // for the modal, we never do this.
    on('blur', input, buffer(5, function () {
      if (context.el && !context.el.contains(document.activeElement)) {
        hideCalendar(context);
      }
    }));
  }

  var bufferShow = buffer(5, function () {
    if (context.isModal && isShowing(context)) {
      hideCalendar(context);
    } else {
      showCalendar(context);
    }
  });

  function tryUpdateDate(e) {
    var date = new Date(e.target.value);
    isNaN(date) || context.onChange(date, true);
  }

  // With the modal, we always begin and end by setting focus to the input
  // so that tabbing works as expected. This means the focus event needs
  // to be smart. With the dropdown, we only ever show on focus.
  on('click', input, bufferShow);
  on('focus', input, bufferShow);
  on('input', input, tryUpdateDate);
}

// Builds the date picker's settings based on the opts provided.
function buildContext(input, opts) {
  var context = {
    input: input,
    mode: opts.mode || 'dp-modal',
    days: opts.days || ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    months: opts.months || ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    today: opts.today || 'Today',
    clear: opts.clear || 'Clear',
    close:...