Skip to content

Commit 5d462e7

Browse files
authored
Merge branch '9.1.x' into skrastev/fix-7561-9.1.x
2 parents 9a9f3e5 + 1e1e1d5 commit 5d462e7

File tree

16 files changed

+295
-122
lines changed

16 files changed

+295
-122
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
379379
const result = [];
380380
start = this.getDateOnly(start);
381381
end = this.getDateOnly(end);
382-
while (start.getTime() !== end.getTime()) {
382+
while (start.getTime() < end.getTime()) {
383383
start = this.calendarModel.timedelta(start, 'day', 1);
384384
result.push(start);
385385
}

projects/igniteui-angular/src/lib/core/styles/base/utilities/_functions.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,12 @@
276276
/// @param {Color} $color - The base color used to generate the palette.
277277
/// @param {Map} $shades - A map of variations as keys and opacities as values.
278278
/// Based on the Material color system.
279-
/// @returns {Map} - A map consisting of 10 grayscale color variations and 10
279+
/// @returns {Map} - A map consisting of 10 color variations and 10
280280
/// text contrast colors for each variation.
281281
@function grayscale-palette($color, $shades) {
282282
$result: ();
283283
@each $saturation, $opacity in $shades {
284-
$shade: rgba(grayscale($color), $opacity);
284+
$shade: rgba($color, $opacity);
285285
$result: map-merge($result, ($saturation: $shade));
286286
}
287287
@return $result;
@@ -297,7 +297,7 @@
297297
/// @param {Color} $success [#4eb862] - The success color used throughout the application.
298298
/// @param {Color} $warn [#fbb13c] - The warning color used throughout the application.
299299
/// @param {Color} $error [#ff134a] - The error color used throughout the application.
300-
/// @param {Color} $grays [#000 | $igx-foreground-color] - The color used for generating the grayscale palette.
300+
/// @param {Color} $grays [#000 | $igx-foreground-color] - The color used for generating the grays palette.
301301
/// @param {Color} $surface [#fff] - The color used as a background in components, such as cards, sheets, and menus.
302302
/// @returns {Map} - A map consisting of 74 color variations, including the `primary`, `secondary`, `grays`,
303303
/// `info`, `success`, `warn`, and `error` colors.
Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
////
22
/// @group typography
3-
/// @access public
43
/// @author <a href="https://github.com/simeonoff" target="_blank">Simeon Simeonoff</a>
54
////
65

@@ -31,16 +30,18 @@
3130
@import '../components/toast/toast-theme';
3231
@import '../components/tooltip/tooltip-theme';
3332

34-
/// Adds typography styles for h1-h6, paragraph and creates
35-
/// custom typography class selectors. The produces styles
36-
/// are based on the passed type scale. If omitted the
37-
/// default-type-scale will be used.
38-
/// @param {String} $font-family ["'Titillium Web', sans-serif"] - The font family to be used across all typographic elements.
39-
/// @param {Map} $type-scale [$default-type-scale] - A type scale map as produced by igx-type-scale.
40-
@mixin igx-typography(
41-
$font-family: "'Titillium Web', sans-serif",
42-
$type-scale: $default-type-scale,
43-
) {
33+
/// @access private
34+
@mixin _igx-typography-styles($font-family, $type-scale) {
35+
font-family: unquote($font-family);
36+
font-size: $browser-context;
37+
line-height: $browser-line-height;
38+
font-size-adjust: 100%;
39+
-webkit-font-smoothing: antialiased;
40+
-moz-osx-font-smoothing: grayscale;
41+
42+
$this: bem--selector-to-string(&);
43+
$selector: bem--extract-first-selector($this);
44+
4445
// Maps type scale typographic categories
4546
// to native elements.
4647
$category-element-map: (
@@ -53,72 +54,81 @@
5354
body-1: 'p'
5455
);
5556

56-
$this: bem--selector-to-string(&);
57-
$scope: if(is-root(), 'igx-typography', #{str-slice($this, 2, -1)});
57+
@each $category, $type-style in $type-scale {
58+
// Get the native element that uses typographic styles directly
59+
// as mapped in the $category-element-map
60+
$e: map-get($category-element-map, $category);
5861

59-
// Use the BEM notation to create a link
60-
// between the igx-typography class selector
61-
// and all typographic elements.
62-
@include b($scope) {
63-
font-family: unquote($font-family);
64-
font-size: $browser-context;
65-
line-height: $browser-line-height;
66-
font-size-adjust: 100%;
67-
-webkit-font-smoothing: antialiased;
68-
-moz-osx-font-smoothing: grayscale;
69-
70-
@each $category, $type-style in $type-scale {
71-
// Get the native element that uses typographic styles directly
72-
// as mapped in the $category-element-map
73-
$e: map-get($category-element-map, $category);
74-
75-
// Create a placeholder selector with styles for each
76-
// typographic style to be able to easily extend it
77-
// elsewhere.
78-
%#{$category} {
79-
@include igx-type-style($type-scale, $category);
80-
}
62+
// Create a placeholder selector with styles for each
63+
// typographic style to be able to easily extend it
64+
// elsewhere.
65+
%#{$category} {
66+
@include igx-type-style($type-scale, $category);
67+
}
8168

82-
// Add native element typographic styles.
83-
@if $e != null {
84-
#{$e} {
85-
@extend %#{$category};
86-
}
69+
// Add native element typographic styles.
70+
@if $e != null {
71+
#{$e} {
72+
@extend %#{$category};
8773
}
74+
}
8875

89-
// Add class selector typographic styles.
76+
// Add class selector typographic styles.
77+
@if ($selector == '.igx-typography') {
9078
@include e(#{$category}) {
91-
$selector: bem--selector-to-string(&);
92-
9379
@extend %#{$category};
9480
}
9581
}
82+
}
83+
84+
// Call the individual component styles with the type scale
85+
@include igx-button-typography($type-scale);
86+
@include igx-bottom-nav-typography($type-scale);
87+
@include igx-banner-typography($type-scale);
88+
@include igx-calendar-typography($type-scale);
89+
@include igx-card-typography($type-scale);
90+
@include igx-checkbox-typography($type-scale);
91+
@include igx-chip-typography($type-scale);
92+
@include igx-column-hiding-typography($type-scale);
93+
@include igx-dialog-typography($type-scale);
94+
@include igx-drop-down-typography($type-scale);
95+
@include igx-date-range-typography($type-scale);
96+
@include igx-expansion-panel-typography($type-scale);
97+
@include _excel-filtering-typography($type-scale);
98+
@include igx-input-group-typography($type-scale);
99+
@include igx-navbar-typography($type-scale);
100+
@include igx-navdrawer-typography($type-scale);
101+
@include igx-list-typography($type-scale);
102+
@include igx-radio-typography($type-scale);
103+
@include igx-snackbar-typography($type-scale);
104+
@include igx-switch-typography($type-scale);
105+
@include igx-slider-typography($type-scale);
106+
@include igx-tabs-typography($type-scale);
107+
@include igx-time-picker-typography($type-scale);
108+
@include igx-toast-typography($type-scale);
109+
@include igx-tooltip-typography($type-scale);
110+
}
96111

97-
// Call the individual component styles with the type scale
98-
@include igx-button-typography($type-scale);
99-
@include igx-bottom-nav-typography($type-scale);
100-
@include igx-banner-typography($type-scale);
101-
@include igx-calendar-typography($type-scale);
102-
@include igx-card-typography($type-scale);
103-
@include igx-checkbox-typography($type-scale);
104-
@include igx-chip-typography($type-scale);
105-
@include igx-column-hiding-typography($type-scale);
106-
@include igx-dialog-typography($type-scale);
107-
@include igx-drop-down-typography($type-scale);
108-
@include igx-date-range-typography($type-scale);
109-
@include igx-expansion-panel-typography($type-scale);
110-
@include _excel-filtering-typography($type-scale);
111-
@include igx-input-group-typography($type-scale);
112-
@include igx-navbar-typography($type-scale);
113-
@include igx-navdrawer-typography($type-scale);
114-
@include igx-list-typography($type-scale);
115-
@include igx-radio-typography($type-scale);
116-
@include igx-snackbar-typography($type-scale);
117-
@include igx-switch-typography($type-scale);
118-
@include igx-slider-typography($type-scale);
119-
@include igx-tabs-typography($type-scale);
120-
@include igx-time-picker-typography($type-scale);
121-
@include igx-toast-typography($type-scale);
122-
@include igx-tooltip-typography($type-scale);
112+
/// Adds typography styles for h1-h6, paragraph and creates
113+
/// custom typography class selectors. The produces styles
114+
/// are based on the passed type scale. If omitted the
115+
/// default-type-scale will be used.
116+
/// @access public
117+
/// @param {String} $font-family ["'Titillium Web', sans-serif"] - The font family to be used across all typographic elements.
118+
/// @param {Map} $type-scale [$default-type-scale] - A type scale map as produced by igx-type-scale.
119+
@mixin igx-typography(
120+
$font-family: "'Titillium Web', sans-serif",
121+
$type-scale: $default-type-scale,
122+
) {
123+
@if(is-root()) {
124+
// Use the BEM notation to create a link
125+
// between the igx-typography class selector
126+
// and all typographic elements.
127+
@include b(igx-typography) {
128+
@include _igx-typography-styles($font-family, $type-scale);
129+
}
130+
} @else {
131+
@include _igx-typography-styles($font-family, $type-scale);
123132
}
124133
}
134+

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.spec.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { IgxDateRangePickerComponent } from './date-range-picker.component';
21
import { ComponentFixture, async, TestBed, fakeAsync, tick } from '@angular/core/testing';
32
import { Component, OnInit, ViewChild, DebugElement } from '@angular/core';
43
import { IgxInputGroupModule } from '../input-group/public_api';
@@ -13,6 +12,8 @@ import { configureTestSuite } from '../test-utils/configure-suite';
1312
import { HelperTestFunctions } from '../calendar/calendar-helper-utils';
1413
import { IgxDateTimeEditorModule } from '../directives/date-time-editor/public_api';
1514
import { DateRangeType } from '../core/dates';
15+
import { IgxDateRangePickerComponent, IgxDateRangeEndComponent } from './public_api';
16+
import { IgxIconModule } from '../icon/public_api';
1617

1718
// The number of milliseconds in one day
1819
const ONE_DAY = 1000 * 60 * 60 * 24;
@@ -494,7 +495,8 @@ describe('IgxDateRangePicker', () => {
494495
DateRangeTwoInputsTestComponent,
495496
DateRangeTwoInputsNgModelTestComponent
496497
],
497-
imports: [IgxDateRangePickerModule, IgxDateTimeEditorModule, IgxInputGroupModule, FormsModule, NoopAnimationsModule]
498+
imports: [IgxDateRangePickerModule, IgxDateTimeEditorModule,
499+
IgxInputGroupModule, FormsModule, NoopAnimationsModule, IgxIconModule]
498500
})
499501
.compileComponents();
500502
}));
@@ -633,6 +635,43 @@ describe('IgxDateRangePicker', () => {
633635
}));
634636
});
635637

