JSFiddle - React, Tailwind, and code Playground

by neonDog

HTML

<div class="time-picker"></div>

SCSS

/*

 Project: Material Time Picker
 Author: @mackness

*/


/* DEFAULTS
   ----------------------------- */

* {
	margin: 0;
	padding: 0;
	font-family: 'Roboto', sans-serif;
  box-sizing: border-box;
}

body {
	color: #1f1f1f;
	font-size: 62.5%;
	background-color: #646464;
  //zoom: 65%;
}

button {
	outline: 0;
	border: 0;
	color: #009688;
	cursor: pointer;
	font-size: 2.0em;
	padding: 14px 25px;
	border-radius: 4px;
	background-color: transparent;
}

button:focus
button:active,
button:hover {
	background-color: #ededed;
}

/* TIME PICKER
   ----------------------------- */
$hand-color: #5D8CAE;

.time-picker {
	top: 50%;
	left: 50%;
	width: 100%;
	width: 400px;
	overflow: hidden;
	border-radius: 5px;
	background-color: #fff;
	position: absolute;
	box-shadow: 0 0 45px rgba(#000, 0.55); 
	transform: translate(-50%,-50%);
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  
  &.hour24 .control-block {
    display:none;
  }
}

.digital {
	padding: 25px 0 20px 0;
	background-color: #5D8CAE;//#009688;
}

.digital--inner {
	display: block; 
	text-align: center;
}

.digital--clock {
	color: #fff;
	font-size: 7.3em;
}

.control-block {
	display: inline-block;
}

.digital--period {
	display: block;
	color: #fff;
	cursor: pointer;
	font-size: 2.0em;
  opacity:0.3;
  &.active {
    opacity: 0.7;	
  }
}

.digital--clock > span {
	transition: opacity 100ms linear;
}

.hours-state .digital--clock .minutes {
	opacity: 0.6;
}

.minutes-state .digital--clock .hours {
	opacity: 0.6;	
}

.smaller {
	font-size: 0.9em;
}


/* ANALOG CLOCK
   ----------------------------- */

.analog {
  width: 100%;
	height: 0px;
  padding-bottom:100%;
	position: relative;
}

.analog--inner {
	top: 25px;
	left: 25px;
	right: 25px;
	bottom: 25px;
	position: absolute;
}

.analog--clock {
  top:0;
  right:0;
  left:0;
  bottom:0;
	position: absolute;
  transition: transform 200ms linear, opacity 200ms linear;
  border-radius: 50%;
	background-color: #dfdfdf;
 ...

JavaScript

function roundTo(x,m=5) {
  return Math.ceil(x/m)*m;
}

function clockPositioning(offset=0.85,num=12) {
	const arr = [];
  const half = num / 2;
  for (let i=0; i<num; i++) {
    const radian = Math.PI/2 + (i*Math.PI/half);
    const x = 0.5 - (offset * Math.cos(radian)/2);
    const y = 0.5 - (offset *Math.sin(radian)/2);
    arr.push([i,y,x]);
  }
  return arr;
}


class NeonTimePicker {

	constructor(container, settings={}) {
  	
    this.defaults = {
    	hour12:false,
      nth:{
      	hour12:false,
        hour24:3,
        minute:false,
        html:'đź’©',
        html:false
      },
      value:'12:30', // current value
      onChange:function(time){}
    };
    
    this.options = Object.assign({},this.defaults,settings);
    
    this.container = container;
    
    this.render();
    
    this.period = 'am';
    
    this.animate = this.animate.bind(this);
    this._mouseup = this._mouseup.bind(this);
    this._mousedown = this._mousedown.bind(this);
    this._mousemove = this._mousemove.bind(this);
    this.eventListenersActive = false;
    this.mousemoveListenerActive = false;
    this.eventListeners(true);
    
    this.setTime(this.options.value);
    this.setFace('hours');
  }
	
  render() {
  	
    this.container.innerHTML = `
    	<div class="digital">
        <div class="digital--inner">
          <span class="digital--clock">
            <span class="hours neon-timepicker-click" data-action="face" data-face="hours"></span>:<span class="minutes neon-timepicker-click" data-action="face" data-face="minutes"></span>
          </span>
          <div class="control-block">
            <span class="digital--period neon-timepicker-click" data-action="period" data-period="am">AM</span>
            <span class="digital--period neon-timepicker-click" data-action="period" data-period="pm">PM</span>
          </div>
        </div>
      </div>
      <div class="analog">
        <div class="analog--inner">
          <div class="analog--clock...