UNPKG

unicorn-components

Version:

<a target="_blank" href="https://getunicorn.io"><img src="https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2017/Jul/07/2615006260-5-nitsnetsstudios-ondemand-UNI_avatar.png" align="left"></a>

175 lines (156 loc) 5.98 kB
import { Component, EventEmitter, HostBinding, Input, OnChanges, Output } from '@angular/core'; import { pad } from '../../../utils'; const HOUR_PATTERN = /^(\d|[01]\d|2[0-3]):?([0-5]\d)$/; @Component({ selector: 'uni-clock', templateUrl: 'clock.component.html', styleUrls: ['clock.component.scss'], }) export class UniClockComponent implements OnChanges { @HostBinding('class.uni-clock') componentClass = true; @Input() model = '00:00'; @Output() modelChange = new EventEmitter(); @Input() set min(value: string) { if (!value) { return; } if (!HOUR_PATTERN.test(value)) { console.warn(`Invalid hour format: ${value}`); return; } const arr = value.split(':'); this.hourMin = +arr[0]; this.minuteMin = +arr[1]; this.refreshModeAvailability(); this.refreshHoursAvailable(); this.refreshMinutesAvailable(); const { hour, minute } = this.getHourMinuteFromModel(); this.updateValue(hour, minute); }; @Input() set max(value: string) { if (!value) { return; } if (!HOUR_PATTERN.test(value)) { console.warn(`Invalid hour format: ${value}`); return; } const arr = value.split(':'); this.hourMax = +arr[0]; this.minuteMax = +arr[1]; this.refreshModeAvailability(); this.refreshHoursAvailable(); this.refreshMinutesAvailable(); this.updateValueFromModel(); }; mode: 'AM' | 'PM' = 'AM'; modeAvailability = { AM: true, PM: true }; hoursModes = { AM: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11'], PM: ['12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'] }; hours: string[] = this.hoursModes['AM']; minutes: string[] = ['00', '05', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55']; minutesAvailable: boolean[] = this.minutes.map(h => true); hoursAvailable: boolean[] = this.hours.map(h => true); hour = 0; hourIndex = 0; hourDegrees = 0; hourMax = 23; hourMin = 0; minute = 0; minuteIndex = 0; minuteDegrees = 0; minuteMax = 59; minuteMin = 0; ngOnChanges(changes) { if (changes.model) { this.updateValueFromModel(); this.refreshHoursAvailable(); this.refreshMinutesAvailable(); } } selectMode(mode) { if (!this.modeAvailability[mode]) { return; } this.setMode(mode); this.updateValueFromIndex(); this.refreshHoursAvailable(); this.refreshMinutesAvailable(); } selectHour(index) { if (!this.hoursAvailable[index]) { return; } this.hourIndex = index; this.updateValueFromIndex(); this.refreshMinutesAvailable(); } selectMinute(index) { if (!this.minutesAvailable[index]) { return; } this.minuteIndex = index; this.updateValueFromIndex(); } private refreshModeAvailability() { this.modeAvailability = { AM: this.hourMin < 12, PM: this.hourMax >= 12 }; } private refreshHoursAvailable() { this.hoursAvailable = this.hours.map(h => +h >= this.hourMin && +h <= this.hourMax); } private refreshMinutesAvailable() { if (this.hour > this.hourMin && this.hour < this.hourMax) { return this.minutesAvailable = this.minutes.map(m => true); } if (this.hour < this.hourMin || this.hour > this.hourMax) { return this.minutesAvailable = this.minutes.map(m => false); } const minMinute = this.hour === this.hourMin ? this.minuteMin : 0; const maxMinute = this.hour === this.hourMax ? this.minuteMax : 59; this.minutesAvailable = this.minutes.map(m => +m >= minMinute && +m <= maxMinute) } private setMode(mode) { this.mode = mode; this.hours = this.hoursModes[mode]; } private applyDegrees() { this.minuteDegrees = 6 * this.minute; this.hourDegrees = 30 * (this.hour % 12) + this.minuteDegrees / 12; } private updateValue(hour, minute) { // Set the clock hours and minutes as integers if (hour < this.hourMin) { this.hour = this.hourMin; this.minute = this.minuteMin; } else if (hour > this.hourMax) { this.hour = this.hourMax; this.minute = this.minuteMax; } else { this.hour = hour; this.minute = minute; if (hour === this.hourMin) { this.minute = Math.max(this.minuteMin, this.minute); } if (hour === this.hourMax) { this.minute = Math.min(this.minuteMax, this.minute); } } // Set the right mode if (this.hour >= 12 && this.mode !== 'PM') { this.setMode('PM'); } else if (this.hour < 12 && this.mode !== 'AM') { this.setMode('AM'); } const paddedHour = pad(this.hour, 2); const paddedMinute = pad(this.minute, 2); // Set the clock indexes to highlight the numbers this.hourIndex = this.hours.indexOf(paddedHour); this.minuteIndex = this.minutes.indexOf(paddedMinute); this.model = `${paddedHour}:${paddedMinute}`; this.modelChange.emit(this.model); this.applyDegrees(); } private updateValueFromIndex() { const { hour, minute } = this.getHourMinuteFromIndex(); this.updateValue(hour, minute); } private updateValueFromModel() { const { hour, minute } = this.getHourMinuteFromModel(); this.updateValue(hour, minute); } private getHourMinuteFromIndex() { return { hour: +this.hours[this.hourIndex], minute: +this.minutes[this.minuteIndex] }; } private getHourMinuteFromModel() { const timeSplitted = (this.model || '00:00').split(':'); return { hour: +timeSplitted[0], minute: +timeSplitted[1] }; } }