638+
it('should focus the last focused input after the calendar closes - dropdown', fakeAsync(() => {
639+
fixture.componentInstance.mode = InteractionMode.DropDown;
640+
fixture.detectChanges();
641+
642+
endInput = fixture.debugElement.queryAll(By.css('.igx-input-group'))[1];
643+
UIInteractions.simulateClickAndSelectEvent(endInput.nativeElement);
644+
645+
UIInteractions.triggerEventHandlerKeyDown('ArrowDown', endInput, true);
646+
tick();
647+
fixture.detectChanges();
648+
649+
UIInteractions.triggerEventHandlerKeyDown('Escape', calendar);
650+
fixture.detectChanges();
651+
tick(100);
652+
653+
expect(fixture.componentInstance.dateRange.projectedInputs
654+
.find(i => i instanceof IgxDateRangeEndComponent).isFocused)
655+
.toBeTruthy();
656+
}));
657+
658+
it('should focus the last focused input after the calendar closes - dialog', fakeAsync(() => {
659+
endInput = fixture.debugElement.queryAll(By.css('.igx-input-group'))[1];
660+
UIInteractions.simulateClickAndSelectEvent(endInput.nativeElement);
661+
662+
UIInteractions.triggerEventHandlerKeyDown('ArrowDown', endInput, true);
663+
tick();
664+
fixture.detectChanges();
665+
666+
UIInteractions.triggerEventHandlerKeyDown('Escape', calendar);
667+
fixture.detectChanges();
668+
tick(100);
669+
670+
expect(fixture.componentInstance.dateRange.projectedInputs
671+
.find(i => i instanceof IgxDateRangeEndComponent).isFocused)
672+
.toBeTruthy();
673+
}));
674+
636675
describe('Data binding', () => {
637676
it('should properly update component value with ngModel bound to projected inputs - #7353', fakeAsync(() => {
638677
fixture = TestBed.createComponent(DateRangeTwoInputsNgModelTestComponent);
@@ -822,6 +861,9 @@ export class DateRangeTestComponent implements OnInit {
822861
template: `
823862
<igx-date-range-picker [mode]="mode" [(ngModel)]="range" required>
824863
<igx-date-range-start>
864+
<igx-picker-toggle igxPrefix>
865+
<igx-icon>calendar_view_day</igx-icon>
866+
</igx-picker-toggle>
825867
<input igxInput igxDateTimeEditor type="text">
826868
</igx-date-range-start>
827869
<igx-date-range-end>

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,13 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
415415
private _value: DateRange;
416416
private _collapsed = true;
417417
private _ngControl: NgControl;
418-
private _statusChanges$: Subscription;
419418
private $destroy = new Subject();
419+
private _statusChanges$: Subscription;
420+
private $toggleClickNotifier = new Subject();
420421
private _minValue: Date | string;
421422
private _maxValue: Date | string;
422-
private $toggleClickNotifier = new Subject();
423423
private _positionSettings: PositionSettings;
424+
private _focusedInput: IgxDateRangeInputsBaseComponent;
424425
private _dialogOverlaySettings: OverlaySettings = {
425426
closeOnOutsideClick: true,
426427
modal: true
@@ -620,6 +621,7 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
620621
this.subscribeToDateEditorEvents();
621622
this.configPositionStrategy();
622623
this.configOverlaySettings();
624+
this.cacheFocusedInput();
623625
this.attachOnTouched();
624626

625627
const subsToClicked = () => {
@@ -688,7 +690,13 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
688690
this.updateValidityOnBlur();
689691
} else {
690692
// input click
691-
this.focusInput();
693+
if (this.hasProjectedInputs && this._focusedInput) {
694+
this._focusedInput.setFocus();
695+
this._focusedInput = null;
696+
}
697+
if (this.inputDirective) {
698+
this.inputDirective.focus();
699+
}
692700
}
693701
}
694702

@@ -715,15 +723,6 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
715723
}
716724
}
717725

718-
private focusInput() {
719-
// TODO: should we always focus start input?
720-
(this.projectedInputs
721-
.find(i => i instanceof IgxDateRangeStartComponent) as IgxDateRangeStartComponent)?.setFocus();
722-
if (this.inputDirective) {
723-
this.inputDirective.focus();
724-
}
725-
}
726-
727726
/** @hidden @internal */
728727
public handleClosed(): void {
729728
this._collapsed = true;
@@ -901,6 +900,16 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
901900
}
902901
}
903902

903+
private cacheFocusedInput(): void {
904+
if (this.hasProjectedInputs) {
905+
this.projectedInputs.forEach(i => {
906+
fromEvent(i.dateTimeEditor.nativeElement, 'focus')
907+
.pipe(takeUntil(this.$destroy))
908+
.subscribe(() => this._focusedInput = i);
909+
});
910+
}
911+
}
912+
904913
private configPositionStrategy(): void {
905914
this._positionSettings = {
906915
openAnimation: fadeIn,

projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,31 @@ describe('IgxAutocomplete', () => {
592592
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
593593
expect(fixture.componentInstance.townSelected).toBe('s');
594594
}));
595+
it('Should trigger onItemSelected only once when the event is cancelled (issue #7483)', fakeAsync(() => {
596+
spyOn(autocomplete.onItemSelected, 'emit').and.callThrough();
597+
598+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
599+
UIInteractions.setInputElementValue(input, 's', fixture);
600+
fixture.detectChanges();
601+
tick();
602+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
603+
expect(fixture.componentInstance.townSelected).toBe('s');
604+
tick();
605+
fixture.detectChanges();
606+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(1);
607+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
608+
609+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
610+
UIInteractions.setInputElementValue(input, 's', fixture);
611+
fixture.detectChanges();
612+
tick();
613+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
614+
expect(fixture.componentInstance.townSelected).toBe('s');
615+
tick();
616+
fixture.detectChanges();
617+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(2);
618+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
619+
}));
595620
it('Should call onInput/open/close methods properly', fakeAsync(() => {
596621
let startsWith = 'g';
597622
spyOn(autocomplete, 'onInput').and.callThrough();

0 commit comments

Comments
 (0)