diff --git a/src/framework/theme/components/calendar-kit/components/calendar-day-picker/calendar-day-picker.component.ts b/src/framework/theme/components/calendar-kit/components/calendar-day-picker/calendar-day-picker.component.ts index ec4d82c524..25b875d084 100644 --- a/src/framework/theme/components/calendar-kit/components/calendar-day-picker/calendar-day-picker.component.ts +++ b/src/framework/theme/components/calendar-kit/components/calendar-day-picker/calendar-day-picker.component.ts @@ -34,7 +34,7 @@ import { convertToBoolProperty, NbBooleanInput } from '../../../helpers'; [weekNumberSymbol]="weekNumberSymbol">
- + implements OnChanges { * */ @Input() weekNumberSymbol: string; + /** + * Sets first day of the week, it can be 1 if week starts from monday and 0 if from sunday and so on. + * `undefined` means that default locale setting will be used. + * */ + @Input() firstDayOfWeek: number | undefined; + /** * Fires newly selected date. * */ @@ -141,9 +147,9 @@ export class NbCalendarDayPickerComponent implements OnChanges { constructor(private monthModel: NbCalendarMonthModelService) { } - ngOnChanges({ visibleDate, boundingMonths }: SimpleChanges) { - if (visibleDate || boundingMonths) { - this.weeks = this.monthModel.createDaysGrid(this.visibleDate, this.boundingMonths); + ngOnChanges({ visibleDate, boundingMonths, firstDayOfWeek }: SimpleChanges) { + if (visibleDate || boundingMonths || firstDayOfWeek) { + this.weeks = this.monthModel.createDaysGrid(this.visibleDate, this.boundingMonths, this.firstDayOfWeek); } } diff --git a/src/framework/theme/components/calendar-kit/components/calendar-days-names/calendar-days-names.component.ts b/src/framework/theme/components/calendar-kit/components/calendar-days-names/calendar-days-names.component.ts index f96a6b02d2..1c2674b01f 100644 --- a/src/framework/theme/components/calendar-kit/components/calendar-days-names/calendar-days-names.component.ts +++ b/src/framework/theme/components/calendar-kit/components/calendar-days-names/calendar-days-names.component.ts @@ -4,7 +4,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. */ -import { ChangeDetectionStrategy, Component, OnInit, Input, HostBinding } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit, Input, HostBinding, SimpleChanges, OnChanges } from '@angular/core'; import { NbCalendarDay, NbCalendarSize, NbCalendarSizeValues } from '../../model'; import { NbDateService } from '../../services/date.service'; @@ -18,7 +18,7 @@ import { NbDateService } from '../../services/date.service'; `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class NbCalendarDaysNamesComponent implements OnInit { +export class NbCalendarDaysNamesComponent implements OnInit, OnChanges { days: NbCalendarDay[]; @@ -30,6 +30,12 @@ export class NbCalendarDaysNamesComponent implements OnInit { return this.size === NbCalendarSize.LARGE; } + /** + * Sets first day of the week, it can be 1 if week starts from monday and 0 if from sunday and so on. + * `undefined` means that default locale setting will be used. + * */ + @Input() firstDayOfWeek: number | undefined; + constructor(private dateService: NbDateService) { } @@ -38,13 +44,21 @@ export class NbCalendarDaysNamesComponent implements OnInit { this.days = this.shiftStartOfWeek(days); } + ngOnChanges({firstDayOfWeek}: SimpleChanges) { + if (firstDayOfWeek) { + const days: NbCalendarDay[] = this.createDaysNames(); + this.days = this.shiftStartOfWeek(days); + } + } + private createDaysNames(): NbCalendarDay[] { return this.dateService.getDayOfWeekNames() .map(this.markIfHoliday); } private shiftStartOfWeek(days: NbCalendarDay[]): NbCalendarDay[] { - for (let i = 0; i < this.dateService.getFirstDayOfWeek(); i++) { + const firstDayOfWeek = this.firstDayOfWeek ?? this.dateService.getFirstDayOfWeek(); + for (let i = 0; i < firstDayOfWeek; i++) { days.push(days.shift()); } diff --git a/src/framework/theme/components/calendar-kit/services/calendar-month-model.service.ts b/src/framework/theme/components/calendar-kit/services/calendar-month-model.service.ts index f05db8e0d0..a93b15c5ec 100644 --- a/src/framework/theme/components/calendar-kit/services/calendar-month-model.service.ts +++ b/src/framework/theme/components/calendar-kit/services/calendar-month-model.service.ts @@ -16,14 +16,14 @@ export class NbCalendarMonthModelService { constructor(protected dateService: NbDateService) { } - createDaysGrid(activeMonth: D, boundingMonth: boolean = true): D[][] { - const weeks = this.createDates(activeMonth); + createDaysGrid(activeMonth: D, boundingMonth: boolean = true, firstDayOfWeek?: number): D[][] { + const weeks = this.createDates(activeMonth, firstDayOfWeek); return this.withBoundingMonths(weeks, activeMonth, boundingMonth); } - private createDates(activeMonth: D): D[][] { + private createDates(activeMonth: D, firstDayOfWeek?: number): D[][] { const days = this.createDateRangeForMonth(activeMonth); - const startOfWeekDayDiff = this.getStartOfWeekDayDiff(activeMonth); + const startOfWeekDayDiff = this.getStartOfWeekDayDiff(activeMonth, firstDayOfWeek); return batch(days, this.dateService.DAYS_IN_WEEK, startOfWeekDayDiff); } @@ -70,13 +70,14 @@ export class NbCalendarMonthModelService { .map(date => boundingMonth ? date : null); } - private getStartOfWeekDayDiff(date: D): number { + private getStartOfWeekDayDiff(date: D, firstDayOfWeek?: number): number { const startOfMonth = this.dateService.getMonthStart(date); - return this.getWeekStartDiff(startOfMonth); + return this.getWeekStartDiff(startOfMonth, firstDayOfWeek); } - private getWeekStartDiff(date: D): number { - return (7 - this.dateService.getFirstDayOfWeek() + this.dateService.getDayOfWeek(date)) % 7; + private getWeekStartDiff(date: D, firstDayOfWeek?: number): number { + const weekOfset = firstDayOfWeek ?? this.dateService.getFirstDayOfWeek(); + return (7 - weekOfset + this.dateService.getDayOfWeek(date)) % 7; } private isShouldAddPrevBoundingMonth(weeks: D[][]): boolean { diff --git a/src/framework/theme/components/calendar/base-calendar.component.html b/src/framework/theme/components/calendar/base-calendar.component.html index 811a37585e..21e4b877af 100644 --- a/src/framework/theme/components/calendar/base-calendar.component.html +++ b/src/framework/theme/components/calendar/base-calendar.component.html @@ -21,6 +21,7 @@ [size]="size" [date]="date" [showWeekNumber]="showWeekNumber" + [firstDayOfWeek]="firstDayOfWeek" (dateChange)="dateChange.emit($any($event))" [weekNumberSymbol]="weekNumberSymbol"> diff --git a/src/framework/theme/components/calendar/base-calendar.component.ts b/src/framework/theme/components/calendar/base-calendar.component.ts index 2106327edb..934640cd84 100644 --- a/src/framework/theme/components/calendar/base-calendar.component.ts +++ b/src/framework/theme/components/calendar/base-calendar.component.ts @@ -111,6 +111,12 @@ export class NbBaseCalendarComponent implements OnInit { * */ @Input() weekNumberSymbol: string; + /** + * Sets first day of the week, it can be 1 if week starts from monday and 0 if from sunday and so on. + * `undefined` means that default locale setting will be used. + * */ + @Input() firstDayOfWeek: number | undefined; + /** * Emits date when selected. * */ diff --git a/src/framework/theme/components/calendar/calendar-range.component.ts b/src/framework/theme/components/calendar/calendar-range.component.ts index aeffc11f5a..04a24cbe87 100644 --- a/src/framework/theme/components/calendar/calendar-range.component.ts +++ b/src/framework/theme/components/calendar/calendar-range.component.ts @@ -182,6 +182,7 @@ export interface NbCalendarRange { [size]="size" [showWeekNumber]="showWeekNumber" [weekNumberSymbol]="weekNumberSymbol" + [firstDayOfWeek]="firstDayOfWeek" > `, }) @@ -284,6 +285,12 @@ export class NbCalendarRangeComponent { * */ @Input() weekNumberSymbol: string = '#'; + /** + * Sets first day of the week, it can be 1 if week starts from monday and 0 if from sunday and so on. + * `undefined` means that default locale setting will be used. + * */ + @Input() firstDayOfWeek: number | undefined; + /** * Emits range when start selected and emits again when end selected. * */ diff --git a/src/framework/theme/components/calendar/calendar.component.ts b/src/framework/theme/components/calendar/calendar.component.ts index fb8e209759..b6af38292a 100644 --- a/src/framework/theme/components/calendar/calendar.component.ts +++ b/src/framework/theme/components/calendar/calendar.component.ts @@ -211,6 +211,7 @@ import { convertToBoolProperty, NbBooleanInput } from '../helpers'; [showNavigation]="showNavigation" [showWeekNumber]="showWeekNumber" [weekNumberSymbol]="weekNumberSymbol" + [firstDayOfWeek]="firstDayOfWeek" (dateChange)="dateChange.emit($event)" > `, @@ -297,6 +298,12 @@ export class NbCalendarComponent { * */ @Input() weekNumberSymbol: string = '#'; + /** + * Sets first day of the week, it can be 1 if week starts from monday and 0 if from sunday and so on. + * `undefined` means that default locale setting will be used. + * */ + @Input() firstDayOfWeek: number | undefined; + /** * Emits date when selected. * */ diff --git a/src/framework/theme/components/datepicker/calendar-with-time.component.ts b/src/framework/theme/components/datepicker/calendar-with-time.component.ts index d7d18e7a67..da0cc65b01 100644 --- a/src/framework/theme/components/datepicker/calendar-with-time.component.ts +++ b/src/framework/theme/components/datepicker/calendar-with-time.component.ts @@ -35,6 +35,7 @@ import { NbTimePickerComponent } from '../timepicker/timepicker.component'; [showNavigation]="showNavigation" [showWeekNumber]="showWeekNumber" [weekNumberSymbol]="weekNumberSymbol" + [firstDayOfWeek]="firstDayOfWeek" (dateChange)="onDateValueChange($event)" > diff --git a/src/framework/theme/components/datepicker/datepicker.component.ts b/src/framework/theme/components/datepicker/datepicker.component.ts index e447f9df9a..47585cb352 100644 --- a/src/framework/theme/components/datepicker/datepicker.component.ts +++ b/src/framework/theme/components/datepicker/datepicker.component.ts @@ -133,6 +133,12 @@ export abstract class NbBasePicker extends NbDatepicker { * */ abstract showWeekNumber: boolean; + /** + * Sets first day of the week, it can be 1 if week starts from monday and 0 if from sunday and so on. + * `undefined` means that default locale setting will be used. + * */ + abstract firstDayOfWeek: number | undefined; + readonly formatChanged$: Subject = new Subject(); /** @@ -351,6 +357,7 @@ export abstract class NbBasePicker extends NbDatepicker { this.picker.visibleDate = this.visibleDate; this.picker.showWeekNumber = this.showWeekNumber; this.picker.weekNumberSymbol = this.weekNumberSymbol; + this.picker.firstDayOfWeek = this.firstDayOfWeek; } protected checkFormat() { @@ -465,6 +472,8 @@ export class NbBasePickerComponent extends NbBasePicker implem protected _showWeekNumber: boolean = false; static ngAcceptInputType_showWeekNumber: NbBooleanInput; + @Input() firstDayOfWeek: number | undefined; + /** * Determines picker overlay offset (in pixels). * */ diff --git a/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.html b/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.html index 809f0e6791..c24bf3a611 100644 --- a/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.html +++ b/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.html @@ -9,6 +9,7 @@ [step]="step" [twelveHoursFormat]="twelveHoursFormat" [showAmPmLabel]="false" + [firstDayOfWeek]="firstDayOfWeek" #dateTimePicker > @@ -47,5 +48,21 @@ {{ formatToggleTimer ? 'Stop' : 'Start' }} auto format toggle + +
+ + LOCALE_ID + Sunday + Moday + Tuesday + Wednesday + Thursday + Friday + Saturday + + +
diff --git a/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.ts b/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.ts index 5ffd690662..751baa9ad5 100644 --- a/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.ts +++ b/src/playground/with-layout/datepicker-with-format/date-timepicker-dynamic-inputs-showcase.component.ts @@ -15,7 +15,7 @@ import { Component } from '@angular/core'; margin-bottom: 2rem; } - button + button { + section > * + * { margin-left: 1rem; } `, @@ -113,4 +113,26 @@ export class DateTimepickerDynamicInputsShowcaseComponent { toggleFormat() { this.format = this.format === 'dd/MM/yyyy HH:mm' ? 'HH:mm dd/MM/yyyy' : 'dd/MM/yyyy HH:mm'; } + + firstDayOfWeek: number | undefined = undefined; + firstDayOfWeekToggleTimer = null; + + toggleFirstDayOfWeekSwitching() { + if (this.firstDayOfWeekToggleTimer == null) { + this.firstDayOfWeekToggleTimer = setInterval(() => { + this.toggleFirstDayOfWeek(); + }, 1000); + } else { + clearInterval(this.firstDayOfWeekToggleTimer); + this.firstDayOfWeekToggleTimer = null; + } + } + + toggleFirstDayOfWeek() { + this.firstDayOfWeek ??= 0; + this.firstDayOfWeek++; + if (this.firstDayOfWeek > 6) { + this.firstDayOfWeek = 0; + } + } } diff --git a/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.html b/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.html index 576a55d916..dca499589d 100644 --- a/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.html +++ b/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.html @@ -2,7 +2,7 @@
- +
@@ -11,5 +11,21 @@ {{ formatToggleTimer ? 'Stop' : 'Start' }} auto format toggle
+ +
+ + LOCALE_ID + Sunday + Moday + Tuesday + Wednesday + Thursday + Friday + Saturday + + +
diff --git a/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.ts b/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.ts index c5bc2683fb..2316c62d5e 100644 --- a/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.ts +++ b/src/playground/with-layout/datepicker-with-format/datepicker-dynamic-inputs-showcase.component.ts @@ -15,7 +15,7 @@ import { Component } from '@angular/core'; margin-bottom: 2rem; } - button + button { + section > * + * { margin-left: 1rem; } `, @@ -26,6 +26,8 @@ export class DatepickerDynamicInputsShowcaseComponent { format = 'dd/MM/yyyy HH:mm'; formatToggleTimer = null; + firstDayOfWeek: number | undefined = undefined; + firstDayOfWeekToggleTimer = null; toggleFormatSwitching() { if (this.formatToggleTimer == null) { @@ -41,4 +43,23 @@ export class DatepickerDynamicInputsShowcaseComponent { toggleFormat() { this.format = this.format === 'dd/MM/yyyy HH:mm' ? 'HH:mm dd/MM/yyyy' : 'dd/MM/yyyy HH:mm'; } + + toggleFirstDayOfWeekSwitching() { + if (this.firstDayOfWeekToggleTimer == null) { + this.firstDayOfWeekToggleTimer = setInterval(() => { + this.toggleFirstDayOfWeek(); + }, 1000); + } else { + clearInterval(this.firstDayOfWeekToggleTimer); + this.firstDayOfWeekToggleTimer = null; + } + } + + toggleFirstDayOfWeek() { + this.firstDayOfWeek ??= 0; + this.firstDayOfWeek++; + if (this.firstDayOfWeek > 6) { + this.firstDayOfWeek = 0; + } + } } diff --git a/src/playground/with-layout/datepicker-with-format/datepicker-with-format.module.ts b/src/playground/with-layout/datepicker-with-format/datepicker-with-format.module.ts index 45a8a754b9..8e96425341 100644 --- a/src/playground/with-layout/datepicker-with-format/datepicker-with-format.module.ts +++ b/src/playground/with-layout/datepicker-with-format/datepicker-with-format.module.ts @@ -6,7 +6,7 @@ import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { NbButtonModule, NbCardModule, NbDatepickerModule, NbInputModule, NbTimepickerModule } from '@nebular/theme'; +import { NbButtonModule, NbCardModule, NbDatepickerModule, NbInputModule, NbSelectModule, NbTimepickerModule } from '@nebular/theme'; import { DatepickerWithFormatRoutingModule } from './datepicker-with-format-routing.module'; import { DateTimepickerDynamicInputsShowcaseComponent } from './date-timepicker-dynamic-inputs-showcase.component'; import { NbDateFnsDateModule } from '@nebular/date-fns'; @@ -29,6 +29,7 @@ import { RangepickerDynamicInputsShowcaseComponent } from './rangepicker-dynamic NbCardModule, NbButtonModule, NbDateFnsDateModule.forRoot({}), + NbSelectModule, ], }) export class DatepickerWithFormatModule {} diff --git a/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.html b/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.html index c104b06eca..89ffda4801 100644 --- a/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.html +++ b/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.html @@ -2,7 +2,7 @@
- +
@@ -11,5 +11,21 @@ {{ formatToggleTimer ? 'Stop' : 'Start' }} auto format toggle
+ +
+ + LOCALE_ID + Sunday + Moday + Tuesday + Wednesday + Thursday + Friday + Saturday + + +
diff --git a/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.ts b/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.ts index 99793107a2..390680da1a 100644 --- a/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.ts +++ b/src/playground/with-layout/datepicker-with-format/rangepicker-dynamic-inputs-showcase.component.ts @@ -15,7 +15,7 @@ import { Component } from '@angular/core'; margin-bottom: 2rem; } - button + button { + section > * + * { margin-left: 1rem; } `, @@ -41,4 +41,26 @@ export class RangepickerDynamicInputsShowcaseComponent { toggleFormat() { this.format = this.format === 'dd/MM/yyyy HH:mm' ? 'HH:mm dd/MM/yyyy' : 'dd/MM/yyyy HH:mm'; } + + firstDayOfWeek: number | undefined = undefined; + firstDayOfWeekToggleTimer = null; + + toggleFirstDayOfWeekSwitching() { + if (this.firstDayOfWeekToggleTimer == null) { + this.firstDayOfWeekToggleTimer = setInterval(() => { + this.toggleFirstDayOfWeek(); + }, 1000); + } else { + clearInterval(this.firstDayOfWeekToggleTimer); + this.firstDayOfWeekToggleTimer = null; + } + } + + toggleFirstDayOfWeek() { + this.firstDayOfWeek ??= 0; + this.firstDayOfWeek++; + if (this.firstDayOfWeek > 6) { + this.firstDayOfWeek = 0; + } + } }