UNPKG

@salimzakari/ngx-time-picker

Version:

An angular time picker component that allows user to select time.

211 lines (205 loc) 15.5 kB
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