moment-timezone-picker
Version:
A simple angular moment timezone picker
270 lines (259 loc) • 11.6 kB
JavaScript
import * as momentZone from 'moment-timezone';
import * as i0 from '@angular/core';
import { forwardRef, Component, ViewEncapsulation, ChangeDetectionStrategy, Input, NgModule } from '@angular/core';
import * as i1 from '@angular/forms';
import { NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as i2 from '@ng-select/ng-select';
import { NgSelectModule } from '@ng-select/ng-select';
const DEFAULT_SELECT_CONFIG = {
hideSelected: false,
dropdownPosition: 'auto',
appearance: 'underline',
clearOnBackspace: true,
closeOnSelect: true,
appendTo: null,
searchable: true,
};
class TZone {
}
/**
* Make TZone object from simple string.
*/
const formatZone = (zone) => {
const foundZone = momentZone.tz(zone);
const utc = foundZone.format('Z');
const abbr = foundZone.zoneAbbr();
return {
name: `${zone} (${utc})`,
nameValue: zone,
timeValue: utc,
group: zone.split('/', 1)[0],
abbr: abbr
};
};
class MomentTimezonePickerComponent {
set config(conf) {
this._config = conf;
}
get config() {
return this._config;
}
constructor(fb, cdr) {
this.fb = fb;
this.cdr = cdr;
/**
* Setup section.
*/
this.getUserZone = false;
this.customPlaceholderText = 'Choose...';
this.customNotFoundText = 'No zone found';
this.clearable = false;
this.virtualScroll = true;
this.disabled = false;
this._config = DEFAULT_SELECT_CONFIG;
this.form = this.fb.group({
timezone: []
});
this.destroy$ = new Subject();
}
/**
* Lifecycle hooks
*/
ngOnChanges(changes) {
if (changes.getUserZone && changes.getUserZone.currentValue) {
this.guessUserTimezone();
}
if (changes.disabled) {
this.toggleTimezoneCtrl(changes.disabled.currentValue);
}
}
ngOnInit() {
this.timeZones = momentZone.tz.names().map((zone) => formatZone(zone));
this.setTimezoneChangeListener();
}
ngAfterViewInit() {
this.guessUserTimezone();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
/**
* Private
*/
toggleTimezoneCtrl(isDisabled) {
isDisabled
? this.form.get('timezone').disable()
: this.form.get('timezone').enable();
this.cdr.detectChanges();
}
setTimezoneChangeListener() {
this.form.get('timezone').valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe(() => this.fireChanges());
}
guessUserTimezone() {
setTimeout(() => {
if (!this.getUserZone) {
console.warn('User zone guess turned off');
return;
}
const guessedZone = momentZone.tz.guess(true);
this.form.get('timezone').setValue(formatZone(guessedZone));
});
}
/**
* Propagate result to parent component.
*/
fireChanges() {
if (!this.propagateChange) {
return;
}
const timezone = this.form.get('timezone').value;
const transformedValue = this.valueTransformFN
? this.valueTransformFN(timezone)
: timezone;
this.propagateChange(transformedValue);
}
clearZone() {
this.form.get('timezone').reset();
}
validateZoneFromUpperLevels(zone) {
if (typeof zone === 'string' && zone.length > 0) {
return this.timeZones.find(z => z.nameValue === zone) ?? null;
}
if (typeof zone === 'object') {
return this.timeZones.find(z => z.nameValue === zone.nameValue) ?? null;
}
return null;
}
/**
* Access controls
*/
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched(fn) {
// not used
}
writeValue(zone) {
if (!zone) {
this.clearZone();
console.warn('Invalid zone passed');
return;
}
let _zone = this.validateZoneFromUpperLevels(zone);
if (_zone) {
this.form.get('timezone').setValue(_zone);
}
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: MomentTimezonePickerComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.1", type: MomentTimezonePickerComponent, selector: "ng-moment-timezone-picker", inputs: { getUserZone: "getUserZone", customPlaceholderText: "customPlaceholderText", customNotFoundText: "customNotFoundText", clearable: "clearable", virtualScroll: "virtualScroll", disabled: "disabled", valueTransformFN: "valueTransformFN", config: "config" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((() => MomentTimezonePickerComponent)),
multi: true
}
], usesOnChanges: true, ngImport: i0, template: `
<div class="wrapper" [formGroup]="form">
<ng-select [formControlName]="'timezone'"
[items]="timeZones"
[clearable]="clearable"
[virtualScroll]="virtualScroll"
[groupBy]="'group'"
bindLabel="name"
[placeholder]="customPlaceholderText"
[notFoundText]="customNotFoundText"
[appearance]="config.appearance"
[appendTo]="config.appendTo"
[clearOnBackspace]="config.clearOnBackspace"
[closeOnSelect]="config.closeOnSelect"
[dropdownPosition]="config.dropdownPosition"
[hideSelected]="config.hideSelected"
[searchable]="config.searchable">
</ng-select>
</div>
`, isInline: true, dependencies: [{ kind: "component", type: i2.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: MomentTimezonePickerComponent, decorators: [{
type: Component,
args: [{
selector: 'ng-moment-timezone-picker',
template: `
<div class="wrapper" [formGroup]="form">
<ng-select [formControlName]="'timezone'"
[items]="timeZones"
[clearable]="clearable"
[virtualScroll]="virtualScroll"
[groupBy]="'group'"
bindLabel="name"
[placeholder]="customPlaceholderText"
[notFoundText]="customNotFoundText"
[appearance]="config.appearance"
[appendTo]="config.appendTo"
[clearOnBackspace]="config.clearOnBackspace"
[closeOnSelect]="config.closeOnSelect"
[dropdownPosition]="config.dropdownPosition"
[hideSelected]="config.hideSelected"
[searchable]="config.searchable">
</ng-select>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((() => MomentTimezonePickerComponent)),
multi: true
}
],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
}]
}], ctorParameters: () => [{ type: i1.UntypedFormBuilder }, { type: i0.ChangeDetectorRef }], propDecorators: { getUserZone: [{
type: Input
}], customPlaceholderText: [{
type: Input
}], customNotFoundText: [{
type: Input
}], clearable: [{
type: Input
}], virtualScroll: [{
type: Input
}], disabled: [{
type: Input
}], valueTransformFN: [{
type: Input
}], config: [{
type: Input
}] } });
class MomentTimezonePickerModule {
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: MomentTimezonePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.1.1", ngImport: i0, type: MomentTimezonePickerModule, declarations: [MomentTimezonePickerComponent], imports: [NgSelectModule,
FormsModule,
ReactiveFormsModule], exports: [MomentTimezonePickerComponent] }); }
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: MomentTimezonePickerModule, imports: [NgSelectModule,
FormsModule,
ReactiveFormsModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: MomentTimezonePickerModule, decorators: [{
type: NgModule,
args: [{
declarations: [MomentTimezonePickerComponent],
imports: [
NgSelectModule,
FormsModule,
ReactiveFormsModule
],
exports: [MomentTimezonePickerComponent]
}]
}] });
/*
* Public API Surface of moment-timezone-picker
*/
/**
* Generated bundle index. Do not edit.
*/
export { DEFAULT_SELECT_CONFIG, MomentTimezonePickerComponent, MomentTimezonePickerModule, TZone, formatZone };
//# sourceMappingURL=moment-timezone-picker.mjs.map