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:...