Skip to content

Commit 1f05d4e

Browse files
authored
Merge branch 'master' into rkaraivanov/performance-measure-service
2 parents d4a2104 + 42cfa28 commit 1f05d4e

25 files changed

+1497
-195
lines changed

CHANGELOG.md

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22

33
All notable changes for each version of this project will be documented in this file.
44

5-
65
## 20.1.0
76
### New Features
8-
`IgxDateRangePicker`
9-
- Added cancel button to the dialog, allowing the user to cancel the selection.
10-
117
- `IgxCarousel`
128
- Added `select` method overload accepting index.
139
```ts
@@ -35,13 +31,44 @@ All notable changes for each version of this project will be documented in this
3531
If property `pinningPosition` is not set on a column, the column will default to the position specified on the grid's `pinning` options for `columns`.
3632

3733
- `IgxDateRangePicker`
38-
- Added new properties:
34+
- Now has a complete set of properties to customize the calendar:
35+
- `headerOrientation`
36+
- `orientation`
37+
- `hideHeader`
38+
- `activeDate`
39+
- `disabledDates`
40+
- `specialDates`
41+
42+
- As well as the following templates, available to customize the contents of the calendar header in `dialog` mode:
43+
- `igxCalendarHeader`
44+
- `igxCalendarHeaderTitle`
45+
- `igxCalendarSubheader`
46+
47+
- Added new properties:
3948
- `usePredefinedRanges` - Whether to render built-in predefined ranges
4049
- `customRanges` - Allows the user to provide custom ranges rendered as chips
4150
- `resourceStrings` - Allows the user to provide set of resource strings
4251

43-
- `IgxPredefinedRangesAreaComponent`
44-
- Added new component for rendering the predefined or custom ranges inside the calendar of the `IgxDateRangePicker`
52+
- **Behavioral Changes**
53+
- Added cancel button to the dialog, allowing the user to cancel the selection.
54+
- The calendar is displayed with header in `dialog` mode by default.
55+
- The picker remains open when typing (in two-inputs and `dropdown` mode).
56+
- The calendar selection is updated with the typed value.
57+
- The calendar view is updated as per the typed value.
58+
- The picker displays a clear icon by default in single input mode.
59+
60+
- `IgxPredefinedRangesAreaComponent`
61+
- Added new component for rendering the predefined or custom ranges inside the calendar of the `IgxDateRangePicker`
62+
63+
- `IgxDatePicker`
64+
- Similar to the `IgxDateRangePicker`, also completes the ability to customize the calendar by introducing the following
65+
properties in addition to the existing ones:
66+
- `hideHeader`
67+
- `orientation`
68+
- `activeDate`
69+
- **Behavioral Changes**
70+
- The calendar selection is updated with the typed value.
71+
- The calendar view is updated as per the typed date value.
4572

4673
- `IgxOverlay`
4774
- Position Settings now accept a new optional `offset` input property of type `number`. Used to set the offset of the element from the target in pixels.

projects/igniteui-angular/src/lib/calendar/calendar-base.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -707,15 +707,15 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
707707

708708
switch (this.selection) {
709709
case CalendarSelection.SINGLE:
710-
if (isDate(value) && !this.isDateDisabled(value as Date)) {
710+
if (isDate(value)) {
711711
this.selectSingle(value as Date);
712712
}
713713
break;
714714
case CalendarSelection.MULTI:
715715
this.selectMultiple(value);
716716
break;
717717
case CalendarSelection.RANGE:
718-
this.selectRange(value, true);
718+
this.selectRange(value);
719719
break;
720720
}
721721
}
@@ -807,9 +807,7 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
807807
: [value, this.lastSelectedDate];
808808

809809
const unselectedDates = [this._startDate, ...this.generateDateRange(this._startDate, this._endDate)]
810-
.filter(date => !this.isDateDisabled(date)
811-
&& this.selectedDates.every((d: Date) => d.getTime() !== date.getTime())
812-
);
810+
.filter(date => this.selectedDates.every((d: Date) => d.getTime() !== date.getTime()));
813811

814812
// select all dates from last selected to shift clicked date
815813
if (this.selectedDates.some((date: Date) => date.getTime() === this.lastSelectedDate.getTime())

projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,8 @@ describe("IgxCalendar - ", () => {
17671767
});
17681768

17691769
it("Should not select date from model, if it is part of disabled dates", () => {
1770-
expect(calendar.value).toBeFalsy();
1770+
// Changed per WC alignment task #16131 - calendar should not block selection of dates through API/model
1771+
expect(calendar.value).toBeTruthy();
17711772
});
17721773

17731774
it("Should not select date from model in range selection, if model passes null", () => {

projects/igniteui-angular/src/lib/calendar/common/helpers.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,34 @@ export function getClosestActiveDate(
8888
* @remarks
8989
* By default, `unit` is set to 'day'.
9090
*/
91-
export function* calendarRange(options: CalendarRangeParams) {
92-
let low = toCalendarDay(options.start);
93-
const unit = options.unit ?? "day";
94-
const high =
95-
typeof options.end === "number"
96-
? low.add(unit, options.end)
97-
: toCalendarDay(options.end);
98-
99-
const reverse = high.lessThan(low);
100-
const step = reverse ? -1 : 1;
101-
102-
while (!reverse ? low.lessThan(high) : low.greaterThan(high)) {
103-
yield low;
104-
low = low.add(unit, step);
91+
export function* calendarRange(
92+
options: CalendarRangeParams
93+
): Generator<CalendarDay, void, unknown> {
94+
const { start, end, unit = 'day', inclusive = false } = options;
95+
96+
let currentDate = toCalendarDay(start);
97+
const endDate =
98+
typeof end === 'number'
99+
? toCalendarDay(start).add(unit, end)
100+
: toCalendarDay(end);
101+
102+
const isReversed = endDate.lessThan(currentDate);
103+
const step = isReversed ? -1 : 1;
104+
105+
const shouldContinue = () => {
106+
if (inclusive) {
107+
return isReversed
108+
? currentDate.greaterThanOrEqual(endDate)
109+
: currentDate.lessThanOrEqual(endDate);
110+
}
111+
return isReversed
112+
? currentDate.greaterThan(endDate)
113+
: currentDate.lessThan(endDate);
114+
};
115+
116+
while (shouldContinue()) {
117+
yield currentDate;
118+
currentDate = currentDate.add(unit, step);
105119
}
106120
}
107121

projects/igniteui-angular/src/lib/calendar/common/model.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type CalendarRangeParams = {
77
start: DayParameter;
88
end: DayParameter | number;
99
unit?: DayInterval;
10+
inclusive?: boolean;
1011
};
1112

1213
type CalendarDayParams = {
@@ -237,11 +238,18 @@ export class CalendarDay {
237238
public greaterThan(value: DayParameter) {
238239
return this.timestamp > toCalendarDay(value).timestamp;
239240
}
241+
public greaterThanOrEqual(value: DayParameter) {
242+
return this.timestamp >= toCalendarDay(value).timestamp;
243+
}
240244

241245
public lessThan(value: DayParameter) {
242246
return this.timestamp < toCalendarDay(value).timestamp;
243247
}
244248

249+
public lessThanOrEqual(value: DayParameter) {
250+
return this.timestamp <= toCalendarDay(value).timestamp;
251+
}
252+
245253
public toString() {
246254
return `${this.native}`;
247255
}

projects/igniteui-angular/src/lib/core/utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,19 @@ export const isEqual = (obj1, obj2): boolean => {
225225
return obj1 === obj2;
226226
};
227227

228+
/**
229+
* Limits a number to a range between a minimum and a maximum value.
230+
*
231+
* @param number
232+
* @param min
233+
* @param max
234+
* @returns: `number`
235+
* @hidden
236+
*/
237+
export const clamp = (number: number, min: number, max: number) =>
238+
Math.max(min, Math.min(number, max));
239+
240+
228241
/**
229242
* Utility service taking care of various utility functions such as
230243
* detecting browser features, general cross browser DOM manipulation, etc.

projects/igniteui-angular/src/lib/date-common/picker-base.directive.ts

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import { IToggleView } from '../core/navigation';
1313
import { IBaseCancelableBrowserEventArgs, IBaseEventArgs } from '../core/utils';
1414
import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive';
1515
import { OverlaySettings } from '../services/overlay/utilities';
16-
import { IgxPickerToggleComponent } from './picker-icons.common';
17-
import { PickerInteractionMode } from './types';
16+
import { IgxPickerClearComponent, IgxPickerToggleComponent } from './picker-icons.common';
17+
import { PickerHeaderOrientation, PickerInteractionMode } from './types';
1818
import { WEEKDAYS } from '../calendar/calendar';
1919
import { DateRange } from '../date-range-picker/date-range-picker-inputs.common';
2020
import { IGX_INPUT_GROUP_TYPE, IgxInputGroupType } from '../input-group/inputGroupType';
@@ -78,6 +78,28 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
7878
@Input()
7979
public mode: PickerInteractionMode = PickerInteractionMode.DropDown;
8080

81+
/**
82+
* Gets/Sets the orientation of the `IgxDatePickerComponent` header.
83+
*
84+
* @example
85+
* ```html
86+
* <igx-date-picker headerOrientation="vertical"></igx-date-picker>
87+
* ```
88+
*/
89+
@Input()
90+
public headerOrientation: PickerHeaderOrientation = PickerHeaderOrientation.Horizontal;
91+
92+
/**
93+
* Gets/Sets whether the header is hidden in dialog mode.
94+
*
95+
* @example
96+
* ```html
97+
* <igx-date-picker mode="dialog" [hideHeader]="true"></igx-date-picker>
98+
* ```
99+
*/
100+
@Input({ transform: booleanAttribute })
101+
public hideHeader = false;
102+
81103
/**
82104
* Overlay settings used to display the pop-up element.
83105
*
@@ -239,6 +261,10 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
239261
@ContentChildren(IgxPickerToggleComponent, { descendants: true })
240262
public toggleComponents: QueryList<IgxPickerToggleComponent>;
241263

264+
/** @hidden @internal */
265+
@ContentChildren(IgxPickerClearComponent, { descendants: true })
266+
public clearComponents: QueryList<IgxPickerClearComponent>;
267+
242268
@ContentChildren(IgxPrefixDirective, { descendants: true })
243269
protected prefixes: QueryList<IgxPrefixDirective>;
244270

@@ -299,9 +325,8 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
299325

300326
/** @hidden @internal */
301327
public ngAfterViewInit(): void {
302-
this.subToIconsClicked(this.toggleComponents, () => this.open());
303-
this.toggleComponents.changes.pipe(takeUntil(this._destroy$))
304-
.subscribe(() => this.subToIconsClicked(this.toggleComponents, () => this.open()));
328+
this.subToIconsClicked(this.toggleComponents, () => this.toggle());
329+
this.subToIconsClicked(this.clearComponents, () => this.clear());
305330
}
306331

307332
/** @hidden @internal */
@@ -322,17 +347,28 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
322347
}
323348

324349
/** Subscribes to the click events of toggle/clear icons in a query */
325-
protected subToIconsClicked(components: QueryList<IgxPickerToggleComponent>, next: () => any): void {
326-
components.forEach(toggle => {
327-
toggle.clicked
328-
.pipe(takeUntil(merge(components.changes, this._destroy$)))
329-
.subscribe(next);
330-
});
350+
private subToIconsClicked(
351+
components: QueryList<IgxPickerToggleComponent | IgxPickerClearComponent>,
352+
handler: () => void
353+
): void {
354+
const subscribeToClick = componentList => {
355+
componentList.forEach(component => {
356+
component.clicked
357+
.pipe(takeUntil(merge(componentList.changes, this._destroy$)))
358+
.subscribe(handler);
359+
});
360+
};
361+
362+
subscribeToClick(components);
363+
364+
components.changes.pipe(takeUntil(this._destroy$))
365+
.subscribe(() => subscribeToClick(components));
331366
}
332367

333368
public abstract select(value: Date | DateRange | string): void;
334369
public abstract open(settings?: OverlaySettings): void;
335370
public abstract toggle(settings?: OverlaySettings): void;
336371
public abstract close(): void;
372+
public abstract clear(): void;
337373
public abstract getEditElement(): HTMLInputElement;
338374
}

projects/igniteui-angular/src/lib/date-common/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ export const PickerHeaderOrientation = {
55
} as const;
66
export type PickerHeaderOrientation = (typeof PickerHeaderOrientation)[keyof typeof PickerHeaderOrientation];
77

8+
/** Calendar orientation. */
9+
export const PickerCalendarOrientation = {
10+
Horizontal: 'horizontal',
11+
Vertical: 'vertical'
12+
} as const;
13+
export type PickerCalendarOrientation = (typeof PickerCalendarOrientation)[keyof typeof PickerCalendarOrientation];
14+
815
/**
916
* This enumeration is used to configure whether the date/time picker has an editable input with drop down
1017
* or is readonly - the date/time is selected only through a dialog.

0 commit comments

Comments
 (0)