-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(angular): add angular compatibility layer for new date and time …
…picker (#498) * chore: init copy * chore: rework component structure and hierarchy * chore: cleanup * chore: add docs * fix: prettier * chore: cleanup * chore: final touches * chore: angular * chore: stuff * chore: time limit * chore: cleanup * chore: cleanup * chore: cleanup * chore: update pnpm * chore: cleanup
- Loading branch information
1 parent
0321ba8
commit 304c226
Showing
20 changed files
with
11,899 additions
and
10,583 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
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
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
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
24 changes: 24 additions & 0 deletions
24
angular/projects/catalyst/src/lib/datetime/datetime.component.spec.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,24 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { DatetimeComponent } from './datetime.component'; | ||
|
||
describe('DatetimeComponent', () => { | ||
let component: DatetimeComponent; | ||
let fixture: ComponentFixture<DatetimeComponent>; | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
declarations: [DatetimeComponent] | ||
}) | ||
.overrideTemplate(DatetimeComponent, '') | ||
.compileComponents(); | ||
|
||
fixture = TestBed.createComponent(DatetimeComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
137 changes: 137 additions & 0 deletions
137
angular/projects/catalyst/src/lib/datetime/datetime.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,137 @@ | ||
import { AfterContentInit, Component, ContentChild, Input, ViewEncapsulation } from '@angular/core'; | ||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; | ||
import { DateValueAccessor } from '../directives/date-value-accessor'; | ||
import { TimeValueAccessor } from '../directives/time-value-accessor'; | ||
|
||
@Component({ | ||
selector: 'cat-datetime', | ||
template: '<ng-content></ng-content>', | ||
styles: ['cat-datetime { display: contents; }'], | ||
encapsulation: ViewEncapsulation.None, | ||
providers: [ | ||
{ | ||
provide: NG_VALUE_ACCESSOR, | ||
useExisting: DatetimeComponent, | ||
multi: true | ||
} | ||
] | ||
}) | ||
export class DatetimeComponent implements AfterContentInit, ControlValueAccessor { | ||
protected lastValue: any; | ||
protected lastDateValue: any; | ||
protected lastTimeValue: any; | ||
|
||
@ContentChild(DateValueAccessor) dateInput?: DateValueAccessor; | ||
@ContentChild(TimeValueAccessor) timeInput?: TimeValueAccessor; | ||
|
||
private _min?: Date | null; | ||
get min(): Date | null { | ||
return this._min ?? null; | ||
} | ||
@Input() set min(value: Date | null | undefined) { | ||
this._min = value; | ||
setTimeout(() => { | ||
const min = value ? this.toLocalISODate(value) : undefined; | ||
this.dateInput?.nativeElement.setAttribute('min', min); | ||
this.limitTime('min'); | ||
}); | ||
} | ||
|
||
private _max?: Date | null; | ||
get max(): Date | null { | ||
return this._max ?? null; | ||
} | ||
@Input() set max(value: Date | null | undefined) { | ||
this._max = value; | ||
setTimeout(() => { | ||
const max = value ? this.toLocalISODate(value) : undefined; | ||
this.dateInput?.nativeElement.setAttribute('max', max); | ||
this.limitTime('max'); | ||
}); | ||
} | ||
|
||
ngAfterContentInit(): void { | ||
if (!this.dateInput) { | ||
throw new Error('Missing child element <cat-date></cat-date>'); | ||
} | ||
if (!this.timeInput) { | ||
throw new Error('Missing child element <cat-time></cat-time>'); | ||
} | ||
} | ||
|
||
writeValue(value: any): void { | ||
this.lastValue = this.lastDateValue = this.lastTimeValue = value; | ||
setTimeout(() => { | ||
this.dateInput?.writeValue(value); | ||
this.timeInput?.writeValue(value); | ||
}); | ||
} | ||
|
||
registerOnChange(fn: (value: any) => void) { | ||
setTimeout(() => { | ||
this.dateInput?.registerOnChange((value: any) => { | ||
this.lastDateValue = value; | ||
this.limitTime('min'); | ||
this.limitTime('max'); | ||
fn(this.value); | ||
}); | ||
this.timeInput?.registerOnChange((value: any) => { | ||
this.lastTimeValue = value; | ||
fn(this.value); | ||
}); | ||
}); | ||
} | ||
|
||
registerOnTouched(fn: () => void) { | ||
setTimeout(() => { | ||
this.dateInput?.registerOnTouched(fn); | ||
this.timeInput?.registerOnTouched(fn); | ||
}); | ||
} | ||
|
||
setDisabledState?(isDisabled: boolean): void { | ||
setTimeout(() => { | ||
this.dateInput?.setDisabledState(isDisabled); | ||
this.timeInput?.setDisabledState(isDisabled); | ||
}); | ||
} | ||
|
||
private get value() { | ||
if (this.lastDateValue && this.lastTimeValue) { | ||
const result = new Date(this.lastDateValue); | ||
result.setHours( | ||
this.lastTimeValue.getHours(), | ||
this.lastTimeValue.getMinutes(), | ||
this.lastTimeValue.getSeconds(), | ||
this.lastTimeValue.getMilliseconds() | ||
); | ||
return result; | ||
} | ||
return null; | ||
} | ||
|
||
private limitTime(mode: 'min' | 'max') { | ||
const limit = mode === 'min' ? this.min : this.max; | ||
const limitIso = limit ? this.toLocalISODate(limit) : undefined; | ||
const dateIso = this.lastDateValue ? this.toLocalISODate(this.lastDateValue) : undefined; | ||
const attr = limit && limitIso === dateIso ? this.toLocalISOTime(limit) : undefined; | ||
if (attr) { | ||
this.timeInput?.nativeElement.setAttribute(mode, attr); | ||
} else { | ||
this.timeInput?.nativeElement.removeAttribute(mode); | ||
} | ||
} | ||
|
||
private toLocalISODate(value: Date) { | ||
const year = value.getFullYear(); | ||
const month = (value.getMonth() + 1).toString().padStart(2, '0'); | ||
const day = value.getDate().toString().padStart(2, '0'); | ||
return `${year}-${month}-${day}`; | ||
} | ||
|
||
private toLocalISOTime(value: Date) { | ||
const hours = value.getHours().toString().padStart(2, '0'); | ||
const mins = value.getMinutes().toString().padStart(2, '0'); | ||
return `${hours}:${mins}`; | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
angular/projects/catalyst/src/lib/directives/date-value-accessor.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,40 @@ | ||
import { Directive, ElementRef } from '@angular/core'; | ||
import { NG_VALUE_ACCESSOR } from '@angular/forms'; | ||
|
||
import { ValueAccessor } from './value-accessor'; | ||
|
||
@Directive({ | ||
/* tslint:disable-next-line:directive-selector */ | ||
selector: 'cat-date, cat-date-inline', | ||
host: { | ||
'(catChange)': 'handleChangeEvent($event.target.value)' | ||
}, | ||
providers: [ | ||
{ | ||
provide: NG_VALUE_ACCESSOR, | ||
useExisting: DateValueAccessor, | ||
multi: true | ||
} | ||
] | ||
}) | ||
export class DateValueAccessor extends ValueAccessor { | ||
constructor(el: ElementRef) { | ||
super(el); | ||
} | ||
get nativeElement() { | ||
return this.el.nativeElement; | ||
} | ||
writeValue(value: any) { | ||
if (value && value instanceof Date) { | ||
const year = value.getFullYear(); | ||
const month = (value.getMonth() + 1).toString().padStart(2, '0'); | ||
const day = value.getDate().toString().padStart(2, '0'); | ||
return super.writeValue(`${year}-${month}-${day}`); | ||
} | ||
return super.writeValue(undefined); | ||
} | ||
handleChangeEvent(value: any) { | ||
const [match, year, month, day] = value?.match(/^(\d{4})-(\d{2})-(\d{2})/) ?? []; | ||
return super.handleChangeEvent(match ? new Date(Number(year), Number(month) - 1, Number(day)) : null); | ||
} | ||
} |
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
44 changes: 44 additions & 0 deletions
44
angular/projects/catalyst/src/lib/directives/time-value-accessor.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,44 @@ | ||
import { Directive, ElementRef } from '@angular/core'; | ||
import { NG_VALUE_ACCESSOR } from '@angular/forms'; | ||
|
||
import { ValueAccessor } from './value-accessor'; | ||
|
||
@Directive({ | ||
/* tslint:disable-next-line:directive-selector */ | ||
selector: 'cat-time', | ||
host: { | ||
'(catChange)': 'handleChangeEvent($event.target.value)' | ||
}, | ||
providers: [ | ||
{ | ||
provide: NG_VALUE_ACCESSOR, | ||
useExisting: TimeValueAccessor, | ||
multi: true | ||
} | ||
] | ||
}) | ||
export class TimeValueAccessor extends ValueAccessor { | ||
constructor(el: ElementRef) { | ||
super(el); | ||
} | ||
get nativeElement() { | ||
return this.el.nativeElement; | ||
} | ||
writeValue(value: any) { | ||
if (value && value instanceof Date) { | ||
const hours = value.getHours().toString().padStart(2, '0'); | ||
const mins = value.getMinutes().toString().padStart(2, '0'); | ||
return super.writeValue(`${hours}:${mins}`); | ||
} | ||
return super.writeValue(undefined); | ||
} | ||
handleChangeEvent(value: any) { | ||
const [match, hours, mins] = value?.match(/^(\d{2}):(\d{2})/) ?? []; | ||
if (match) { | ||
const date = new Date(); | ||
date.setHours(Number(hours), Number(mins), 0, 0); | ||
return super.handleChangeEvent(date); | ||
} | ||
return super.handleChangeEvent(null); | ||
} | ||
} |
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,13 +1,16 @@ | ||
export * from './lib/catalyst.module'; | ||
export * from './lib/datetime/datetime.component'; | ||
export { CatDialogActionsComponent } from './lib/dialog/dialog-actions.component'; | ||
export { CatDialogHeaderComponent } from './lib/dialog/dialog-header.component'; | ||
export { CatDialogComponent } from './lib/dialog/dialog.component'; | ||
export { CatDialogConfig, CatDialogService } from './lib/dialog/dialog.service'; | ||
export * from './lib/directives/boolean-value-accessor'; | ||
export * from './lib/directives/date-value-accessor'; | ||
export * from './lib/directives/proxies'; | ||
export * from './lib/directives/radio-value-accessor'; | ||
export * from './lib/directives/select-value-accessor'; | ||
export * from './lib/directives/select-value-accessor-decorator'; | ||
export * from './lib/directives/text-value-accessor'; | ||
export * from './lib/directives/time-value-accessor'; | ||
export * from './lib/directives/value-accessor'; | ||
export * from './lib/directives/value-accessor-decorator'; |
Oops, something went wrong.