Skip to content

Commit f7047da

Browse files
author
MPopov
committed
Merge branch 'master' of https://github.com/IgniteUI/igniteui-angular into fluent-theme
# Conflicts: # projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss # projects/igniteui-angular/src/lib/core/styles/themes/schemas/elevation/_chip.scss
2 parents 7a04d37 + 1ad1df3 commit f7047da

File tree

65 files changed

+3972
-1906
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+3972
-1906
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes for each version of this project will be documented in this
88
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
99
- `uniqueColumnValuesStrategy` input is added. This property provides a callback for loading unique column values on demand. If this property is provided, the unique values it generates will be used by the Excel Style Filtering (instead of using the unique values from the data that is bound to the grid).
1010
- `igxExcelStyleLoading` directive is added, which can be used to provide a custom loading template for the Excel Style Filtering. If this property is not provided, a default loading template will be used instead.
11+
- introduced new properties `cellSelection` and `rowSelection` which accept GridSelection mode enumeration. Grid selection mode could be none, single or multiple. Also `hideRowSelectors` property is added, which allows you to show and hide row selectors when row selection is enabled.
1112
- `IgxHierarchicalGrid`
1213
- Row Islands now emit child grid events with an additional argument - `owner`, which holds reference to the related child grid component instance.
1314
- `IgxDrag`
@@ -24,9 +25,13 @@ All notable changes for each version of this project will be documented in this
2425

2526
### General
2627
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
28+
- `isCellSelected` method has been deprecated. Now you can use `selected` property.
29+
- `rowSelectable` property has been deprecated. Now you can use `rowSelection` property to enable row selection and also you can show and hide the row selectors by setting `hideRowSelectors` property to true or false (which is the default value).
30+
- Removed deprecated event `OnFocusChange`
2731
- **Breaking Change** `igxExcelStyleSortingTemplate` directive is renamed to `igxExcelStyleSorting`.
2832
- **Breaking Change** `igxExcelStyleMovingTemplate` directive is renamed to `igxExcelStyleMoving`.
2933
- **Breaking Change** `igxExcelStyleHidingTemplate` directive is renamed to `igxExcelStyleHiding`.
34+
- **Breaking Change** `onRowSelectionChange` event arguments are changed. The `row` property has been removed and the properties `added`, `removed` and `cancel` are newly added.
3035
- **Breaking Change** `igxExcelStylePinningTemplate` directive is renamed to `igxExcelStylePinning`.
3136
- **Breaking Change** `onRowDragEnd` and `onRowDragStart` event arguments are changed - `owner` now holds reference to the grid component instance, while `dragDirective` hold reference to the drag directive.
3237
- `IgxCombo`
@@ -50,7 +55,7 @@ All notable changes for each version of this project will be documented in this
5055
- For more information, visit the component's [readme](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/src/lib/combo/README.md)
5156

5257
## 8.1.4
53-
- `IgxDialog` new @Input `positionSettings` is now available. It provides the ability to get/set both position and animation settings of the Dialog component.
58+
- `IgxDialog` new @Input `positionSettings` is now available. It provides the ability to get/set both position and animation settings of the Dialog component.
5459

5560
- `IgxDrag`
5661
- Deprecated inputs - `hideBaseOnDrag`, `animateOnRelease`, `visible`.

projects/igniteui-angular/src/lib/core/grid-selection.ts

Lines changed: 152 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Injectable, EventEmitter, NgZone } from '@angular/core';
22
import { IGridEditEventArgs } from '../grids/grid-base.component';
33

