forked from NationalBankBelgium/stark
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(stark-ui): add
stark-date-time-picker
component
- add component - add demo CLOSES ISSUE: NationalBankBelgium#587
- Loading branch information
1 parent
686c0f7
commit a67cd67
Showing
16 changed files
with
378 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,59 @@ | ||
/* Stark styles */ | ||
@import "../assets/styles/base"; | ||
@import "../assets/theming/base-theme"; | ||
@import "../assets/styles/base"; | ||
@import "../assets/styles/components/button"; | ||
@import "../assets/styles/components/button-theme"; | ||
@import "../assets/styles/components/icon"; | ||
@import "../assets/styles/components/card"; | ||
@import "../assets/styles/components/card-theme"; | ||
@import "../assets/styles/components/header"; | ||
@import "../assets/styles/components/header-theme"; | ||
@import "../assets/styles/components/icon"; | ||
/* Stark components */ | ||
@import "../src/modules/app-logo/components/app-logo.component"; | ||
@import "../src/modules/app-logo/components/app-logo-theme"; | ||
@import "../src/modules/app-data/components/app-data.component"; | ||
@import "../src/modules/action-bar/components/action-bar-theme"; | ||
@import "../src/modules/action-bar/components/action-bar.component"; | ||
@import "../src/modules/app-data/components/app-data-theme"; | ||
@import "../src/modules/app-footer/components/app-footer.component"; | ||
@import "../src/modules/app-data/components/app-data.component"; | ||
@import "../src/modules/app-footer/components/app-footer-theme"; | ||
@import "../src/modules/app-menu/components/app-menu.component"; | ||
@import "../src/modules/app-footer/components/app-footer.component"; | ||
@import "../src/modules/app-logo/components/app-logo-theme"; | ||
@import "../src/modules/app-logo/components/app-logo.component"; | ||
@import "../src/modules/app-menu/components/app-menu-theme"; | ||
@import "../src/modules/action-bar/components/action-bar.component"; | ||
@import "../src/modules/action-bar/components/action-bar-theme"; | ||
@import "../src/modules/app-sidebar/components/app-sidebar.component"; | ||
@import "../src/modules/app-menu/components/app-menu.component"; | ||
@import "../src/modules/app-sidebar/components/app-sidebar-theme"; | ||
@import "../src/modules/app-sidebar/components/app-sidebar.component"; | ||
@import "../src/modules/breadcrumb/components/breadcrumb.component"; | ||
@import "../src/modules/collapsible/components/collapsible.component"; | ||
@import "../src/modules/collapsible/components/collapsible-theme"; | ||
@import "../src/modules/collapsible/components/collapsible.component"; | ||
@import "../src/modules/date-range-picker/components/date-range-picker.component"; | ||
@import "../src/modules/date-time-picker/components/date-time-picker.component"; | ||
@import "../src/modules/dialogs/components/alert-dialog-theme"; | ||
@import "../src/modules/dialogs/components/alert-dialog.component"; | ||
@import "../src/modules/dialogs/components/confirm-dialog-theme"; | ||
@import "../src/modules/dialogs/components/prompt-dialog.component"; | ||
@import "../src/modules/dialogs/components/prompt-dialog-theme"; | ||
@import "../src/modules/dialogs/components/prompt-dialog.component"; | ||
@import "../src/modules/dropdown/components/dropdown-theme"; | ||
@import "../src/modules/dropdown/components/dropdown.component"; | ||
@import "../src/modules/generic-search/components/generic-search/generic-search.component"; | ||
@import "../src/modules/language-selector/components/language-selector.component"; | ||
@import "../src/modules/message-pane/components/message-pane.component"; | ||
@import "../src/modules/message-pane/components/message-pane-theme"; | ||
@import "../src/modules/minimap/components/minimap.component"; | ||
@import "../src/modules/message-pane/components/message-pane.component"; | ||
@import "../src/modules/minimap/components/minimap-theme"; | ||
@import "../src/modules/slider/components/slider-theme"; | ||
@import "../src/modules/pagination/components/pagination.component"; | ||
@import "../src/modules/minimap/components/minimap.component"; | ||
@import "../src/modules/pagination/components/pagination-theme"; | ||
@import "../src/modules/pagination/components/pagination.component"; | ||
@import "../src/modules/pretty-print/components/pretty-print.component"; | ||
@import "../src/modules/table/components/table.component"; | ||
@import "../src/modules/table/components/table-theme"; | ||
@import "../src/modules/table/components/dialogs/multisort.component"; | ||
@import "../src/modules/dropdown/components/dropdown-theme"; | ||
@import "../src/modules/route-search/components/route-search.component"; | ||
@import "../src/modules/route-search/components/route-search-theme"; | ||
@import "../src/modules/toast-notification/components/toast-notification.component"; | ||
@import "../src/modules/toast-notification/components/toast-notification-theme"; | ||
@import "../src/modules/dropdown/components/dropdown.component"; | ||
@import "../src/modules/route-search/components/route-search.component"; | ||
@import "../src/modules/session-ui/components/session-card/session-card.component"; | ||
@import "../src/modules/slider/components/slider-theme"; | ||
@import "../src/modules/table/components/dialogs/multisort.component"; | ||
@import "../src/modules/table/components/table-theme"; | ||
@import "../src/modules/table/components/table.component"; | ||
@import "../src/modules/toast-notification/components/toast-notification-theme"; | ||
@import "../src/modules/toast-notification/components/toast-notification.component"; | ||
/* Stark session-ui pages */ | ||
@import "../src/modules/session-ui/pages/session-ui-pages"; | ||
@import "../src/modules/session-ui/pages/login/login-page.component"; | ||
@import "../src/modules/session-ui/pages/preloading/preloading-page.component"; | ||
@import "../src/modules/session-ui/pages/session-expired/session-expired-page.component"; | ||
@import "../src/modules/session-ui/pages/session-logout/session-logout-page.component"; | ||
@import "../src/modules/session-ui/pages/session-ui-pages"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./date-time-picker/date-time-picker.module"; | ||
export * from "./date-time-picker/components"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./components/date-time-picker.component"; |
10 changes: 10 additions & 0 deletions
10
packages/stark-ui/src/modules/date-time-picker/components/date-time-picker.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<div class="date-time-wrapper" [formGroup]="dateTimeFormGroup"> | ||
<stark-date-picker formControlName="date" (dateChange)="handleChange()"></stark-date-picker> | ||
|
||
<input #timeInput [starkTimestampMask]="timeMaskConfig" matInput formControlName="time" (blur)="handleChange()" /> | ||
<div class="mat-form-field-suffix mat-datepicker-toggle"> | ||
<button mat-icon-button (click)="focusTime($event)"> | ||
<mat-icon svgIcon="clock"></mat-icon> | ||
</button> | ||
</div> | ||
</div> |
28 changes: 28 additions & 0 deletions
28
packages/stark-ui/src/modules/date-time-picker/components/date-time-picker.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
stark-date-time-picker { | ||
.date-time-wrapper { | ||
width: 100%; | ||
display: flex; | ||
|
||
input { | ||
text-align: right; | ||
} | ||
|
||
// Time | ||
> input.mat-input-element { | ||
flex: 1; | ||
} | ||
|
||
// Date | ||
> stark-date-picker { | ||
flex: 1; | ||
} | ||
} | ||
|
||
.mat-datepicker-toggle { | ||
transition: color 500ms; | ||
} | ||
|
||
&:not(.floating) .mat-datepicker-toggle { | ||
color: rgba(0, 0, 0, 0); | ||
} | ||
} |
222 changes: 222 additions & 0 deletions
222
packages/stark-ui/src/modules/date-time-picker/components/date-time-picker.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
/* tslint:disable:no-null-keyword */ | ||
import { Component, ElementRef, EventEmitter, HostBinding, Input, OnDestroy, Optional, Output, Self, ViewChild } from "@angular/core"; | ||
import { ControlValueAccessor, FormBuilder, FormGroup, NgControl } from "@angular/forms"; | ||
import { FocusMonitor, FocusOrigin } from "@angular/cdk/a11y"; | ||
import { coerceBooleanProperty } from "@angular/cdk/coercion"; | ||
import { MatFormFieldControl } from "@angular/material/form-field"; | ||
import moment from "moment"; | ||
import { Subject } from "rxjs"; | ||
import noop from "lodash-es/noop"; | ||
import { StarkTimestampMaskConfig } from "../../input-mask-directives/directives/timestamp-mask-config.intf"; | ||
|
||
@Component({ | ||
selector: "stark-date-time-picker", | ||
templateUrl: "./date-time-picker.component.html", | ||
providers: [{ provide: MatFormFieldControl, useExisting: StarkDateTimePickerComponent }] | ||
}) | ||
export class StarkDateTimePickerComponent implements MatFormFieldControl<Date>, ControlValueAccessor, OnDestroy { | ||
public stateChanges = new Subject<void>(); | ||
|
||
private static nextId = 0; | ||
@HostBinding() public id = `stark-date-time-picker${StarkDateTimePickerComponent.nextId++}`; | ||
|
||
@HostBinding("attr.aria-describedby") public describedBy = ""; | ||
|
||
@HostBinding("class.floating") | ||
public get shouldLabelFloat(): boolean { | ||
return this.focused || !this.empty; | ||
} | ||
|
||
@ViewChild("timeInput") | ||
public timeInput!: ElementRef<HTMLInputElement>; | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public setDescribedByIds(ids: string[]): void { | ||
this.describedBy = ids.join(" "); | ||
} | ||
|
||
@Input() | ||
public get value(): Date | null { | ||
return this._value; | ||
} | ||
|
||
public set value(value: Date | null) { | ||
this._value = value; | ||
this.stateChanges.next(); | ||
} | ||
|
||
private _value: Date | null = null; | ||
|
||
@Input() | ||
public get placeholder(): string { | ||
return this._placeholder; | ||
} | ||
|
||
public set placeholder(plh: string) { | ||
this._placeholder = plh; | ||
this.stateChanges.next(); | ||
} | ||
|
||
private _placeholder = ""; | ||
|
||
@Input() | ||
public get required(): boolean { | ||
return this._required; | ||
} | ||
|
||
public set required(req: boolean) { | ||
this._required = coerceBooleanProperty(req); | ||
this.stateChanges.next(); | ||
} | ||
|
||
private _required = false; | ||
|
||
@Input() | ||
public get disabled(): boolean { | ||
return this._disabled; | ||
} | ||
|
||
public set disabled(dis: boolean) { | ||
this._disabled = coerceBooleanProperty(dis); | ||
} | ||
|
||
private _disabled = false; | ||
|
||
@Input() | ||
public timeMaskConfig: StarkTimestampMaskConfig = { format: "HH:mm:ss" }; | ||
|
||
@Output() | ||
public dateTimeChange = new EventEmitter<Date | null>(); | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
private _onChange: (val: Date | null) => void = noop; | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
private _onTouched: () => void = noop; | ||
|
||
public focused = false; | ||
|
||
public get empty(): boolean { | ||
return !this.dateTimeFormGroup.value.date && !this.dateTimeFormGroup.value.time; | ||
} | ||
|
||
public get errorState(): boolean { | ||
if (!this.ngControl) { | ||
return false; | ||
} | ||
|
||
return !!this.ngControl.invalid; | ||
} | ||
|
||
public controlType = "stark-date-time-picker"; | ||
|
||
public dateTimeFormGroup: FormGroup; | ||
|
||
public constructor( | ||
private _fb: FormBuilder, | ||
@Optional() | ||
@Self() | ||
public ngControl: NgControl, | ||
private _fm: FocusMonitor, | ||
private _elRef: ElementRef | ||
) { | ||
if (this.ngControl) { | ||
this.ngControl.valueAccessor = this; | ||
} | ||
|
||
this.dateTimeFormGroup = this._fb.group({ | ||
date: null, | ||
time: null | ||
}); | ||
|
||
this._fm.monitor(this._elRef.nativeElement, true).subscribe((origin: FocusOrigin) => { | ||
this.focused = !!origin; | ||
this.stateChanges.next(); | ||
}); | ||
} | ||
|
||
/** | ||
* Angular lifecycle method | ||
*/ | ||
public ngOnDestroy(): void { | ||
this.stateChanges.complete(); | ||
} | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public onContainerClick(event: MouseEvent): void { | ||
if ((event.target as Element).tagName.toLowerCase() !== "input") { | ||
this._elRef.nativeElement.querySelector("input").focus(); | ||
} | ||
} | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public handleChange(): void { | ||
const time = this._parseTime(this.dateTimeFormGroup.value.time); | ||
const date = this.dateTimeFormGroup.value.date || new Date(0); | ||
|
||
const timeValues = !time ? [] : [time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()]; | ||
const dateTime = new Date(date.getFullYear(), date.getMonth(), date.getDate(), ...timeValues); | ||
|
||
this._onTouched(); | ||
this._onChange(dateTime); | ||
this.dateTimeChange.emit(dateTime); | ||
} | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
private _parseTime(timeValue: string = ""): Date | null { | ||
const time = moment(timeValue, this.timeMaskConfig.format); | ||
return time.isValid() ? time.toDate() : null; | ||
} | ||
|
||
/** | ||
* Focus the input for time | ||
*/ | ||
public focusTime(event: Event): void { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
|
||
this.timeInput.nativeElement.focus(); | ||
} | ||
|
||
/*Control Value Accessor methods*/ | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public writeValue(value: Date): void { | ||
this.value = value; | ||
} | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public registerOnChange(fn: (val: Date | null) => void): void { | ||
this._onChange = fn; | ||
} | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public registerOnTouched(fn: () => void): void { | ||
this._onTouched = fn; | ||
} | ||
|
||
/** | ||
* @ignore | ||
*/ | ||
public setDisabledState(isDisabled: boolean): void { | ||
this.disabled = isDisabled; | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/stark-ui/src/modules/date-time-picker/date-time-picker.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { NgModule } from "@angular/core"; | ||
import { CommonModule } from "@angular/common"; | ||
import { FormsModule, ReactiveFormsModule } from "@angular/forms"; | ||
import { MatFormFieldModule } from "@angular/material/form-field"; | ||
import { MatInputModule } from "@angular/material/input"; | ||
import { MatButtonModule } from "@angular/material/button"; | ||
import { MatIconModule } from "@angular/material/icon"; | ||
import { StarkDatePickerModule } from "../date-picker"; | ||
import { StarkInputMaskDirectivesModule } from "../input-mask-directives"; | ||
import { StarkDateTimePickerComponent } from "./components/date-time-picker.component"; | ||
|
||
@NgModule({ | ||
imports: [ | ||
CommonModule, | ||
MatFormFieldModule, | ||
MatInputModule, | ||
FormsModule, | ||
ReactiveFormsModule, | ||
StarkDatePickerModule, | ||
StarkInputMaskDirectivesModule, | ||
MatButtonModule, | ||
MatIconModule | ||
], | ||
declarations: [StarkDateTimePickerComponent], | ||
exports: [StarkDateTimePickerComponent] | ||
}) | ||
export class StarkDateTimePickerModule {} |
Oops, something went wrong.