@salimzakari/ngx-time-picker
Version:
An angular time picker component that allows user to select time.
211 lines (205 loc) • 15.5 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, Component, Self, Optional, Input, Output, ViewChild, ViewChildren, HostListener, NgModule } from '@angular/core';
import * as i1 from '@angular/forms';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
class NgxTimePickerComponent {
el;
control;
placeholder = "";
inputClass = "";
selectedClass = "";
dropdownClass = "";
selectInputChange = new EventEmitter();
top = 0;
left = 0;
selectedHour = "00";
selectedMinute = "00";
dropdownOpen = false;
selectedOption = null;
hours = Array.from(new Array(24).keys()).map((_, i) => `${i < 10 ? '0' : ''}${i}`);
minutes = Array.from(new Array(60).keys()).map((_, i) => `${i < 10 ? '0' : ''}${i}`);
input;
hourElements;
minuteElements;
hourContainer;
minuteContainer;
onTouched = () => { };
onChanged = (item) => { };
constructor(el, control) {
this.el = el;
this.control = control;
if (this.control)
this.control.valueAccessor = this;
}
get invalid() {
return this.control ? this.control.invalid : false;
}
get disabled() {
return this.control ? this.control.disabled : false;
}
get showError() {
if (!this.control) {
return false;
}
const { dirty, touched } = this.control;
return this.invalid ? (dirty || touched) : false;
}
writeValue(item) {
this.selectedHour = item?.split(':')[0] || "00";
this.selectedMinute = item?.split(':')[1] || "00";
if (this.hourContainer && this.minuteContainer && this.hourElements && this.minuteElements)
this.scrollToPosition();
}
scrollToPosition() {
const scrollTop = this.hourContainer?.nativeElement.scrollTop;
const containerRect = this.hourContainer?.nativeElement.getBoundingClientRect();
const top = this.hourElements?.get(+this.selectedHour)?.nativeElement?.getBoundingClientRect()?.top;
const scrollPosition = top - containerRect?.top + scrollTop;
this.hourContainer?.nativeElement?.scrollTo({
top: scrollPosition,
behavior: "smooth"
});
const m_scrollTop = this.minuteContainer?.nativeElement.scrollTop;
const m_containerRect = this.minuteContainer?.nativeElement.getBoundingClientRect();
const m_top = this.minuteElements?.get(+this.selectedMinute)?.nativeElement?.getBoundingClientRect()?.top;
const m_scrollPosition = m_top - m_containerRect?.top + m_scrollTop;
this.minuteContainer?.nativeElement?.scrollTo({
top: m_scrollPosition,
behavior: "smooth"
});
}
registerOnChange(fn) {
this.onChanged = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
selectHour(hour) {
this.selectedHour = hour;
const value = this.selectedHour + ":" + this.selectedMinute;
this.onTouched();
this.writeValue(value);
this.onChanged(value);
}
selectMinute(minute) {
this.selectedMinute = minute;
const value = this.selectedHour + ":" + this.selectedMinute;
this.onTouched();
this.writeValue(value);
this.onChanged(value);
}
clickout(event) {
if (!this.el.nativeElement.contains(event.target) && this.dropdownOpen) {
this.dropdownOpen = false;
this.onTouched(); //Calls onTouched whenever dropdown is closed, check if there's a validation error
}
}
onResize() {
this.updatePosition();
}
onScroll() {
this.updatePosition();
}
toggleDropdown() {
if (this.dropdownOpen)
this.onTouched(); //Calls onTouched whenever dropdown is closed, check if there's a validation error
this.dropdownOpen = !this.dropdownOpen;
if (this.dropdownOpen) {
setTimeout(() => {
this.scrollToPosition();
}, 10);
this.updatePosition();
}
}
selectNow() {
const date = new Date();
this.selectHour(date.toTimeString().split(":")[0]);
this.selectMinute(date.toTimeString().split(":")[1]);
this.toggleDropdown();
}
emitChange() {
this.onTouched();
this.selectInputChange.emit();
}
updatePosition = () => {
this.top = this.input?.nativeElement.getBoundingClientRect().top + this.input?.nativeElement.getBoundingClientRect().height;
this.left = this.input?.nativeElement.getBoundingClientRect().left;
};
ngAfterViewInit() {
setTimeout(() => {
this.updatePosition();
}, 0);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxTimePickerComponent, deps: [{ token: i0.ElementRef }, { token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: NgxTimePickerComponent, isStandalone: false, selector: "ngx-time-picker", inputs: { placeholder: "placeholder", inputClass: "inputClass", selectedClass: "selectedClass", dropdownClass: "dropdownClass" }, outputs: { selectInputChange: "selectInputChange" }, host: { listeners: { "document:click": "clickout($event)", "window:resize": "onResize($event)", "window:scroll": "onScroll($event)" } }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true }, { propertyName: "hourContainer", first: true, predicate: ["hourContainer"], descendants: true }, { propertyName: "minuteContainer", first: true, predicate: ["minuteContainer"], descendants: true }, { propertyName: "hourElements", predicate: ["hour"], descendants: true }, { propertyName: "minuteElements", predicate: ["minute"], descendants: true }], ngImport: i0, template: "<div class=\"ngx-time-picker\">\n <input #input [ngClass]=\"{'ngx-time-picker-error': showError}\" (click)=\"toggleDropdown()\" type=\"text\"\n [readOnly]=\"true\" [value]=\"selectedHour || selectedMinute ? selectedHour+':'+selectedMinute : null\"\n [placeholder]=\"placeholder\" [disabled]=\"disabled\" (change)=\"emitChange()\" class=\"time-picker-input\"\n [class]=\"inputClass\" />\n <div *ngIf=\"dropdownOpen\" class=\"ngx-time-picker-dropdown\" [style.top]=\"top+'px'\" [style.left]=\"left+'px'\"\n [class]=\"dropdownClass\">\n <div class=\"ngx-time-picker-time-options\">\n <ul #hourContainer>\n <li #hour *ngFor=\"let hour of hours\" class=\"time-option\" (click)=\"selectHour(hour)\"\n [ngClass]=\" hour == selectedHour && selectedClass.length != 0 ? selectedClass : hour == selectedHour ? 'ngx-time-picker-selected' : ''\">\n {{hour}}\n </li>\n </ul>\n <ul #minuteContainer>\n <li #minute *ngFor=\"let minute of minutes\" class=\"time-option\" (click)=\"selectMinute(minute)\"\n [ngClass]=\" minute == selectedMinute && selectedClass.length != 0 ? selectedClass : minute == selectedMinute ? 'ngx-time-picker-selected' : ''\">\n {{minute}}\n </li>\n </ul>\n </div>\n <div class=\"ngx-time-picker-selected\">\n <button type=\"button\" (click)=\"toggleDropdown()\">Ok</button>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}.ngx-time-picker{display:block;position:relative}.ngx-time-picker ::-webkit-scrollbar{width:5px;height:5px}.ngx-time-picker ::-webkit-scrollbar-track{box-shadow:inset 0 0 40px #f1f1f1;border-radius:10px}.ngx-time-picker ::-webkit-scrollbar-thumb{background:#ccc;border-radius:10px}.ngx-time-picker ::-webkit-scrollbar-thumb:hover{opacity:.6}.ngx-time-picker .ngx-time-picker-icon-prefix{position:absolute;top:.5rem;left:.625rem;z-index:10;cursor:pointer}.ngx-time-picker .ngx-time-picker-icon-suffix{position:absolute;top:.5rem;right:.625rem;z-index:10;cursor:pointer}.ngx-time-picker .ngx-time-picker-input{position:relative;width:100%;appearance:none;text-align:center}.ngx-time-picker .ngx-time-picker-error{border:1px solid #c82020}.ngx-time-picker .ngx-time-picker-dropdown{position:fixed;z-index:20;border-radius:1rem;padding:.5rem .3rem;font-size:.875rem;box-shadow:0 4px 8px #0000001a;background:#fff}.ngx-time-picker .ngx-time-picker-time-options{display:flex;gap:.5rem;margin-top:.5rem;max-height:200px}.ngx-time-picker .ngx-time-picker-time-options ul{list-style:none;flex:1;display:flex;flex-direction:column;overflow-y:auto;margin:0;padding:0}.ngx-time-picker .ngx-time-picker-time-options li{padding:.25rem 1rem;margin:.25rem 0;cursor:pointer;text-align:center;border-radius:.75rem}.ngx-time-picker .ngx-time-picker-time-options .ngx-time-picker-selected{background:#000;color:#fff}.ngx-time-picker .ngx-time-picker-selected{display:flex;gap:.75rem;align-items:center;padding-top:.5rem}.ngx-time-picker .ngx-time-picker-selected button{width:100%;outline:none;background:none;border-radius:.75rem;cursor:pointer;padding:.2rem;border:none}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxTimePickerComponent, decorators: [{
type: Component,
args: [{ standalone: false, selector: 'ngx-time-picker', template: "<div class=\"ngx-time-picker\">\n <input #input [ngClass]=\"{'ngx-time-picker-error': showError}\" (click)=\"toggleDropdown()\" type=\"text\"\n [readOnly]=\"true\" [value]=\"selectedHour || selectedMinute ? selectedHour+':'+selectedMinute : null\"\n [placeholder]=\"placeholder\" [disabled]=\"disabled\" (change)=\"emitChange()\" class=\"time-picker-input\"\n [class]=\"inputClass\" />\n <div *ngIf=\"dropdownOpen\" class=\"ngx-time-picker-dropdown\" [style.top]=\"top+'px'\" [style.left]=\"left+'px'\"\n [class]=\"dropdownClass\">\n <div class=\"ngx-time-picker-time-options\">\n <ul #hourContainer>\n <li #hour *ngFor=\"let hour of hours\" class=\"time-option\" (click)=\"selectHour(hour)\"\n [ngClass]=\" hour == selectedHour && selectedClass.length != 0 ? selectedClass : hour == selectedHour ? 'ngx-time-picker-selected' : ''\">\n {{hour}}\n </li>\n </ul>\n <ul #minuteContainer>\n <li #minute *ngFor=\"let minute of minutes\" class=\"time-option\" (click)=\"selectMinute(minute)\"\n [ngClass]=\" minute == selectedMinute && selectedClass.length != 0 ? selectedClass : minute == selectedMinute ? 'ngx-time-picker-selected' : ''\">\n {{minute}}\n </li>\n </ul>\n </div>\n <div class=\"ngx-time-picker-selected\">\n <button type=\"button\" (click)=\"toggleDropdown()\">Ok</button>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}.ngx-time-picker{display:block;position:relative}.ngx-time-picker ::-webkit-scrollbar{width:5px;height:5px}.ngx-time-picker ::-webkit-scrollbar-track{box-shadow:inset 0 0 40px #f1f1f1;border-radius:10px}.ngx-time-picker ::-webkit-scrollbar-thumb{background:#ccc;border-radius:10px}.ngx-time-picker ::-webkit-scrollbar-thumb:hover{opacity:.6}.ngx-time-picker .ngx-time-picker-icon-prefix{position:absolute;top:.5rem;left:.625rem;z-index:10;cursor:pointer}.ngx-time-picker .ngx-time-picker-icon-suffix{position:absolute;top:.5rem;right:.625rem;z-index:10;cursor:pointer}.ngx-time-picker .ngx-time-picker-input{position:relative;width:100%;appearance:none;text-align:center}.ngx-time-picker .ngx-time-picker-error{border:1px solid #c82020}.ngx-time-picker .ngx-time-picker-dropdown{position:fixed;z-index:20;border-radius:1rem;padding:.5rem .3rem;font-size:.875rem;box-shadow:0 4px 8px #0000001a;background:#fff}.ngx-time-picker .ngx-time-picker-time-options{display:flex;gap:.5rem;margin-top:.5rem;max-height:200px}.ngx-time-picker .ngx-time-picker-time-options ul{list-style:none;flex:1;display:flex;flex-direction:column;overflow-y:auto;margin:0;padding:0}.ngx-time-picker .ngx-time-picker-time-options li{padding:.25rem 1rem;margin:.25rem 0;cursor:pointer;text-align:center;border-radius:.75rem}.ngx-time-picker .ngx-time-picker-time-options .ngx-time-picker-selected{background:#000;color:#fff}.ngx-time-picker .ngx-time-picker-selected{display:flex;gap:.75rem;align-items:center;padding-top:.5rem}.ngx-time-picker .ngx-time-picker-selected button{width:100%;outline:none;background:none;border-radius:.75rem;cursor:pointer;padding:.2rem;border:none}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.NgControl, decorators: [{
type: Self
}, {
type: Optional
}] }], propDecorators: { placeholder: [{
type: Input
}], inputClass: [{
type: Input
}], selectedClass: [{
type: Input
}], dropdownClass: [{
type: Input
}], selectInputChange: [{
type: Output
}], input: [{
type: ViewChild,
args: ['input']
}], hourElements: [{
type: ViewChildren,
args: ['hour']
}], minuteElements: [{
type: ViewChildren,
args: ['minute']
}], hourContainer: [{
type: ViewChild,
args: ['hourContainer']
}], minuteContainer: [{
type: ViewChild,
args: ['minuteContainer']
}], clickout: [{
type: HostListener,
args: ['document:click', ['$event']]
}], onResize: [{
type: HostListener,
args: ['window:resize', ['$event']]
}], onScroll: [{
type: HostListener,
args: ['window:scroll', ['$event']]
}] } });
class NgxTimePickerModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxTimePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: NgxTimePickerModule, declarations: [NgxTimePickerComponent], imports: [CommonModule], exports: [NgxTimePickerComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxTimePickerModule, imports: [CommonModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxTimePickerModule, decorators: [{
type: NgModule,
args: [{
declarations: [
NgxTimePickerComponent
],
imports: [
CommonModule
],
exports: [
NgxTimePickerComponent,
]
}]
}] });
/*
* Public API Surface of ngx-time-picker
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxTimePickerComponent, NgxTimePickerModule };
//# sourceMappingURL=salimzakari-ngx-time-picker.mjs.map