4-
54
export interface GridSelectionRange {
65
rowStart: number;
76
rowEnd: number;
@@ -202,7 +201,7 @@ export class IgxGridCRUDService {
202201

203202
@Injectable()
204203
export class IgxGridSelectionService {
205-
204+
grid;
206205
dragMode = false;
207206
activeElement: ISelectionNode | null;
208207
keyboardState = {} as ISelectionKeyboardState;
@@ -213,7 +212,8 @@ export class IgxGridSelectionService {
213212
temp = new Map<number, Set<number>>();
214213
_ranges: Set<string> = new Set<string>();
215214
_selectionRange: Range;
216-
215+
rowSelection: Set<any> = new Set<any>();
216+
private allRowsSelected: boolean;
217217

218218
/**
219219
* Returns the current selected ranges in the grid from both
@@ -227,7 +227,7 @@ export class IgxGridSelectionService {
227227
const ranges = Array.from(this._ranges).map(range => JSON.parse(range));
228228

229229
// No ranges but we have a focused cell -> add it
230-
if (!ranges.length && this.activeElement) {
230+
if (!ranges.length && this.activeElement && this.grid.isCellSelectable) {
231231
ranges.push(this.generateRange(this.activeElement));
232232
}
233233

@@ -304,7 +304,7 @@ export class IgxGridSelectionService {
304304
}
305305

306306
selected(node: ISelectionNode): boolean {
307-
return this.isActiveNode(node) || this.isInMap(node);
307+
return (this.isActiveNode(node) && this.grid.isCellSelectable) || this.isInMap(node);
308308
}
309309

310310
isActiveNode(node: ISelectionNode, mrl = false): boolean {
@@ -394,7 +394,6 @@ export class IgxGridSelectionService {
394394
}
395395

396396
pointerDown(node: ISelectionNode, shift: boolean, ctrl: boolean): void {
397-
398397
this.addKeyboardRange();
399398
this.initKeyboardState();
400399
this.pointerState.ctrl = ctrl;
@@ -506,7 +505,8 @@ export class IgxGridSelectionService {
506505
this.selectRange(node, state);
507506
}
508507

509-
clear(): void {
508+
clear(clearAcriveEl = false): void {
509+
if (clearAcriveEl) { this.activeElement = null; }
510510
this.selection.clear();
511511
this.temp.clear();
512512
this._ranges.clear();
@@ -541,6 +541,151 @@ export class IgxGridSelectionService {
541541
range.collapse(true);
542542
selection.addRange(range);
543543
}
544+
545+
/** Returns array of the selected row id's. */
546+
getSelectedRows(): Array<any> {
547+
return this.rowSelection.size ? Array.from(this.rowSelection.keys()) : [];
548+
}
549+
550+
/** Clears row selection, if filtering is applied clears only selected rows from filtered data. */
551+
clearRowSelection(event?): void {
552+
const removedRec = this.isFilteringApplied() ?
553+
this.getRowIDs(this.allData).filter(rID => this.isRowSelected(rID)) : this.getSelectedRows();
554+
const newSelection = this.isFilteringApplied() ? this.getSelectedRows().filter(x => !removedRec.includes(x)) : [];
555+
this.emitRowSelectionEvent(newSelection, [], removedRec, event);
556+
}
557+
558+
/** Select all rows, if filtering is applied select only from filtered data. */
559+
selectAllRows(event?) {
560+
const allRowIDs = this.getRowIDs(this.allData);
561+
const addedRows = allRowIDs.filter((rID) => !this.isRowSelected(rID));
562+
const newSelection = this.rowSelection.size ? allRowIDs.concat(this.getSelectedRows()) : addedRows;
563+
564+
this.emitRowSelectionEvent(newSelection, addedRows, [], event);
565+
}
566+
567+
/** Select the specified row and emit event. */
568+
selectRowById(rowID, clearPrevSelection?, event?): void {
569+
if (!this.grid.isRowSelectable || this.isRowDeleted(rowID)) { return; }
570+
clearPrevSelection = !this.grid.isMultiRowSelectionEnabled || clearPrevSelection;
571+
572+
const newSelection = clearPrevSelection ? [rowID] : this.getSelectedRows().indexOf(rowID) !== -1 ?
573+
this.getSelectedRows() : [...this.getSelectedRows(), rowID];
574+
const removed = clearPrevSelection ? this.getSelectedRows() : [];
575+
this.emitRowSelectionEvent(newSelection, [rowID], removed, event);
576+
}
577+
578+
/** Deselect the specified row and emit event. */
579+
deselectRow(rowID, event?): void {
580+
if (!this.isRowSelected(rowID)) { return; }
581+
const newSelection = this.getSelectedRows().filter(r => r !== rowID);
582+
if (this.rowSelection.size && this.rowSelection.has(rowID)) {
583+
this.emitRowSelectionEvent(newSelection, [], [rowID], event);
584+
}
585+
}
586+
587+
/** Select specified rows. No event is emitted. */
588+
selectRowsWithNoEvent(rowIDs: any[], clearPrevSelection?): void {
589+
if (clearPrevSelection) { this.rowSelection.clear(); }
590+
rowIDs.forEach(rowID => { this.rowSelection.add(rowID); });
591+
this.allRowsSelected = undefined;
592+
}
593+
594+
/** Deselect specified rows. No event is emitted. */
595+
deselectRowsWithNoEvent(rowIDs: any[]): void {
596+
rowIDs.forEach(rowID => this.rowSelection.delete(rowID));
597+
this.allRowsSelected = undefined;
598+
}
599+
600+
isRowSelected(rowID): boolean {
601+
return this.rowSelection.size > 0 && this.rowSelection.has(rowID);
602+
}
603+
604+
/** Select range from last selected row to the current specified row.*/
605+
selectMultipleRows(rowID, rowData, event?): void {
606+
this.allRowsSelected = undefined;
607+
if (!this.rowSelection.size || this.isRowDeleted(rowID)) {
608+
this.selectRowById(rowID);
609+
return;
610+
}
611+
const gridData = this.allData;
612+
const lastRowID = this.getSelectedRows()[this.rowSelection.size - 1];
613+
const currIndex = gridData.indexOf(this.getRowDataById(lastRowID));
614+
const newIndex = gridData.indexOf(rowData);
615+
const rows = gridData.slice(Math.min(currIndex, newIndex), Math.max(currIndex, newIndex) + 1);
616+
617+
const added = this.getRowIDs(rows).filter(rID => !this.isRowSelected(rID));
618+
const newSelection = this.getSelectedRows().concat(added);
619+
620+
this.emitRowSelectionEvent(newSelection, added, [], event);
621+
}
622+
623+
areAllRowSelected(): boolean {
624+
if (!this.grid.data) { return false; }
625+
if (this.allRowsSelected !== undefined) { return this.allRowsSelected; }
626+
627+
const dataItemsID = this.getRowIDs(this.allData);
628+
return this.allRowsSelected = Math.min(this.rowSelection.size, dataItemsID.length) > 0 &&
629+
new Set(Array.from(this.rowSelection.values()).concat(dataItemsID)).size === this.rowSelection.size;
630+
}
631+
632+
hasSomeRowSelected(): boolean {
633+
const filteredData = this.isFilteringApplied() ?
634+
this.getRowIDs(this.grid.filteredData).some(rID => this.isRowSelected(rID)) : true;
635+
return this.rowSelection.size > 0 && filteredData && !this.areAllRowSelected();
636+
}
637+
638+
public emitRowSelectionEvent(newSelection, added, removed, event?): boolean {
639+
const currSelection = this.getSelectedRows();
640+
if (this.areEqualCollections(currSelection, newSelection)) { return; }
641+
642+
const args = {
643+
oldSelection: currSelection, newSelection: newSelection,
644+
added: added, removed: removed, event: event, cancel: false
645+
};
646+
this.grid.onRowSelectionChange.emit(args);
647+
if (args.cancel) { return; }
648+
this.selectRowsWithNoEvent(args.newSelection, true);
649+
}
650+
651+
public getRowDataById(rowID): Object {
652+
if (!this.grid.primaryKey) { return rowID; }
653+
const rowIndex = this.getRowIDs(this.grid.gridAPI.get_all_data(true)).indexOf(rowID);
654+
return rowIndex < 0 ? {} : this.grid.gridAPI.get_all_data(true)[rowIndex];
655+
}
656+
657+
public getRowIDs(data): Array<any> {
658+
return this.grid.primaryKey && data.length ? data.map(rec => rec[this.grid.primaryKey]) : data;
659+
}
660+
661+
public clearHeaderCBState(): void {
662+
this.allRowsSelected = undefined;
663+
}
664+
665+
/**Clear rowSelection and update checkbox state*/
666+
public clearAllSelectedRows(): void {
667+
this.rowSelection.clear();
668+
this.clearHeaderCBState();
669+
}
670+
671+
/** Returns all data in the grid, with applied filtering and sorting and without deleted rows. */
672+
public get allData(): Array<any> {
673+
const allData = this.isFilteringApplied() || this.grid.sortingExpressions.length ?
674+
this.grid.filteredSortedData : this.grid.gridAPI.get_all_data(true);
675+
return allData.filter(rData => !this.isRowDeleted(this.grid.gridAPI.get_row_id(rData)));
676+
}
677+
678+
private areEqualCollections(first, second): boolean {
679+
return first.length === second.length && new Set(first.concat(second)).size === first.length;
680+
}
681+
682+
private isFilteringApplied(): boolean {
683+
return this.grid.filteringExpressionsTree.filteringOperands.length > 0;
684+
}
685+
686+
private isRowDeleted(rowID): boolean {
687+
return this.grid.gridAPI.row_deleted_transaction(rowID);
688+
}
544689
}
545690

546691
export function isChromium(): boolean {

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,15 @@
349349
/// // }
350350
/// // otherwise, it will return the value for key 'icon-color' in the '$avatar-theme';
351351
/// @returns {String} - The value of the key in the passed map, or the name of key concatenated with the key name.
352-
@function --var($map, $key, $fallback: '') {
352+
@function --var($map, $key, $fallback: null) {
353353
$igx-legacy-support: if(global-variable-exists('igx-legacy-support'), $igx-legacy-support, true);
354354

355355
@if map-has-key($map, $key) {
356356
@if $igx-legacy-support == false {
357-
@return unquote('var(--#{map-get($map, 'name')}-#{$key}, #{$fallback})');
357+
@if not($fallback) {
358+
@return unquote('var(--#{map-get($map, 'name')}-#{$key})')
359+
}
360+
@return unquote('var(--#{map-get($map, 'name')}-#{$key}, #{$fallback})')
358361
} @else {
359362
@return map-get($map, $key);
360363
}

projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
@function igx-chip-theme(
4343
$palette: $default-palette,
4444
$schema: $light-schema,
45+
$elevations: $elevations,
4546
$border-radius: null,
4647
4748
$text-color: null,
@@ -69,7 +70,7 @@
6970
$focus-selected-background: null,
7071
$focus-selected-border-color: null,
7172
72-
$chip-ghost-shadow: null
73+
$ghost-shadow: null,
7374
) {
7475
$name: 'igx-chip';
7576
$chip-schema: map-get($schema, $name);
@@ -79,11 +80,6 @@
7980
if($border-radius, $border-radius, map-get($chip-schema, 'border-radius')), 0, 16px
8081
);
8182

82-
@if not($chip-ghost-shadow) {
83-
$chip-ghost-elevation: map-get($chip-schema, 'chip-ghost-elevation');
84-
$chip-ghost-shadow: igx-elevation($elevations, $chip-ghost-elevation);
85-
}
86-
8783
@if not($text-color) and $background {
8884
$text-color: text-contrast($background);
8985
}
@@ -172,6 +168,11 @@
172168
$focus-selected-border-color: $border-color;
173169
}
174170

171+
@if not($ghost-shadow) {
172+
$ghost-elevation: map-get($chip-schema, 'ghost-elevation');
173+
$ghost-shadow: igx-elevation($elevations, $ghost-elevation);
174+
}
175+
175176
@return extend($theme, (
176177
name: $name,
177178
palette: $palette,
@@ -181,7 +182,6 @@
181182
background: $background,
182183
border-color: $border-color,
183184
ghost-background: $ghost-background,
184-
chip-ghost-shadow: $chip-ghost-shadow,
185185

186186
hover-text-color: $hover-text-color,
187187
hover-background: $hover-background,
@@ -201,7 +201,9 @@
201201

202202
focus-selected-text-color: $focus-selected-text-color,
203203
focus-selected-background: $focus-selected-background,
204-
focus-selected-border-color: $focus-selected-border-color
204+
focus-selected-border-color: $focus-selected-border-color,
205+
206+
ghost-shadow: $ghost-shadow,
205207
));
206208
}
207209

@@ -220,32 +222,32 @@
220222
cosy: rem(24px),
221223
compact: rem(18px)
222224
);
223-
225+
224226
$chip-height-fluent: (
225227
comfortable: rem(26px),
226228
cosy: rem(24px),
227229
compact: rem(18px)
228230
);
229-
231+
230232
$chip-height: map-get((
231233
material: $chip-height-material,
232234
fluent: $chip-height-fluent
233235
), map-get($theme, variant));
234-
236+
235237
$chip-padding: (
236238
comfortable: 0 rem(8px),
237239
cosy: 0 rem(4px),
238240
compact: 0 rem(2px)
239241
);
240-
242+
241243
$item-padding: 4px;
242244
$chip-item-padding: 0 rem($item-padding);
243-
245+
244246
$chip-avatar-inset: map-get((
245247
material: 0,
246248
fluent: -$item-padding
247249
), map-get($theme, variant));
248-
250+
249251
$chip-icon-size: (
250252
comfortable: rem(18px),
251253
cosy: rem(18px),
@@ -358,13 +360,13 @@
358360
+ igx-prefix,
359361
+ [igxPrefix] {
360362
margin-left: rem(4px);
361-
363+
362364
&%igx-avatar-display {
363365
max-height: 100%;
364366
max-width: 100%;
365367
margin-left: $chip-avatar-inset!important;
366368
}
367-
369+
368370
[dir='rtl'] & {
369371
margin-left: 0;
370372
margin-right: rem(4px);
@@ -519,7 +521,7 @@
519521
%igx-chip__ghost {
520522
position: absolute;
521523
z-index: 10;
522-
box-shadow: --var($theme, 'chip-ghost-shadow');
524+
box-shadow: --var($theme, 'ghost-shadow');
523525
overflow: hidden;
524526
background: --var($theme, 'ghost-background');
525527

projects/igniteui-angular/src/lib/core/styles/components/navdrawer/_navdrawer-theme.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
/// @param {Color} $item-hover-text-color [null] - The item's hover text color.
2222
/// @param {Color} $item-hover-icon-color [null] - The item's hover icon color.
2323
/// @param {Color} $shadow [null] - Sets a custom shadow to be used by the drawer.
24-
/// @param {border-radius} border-radius [null] - The border radius used for the navdrawer.
25-
/// @param {border-radius} item-border-radius [null] - The border radius used for the navdrawer item.
24+
/// @param {border-radius} $border-radius [null] - The border radius used for the navdrawer.
25+
/// @param {border-radius} $item-border-radius [null] - The border radius used for the navdrawer item.
2626
///
2727
/// @requires $default-palette
2828
/// @requires $light-schema

0 commit comments

Comments
 (0)