@progress/kendo-angular-grid 13.0.2 → 13.0.3-develop.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,12 +10,12 @@ import { merge, of, Subject, from, Subscription, interval, fromEvent, zip as zip
10
10
  import { switchMap, take, map, filter, takeUntil, switchMapTo, delay, auditTime, distinctUntilChanged, tap, throttleTime, debounceTime, bufferCount } from 'rxjs/operators';
11
11
  import * as i1 from '@progress/kendo-angular-l10n';
12
12
  import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
13
+ import { orderBy, isCompositeFilterDescriptor, process, filterBy } from '@progress/kendo-data-query';
13
14
  import * as i4 from '@angular/common';
14
15
  import { CommonModule } from '@angular/common';
15
16
  import * as i4$2 from '@angular/forms';
16
17
  import { NG_VALUE_ACCESSOR, FormControl, FormGroup, ReactiveFormsModule, FormsModule } from '@angular/forms';
17
18
  import { validatePackage } from '@progress/kendo-licensing';
18
- import { orderBy, isCompositeFilterDescriptor, process, filterBy } from '@progress/kendo-data-query';
19
19
  import * as i1$2 from '@progress/kendo-angular-popup';
20
20
  import { PopupModule } from '@progress/kendo-angular-popup';
21
21
  import * as i1$3 from '@angular/platform-browser';
@@ -2065,1994 +2065,2343 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
2065
2065
  type: Optional
2066
2066
  }] }]; } });
2067
2067
 
2068
+ // Incremented each time the service is instantiated.
2069
+ let sequence = 0;
2068
2070
  /**
2069
2071
  * @hidden
2070
2072
  */
2071
- class SelectionService {
2072
- constructor(domEvents, localDataChangesService, navigationService, ctxService) {
2073
- this.domEvents = domEvents;
2074
- this.localDataChangesService = localDataChangesService;
2075
- this.navigationService = navigationService;
2076
- this.ctxService = ctxService;
2077
- this.changes = new EventEmitter();
2078
- this.aggregateChanges = new EventEmitter();
2079
- this.currentSelection = [];
2080
- this.selectAllChecked = false;
2081
- this.active = false;
2082
- this.dragging = false;
2083
- this.lastSelectionData = {};
2084
- this.addSubscriptions();
2085
- }
2086
- get enableMarquee() {
2087
- const checkboxOnly = this.settings && typeof this.settings === 'object' && this.settings.checkboxOnly;
2088
- if (!this.settings || checkboxOnly) {
2089
- return false;
2090
- }
2091
- const selectableSettings = this.settings.selectable;
2092
- const dragAndMultiple = typeof (selectableSettings) === 'object' &&
2093
- isPresent(selectableSettings) &&
2094
- selectableSettings.mode === 'multiple' &&
2095
- selectableSettings.enabled !== false &&
2096
- !selectableSettings.checkboxOnly &&
2097
- selectableSettings.drag;
2098
- return this.active && dragAndMultiple;
2073
+ class IdService {
2074
+ constructor() {
2075
+ this.prefix = `k-grid${sequence++}`;
2099
2076
  }
2100
- init(settings) {
2101
- this.settings = settings;
2102
- if (!isPresent(this.lastSelectionStartIndex)) {
2103
- this.lastSelectionStartIndex = this.ctxService?.grid.selectionDirective?.rangeSelectionStartRow?.index || 0;
2104
- this.lastSelectionData = this.ctxService?.grid.selectionDirective?.rangeSelectionStartRow?.dataItem || {};
2105
- }
2106
- this.currentSelection = [];
2107
- if (settings.selectable && settings.selectable.enabled !== false) {
2108
- const iterator = this.getIterator();
2109
- this._selectAllState = true;
2110
- let item = iterator.next();
2111
- while (!item.done) {
2112
- if (item.value && item.value.type === "data") {
2113
- const rowArgs = {
2114
- dataItem: item.value.data,
2115
- index: item.value.index
2116
- };
2117
- if (settings.rowSelected(rowArgs)) {
2118
- this.currentSelection[item.value.index] = rowArgs;
2119
- }
2120
- else {
2121
- this._selectAllState = undefined;
2122
- }
2123
- }
2124
- item = iterator.next();
2125
- }
2126
- if (this.currentSelection.length === 0) {
2127
- this._selectAllState = false;
2128
- }
2129
- }
2077
+ gridId() {
2078
+ return this.prefix;
2130
2079
  }
2131
- isSelected(index) {
2132
- if (this.settings && this.active) {
2133
- return this.options.enabled && isPresent(this.currentSelection[index]);
2134
- }
2080
+ cellId(rowIndex, colIndex) {
2081
+ return `${this.prefix}-r${rowIndex}c${colIndex}`;
2135
2082
  }
2136
- handleClick(item, event) {
2137
- if (this.dragging) {
2138
- this.dragging = false;
2139
- return;
2140
- }
2141
- let ev;
2142
- const ctrlKey = event.ctrlKey || event.metaKey;
2143
- if (this.options.mode === "single" && ctrlKey && this.isSelected(item.index)) {
2144
- ev = this.toggle(item);
2145
- }
2146
- else if (this.options.mode === "multiple") {
2147
- if (ctrlKey && !event.shiftKey) {
2148
- ev = this.toggle(item);
2149
- }
2150
- else if (event.shiftKey) {
2151
- ev = this.addAllTo(item, ctrlKey);
2152
- }
2153
- }
2154
- if (!isPresent(ev)) {
2155
- ev = this.select(item);
2156
- this.currentSelection[item.index] = {
2157
- dataItem: item.data,
2158
- index: item.index
2159
- };
2160
- }
2161
- if (!ev.selectedRows.length && !ev.deselectedRows.length) {
2162
- return;
2163
- }
2164
- ev.ctrlKey = ctrlKey;
2165
- ev.shiftKey = event.shiftKey;
2166
- if (this.options.cellAggregates) {
2167
- this.aggregateChanges.emit(ev);
2168
- ev.cellAggregates = this.aggregates;
2169
- }
2170
- if (ev.shiftKey) {
2171
- ev.rangeStartRow = { dataItem: this.lastSelectionData, index: this.lastSelectionStartIndex };
2172
- ev.rangeEndRow = { dataItem: item.data, index: item.index };
2173
- }
2174
- this.changes.emit(ev);
2083
+ selectionCheckboxId(itemIndex) {
2084
+ return `${this.prefix}-checkbox${itemIndex}`;
2175
2085
  }
2176
- toggle(item) {
2177
- const selectedRows = [];
2178
- const deselectedRows = [];
2179
- this.lastSelectionStartIndex = item.index;
2180
- this.lastSelectionData = item.data;
2181
- const rowArgs = { dataItem: item.data, index: item.index };
2182
- if (this.isSelected(item.index)) {
2183
- deselectedRows.push(rowArgs);
2184
- }
2185
- else {
2186
- selectedRows.push(rowArgs);
2187
- }
2188
- return {
2189
- deselectedRows: deselectedRows,
2190
- selectedRows: selectedRows
2191
- };
2086
+ selectAllCheckboxId() {
2087
+ return `${this.prefix}-select-all`;
2192
2088
  }
2193
- toggleByIndex(index) {
2194
- const iterator = this.getIterator();
2195
- if (this.selectAllChecked && this.isSelected(index)) {
2196
- this.selectAllChecked = false;
2197
- }
2198
- let item = iterator.next();
2199
- while (!item.done) {
2200
- if (item.value && item.value.type === "data" && item.value.index === index) {
2201
- const itemToToggle = {
2202
- data: item.value.data,
2203
- index: item.value.index
2204
- };
2205
- if (this.isSelected(index) || this.options.mode === "multiple") {
2206
- return this.toggle(itemToToggle);
2207
- }
2208
- else {
2209
- return this.select(itemToToggle);
2210
- }
2211
- }
2212
- item = iterator.next();
2213
- }
2089
+ }
2090
+ IdService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: IdService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2091
+ IdService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: IdService });
2092
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: IdService, decorators: [{
2093
+ type: Injectable
2094
+ }], ctorParameters: function () { return []; } });
2095
+
2096
+ /**
2097
+ * Represents the column header cell template of the Grid
2098
+ * ([more information and example]({% slug templates_columns_grid %}#toc-header-template)).
2099
+ * Helps to customize the table header cell for the column.
2100
+ * To define a header template, nest an `<ng-template>` tag with the
2101
+ * `kendoGridHeaderTemplate` directive inside the `<kendo-grid-column>` tag.
2102
+ *
2103
+ * The template context is set to the current column and then the following additional fields are passed:
2104
+ * * `column`&mdash;Defines an instance of the [ColumnComponent]({% slug api_grid_columncomponent %}) option.
2105
+ * * `columnIndex`&mdash;Defines the current column index.
2106
+ *
2107
+ * @example
2108
+ * ```html
2109
+ * <kendo-grid [data]="gridData">
2110
+ * <kendo-grid-column field="ProductName">
2111
+ * <ng-template kendoGridHeaderTemplate let-column let-columnIndex="columnIndex">
2112
+ * {{column.field}}({{columnIndex}})
2113
+ * </ng-template>
2114
+ * </kendo-grid-column>
2115
+ * </kendo-grid>
2116
+ * ```
2117
+ */
2118
+ class HeaderTemplateDirective {
2119
+ constructor(templateRef) {
2120
+ this.templateRef = templateRef;
2214
2121
  }
2215
- select(item) {
2216
- const deselectedRows = [];
2217
- const selectedRows = [];
2218
- this.lastSelectionStartIndex = item.index;
2219
- this.lastSelectionData = item.data;
2220
- if (!this.isSelected(item.index)) {
2221
- selectedRows.push({ dataItem: item.data, index: item.index });
2222
- }
2223
- this.currentSelection.forEach((row) => {
2224
- if (row.index !== item.index) {
2225
- deselectedRows.push(row);
2226
- }
2227
- });
2228
- return {
2229
- deselectedRows: deselectedRows,
2230
- selectedRows: selectedRows
2231
- };
2122
+ }
2123
+ HeaderTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2124
+ HeaderTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: HeaderTemplateDirective, selector: "[kendoGridHeaderTemplate]", ngImport: i0 });
2125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderTemplateDirective, decorators: [{
2126
+ type: Directive,
2127
+ args: [{
2128
+ selector: '[kendoGridHeaderTemplate]'
2129
+ }]
2130
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2131
+ type: Optional
2132
+ }] }]; } });
2133
+
2134
+ /**
2135
+ * Represents the column footer cell template of the Grid
2136
+ * ([more information and example]({% slug templates_columns_grid %}#toc-footer-template)).
2137
+ * Helps to customize the table footer cell for the column.
2138
+ * To define a footer template, nest an `<ng-template>` tag with the
2139
+ * [kendoGridFooterTemplate]({% slug api_grid_footertemplatedirective %}) directive inside the `<kendo-grid-column>` tag.
2140
+ *
2141
+ * The template context is set to the current column and the following additional fields are passed:
2142
+ * * `column`&mdash;Defines an instance of the [ColumnComponent]({% slug api_grid_columncomponent %}) option.
2143
+ * * `columnIndex`&mdash;Defines the current column index.
2144
+ *
2145
+ * For more information on how to display aggregates in the footer of the Grid,
2146
+ * refer to the article on [aggregates]({% slug groupable_grid_with_aggregates %}).
2147
+ *
2148
+ * @example
2149
+ * ```html
2150
+ * <kendo-grid [data]="gridData" scrollable="none">
2151
+ * <kendo-grid-column field="ProductName">
2152
+ * <ng-template kendoGridFooterTemplate let-column let-columnIndex="columnIndex">
2153
+ * {{column.field}}({{columnIndex}})
2154
+ * </ng-template>
2155
+ * </kendo-grid-column>
2156
+ * </kendo-grid>
2157
+ * ```
2158
+ */
2159
+ class FooterTemplateDirective {
2160
+ constructor(templateRef) {
2161
+ this.templateRef = templateRef;
2232
2162
  }
2233
- //Used to manually deselect removed items
2234
- deselect(removedItem) {
2235
- const iterator = this.getIterator();
2236
- let item = iterator.next();
2237
- while (!item.done) {
2238
- if (item.value && item.value.type === "data" && item.value.data === removedItem) {
2239
- const rowArgs = {
2240
- dataItem: item.value.data,
2241
- index: item.value.index
2242
- };
2243
- if (this.isSelected(rowArgs.index)) {
2244
- const ev = {
2245
- ctrlKey: false,
2246
- deselectedRows: [rowArgs],
2247
- selectedRows: []
2248
- };
2249
- this.changes.emit(ev);
2250
- }
2251
- }
2252
- item = iterator.next();
2253
- }
2163
+ }
2164
+ FooterTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FooterTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2165
+ FooterTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FooterTemplateDirective, selector: "[kendoGridFooterTemplate]", ngImport: i0 });
2166
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FooterTemplateDirective, decorators: [{
2167
+ type: Directive,
2168
+ args: [{
2169
+ selector: '[kendoGridFooterTemplate]'
2170
+ }]
2171
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2172
+ type: Optional
2173
+ }] }]; } });
2174
+
2175
+ /**
2176
+ * Represents the template for the column menu in the Grid. Provides an option for
2177
+ * customizing the content of the column menu for all or for specific columns.
2178
+ * To define the content template, nest an `<ng-template>` tag with the
2179
+ * `kendoGridColumnMenuTemplate` directive inside the `<kendo-grid>` or the `<kendo-grid-column>` component.
2180
+ *
2181
+ * The template context is passes through the following fields:
2182
+ * - `service`&mdash;Represents the [ColumnMenuService]({% slug api_grid_columnmenuservice %}).
2183
+ * - `column`&mdash;Represents the Grid column.
2184
+ *
2185
+ * @example
2186
+ * ```html
2187
+ * <kendo-grid [kendoGridBinding]="data" [sortable]="true" [columnMenu]="true">
2188
+ * <ng-template kendoGridColumnMenuTemplate let-service="service">
2189
+ * <kendo-grid-columnmenu-sort [service]="service"></kendo-grid-columnmenu-sort>
2190
+ * </ng-template>
2191
+ * <kendo-grid-column field="Field1">
2192
+ * <ng-template kendoGridColumnMenuTemplate let-service="service">
2193
+ * <kendo-grid-columnmenu-lock [service]="service"></kendo-grid-columnmenu-lock>
2194
+ * <kendo-grid-columnmenu-sort [service]="service"></kendo-grid-columnmenu-sort>
2195
+ * </ng-template>
2196
+ * </kendo-grid-column>
2197
+ * <kendo-grid-column field="Field2"></kendo-grid-column>
2198
+ * </kendo-grid>
2199
+ * ```
2200
+ */
2201
+ class ColumnMenuTemplateDirective {
2202
+ constructor(templateRef) {
2203
+ this.templateRef = templateRef;
2254
2204
  }
2255
- addAllTo(item, ctrlKey) {
2256
- const selectedRows = [];
2257
- const deselectedRows = [];
2258
- const start = Math.min(this.lastSelectionStartIndex, item.index);
2259
- const end = Math.max(this.lastSelectionStartIndex, item.index);
2260
- const iterator = this.getIterator();
2261
- let next = iterator.next();
2262
- while (!next.done) {
2263
- if (next.value && next.value.type === "data") {
2264
- const idx = next.value.index;
2265
- const rowArgs = { dataItem: next.value.data, index: idx };
2266
- if ((idx < start || idx > end) && this.isSelected(idx) && !ctrlKey) {
2267
- deselectedRows.push(rowArgs);
2268
- }
2269
- if ((idx >= start && idx <= end) && !this.isSelected(idx)) {
2270
- selectedRows.push(rowArgs);
2271
- }
2272
- }
2273
- next = iterator.next();
2205
+ }
2206
+ ColumnMenuTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnMenuTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2207
+ ColumnMenuTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: ColumnMenuTemplateDirective, selector: "[kendoGridColumnMenuTemplate]", ngImport: i0 });
2208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnMenuTemplateDirective, decorators: [{
2209
+ type: Directive,
2210
+ args: [{
2211
+ selector: '[kendoGridColumnMenuTemplate]'
2212
+ }]
2213
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2214
+ type: Optional
2215
+ }] }]; } });
2216
+
2217
+ /**
2218
+ * @hidden
2219
+ */
2220
+ const isSpanColumn = column => column.isSpanColumn;
2221
+ /**
2222
+ * @hidden
2223
+ */
2224
+ const isCheckboxColumn = column => column.isCheckboxColumn;
2225
+ /**
2226
+ * @hidden
2227
+ */
2228
+ const isRowReorderColumn = column => column.isRowReorderColumn;
2229
+ const isColumnContainer = column => column.isColumnGroup || isSpanColumn(column);
2230
+ /**
2231
+ * The base class for the column components of the Grid.
2232
+ */
2233
+ class ColumnBase {
2234
+ /**
2235
+ * @hidden
2236
+ */
2237
+ constructor(parent, idService) {
2238
+ this.parent = parent;
2239
+ /**
2240
+ * @hidden
2241
+ */
2242
+ this.matchesMedia = true;
2243
+ /**
2244
+ * The column index after reordering. The `orderIndex` is a read-only property. Setting this field does not affect column order.
2245
+ *
2246
+ * @default 0
2247
+ */
2248
+ this.orderIndex = 0;
2249
+ /**
2250
+ * @hidden
2251
+ */
2252
+ this.isColumnGroup = false;
2253
+ /**
2254
+ * @hidden
2255
+ */
2256
+ this.isSpanColumn = false;
2257
+ /**
2258
+ * Indicates whether the column is resizable.
2259
+ * @default true
2260
+ */
2261
+ this.resizable = true;
2262
+ /**
2263
+ * Indicates whether the column is reorderable.
2264
+ * @default true
2265
+ */
2266
+ this.reorderable = true;
2267
+ /**
2268
+ * The width (in pixels) below which the user is not able to resize the column by using the UI ([see example]({% slug resizing_columns_grid %}#toc-limiting-the-resizing)).
2269
+ * The `autoFitColumn` and `autoFitColumns` methods have higher priority.
2270
+ * @default 10
2271
+ */
2272
+ this.minResizableWidth = 10;
2273
+ this._locked = false;
2274
+ /**
2275
+ * Determines whether the column will be always visible when scrolling the Grid horizontally.
2276
+ *
2277
+ * @default false
2278
+ */
2279
+ this.sticky = false;
2280
+ /**
2281
+ * Specifies if the column can be locked or unlocked from the column menu or by reordering the columns.
2282
+ * @default true
2283
+ */
2284
+ this.lockable = true;
2285
+ /**
2286
+ * Specifies if the column can be stuck or unstuck from the column menu.
2287
+ * @default true
2288
+ */
2289
+ this.stickable = true;
2290
+ /**
2291
+ * Specifies if the column menu will be shown for the column.
2292
+ * @default true
2293
+ */
2294
+ this.columnMenu = true;
2295
+ /**
2296
+ * Specifies if the column will be included in the column-chooser list.
2297
+ * @default true
2298
+ */
2299
+ this.includeInChooser = true;
2300
+ /**
2301
+ * @hidden
2302
+ */
2303
+ this.headerTemplates = new QueryList();
2304
+ /**
2305
+ * @hidden
2306
+ */
2307
+ this.columnMenuTemplates = new QueryList();
2308
+ this.idService = idService;
2309
+ if (parent && idService && parent.idService.gridId() === idService.gridId() && !isColumnContainer(parent)) {
2310
+ throw new Error('Columns can be nested only inside ColumnGroupComponent');
2274
2311
  }
2275
- return {
2276
- deselectedRows: deselectedRows,
2277
- selectedRows: selectedRows
2278
- };
2279
2312
  }
2280
- updateAll(selectAllChecked) {
2281
- this.selectAllChecked = selectAllChecked;
2282
- const selectedRows = [];
2283
- const deselectedRows = [];
2284
- const iterator = this.getIterator();
2285
- let next = iterator.next();
2286
- while (!next.done) {
2287
- if (next.value && next.value.type === "data") {
2288
- const idx = next.value.index;
2289
- const rowArgs = { dataItem: next.value.data, index: idx };
2290
- if (this.isSelected(idx) && !selectAllChecked) {
2291
- deselectedRows.push(rowArgs);
2292
- }
2293
- if (!this.isSelected(idx) && selectAllChecked) {
2294
- selectedRows.push(rowArgs);
2295
- }
2296
- }
2297
- next = iterator.next();
2298
- }
2299
- if (!selectedRows.length && !deselectedRows.length) {
2300
- return;
2301
- }
2302
- const ev = {
2303
- ctrlKey: true,
2304
- deselectedRows: deselectedRows,
2305
- selectedRows: selectedRows,
2306
- shiftKey: true
2307
- };
2308
- this.changes.emit(ev);
2313
+ /**
2314
+ * @hidden
2315
+ */
2316
+ set leafIndex(value) {
2317
+ this._leafIndex = value;
2309
2318
  }
2310
- selectRange(startIndex, endIndex) {
2311
- const selectedRows = [];
2312
- const deselectedRows = [];
2313
- const start = Math.min(startIndex, endIndex);
2314
- const end = Math.max(startIndex, endIndex);
2315
- const iterator = this.getIterator();
2316
- let next = iterator.next();
2317
- while (!next.done) {
2318
- if (next.value && next.value.type === "data") {
2319
- const idx = next.value.index;
2320
- const rowArgs = { dataItem: next.value.data, index: idx };
2321
- if ((idx < start || idx > end) && this.isSelected(idx)) {
2322
- deselectedRows.push(rowArgs);
2323
- }
2324
- if ((idx >= start && idx <= end) && !this.isSelected(idx)) {
2325
- selectedRows.push(rowArgs);
2326
- }
2319
+ /**
2320
+ * @hidden
2321
+ */
2322
+ get leafIndex() {
2323
+ return this._leafIndex;
2324
+ }
2325
+ /**
2326
+ * The width of the column (in pixels).
2327
+ */
2328
+ set width(value) {
2329
+ if (typeof value === 'string') {
2330
+ const parsedValue = this._width = parseInt(value, 10);
2331
+ if (isDevMode()) {
2332
+ console.warn(`Expected numeric value for column width, but got a string "${value}". Treating as ${parsedValue}px.`);
2327
2333
  }
2328
- next = iterator.next();
2329
2334
  }
2330
- let cellAggregates;
2331
- if (this.options.cellAggregates) {
2332
- this.aggregateChanges.emit({ selectedRows, deselectedRows });
2333
- cellAggregates = this.aggregates;
2335
+ else {
2336
+ this._width = value;
2334
2337
  }
2335
- return {
2336
- deselectedRows: deselectedRows,
2337
- selectedRows: selectedRows,
2338
- cellAggregates
2339
- };
2340
- }
2341
- get selectAllState() {
2342
- return this._selectAllState;
2343
- }
2344
- get selected() {
2345
- return this.currentSelection.map((item) => {
2346
- return item.index;
2347
- }).filter((n) => typeof n === "number");
2348
2338
  }
2349
- get options() {
2350
- const defaultOptions = {
2351
- cellAggregates: false,
2352
- checkboxOnly: false,
2353
- enabled: true,
2354
- mode: "multiple"
2355
- };
2356
- if (!isPresent(this.settings)) {
2357
- return defaultOptions;
2358
- }
2359
- if (typeof this.settings.selectable === 'boolean') {
2360
- return {
2361
- cellAggregates: false,
2362
- checkboxOnly: false,
2363
- enabled: this.settings.selectable,
2364
- mode: "multiple"
2365
- };
2366
- }
2367
- else {
2368
- return Object.assign(defaultOptions, this.settings.selectable);
2339
+ get width() { return this._width; }
2340
+ /**
2341
+ * Toggles the locked (frozen) state of the columns ([more information and example]({% slug locked_columns_grid %})).
2342
+ *
2343
+ * @default false
2344
+ *
2345
+ */
2346
+ set locked(value) {
2347
+ this._locked = value;
2348
+ }
2349
+ get locked() {
2350
+ return this._locked;
2351
+ }
2352
+ /**
2353
+ * @hidden
2354
+ */
2355
+ get level() {
2356
+ if (this.parent && isSpanColumn(this.parent)) {
2357
+ return this.parent.level;
2369
2358
  }
2359
+ return this.parent ? this.parent.level + 1 : 0;
2370
2360
  }
2371
- ngOnDestroy() {
2372
- this.removeSubscriptions();
2361
+ /**
2362
+ * @hidden
2363
+ */
2364
+ get isLocked() {
2365
+ return this.parent ? this.parent.isLocked : this.locked;
2373
2366
  }
2374
- targetArgs() {
2375
- return {
2376
- index: this.mouseDownEventArgs.rowIndex,
2377
- dataItem: this.mouseDownEventArgs.dataItem
2378
- };
2367
+ /**
2368
+ * @hidden
2369
+ */
2370
+ get colspan() {
2371
+ return 1;
2379
2372
  }
2380
- addSubscriptions() {
2381
- if (!this.cellClickSubscription) {
2382
- this.cellClickSubscription = this.domEvents.cellClick.subscribe((args) => {
2383
- if (this.options.enabled && !this.options.checkboxOnly && args.type !== 'contextmenu') {
2384
- if (this.active) {
2385
- this.handleClick({ index: args.rowIndex, data: args.dataItem }, args.originalEvent);
2386
- }
2387
- }
2388
- });
2389
- }
2390
- if (!this.mousedownSubscription) {
2391
- this.mousedownSubscription = this.domEvents.cellMousedown.subscribe((args) => {
2392
- this.mouseDownEventArgs = args;
2393
- if ((this.options.enabled && (!this.options.mode || this.options.mode === "multiple") &&
2394
- !this.options.checkboxOnly && args.originalEvent.shiftKey)) {
2395
- if (this.active) {
2396
- args.originalEvent.preventDefault();
2397
- this.navigationService.focusCellByElement(args.originalEvent.target);
2398
- }
2399
- }
2400
- });
2401
- }
2402
- if (this.localDataChangesService && !this.dataChangedSubscription) {
2403
- this.dataChangedSubscription = this.localDataChangesService.changes.subscribe((args) => {
2404
- if (this.active) {
2405
- if (isPresent(args.action) && args.action === 'remove') {
2406
- this.deselect(args.item);
2407
- }
2408
- }
2409
- });
2410
- }
2373
+ /**
2374
+ * @hidden
2375
+ */
2376
+ rowspan(totalColumnLevels) {
2377
+ return this.level < totalColumnLevels ? (totalColumnLevels - this.level) + 1 : 1;
2411
2378
  }
2412
- getIterator() {
2413
- const accessor = this.settings.view.accessor();
2414
- if (!accessor) {
2415
- return;
2416
- }
2417
- return accessor[iterator]();
2379
+ /**
2380
+ * @hidden
2381
+ */
2382
+ get headerTemplateRef() {
2383
+ const template = this.headerTemplates.first;
2384
+ return template ? template.templateRef : undefined;
2418
2385
  }
2419
- removeSubscriptions() {
2420
- if (this.cellClickSubscription) {
2421
- this.cellClickSubscription.unsubscribe();
2422
- this.cellClickSubscription = null;
2423
- }
2424
- if (this.mousedownSubscription) {
2425
- this.mousedownSubscription.unsubscribe();
2426
- this.mousedownSubscription = null;
2427
- }
2428
- if (this.dataChangedSubscription) {
2429
- this.dataChangedSubscription.unsubscribe();
2430
- this.dataChangedSubscription = null;
2431
- }
2386
+ /**
2387
+ * @hidden
2388
+ */
2389
+ get footerTemplateRef() {
2390
+ return this.footerTemplate ? this.footerTemplate.templateRef : undefined;
2391
+ }
2392
+ /**
2393
+ * @hidden
2394
+ */
2395
+ get columnMenuTemplateRef() {
2396
+ const template = this.columnMenuTemplates.first;
2397
+ return template ? template.templateRef : null;
2398
+ }
2399
+ /**
2400
+ * @hidden
2401
+ */
2402
+ get displayTitle() {
2403
+ return this.title;
2404
+ }
2405
+ /**
2406
+ * @hidden
2407
+ */
2408
+ get isVisible() {
2409
+ return !this.hidden && this.matchesMedia;
2432
2410
  }
2433
2411
  }
2434
- SelectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionService, deps: [{ token: DomEventsService }, { token: LocalDataChangesService }, { token: NavigationService }, { token: ContextService }], target: i0.ɵɵFactoryTarget.Injectable });
2435
- SelectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionService });
2436
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionService, decorators: [{
2437
- type: Injectable
2438
- }], ctorParameters: function () { return [{ type: DomEventsService }, { type: LocalDataChangesService }, { type: NavigationService }, { type: ContextService }]; } });
2412
+ ColumnBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnBase, deps: [{ token: ColumnBase }, { token: IdService }], target: i0.ɵɵFactoryTarget.Component });
2413
+ ColumnBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ColumnBase, selector: "kendo-grid-column-base", inputs: { resizable: "resizable", reorderable: "reorderable", minResizableWidth: "minResizableWidth", maxResizableWidth: "maxResizableWidth", title: "title", width: "width", autoSize: "autoSize", locked: "locked", sticky: "sticky", hidden: "hidden", media: "media", lockable: "lockable", stickable: "stickable", columnMenu: "columnMenu", includeInChooser: "includeInChooser", style: "style", headerStyle: "headerStyle", filterStyle: "filterStyle", footerStyle: "footerStyle", cssClass: ["class", "cssClass"], headerClass: "headerClass", filterClass: "filterClass", footerClass: "footerClass" }, queries: [{ propertyName: "footerTemplate", first: true, predicate: FooterTemplateDirective, descendants: true }, { propertyName: "headerTemplates", predicate: HeaderTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], ngImport: i0, template: ``, isInline: true });
2414
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnBase, decorators: [{
2415
+ type: Component,
2416
+ args: [{
2417
+ selector: 'kendo-grid-column-base',
2418
+ template: ``
2419
+ }]
2420
+ }], ctorParameters: function () { return [{ type: ColumnBase }, { type: IdService }]; }, propDecorators: { resizable: [{
2421
+ type: Input
2422
+ }], reorderable: [{
2423
+ type: Input
2424
+ }], minResizableWidth: [{
2425
+ type: Input
2426
+ }], maxResizableWidth: [{
2427
+ type: Input
2428
+ }], title: [{
2429
+ type: Input
2430
+ }], width: [{
2431
+ type: Input
2432
+ }], autoSize: [{
2433
+ type: Input
2434
+ }], locked: [{
2435
+ type: Input
2436
+ }], sticky: [{
2437
+ type: Input
2438
+ }], hidden: [{
2439
+ type: Input
2440
+ }], media: [{
2441
+ type: Input
2442
+ }], lockable: [{
2443
+ type: Input
2444
+ }], stickable: [{
2445
+ type: Input
2446
+ }], columnMenu: [{
2447
+ type: Input
2448
+ }], includeInChooser: [{
2449
+ type: Input
2450
+ }], style: [{
2451
+ type: Input
2452
+ }], headerStyle: [{
2453
+ type: Input
2454
+ }], filterStyle: [{
2455
+ type: Input
2456
+ }], footerStyle: [{
2457
+ type: Input
2458
+ }], cssClass: [{
2459
+ type: Input,
2460
+ args: ['class']
2461
+ }], headerClass: [{
2462
+ type: Input
2463
+ }], filterClass: [{
2464
+ type: Input
2465
+ }], footerClass: [{
2466
+ type: Input
2467
+ }], headerTemplates: [{
2468
+ type: ContentChildren,
2469
+ args: [HeaderTemplateDirective, { descendants: false }]
2470
+ }], footerTemplate: [{
2471
+ type: ContentChild,
2472
+ args: [FooterTemplateDirective, { static: false }]
2473
+ }], columnMenuTemplates: [{
2474
+ type: ContentChildren,
2475
+ args: [ColumnMenuTemplateDirective]
2476
+ }] } });
2439
2477
 
2440
2478
  /**
2441
- * @hidden
2479
+ * Represents the column cell template of the Grid.
2480
+ * Helps to customize the content of the cells. To define the cell template, nest an `<ng-template>` tag with the
2481
+ * `kendoGridCellTemplate` directive inside a `<kendo-grid-column>` tag [see example](slug:templates_columns_grid#toc-cell-template).
2482
+ *
2483
+ * The template context is set to the current data item and the following additional fields are passed:
2484
+ * - `columnIndex`&mdash;The current column index. Use it as an alias for a template variable by utilizing the `let-columnIndex="columnIndex"` syntax.
2485
+ * - `rowIndex`&mdash;The current data row index. Use it as an alias for a template variable by utilizing the `let-rowIndex="rowIndex"` syntax.
2486
+ * - `dataItem`&mdash;The current data item. Represents the default context that will be assigned to any template variable which utilizes the `let-x` syntax&mdash;for example, `let-dataItem`.
2487
+ * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
2488
+ *
2489
+ * @example
2490
+ * ```html
2491
+ * <kendo-grid [data]="gridData" ...>
2492
+ * <kendo-grid-column field="ProductName">
2493
+ * <ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex" let-column="column">
2494
+ * Data Row: {{rowIndex}}
2495
+ * </ng-template>
2496
+ * </kendo-grid-column>
2497
+ * </kendo-grid>
2498
+ * ```
2442
2499
  */
2443
- class CellSelectionService {
2444
- constructor(domEvents, localDataChangesService, navigationService) {
2445
- this.domEvents = domEvents;
2446
- this.localDataChangesService = localDataChangesService;
2447
- this.navigationService = navigationService;
2448
- this.changes = new EventEmitter();
2449
- this.aggregateChanges = new EventEmitter();
2450
- this.mouseUpEvent = new EventEmitter();
2451
- this.currentSelection = [];
2452
- this.active = false;
2453
- this.dragging = false;
2454
- this.dragSelectDeselect = false;
2455
- this.lastSelectionItem = { itemKey: 0, columnKey: 0 };
2456
- this.lastSelectionItemRowIndex = 0;
2457
- this.lastSelectionItemColIndex = 0;
2458
- this.addSubscriptions();
2500
+ class CellTemplateDirective {
2501
+ constructor(templateRef) {
2502
+ this.templateRef = templateRef;
2459
2503
  }
2460
- get enableMarquee() {
2461
- const checkboxOnly = this.settings && typeof this.settings === 'object' && this.settings.checkboxOnly;
2462
- if (!this.settings || checkboxOnly) {
2463
- return false;
2464
- }
2465
- const selectableSettings = this.settings.selectable;
2466
- const dragAndMultiple = typeof (selectableSettings) === 'object' &&
2467
- isPresent(selectableSettings) &&
2468
- selectableSettings.mode === 'multiple' &&
2469
- selectableSettings.cell &&
2470
- selectableSettings.enabled !== false &&
2471
- selectableSettings.drag;
2472
- return this.active && dragAndMultiple;
2504
+ }
2505
+ CellTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2506
+ CellTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: CellTemplateDirective, selector: "[kendoGridCellTemplate]", ngImport: i0 });
2507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellTemplateDirective, decorators: [{
2508
+ type: Directive,
2509
+ args: [{
2510
+ selector: '[kendoGridCellTemplate]'
2511
+ }]
2512
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2513
+ type: Optional
2514
+ }] }]; } });
2515
+
2516
+ /**
2517
+ * Represents the column edit-cell template of the Grid ([see example](slug:custom_reactive_editing_grid#toc-setting-up-custom-inputs)).
2518
+ * Helps to customize the content of the edited cells. To define the cell template, nest an `<ng-template>`
2519
+ * tag with the `kendoGridEditTemplate` directive inside a `<kendo-grid-column>` tag.
2520
+ *
2521
+ * The template context is set to the current form group and the following additional fields are passed:
2522
+ * - `formGroup`&mdash;The current [FormGroup](link:site.data.urls.angular['formgroupapi']). Represents the default context that will be assigned to any template variable which utilizes the `let-x` syntax, for example, `let-formGroup`. If you use the Grid inside [Template-Driven Forms](link:site.data.urls.angular['forms']), it will be `undefined`.
2523
+ * - `rowIndex`&mdash;The current data row index. If inside a new item row, `rowIndex` is `-1`. Use it as an alias for a template variable by utilizing the `let-rowIndex="rowIndex"` syntax.
2524
+ * - `dataItem`&mdash;The current data item. Use it as an alias for a template variable by utilizing the `let-dataItem="dataItem"` syntax.
2525
+ * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
2526
+ * - `isNew`&mdash;The state of the current item. Use it as an alias for a template variable by utilizing the `let-isNew="isNew"` syntax.
2527
+ */
2528
+ class EditTemplateDirective {
2529
+ constructor(templateRef) {
2530
+ this.templateRef = templateRef;
2473
2531
  }
2474
- init(settings) {
2475
- this.settings = settings;
2476
- this.currentSelection = [];
2477
- if (settings.selectable && settings.selectable.enabled !== false) {
2478
- const iterator = this.getIterator();
2479
- let item = iterator.next();
2480
- while (!item.done) {
2481
- if (item.value && item.value.type === "data") {
2482
- const rowArgs = {
2483
- dataItem: item.value.data,
2484
- index: item.value.index
2485
- };
2486
- settings.columns.forEach(col => {
2487
- const selectedCellArgs = settings.cellSelected(rowArgs, col, col.leafIndex);
2488
- if (selectedCellArgs.selected) {
2489
- this.currentSelection.push(selectedCellArgs.item);
2490
- }
2491
- });
2492
- }
2493
- item = iterator.next();
2494
- }
2495
- }
2532
+ }
2533
+ EditTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: EditTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2534
+ EditTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: EditTemplateDirective, selector: "[kendoGridEditTemplate]", ngImport: i0 });
2535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: EditTemplateDirective, decorators: [{
2536
+ type: Directive,
2537
+ args: [{
2538
+ selector: '[kendoGridEditTemplate]'
2539
+ }]
2540
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2541
+ type: Optional
2542
+ }] }]; } });
2543
+
2544
+ /**
2545
+ * Represents the group-header cell template of the Grid which helps to customize the content of the group header item.
2546
+ * To define the group header template, nest an `<ng-template>` tag with the `kendoGridGroupHeaderTemplate`
2547
+ * directive inside `<kendo-grid-column>`. ([See example](slug:grouping_grid_templates#toc-header-template)).
2548
+ *
2549
+ * The template context is set to the current data item and the following additional fields are passed:
2550
+ * - `group`&mdash;The current group item.
2551
+ * - `field`&mdash;The name of the field by which data is grouped.
2552
+ * - `value`&mdash;The current group value.
2553
+ * - `aggregates`&mdash;All aggregate values for the current group.
2554
+ * - `index`&mdash;The index of the current group.
2555
+ * - `expanded`&mdash;A boolean value indicating if the group is currently expanded.
2556
+ *
2557
+ * @example
2558
+ * ```html
2559
+ * <kendo-grid [data]="gridData" [group]="groups">
2560
+ * <kendo-grid-column field="ProductName">
2561
+ * <ng-template kendoGridGroupHeaderTemplate let-group let-field="field" let-value="value">
2562
+ * <strong>{{field}}</strong>: {{value}}
2563
+ * </ng-template>
2564
+ * </kendo-grid-column>
2565
+ * </kendo-grid>
2566
+ * ```
2567
+ */
2568
+ class GroupHeaderTemplateDirective {
2569
+ constructor(templateRef) {
2570
+ this.templateRef = templateRef;
2496
2571
  }
2497
- isCellSelected(item, col) {
2498
- if (this.settings && this.active) {
2499
- const selectedCellArgs = this.settings.cellSelected({ dataItem: item.data, index: item.index }, col, col.leafIndex);
2500
- return this.options.enabled && selectedCellArgs.selected;
2501
- }
2502
- return false;
2572
+ }
2573
+ GroupHeaderTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2574
+ GroupHeaderTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GroupHeaderTemplateDirective, selector: "[kendoGridGroupHeaderTemplate]", ngImport: i0 });
2575
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderTemplateDirective, decorators: [{
2576
+ type: Directive,
2577
+ args: [{
2578
+ selector: '[kendoGridGroupHeaderTemplate]'
2579
+ }]
2580
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2581
+ type: Optional
2582
+ }] }]; } });
2583
+
2584
+ /**
2585
+ * Represents the group-header column template of the Grid which helps to customize the content of the group headers.
2586
+ * To define the group header template, nest an `<ng-template>` tag with the `kendoGridGroupHeaderColumnTemplate`
2587
+ * directive inside `<kendo-grid-column>`. ([See example](slug:grouping_grid_templates#toc-header-column-template)).
2588
+ *
2589
+ * The template context is set to the current data item and the following additional fields are passed:
2590
+ * - `group`&mdash;The current group item.
2591
+ * - `field`&mdash;The name of the field by which data is grouped.
2592
+ * - `value`&mdash;The current group value.
2593
+ * - `aggregates`&mdash;All aggregate values for the current group.
2594
+ *
2595
+ * @example
2596
+ * ```html
2597
+ * <kendo-grid-column field="ProductName" title="Product Name">
2598
+ * <ng-template kendoGridGroupHeaderColumnTemplate let-group="group" let-aggregates="aggregates">
2599
+ * <span title="Group Header Column Template for ProductName">
2600
+ * Count: {{ aggregates.Discontinued.count }}
2601
+ * </span>
2602
+ * </ng-template>
2603
+ * </kendo-grid-column>
2604
+ * ```
2605
+ */
2606
+ class GroupHeaderColumnTemplateDirective {
2607
+ constructor(templateRef) {
2608
+ this.templateRef = templateRef;
2503
2609
  }
2504
- handleClick(item, event) {
2505
- if (this.dragging) {
2506
- this.dragging = false;
2507
- return;
2508
- }
2509
- let ev;
2510
- const ctrlKey = event.ctrlKey || event.metaKey;
2511
- if (this.options.mode === "single" && ctrlKey && this.isCellSelected(item, item.column)) {
2512
- ev = this.toggle(item);
2513
- }
2514
- else if (this.options.mode === "multiple") {
2515
- if (ctrlKey && !event.shiftKey) {
2516
- ev = this.toggle(item);
2517
- }
2518
- else if (event.shiftKey) {
2519
- const startRowIndex = Math.min(this.lastSelectionItemRowIndex, item.index);
2520
- const startColIndex = Math.min(this.lastSelectionItemColIndex, item.column.leafIndex);
2521
- const endRowIndex = Math.max(this.lastSelectionItemRowIndex, item.index);
2522
- const endColIndex = Math.max(this.lastSelectionItemColIndex, item.column.leafIndex);
2523
- ev = this.selectRange(startRowIndex, startColIndex, endRowIndex, endColIndex);
2524
- }
2525
- }
2526
- if (!isPresent(ev)) {
2527
- ev = this.select(item);
2528
- this.currentSelection = [this.lastSelectionItem];
2529
- }
2530
- if (!ev.selectedCells.length && !ev.deselectedCells.length) {
2531
- return;
2532
- }
2533
- ev.ctrlKey = ctrlKey;
2534
- ev.shiftKey = event.shiftKey;
2535
- if (this.options.cellAggregates) {
2536
- this.aggregateChanges.emit(ev);
2537
- ev.cellAggregates = this.aggregates;
2538
- }
2539
- if (ev.shiftKey) {
2540
- ev.rangeStartCell = this.lastSelectionItem;
2541
- ev.rangeEndCell = {
2542
- ...this.settings.cellSelected({ dataItem: item.data, index: item.index }, item.column, item.column.leafIndex).item
2543
- };
2544
- }
2545
- this.changes.emit(ev);
2610
+ }
2611
+ GroupHeaderColumnTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderColumnTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2612
+ GroupHeaderColumnTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GroupHeaderColumnTemplateDirective, selector: "[kendoGridGroupHeaderColumnTemplate]", ngImport: i0 });
2613
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderColumnTemplateDirective, decorators: [{
2614
+ type: Directive,
2615
+ args: [{
2616
+ selector: '[kendoGridGroupHeaderColumnTemplate]'
2617
+ }]
2618
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2619
+ type: Optional
2620
+ }] }]; } });
2621
+
2622
+ /**
2623
+ * Represents the column group footer cell template of the Grid which helps to customize the group footer cell for the column.
2624
+ * To define the group footer template, nest an `<ng-template>` tag with the `kendoGridGroupFooterTemplate` directive
2625
+ * inside `<kendo-grid-column>`.
2626
+ *
2627
+ * The template context is set to the current data item and the following additional fields are passed:
2628
+ * - `column`&mdash;Defines an instance of the `ColumnComponent` option.
2629
+ * - `field`&mdash;The current column field name.
2630
+ * - `group`&mdash;The current group data item.
2631
+ * - `aggregates`&mdash;All aggregate values for the current group.
2632
+ *
2633
+ * @example
2634
+ * ```html
2635
+ * <kendo-grid [data]="gridData" [group]="groups">
2636
+ * <kendo-grid-column field="ProductName">
2637
+ * <ng-template kendoGridGroupFooterTemplate let-aggregates let-field="field">
2638
+ * Count: {{aggregates[field].count}}
2639
+ * </ng-template>
2640
+ * </kendo-grid-column>
2641
+ * </kendo-grid>
2642
+ * ```
2643
+ */
2644
+ class GroupFooterTemplateDirective {
2645
+ constructor(templateRef) {
2646
+ this.templateRef = templateRef;
2546
2647
  }
2547
- toggle(item) {
2548
- const selectedCells = [];
2549
- const deselectedCells = [];
2550
- this.lastSelectionItem =
2551
- this.settings.cellSelected({ dataItem: item.data, index: item.index }, item.column, item.column.leafIndex).item;
2552
- this.lastSelectionItemRowIndex = item.index;
2553
- this.lastSelectionItemColIndex = item.column.leafIndex;
2554
- if (this.isCellSelected(item, item.column)) {
2555
- deselectedCells.push(this.lastSelectionItem);
2556
- }
2557
- else {
2558
- selectedCells.push(this.lastSelectionItem);
2559
- }
2560
- return {
2561
- deselectedCells,
2562
- selectedCells
2563
- };
2648
+ }
2649
+ GroupFooterTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupFooterTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2650
+ GroupFooterTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GroupFooterTemplateDirective, selector: "[kendoGridGroupFooterTemplate]", ngImport: i0 });
2651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupFooterTemplateDirective, decorators: [{
2652
+ type: Directive,
2653
+ args: [{
2654
+ selector: '[kendoGridGroupFooterTemplate]'
2655
+ }]
2656
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2657
+ type: Optional
2658
+ }] }]; } });
2659
+
2660
+ /**
2661
+ * Represents the filter-cell template ([see example]({% slug filter_row %}#toc-custom-filters)).
2662
+ */
2663
+ class FilterCellTemplateDirective {
2664
+ constructor(templateRef) {
2665
+ this.templateRef = templateRef;
2564
2666
  }
2565
- select(item) {
2566
- const selectedCells = [];
2567
- const deselectedCells = [];
2568
- this.lastSelectionItem =
2569
- this.settings.cellSelected({ dataItem: item.data, index: item.index }, item.column, item.column.leafIndex).item;
2570
- this.lastSelectionItemRowIndex = item.index;
2571
- this.lastSelectionItemColIndex = item.column.leafIndex;
2572
- if (!this.isCellSelected(item, item.column)) {
2573
- selectedCells.push(this.lastSelectionItem);
2574
- }
2575
- this.currentSelection.forEach((selectedItem) => {
2576
- if (selectedItem.itemKey !== this.lastSelectionItem.itemKey || selectedItem.columnKey !== this.lastSelectionItem.columnKey) {
2577
- deselectedCells.push(selectedItem);
2578
- }
2579
- });
2580
- return {
2581
- deselectedCells,
2582
- selectedCells
2583
- };
2667
+ }
2668
+ FilterCellTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterCellTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2669
+ FilterCellTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FilterCellTemplateDirective, selector: "[kendoGridFilterCellTemplate]", ngImport: i0 });
2670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterCellTemplateDirective, decorators: [{
2671
+ type: Directive,
2672
+ args: [{
2673
+ selector: '[kendoGridFilterCellTemplate]'
2674
+ }]
2675
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2676
+ type: Optional
2677
+ }] }]; } });
2678
+
2679
+ /**
2680
+ * Represents the filter-menu template
2681
+ * ([see example]({% slug filter_menu %}#toc-custom-filters)).
2682
+ */
2683
+ class FilterMenuTemplateDirective {
2684
+ constructor(templateRef) {
2685
+ this.templateRef = templateRef;
2584
2686
  }
2585
- //Used to manually deselect removed items
2586
- deselect(removedItem) {
2587
- const iterator = this.getIterator();
2588
- let item = iterator.next();
2589
- let rowArgs;
2590
- while (!item.done) {
2591
- if (item.value && item.value.type === "data" && item.value.data === removedItem) {
2592
- rowArgs = {
2593
- dataItem: item.value.data,
2594
- index: item.value.index
2595
- };
2596
- break;
2597
- }
2598
- item = iterator.next();
2599
- }
2600
- if (rowArgs) {
2601
- const cellsToRemove = this.currentSelection.filter(selectedItem => {
2602
- const contender = this.settings.cellSelected(rowArgs, null, null).item;
2603
- return selectedItem.itemKey === contender.itemKey;
2604
- });
2605
- if (cellsToRemove.length) {
2606
- const ev = {
2607
- ctrlKey: false,
2608
- deselectedCells: cellsToRemove,
2609
- selectedCells: []
2610
- };
2611
- this.changes.emit(ev);
2612
- }
2613
- }
2687
+ }
2688
+ FilterMenuTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterMenuTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2689
+ FilterMenuTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FilterMenuTemplateDirective, selector: "[kendoGridFilterMenuTemplate]", ngImport: i0 });
2690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterMenuTemplateDirective, decorators: [{
2691
+ type: Directive,
2692
+ args: [{
2693
+ selector: '[kendoGridFilterMenuTemplate]'
2694
+ }]
2695
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2696
+ type: Optional
2697
+ }] }]; } });
2698
+
2699
+ /**
2700
+ * @hidden
2701
+ */
2702
+ function isColumnComponent(column) {
2703
+ return isPresent(column.field);
2704
+ }
2705
+ /**
2706
+ * Represents the column of the Grid. [See example](slug:columns_config#toc-using-the-column-component)
2707
+ *
2708
+ * @example
2709
+ * ```html
2710
+ * <kendo-grid [data]="gridData">
2711
+ * <kendo-grid-column field="ProductID" title="Product ID"></kendo-grid-column>
2712
+ * <kendo-grid-column field="ProductName" title="Product Name"></kendo-grid-column>
2713
+ * <kendo-grid-column field="UnitPrice" title="Unit Price"></kendo-grid-column>
2714
+ * </kendo-grid>
2715
+ * ```
2716
+ */
2717
+ class ColumnComponent extends ColumnBase {
2718
+ constructor(parent, idService) {
2719
+ super(parent, idService);
2720
+ /**
2721
+ * Allows the user to click the column headers and emits the `sortChange` event. [See example](slug:sorting_grid).
2722
+ *
2723
+ * @default true
2724
+ */
2725
+ this.sortable = true;
2726
+ /**
2727
+ * Determines if the column can be dragged to the group panel.
2728
+ * If set to `false`, you can group the columns by the column field by using the API of the Grid.
2729
+ *
2730
+ * @default true
2731
+ */
2732
+ this.groupable = true;
2733
+ /**
2734
+ * Defines the editor type. [See example](slug:inline_editing_grid#toc-using-reactive-forms).
2735
+ * Used when the column enters the edit mode.
2736
+ *
2737
+ * @default 'text'
2738
+ */
2739
+ this.editor = 'text';
2740
+ /**
2741
+ * Defines the filter type that is displayed inside the filter row. [See example](slug:filtering_grid#toc-filter-data-types).
2742
+ *
2743
+ * @default 'text'
2744
+ */
2745
+ this.filter = 'text';
2746
+ /**
2747
+ * Defines if a filter UI will be displayed for this column. [See example](slug:filtering_grid).
2748
+ *
2749
+ * @default true
2750
+ */
2751
+ this.filterable = true;
2752
+ /**
2753
+ * Defines whether the column is editable. [See example](slug:make_fields_uneditable_grid).
2754
+ *
2755
+ * @default true
2756
+ */
2757
+ this.editable = true;
2614
2758
  }
2615
- selectRange(startRowIndex, startColIndex, endRowIndex, endColIndex) {
2616
- const selectedCells = [];
2617
- const deselectedCells = [];
2618
- const selectionStartRow = Math.min(startRowIndex, endRowIndex);
2619
- const selectionStartCol = Math.min(startColIndex, endColIndex);
2620
- const selectionEndRow = Math.max(startRowIndex, endRowIndex);
2621
- const selectionEndCol = Math.max(startColIndex, endColIndex);
2622
- const iterator = this.getIterator();
2623
- let next = iterator.next();
2624
- while (!next.done) {
2625
- if (next.value && next.value.type === "data") {
2626
- const idx = next.value.index;
2627
- const data = next.value.data;
2628
- const rowArgs = {
2629
- dataItem: data,
2630
- index: idx
2631
- };
2632
- this.settings.columns.forEach(col => {
2633
- const { item } = this.settings.cellSelected(rowArgs, col, col.leafIndex);
2634
- const selected = this.isCellSelected(next.value, col);
2635
- const isInRowRange = selectionStartRow <= idx && idx <= selectionEndRow;
2636
- const isInColRange = selectionStartCol <= col.leafIndex && col.leafIndex <= selectionEndCol;
2637
- const isInSelectionRect = isInRowRange && isInColRange;
2638
- if (!isInSelectionRect && selected) {
2639
- deselectedCells.push(item);
2640
- }
2641
- if (isInSelectionRect && !selected) {
2642
- selectedCells.push(item);
2643
- }
2644
- });
2645
- }
2646
- next = iterator.next();
2647
- }
2648
- let cellAggregates;
2649
- if (this.options.cellAggregates) {
2650
- this.aggregateChanges.emit({ selectedCells, deselectedCells });
2651
- cellAggregates = this.aggregates;
2652
- }
2653
- return {
2654
- deselectedCells,
2655
- selectedCells,
2656
- cellAggregates
2657
- };
2759
+ get templateRef() {
2760
+ return this.template ? this.template.templateRef : undefined;
2658
2761
  }
2659
- get options() {
2660
- const defaultOptions = {
2661
- cellAggregates: false,
2662
- checkboxOnly: false,
2663
- enabled: true,
2664
- mode: "multiple"
2665
- };
2666
- if (!isPresent(this.settings)) {
2667
- return defaultOptions;
2668
- }
2669
- if (typeof this.settings.selectable === 'boolean') {
2670
- return {
2671
- cellAggregates: false,
2672
- checkboxOnly: false,
2673
- enabled: this.settings.selectable,
2674
- mode: "multiple"
2675
- };
2676
- }
2677
- else {
2678
- return Object.assign(defaultOptions, this.settings.selectable);
2679
- }
2762
+ get groupHeaderTemplateRef() {
2763
+ return this.groupHeaderTemplate ? this.groupHeaderTemplate.templateRef : undefined;
2680
2764
  }
2681
- ngOnDestroy() {
2682
- this.removeSubscriptions();
2765
+ get groupHeaderColumnTemplateRef() {
2766
+ return this.groupHeaderColumnTemplate ? this.groupHeaderColumnTemplate.templateRef : undefined;
2683
2767
  }
2684
- addSubscriptions() {
2685
- if (!this.cellClickSubscription) {
2686
- this.cellClickSubscription = this.domEvents.cellClick.subscribe((args) => {
2687
- if (this.options.enabled && !this.options.checkboxOnly && args.type !== 'contextmenu') {
2688
- if (this.active) {
2689
- this.handleClick({ index: args.rowIndex, data: args.dataItem, column: args.column }, args.originalEvent);
2690
- }
2691
- }
2692
- });
2693
- }
2694
- if (!this.mousedownSubscription) {
2695
- this.mousedownSubscription = this.domEvents.cellMousedown.subscribe((args) => {
2696
- this.mouseDownEventArgs = args;
2697
- if (this.options.enabled && (!this.options.mode || this.options.mode === "multiple") &&
2698
- !this.options.checkboxOnly && args.originalEvent.shiftKey) {
2699
- if (this.active) {
2700
- args.originalEvent.preventDefault();
2701
- this.navigationService.focusCellByElement(args.originalEvent.target);
2702
- }
2703
- }
2704
- });
2705
- }
2706
- if (this.localDataChangesService && !this.dataChangedSubscription) {
2707
- this.dataChangedSubscription = this.localDataChangesService.changes.subscribe((args) => {
2708
- if (this.active) {
2709
- if (isPresent(args.action) && args.action === 'remove') {
2710
- this.deselect(args.item);
2711
- }
2712
- }
2713
- });
2714
- }
2768
+ get groupFooterTemplateRef() {
2769
+ return this.groupFooterTemplate ? this.groupFooterTemplate.templateRef : undefined;
2715
2770
  }
2716
- getIterator() {
2717
- const accessor = this.settings.view.accessor();
2718
- if (!accessor) {
2719
- return;
2720
- }
2721
- return accessor[iterator]();
2771
+ get editTemplateRef() {
2772
+ return this.editTemplate ? this.editTemplate.templateRef : undefined;
2722
2773
  }
2723
- removeSubscriptions() {
2724
- if (this.cellClickSubscription) {
2725
- this.cellClickSubscription.unsubscribe();
2726
- this.cellClickSubscription = null;
2727
- }
2728
- if (this.mousedownSubscription) {
2729
- this.mousedownSubscription.unsubscribe();
2730
- this.mousedownSubscription = null;
2731
- }
2732
- if (this.dataChangedSubscription) {
2733
- this.dataChangedSubscription.unsubscribe();
2734
- this.dataChangedSubscription = null;
2735
- }
2774
+ get filterCellTemplateRef() {
2775
+ return this.filterCellTemplate ? this.filterCellTemplate.templateRef : undefined;
2776
+ }
2777
+ get filterMenuTemplateRef() {
2778
+ return this.filterMenuTemplate ? this.filterMenuTemplate.templateRef : undefined;
2779
+ }
2780
+ get displayTitle() {
2781
+ return this.title === undefined ? this.field : this.title;
2736
2782
  }
2737
2783
  }
2738
- CellSelectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionService, deps: [{ token: DomEventsService }, { token: LocalDataChangesService }, { token: NavigationService }], target: i0.ɵɵFactoryTarget.Injectable });
2739
- CellSelectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionService });
2740
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionService, decorators: [{
2741
- type: Injectable
2742
- }], ctorParameters: function () { return [{ type: DomEventsService }, { type: LocalDataChangesService }, { type: NavigationService }]; } });
2784
+ ColumnComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
2785
+ ColumnComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ColumnComponent, selector: "kendo-grid-column", inputs: { field: "field", format: "format", sortable: "sortable", groupable: "groupable", editor: "editor", filter: "filter", filterable: "filterable", editable: "editable" }, providers: [
2786
+ {
2787
+ provide: ColumnBase,
2788
+ useExisting: forwardRef(() => ColumnComponent)
2789
+ }
2790
+ ], queries: [{ propertyName: "template", first: true, predicate: CellTemplateDirective, descendants: true }, { propertyName: "groupHeaderTemplate", first: true, predicate: GroupHeaderTemplateDirective, descendants: true }, { propertyName: "groupHeaderColumnTemplate", first: true, predicate: GroupHeaderColumnTemplateDirective, descendants: true }, { propertyName: "groupFooterTemplate", first: true, predicate: GroupFooterTemplateDirective, descendants: true }, { propertyName: "editTemplate", first: true, predicate: EditTemplateDirective, descendants: true }, { propertyName: "filterCellTemplate", first: true, predicate: FilterCellTemplateDirective, descendants: true }, { propertyName: "filterMenuTemplate", first: true, predicate: FilterMenuTemplateDirective, descendants: true }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
2791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnComponent, decorators: [{
2792
+ type: Component,
2793
+ args: [{
2794
+ providers: [
2795
+ {
2796
+ provide: ColumnBase,
2797
+ useExisting: forwardRef(() => ColumnComponent)
2798
+ }
2799
+ ],
2800
+ selector: 'kendo-grid-column',
2801
+ template: ``
2802
+ }]
2803
+ }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{
2804
+ type: SkipSelf
2805
+ }, {
2806
+ type: Host
2807
+ }, {
2808
+ type: Optional
2809
+ }] }, { type: IdService, decorators: [{
2810
+ type: Optional
2811
+ }] }]; }, propDecorators: { field: [{
2812
+ type: Input
2813
+ }], format: [{
2814
+ type: Input
2815
+ }], sortable: [{
2816
+ type: Input
2817
+ }], groupable: [{
2818
+ type: Input
2819
+ }], editor: [{
2820
+ type: Input
2821
+ }], filter: [{
2822
+ type: Input
2823
+ }], filterable: [{
2824
+ type: Input
2825
+ }], editable: [{
2826
+ type: Input
2827
+ }], template: [{
2828
+ type: ContentChild,
2829
+ args: [CellTemplateDirective, { static: false }]
2830
+ }], groupHeaderTemplate: [{
2831
+ type: ContentChild,
2832
+ args: [GroupHeaderTemplateDirective, { static: false }]
2833
+ }], groupHeaderColumnTemplate: [{
2834
+ type: ContentChild,
2835
+ args: [GroupHeaderColumnTemplateDirective, { static: false }]
2836
+ }], groupFooterTemplate: [{
2837
+ type: ContentChild,
2838
+ args: [GroupFooterTemplateDirective, { static: false }]
2839
+ }], editTemplate: [{
2840
+ type: ContentChild,
2841
+ args: [EditTemplateDirective, { static: false }]
2842
+ }], filterCellTemplate: [{
2843
+ type: ContentChild,
2844
+ args: [FilterCellTemplateDirective, { static: false }]
2845
+ }], filterMenuTemplate: [{
2846
+ type: ContentChild,
2847
+ args: [FilterMenuTemplateDirective, { static: false }]
2848
+ }] } });
2743
2849
 
2744
- const createElement$1 = () => {
2745
- if (!isDocumentAvailable()) {
2746
- return;
2747
- }
2748
- const marquee = document.createElement("div");
2749
- marquee.className = "k-marquee";
2750
- const marqueeColor = document.createElement("div");
2751
- marqueeColor.className = "k-marquee-color";
2752
- marquee.appendChild(marqueeColor);
2753
- return marquee;
2754
- };
2755
- const POINTER_OFFSET = 2;
2756
- const MINIMAL_DRAG_DISTANCE = 5;
2757
- const offsets = {
2758
- topLeft: { x: POINTER_OFFSET, y: POINTER_OFFSET },
2759
- topRight: { x: -POINTER_OFFSET, y: POINTER_OFFSET },
2760
- bottomLeft: { x: POINTER_OFFSET, y: -POINTER_OFFSET },
2761
- bottomRight: { x: -POINTER_OFFSET, y: -POINTER_OFFSET }
2762
- };
2763
2850
  /**
2764
2851
  * @hidden
2765
2852
  */
2766
- class GridMarqueeDirective {
2767
- constructor(draggable, selection, cellSelection, domEvents) {
2768
- this.draggable = draggable;
2769
- this.selection = selection;
2770
- this.cellSelection = cellSelection;
2771
- this.domEvents = domEvents;
2772
- this.selectionStarted = false;
2773
- }
2774
- get webkitUserSelection() {
2775
- return (this.cellSelection.enableMarquee || this.selection.enableMarquee) ? 'none' : null;
2853
+ function isSpanColumnComponent(column) {
2854
+ return column.isSpanColumn;
2855
+ }
2856
+ /**
2857
+ * Represents a column which can be spanned over multiple data cells while the individual
2858
+ * header and footer cells are retained ([see example]({% slug spanned_columns_grid %})).
2859
+ * Enables you to achieve more flexible layout while keeping the built-in UI element for
2860
+ * [sorting]({% slug sorting_grid %}), [filtering]({% slug filtering_grid %}), and
2861
+ * [grouping]({% slug grouping_grid %}). Wrap the columns that will be
2862
+ * merged inside the `<kendo-grid-span-column>` tag.
2863
+ *
2864
+ * ```html
2865
+ * <kendo-grid-span-column>
2866
+ * <kendo-grid-column field="field1"></kendo-grid-column>
2867
+ * <kendo-grid-column field="field2"></kendo-grid-column>
2868
+ * <ng-template kendoGridCellTemplate let-dataItem>
2869
+ * <h5>{{ dataItem.field1 }}</h5>
2870
+ * <p>{{ dataItem.field2 }}</p>
2871
+ * </ng-template>
2872
+ * </kendo-grid-span-column>
2873
+ * ```
2874
+ */
2875
+ class SpanColumnComponent extends ColumnBase {
2876
+ constructor(parent, idService) {
2877
+ super(parent, idService);
2878
+ /*
2879
+ * @hidden
2880
+ */
2881
+ this.isSpanColumn = true;
2882
+ this.template = new QueryList();
2883
+ this.editTemplate = new QueryList();
2884
+ /**
2885
+ * @hidden
2886
+ */
2887
+ this.childColumns = new QueryList();
2888
+ /**
2889
+ * @hidden
2890
+ */
2891
+ this.includeInChooser = false;
2892
+ this._editable = true;
2893
+ if (parent && parent.isSpanColumn) {
2894
+ throw new Error('SpanColumn cannot be nested inside another SpanColumn');
2895
+ }
2776
2896
  }
2777
- get userSelection() {
2778
- return (this.cellSelection.enableMarquee || this.selection.enableMarquee);
2897
+ /**
2898
+ * Defines whether the edit template of the column will be rendered.
2899
+ * To enable the editing functionality for a spanned column, set an edit template for it ([see example](slug:custom_reactive_editing_grid)).
2900
+ * @default false
2901
+ */
2902
+ set editable(value) {
2903
+ this._editable = value;
2779
2904
  }
2780
- ngOnInit() {
2781
- this.subscriptions = (this.draggable.kendoPress.subscribe(this.start.bind(this)));
2782
- this.subscriptions.add(this.draggable.kendoDrag.subscribe(this.moveMarquee.bind(this)));
2905
+ get editable() {
2906
+ return isPresent(this.editTemplateRef) && this._editable;
2783
2907
  }
2784
- ngOnDestroy() {
2785
- this.subscriptions.unsubscribe();
2786
- this.clean();
2908
+ /**
2909
+ * @hidden
2910
+ * added for backwards compitability
2911
+ */
2912
+ set width(_value) {
2787
2913
  }
2788
- start(args) {
2789
- const isInvalidTarget = args.originalEvent.target.matches('.k-grid-content, .k-grid-content-locked, .k-grid-aria-root, .k-checkbox');
2790
- if (isInvalidTarget) {
2791
- this.pressArgs = null;
2792
- return;
2793
- }
2794
- this.pressArgs = args;
2795
- this.pressTarget = null;
2914
+ get width() {
2915
+ return this.childColumns.reduce((total, column) => total + column.width, 0);
2796
2916
  }
2797
- moveMarquee(args) {
2798
- if (!this.pressTarget) {
2799
- this.pressTarget = this.cellSelection.active ? this.cellSelection.mouseDownEventArgs : this.selection.mouseDownEventArgs;
2800
- }
2801
- const press = this.pressArgs;
2802
- if (!press) {
2803
- return;
2804
- }
2805
- if (!this.selectionStarted) {
2806
- const distance = Math.sqrt((args.pageX - press.pageX) ** 2 + (args.pageY - press.pageY) ** 2);
2807
- if (distance > MINIMAL_DRAG_DISTANCE) {
2808
- this.selectionStarted = true;
2809
- this.dragEndSubscription = merge(this.domEvents.cellMouseup.pipe(take(1)), this.draggable.kendoRelease.pipe(delay(1), take(1)))
2810
- .subscribe(this.endSelection.bind(this));
2811
- }
2812
- else {
2813
- return;
2814
- }
2815
- }
2816
- this.initMarquee();
2817
- const element = this.marqueeElement;
2818
- const marqueeQuadrant = this.getMarqueeQuadrant(args.pageX, args.pageY, press.pageX, press.pageY);
2819
- let left = Math.min(args.pageX, press.pageX);
2820
- let top = Math.min(args.pageY, press.pageY);
2821
- const width = Math.abs(args.pageX - press.pageX);
2822
- const height = Math.abs(args.pageY - press.pageY);
2823
- if (marqueeQuadrant) {
2824
- left += offsets[marqueeQuadrant].x;
2825
- top += offsets[marqueeQuadrant].y;
2826
- }
2827
- element.style.left = `${left}px`;
2828
- element.style.top = `${top}px`;
2829
- element.style.width = `${width}px`;
2830
- element.style.height = `${height}px`;
2917
+ /**
2918
+ * @hidden
2919
+ */
2920
+ get leafIndex() {
2921
+ return this.childColumns.first.leafIndex;
2831
2922
  }
2832
- endSelection(args) {
2833
- if (args.type === 'mouseup' || args.type === 'touchend') {
2834
- if (this.cellSelection.active) {
2835
- this.cellSelection.dragging = true;
2836
- this.cellSelection.changes.emit(this.cellSelection.selectRange(this.pressTarget.rowIndex, this.pressTarget.column.leafIndex, args.rowIndex, args.column.leafIndex));
2837
- }
2838
- else if (this.selection.active) {
2839
- this.selection.dragging = true;
2840
- this.selection.changes.emit(this.selection.selectRange(this.pressTarget.rowIndex, args.rowIndex));
2841
- }
2842
- }
2843
- this.clean();
2923
+ /**
2924
+ * @hidden
2925
+ */
2926
+ get templateRef() {
2927
+ const template = this.template.first;
2928
+ return template ? template.templateRef : undefined;
2844
2929
  }
2845
- clean() {
2846
- if (this.marqueeElement) {
2847
- document.body.removeChild(this.marqueeElement);
2848
- this.marqueeElement = null;
2849
- }
2850
- if (this.dragEndSubscription) {
2851
- this.dragEndSubscription.unsubscribe();
2852
- }
2853
- this.dragEndSubscription = null;
2854
- this.pressTarget = null;
2855
- this.pressArgs = null;
2856
- this.selectionStarted = false;
2857
- // eslint-disable-next-line no-unused-expressions
2858
- this.cellSelection.active ? this.cellSelection.dragging = false : this.selection.dragging = false;
2930
+ /**
2931
+ * @hidden
2932
+ */
2933
+ get editTemplateRef() {
2934
+ const editTemplate = this.editTemplate.first;
2935
+ return editTemplate ? editTemplate.templateRef : undefined;
2859
2936
  }
2860
- initMarquee() {
2861
- if (!isDocumentAvailable()) {
2862
- return;
2863
- }
2864
- if (!this.marqueeElement) {
2865
- this.marqueeElement = createElement$1();
2866
- document.body.appendChild(this.marqueeElement);
2867
- }
2937
+ /**
2938
+ * @hidden
2939
+ */
2940
+ get colspan() {
2941
+ return this.childColumns.filter(c => c.isVisible).length;
2868
2942
  }
2869
- getMarqueeQuadrant(pointerX, pointerY, startX, startY) {
2870
- const leftHalf = pointerX < startX;
2871
- const rightHalf = pointerX > startX;
2872
- const topHalf = pointerY < startY;
2873
- const bottomHalf = pointerY > startY;
2874
- if (leftHalf && topHalf) {
2875
- return 'topLeft';
2876
- }
2877
- if (leftHalf && bottomHalf) {
2878
- return 'bottomLeft';
2879
- }
2880
- if (rightHalf && topHalf) {
2881
- return 'topRight';
2882
- }
2883
- if (rightHalf && bottomHalf) {
2884
- return 'bottomRight';
2885
- }
2886
- return null;
2943
+ /**
2944
+ * Toggles the locked (frozen) state of the columns ([see example](slug:locked_columns_grid)).
2945
+ * @default false
2946
+ */
2947
+ set locked(value) {
2948
+ this._locked = value;
2949
+ }
2950
+ get locked() {
2951
+ return this._locked || this.childColumns.some(c => c.locked);
2952
+ }
2953
+ get childrenArray() {
2954
+ return this.childColumns.toArray();
2955
+ }
2956
+ get hasChildren() {
2957
+ return this.childColumns.length > 0;
2887
2958
  }
2888
2959
  }
2889
- GridMarqueeDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridMarqueeDirective, deps: [{ token: i1$1.DraggableDirective }, { token: SelectionService }, { token: CellSelectionService }, { token: DomEventsService }], target: i0.ɵɵFactoryTarget.Directive });
2890
- GridMarqueeDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]", host: { properties: { "style.-webkit-user-select": "this.webkitUserSelection", "class.user-select-none": "this.userSelection" } }, ngImport: i0 });
2891
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridMarqueeDirective, decorators: [{
2892
- type: Directive,
2960
+ SpanColumnComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SpanColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
2961
+ SpanColumnComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: SpanColumnComponent, selector: "kendo-grid-span-column", inputs: { editable: "editable", locked: "locked" }, providers: [
2962
+ {
2963
+ provide: ColumnBase,
2964
+ useExisting: forwardRef(() => SpanColumnComponent)
2965
+ }
2966
+ ], queries: [{ propertyName: "template", predicate: CellTemplateDirective }, { propertyName: "editTemplate", predicate: EditTemplateDirective }, { propertyName: "childColumns", predicate: ColumnComponent }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
2967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SpanColumnComponent, decorators: [{
2968
+ type: Component,
2893
2969
  args: [{
2894
- selector: '[kendoGridSelectionMarquee]'
2970
+ providers: [
2971
+ {
2972
+ provide: ColumnBase,
2973
+ useExisting: forwardRef(() => SpanColumnComponent)
2974
+ }
2975
+ ],
2976
+ selector: 'kendo-grid-span-column',
2977
+ template: ``
2895
2978
  }]
2896
- }], ctorParameters: function () { return [{ type: i1$1.DraggableDirective }, { type: SelectionService }, { type: CellSelectionService }, { type: DomEventsService }]; }, propDecorators: { webkitUserSelection: [{
2897
- type: HostBinding,
2898
- args: ['style.-webkit-user-select']
2899
- }], userSelection: [{
2900
- type: HostBinding,
2901
- args: ['class.user-select-none']
2979
+ }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{
2980
+ type: SkipSelf
2981
+ }, {
2982
+ type: Host
2983
+ }, {
2984
+ type: Optional
2985
+ }] }, { type: IdService, decorators: [{
2986
+ type: Optional
2987
+ }] }]; }, propDecorators: { template: [{
2988
+ type: ContentChildren,
2989
+ args: [CellTemplateDirective, { descendants: false }]
2990
+ }], editTemplate: [{
2991
+ type: ContentChildren,
2992
+ args: [EditTemplateDirective, { descendants: false }]
2993
+ }], childColumns: [{
2994
+ type: ContentChildren,
2995
+ args: [ColumnComponent]
2996
+ }], editable: [{
2997
+ type: Input
2998
+ }], locked: [{
2999
+ type: Input
2902
3000
  }] } });
2903
3001
 
2904
3002
  /**
2905
3003
  * @hidden
2906
3004
  */
2907
- class ZoneAwareEventEmitter extends EventEmitter {
2908
- constructor(ngZone, isAsync = false) {
2909
- super(isAsync);
2910
- this.ngZone = ngZone;
2911
- }
2912
- subscribe(generatorOrNext, error, complete) {
2913
- let schedulerFn;
2914
- let errorFn = (_) => null;
2915
- let completeFn = () => null;
2916
- if (generatorOrNext && typeof generatorOrNext === 'object') {
2917
- schedulerFn = (value) => { this.ngZone.run(() => generatorOrNext.next(value)); };
2918
- if (generatorOrNext.error) {
2919
- errorFn = (err) => { this.ngZone.run(() => generatorOrNext.error(err)); };
2920
- }
2921
- if (generatorOrNext.complete) {
2922
- completeFn = () => { this.ngZone.run(() => generatorOrNext.complete()); };
2923
- }
3005
+ const expandColumns = (columns) => (columns.reduce((acc, column) => acc.concat(isSpanColumnComponent(column) ? column.childrenArray : [column]), []));
3006
+ /**
3007
+ * @hidden
3008
+ */
3009
+ const expandColumnsWithSpan = (columns) => (columns.reduce((acc, column) => acc.concat(isSpanColumnComponent(column) ?
3010
+ [column].concat(column.childrenArray) :
3011
+ [column]), []));
3012
+ /**
3013
+ * @hidden
3014
+ */
3015
+ const columnsToRender = (columns) => (expandColumns(columns).filter(x => x.isVisible));
3016
+ const sumProp = (prop) => (array) => (array || []).reduce((prev, curr) => prev + (curr[prop] || 0), 0);
3017
+ /**
3018
+ * @hidden
3019
+ */
3020
+ const sumColumnWidths = sumProp('width');
3021
+ /**
3022
+ * @hidden
3023
+ */
3024
+ const columnsSpan = sumProp('colspan');
3025
+ const validField = new RegExp(`^[$A-Z\_a-z][$A-Z\_a-z0-9\\.]*$`);
3026
+ /**
3027
+ * @hidden
3028
+ */
3029
+ const isValidFieldName = (fieldName) => !isNullOrEmptyString(fieldName) && validField.test(fieldName) &&
3030
+ fieldName[0] !== "." && fieldName[fieldName.length - 1] !== ".";
3031
+ /**
3032
+ * @hidden
3033
+ */
3034
+ const children = column => column.children.filter(child => child !== column);
3035
+ /**
3036
+ * @hidden
3037
+ */
3038
+ const leafColumns = columns => {
3039
+ return columns.reduce((acc, column) => {
3040
+ if (column.isColumnGroup) {
3041
+ acc = acc.concat(leafColumns(children(column)));
3042
+ }
3043
+ else if (column.isSpanColumn) {
3044
+ acc = acc.concat(column.childrenArray);
2924
3045
  }
2925
3046
  else {
2926
- schedulerFn = (value) => { this.ngZone.run(() => generatorOrNext(value)); };
2927
- if (error) {
2928
- errorFn = (err) => { this.ngZone.run(() => error(err)); };
2929
- }
2930
- if (complete) {
2931
- completeFn = () => { this.ngZone.run(() => complete()); };
2932
- }
3047
+ acc.push(column);
2933
3048
  }
2934
- return super.subscribe(schedulerFn, errorFn, completeFn);
2935
- }
2936
- }
2937
-
3049
+ return acc;
3050
+ }, []).filter(x => x.isVisible);
3051
+ };
2938
3052
  /**
2939
3053
  * @hidden
2940
3054
  */
2941
- const packageMetadata = {
2942
- name: '@progress/kendo-angular-grid',
2943
- productName: 'Kendo UI for Angular',
2944
- productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
2945
- publishDate: 1686117789,
2946
- version: '13.0.2',
2947
- licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
2948
- };
3055
+ const someLeafColumn = (callback, ...columns) => leafColumns(columns).some(callback);
3056
+ /**
3057
+ * @hidden
3058
+ */
3059
+ const resizableColumns = columns => columns.filter(column => isTruthy(column.resizable) && column.isVisible);
3060
+ /**
3061
+ * @hidden
3062
+ */
3063
+ const sortColumns = (columns) => orderBy(columns, [{ field: 'orderIndex', dir: 'asc' }]);
3064
+ /**
3065
+ * @hidden
3066
+ */
3067
+ const isInSpanColumn$1 = (column) => isTruthy(column.parent) && isSpanColumnComponent(column.parent);
2949
3068
 
2950
3069
  /**
2951
- * Represents the column cell template of the Grid.
2952
- * Helps to customize the content of the cells. To define the cell template, nest an `<ng-template>` tag with the
2953
- * `kendoGridCellTemplate` directive inside a `<kendo-grid-column>` tag [see example](slug:templates_columns_grid#toc-cell-template).
2954
- *
2955
- * The template context is set to the current data item and the following additional fields are passed:
2956
- * - `columnIndex`&mdash;The current column index. Use it as an alias for a template variable by utilizing the `let-columnIndex="columnIndex"` syntax.
2957
- * - `rowIndex`&mdash;The current data row index. Use it as an alias for a template variable by utilizing the `let-rowIndex="rowIndex"` syntax.
2958
- * - `dataItem`&mdash;The current data item. Represents the default context that will be assigned to any template variable which utilizes the `let-x` syntax&mdash;for example, `let-dataItem`.
2959
- * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
2960
- *
2961
- * @example
2962
- * ```html
2963
- * <kendo-grid [data]="gridData" ...>
2964
- * <kendo-grid-column field="ProductName">
2965
- * <ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex" let-column="column">
2966
- * Data Row: {{rowIndex}}
2967
- * </ng-template>
2968
- * </kendo-grid-column>
2969
- * </kendo-grid>
2970
- * ```
3070
+ * @hidden
2971
3071
  */
2972
- class CellTemplateDirective {
2973
- constructor(templateRef) {
2974
- this.templateRef = templateRef;
2975
- }
3072
+ function isColumnGroupComponent(column) {
3073
+ return column.isColumnGroup;
2976
3074
  }
2977
- CellTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2978
- CellTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: CellTemplateDirective, selector: "[kendoGridCellTemplate]", ngImport: i0 });
2979
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellTemplateDirective, decorators: [{
2980
- type: Directive,
2981
- args: [{
2982
- selector: '[kendoGridCellTemplate]'
2983
- }]
2984
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
2985
- type: Optional
2986
- }] }]; } });
2987
-
2988
3075
  /**
2989
- * Represents the group-header cell template of the Grid which helps to customize the content of the group header item.
2990
- * To define the group header template, nest an `<ng-template>` tag with the `kendoGridGroupHeaderTemplate`
2991
- * directive inside `<kendo-grid-column>`. ([See example](slug:grouping_grid_templates#toc-header-template)).
2992
- *
2993
- * The template context is set to the current data item and the following additional fields are passed:
2994
- * - `group`&mdash;The current group item.
2995
- * - `field`&mdash;The name of the field by which data is grouped.
2996
- * - `value`&mdash;The current group value.
2997
- * - `aggregates`&mdash;All aggregate values for the current group.
2998
- * - `index`&mdash;The index of the current group.
2999
- * - `expanded`&mdash;A boolean value indicating if the group is currently expanded.
3076
+ * Represents the column group header of the Grid
3077
+ * ([more information and examples](slug:multicolumnheaders_columns_grid)).
3000
3078
  *
3001
3079
  * @example
3002
3080
  * ```html
3003
- * <kendo-grid [data]="gridData" [group]="groups">
3004
- * <kendo-grid-column field="ProductName">
3005
- * <ng-template kendoGridGroupHeaderTemplate let-group let-field="field" let-value="value">
3006
- * <strong>{{field}}</strong>: {{value}}
3007
- * </ng-template>
3008
- * </kendo-grid-column>
3081
+ * <kendo-grid [data]="gridData">
3082
+ * <kendo-grid-column-group title="Product Info">
3083
+ * <kendo-grid-column field="ProductID"></kendo-grid-column>
3084
+ * <kendo-grid-column field="ProductName"></kendo-grid-column>
3085
+ * </kendo-grid-column-group>
3086
+ * <kendo-grid-column field="UnitPrice"></kendo-grid-column>
3009
3087
  * </kendo-grid>
3010
3088
  * ```
3011
3089
  */
3012
- class GroupHeaderTemplateDirective {
3013
- constructor(templateRef) {
3014
- this.templateRef = templateRef;
3015
- }
3016
- }
3017
- GroupHeaderTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3018
- GroupHeaderTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GroupHeaderTemplateDirective, selector: "[kendoGridGroupHeaderTemplate]", ngImport: i0 });
3019
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderTemplateDirective, decorators: [{
3020
- type: Directive,
3021
- args: [{
3022
- selector: '[kendoGridGroupHeaderTemplate]'
3023
- }]
3024
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3025
- type: Optional
3026
- }] }]; } });
3027
-
3028
- /**
3029
- * Represents the group-header column template of the Grid which helps to customize the content of the group headers.
3030
- * To define the group header template, nest an `<ng-template>` tag with the `kendoGridGroupHeaderColumnTemplate`
3031
- * directive inside `<kendo-grid-column>`. ([See example](slug:grouping_grid_templates#toc-header-column-template)).
3032
- *
3033
- * The template context is set to the current data item and the following additional fields are passed:
3034
- * - `group`&mdash;The current group item.
3035
- * - `field`&mdash;The name of the field by which data is grouped.
3036
- * - `value`&mdash;The current group value.
3037
- * - `aggregates`&mdash;All aggregate values for the current group.
3038
- *
3039
- * @example
3040
- * ```html
3041
- * <kendo-grid-column field="ProductName" title="Product Name">
3042
- * <ng-template kendoGridGroupHeaderColumnTemplate let-group="group" let-aggregates="aggregates">
3043
- * <span title="Group Header Column Template for ProductName">
3044
- * Count: {{ aggregates.Discontinued.count }}
3045
- * </span>
3046
- * </ng-template>
3047
- * </kendo-grid-column>
3048
- * ```
3049
- */
3050
- class GroupHeaderColumnTemplateDirective {
3051
- constructor(templateRef) {
3052
- this.templateRef = templateRef;
3090
+ class ColumnGroupComponent extends ColumnBase {
3091
+ constructor(parent, idService) {
3092
+ super(parent, idService);
3093
+ this.parent = parent;
3094
+ /**
3095
+ * @hidden
3096
+ */
3097
+ this.includeInChooser = false;
3098
+ /**
3099
+ * @hidden
3100
+ */
3101
+ this.isColumnGroup = true;
3102
+ /**
3103
+ * @hidden
3104
+ */
3105
+ this.minResizableWidth = 10;
3106
+ if (parent && parent.isSpanColumn) {
3107
+ throw new Error('ColumnGroupComponent cannot be nested inside SpanColumnComponent');
3108
+ }
3109
+ }
3110
+ /**
3111
+ * @hidden
3112
+ */
3113
+ rowspan() {
3114
+ return 1;
3115
+ }
3116
+ /**
3117
+ * @hidden
3118
+ */
3119
+ get colspan() {
3120
+ if (!this.children) {
3121
+ return 1;
3122
+ }
3123
+ return columnsSpan(this.children
3124
+ .filter(child => child !== this && child.isVisible));
3125
+ }
3126
+ /**
3127
+ * @hidden
3128
+ */
3129
+ get leafIndex() {
3130
+ return this.children ? (this.firstChild || {}).leafIndex : -1;
3131
+ }
3132
+ get childrenArray() {
3133
+ return this.children.filter(c => c !== this);
3134
+ }
3135
+ get hasChildren() {
3136
+ return Boolean(this.firstChild);
3137
+ }
3138
+ get firstChild() {
3139
+ return this.children.find(column => column !== this);
3053
3140
  }
3054
3141
  }
3055
- GroupHeaderColumnTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderColumnTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3056
- GroupHeaderColumnTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GroupHeaderColumnTemplateDirective, selector: "[kendoGridGroupHeaderColumnTemplate]", ngImport: i0 });
3057
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupHeaderColumnTemplateDirective, decorators: [{
3058
- type: Directive,
3142
+ ColumnGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnGroupComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3143
+ ColumnGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ColumnGroupComponent, selector: "kendo-grid-column-group", providers: [
3144
+ {
3145
+ provide: ColumnBase,
3146
+ useExisting: forwardRef(() => ColumnGroupComponent)
3147
+ }
3148
+ ], queries: [{ propertyName: "children", predicate: ColumnBase }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
3149
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnGroupComponent, decorators: [{
3150
+ type: Component,
3059
3151
  args: [{
3060
- selector: '[kendoGridGroupHeaderColumnTemplate]'
3152
+ providers: [
3153
+ {
3154
+ provide: ColumnBase,
3155
+ useExisting: forwardRef(() => ColumnGroupComponent)
3156
+ }
3157
+ ],
3158
+ selector: 'kendo-grid-column-group',
3159
+ template: ``
3061
3160
  }]
3062
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3161
+ }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{
3162
+ type: SkipSelf
3163
+ }, {
3164
+ type: Host
3165
+ }, {
3063
3166
  type: Optional
3064
- }] }]; } });
3167
+ }] }, { type: IdService, decorators: [{
3168
+ type: Optional
3169
+ }] }]; }, propDecorators: { children: [{
3170
+ type: ContentChildren,
3171
+ args: [ColumnBase]
3172
+ }] } });
3065
3173
 
3174
+ const reset = (...lists) => {
3175
+ let diff = false;
3176
+ for (let idx = 0; idx < lists.length; idx++) {
3177
+ const [list, columns] = lists[idx];
3178
+ diff = diff || list.length !== columns.length;
3179
+ list.reset(columns);
3180
+ }
3181
+ return diff;
3182
+ };
3066
3183
  /**
3067
- * Represents the column edit-cell template of the Grid ([see example](slug:custom_reactive_editing_grid#toc-setting-up-custom-inputs)).
3068
- * Helps to customize the content of the edited cells. To define the cell template, nest an `<ng-template>`
3069
- * tag with the `kendoGridEditTemplate` directive inside a `<kendo-grid-column>` tag.
3070
- *
3071
- * The template context is set to the current form group and the following additional fields are passed:
3072
- * - `formGroup`&mdash;The current [FormGroup](link:site.data.urls.angular['formgroupapi']). Represents the default context that will be assigned to any template variable which utilizes the `let-x` syntax, for example, `let-formGroup`. If you use the Grid inside [Template-Driven Forms](link:site.data.urls.angular['forms']), it will be `undefined`.
3073
- * - `rowIndex`&mdash;The current data row index. If inside a new item row, `rowIndex` is `-1`. Use it as an alias for a template variable by utilizing the `let-rowIndex="rowIndex"` syntax.
3074
- * - `dataItem`&mdash;The current data item. Use it as an alias for a template variable by utilizing the `let-dataItem="dataItem"` syntax.
3075
- * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
3076
- * - `isNew`&mdash;The state of the current item. Use it as an alias for a template variable by utilizing the `let-isNew="isNew"` syntax.
3184
+ * @hidden
3077
3185
  */
3078
- class EditTemplateDirective {
3079
- constructor(templateRef) {
3080
- this.templateRef = templateRef;
3186
+ class ColumnsContainer {
3187
+ constructor(columns) {
3188
+ this.columns = columns;
3189
+ this.allColumns = new QueryList();
3190
+ this.leafColumns = new QueryList();
3191
+ this.lockedColumns = new QueryList();
3192
+ this.nonLockedColumns = new QueryList();
3193
+ this.lockedLeafColumns = new QueryList();
3194
+ this.nonLockedLeafColumns = new QueryList();
3195
+ this.totalLevels = 0;
3196
+ this.changes = new EventEmitter();
3197
+ this.leafColumnsToRender = [];
3198
+ this.lockedColumnsToRender = [];
3199
+ this.nonLockedColumnsToRender = [];
3200
+ this.hasGroupHeaderColumn = false;
3201
+ this.hasGroupFooter = false;
3202
+ this.hasFooter = false;
3203
+ this.unlockedWidth = 0;
3204
+ }
3205
+ refresh() {
3206
+ const currentLevels = this.totalLevels;
3207
+ const leafColumns = new Array();
3208
+ const lockedLeafColumns = new Array();
3209
+ const nonLockedLeafColumns = new Array();
3210
+ const lockedColumns = new Array();
3211
+ const nonLockedColumns = new Array();
3212
+ const allColumns = new Array();
3213
+ const leafColumnsToRender = new Array();
3214
+ const lockedColumnsToRender = new Array();
3215
+ const nonLockedColumnsToRender = new Array();
3216
+ let hasGroupHeaderColumn = false;
3217
+ let hasGroupFooter = false;
3218
+ let hasFooter = false;
3219
+ let unlockedWidth = 0;
3220
+ let leafIndex = 0;
3221
+ this.totalLevels = 0;
3222
+ this.columns().forEach(column => {
3223
+ const containerLeafColumns = column.isLocked === true ? lockedLeafColumns : nonLockedLeafColumns;
3224
+ const containerColumns = column.isLocked === true ? lockedColumns : nonLockedColumns;
3225
+ const toRenderContainer = column.isLocked === true ? lockedColumnsToRender : nonLockedColumnsToRender;
3226
+ if (!isColumnGroupComponent(column)) {
3227
+ containerLeafColumns.push(column);
3228
+ leafColumns.push(column);
3229
+ leafColumnsToRender.push(...columnsToRender([column]));
3230
+ toRenderContainer.push(...columnsToRender([column]));
3231
+ hasGroupHeaderColumn = hasGroupHeaderColumn || someLeafColumn(leaf => Boolean(leaf.groupHeaderColumnTemplateRef), column);
3232
+ hasGroupFooter = hasGroupFooter || someLeafColumn(leaf => Boolean(leaf.groupFooterTemplateRef), column);
3233
+ hasFooter = hasFooter || someLeafColumn(leaf => Boolean(leaf.footerTemplateRef), column);
3234
+ if (!column.isLocked) {
3235
+ unlockedWidth += column.width || 0;
3236
+ }
3237
+ if (column.isSpanColumn) {
3238
+ column.childColumns.forEach(c => {
3239
+ c.leafIndex = leafIndex++;
3240
+ });
3241
+ }
3242
+ else {
3243
+ column.leafIndex = leafIndex++;
3244
+ }
3245
+ }
3246
+ containerColumns.push(column);
3247
+ allColumns.push(column);
3248
+ this.totalLevels = column.level > this.totalLevels ? column.level : this.totalLevels;
3249
+ });
3250
+ this.hasGroupHeaderColumn = hasGroupHeaderColumn;
3251
+ this.hasGroupFooter = hasGroupFooter;
3252
+ this.hasFooter = hasFooter;
3253
+ this.leafColumnsToRender = leafColumnsToRender;
3254
+ this.lockedColumnsToRender = lockedColumnsToRender;
3255
+ this.nonLockedColumnsToRender = nonLockedColumnsToRender;
3256
+ this.unlockedWidth = unlockedWidth;
3257
+ const changes = reset([this.leafColumns, leafColumns], [this.lockedLeafColumns, lockedLeafColumns], [this.nonLockedLeafColumns, nonLockedLeafColumns], [this.lockedColumns, lockedColumns], [this.allColumns, allColumns], [this.nonLockedColumns, nonLockedColumns]) || currentLevels !== this.totalLevels;
3258
+ if (changes) {
3259
+ this.changes.emit();
3260
+ }
3261
+ return changes;
3081
3262
  }
3082
3263
  }
3083
- EditTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: EditTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3084
- EditTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: EditTemplateDirective, selector: "[kendoGridEditTemplate]", ngImport: i0 });
3085
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: EditTemplateDirective, decorators: [{
3086
- type: Directive,
3087
- args: [{
3088
- selector: '[kendoGridEditTemplate]'
3089
- }]
3090
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3091
- type: Optional
3092
- }] }]; } });
3093
3264
 
3265
+ const NO_STICKY = { left: '0px', right: '0px' };
3094
3266
  /**
3095
- * Represents the column group footer cell template of the Grid which helps to customize the group footer cell for the column.
3096
- * To define the group footer template, nest an `<ng-template>` tag with the `kendoGridGroupFooterTemplate` directive
3097
- * inside `<kendo-grid-column>`.
3098
- *
3099
- * The template context is set to the current data item and the following additional fields are passed:
3100
- * - `column`&mdash;Defines an instance of the `ColumnComponent` option.
3101
- * - `field`&mdash;The current column field name.
3102
- * - `group`&mdash;The current group data item.
3103
- * - `aggregates`&mdash;All aggregate values for the current group.
3104
- *
3105
- * @example
3106
- * ```html
3107
- * <kendo-grid [data]="gridData" [group]="groups">
3108
- * <kendo-grid-column field="ProductName">
3109
- * <ng-template kendoGridGroupFooterTemplate let-aggregates let-field="field">
3110
- * Count: {{aggregates[field].count}}
3111
- * </ng-template>
3112
- * </kendo-grid-column>
3113
- * </kendo-grid>
3114
- * ```
3267
+ * @hidden
3115
3268
  */
3116
- class GroupFooterTemplateDirective {
3117
- constructor(templateRef) {
3118
- this.templateRef = templateRef;
3119
- }
3120
- }
3121
- GroupFooterTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupFooterTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3122
- GroupFooterTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GroupFooterTemplateDirective, selector: "[kendoGridGroupFooterTemplate]", ngImport: i0 });
3123
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GroupFooterTemplateDirective, decorators: [{
3124
- type: Directive,
3125
- args: [{
3126
- selector: '[kendoGridGroupFooterTemplate]'
3127
- }]
3128
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3129
- type: Optional
3130
- }] }]; } });
3131
-
3132
- /**
3133
- * Represents the column header cell template of the Grid
3134
- * ([more information and example]({% slug templates_columns_grid %}#toc-header-template)).
3135
- * Helps to customize the table header cell for the column.
3136
- * To define a header template, nest an `<ng-template>` tag with the
3137
- * `kendoGridHeaderTemplate` directive inside the `<kendo-grid-column>` tag.
3138
- *
3139
- * The template context is set to the current column and then the following additional fields are passed:
3140
- * * `column`&mdash;Defines an instance of the [ColumnComponent]({% slug api_grid_columncomponent %}) option.
3141
- * * `columnIndex`&mdash;Defines the current column index.
3142
- *
3143
- * @example
3144
- * ```html
3145
- * <kendo-grid [data]="gridData">
3146
- * <kendo-grid-column field="ProductName">
3147
- * <ng-template kendoGridHeaderTemplate let-column let-columnIndex="columnIndex">
3148
- * {{column.field}}({{columnIndex}})
3149
- * </ng-template>
3150
- * </kendo-grid-column>
3151
- * </kendo-grid>
3152
- * ```
3153
- */
3154
- class HeaderTemplateDirective {
3155
- constructor(templateRef) {
3156
- this.templateRef = templateRef;
3269
+ class ColumnInfoService {
3270
+ constructor() {
3271
+ this.visibilityChange = new EventEmitter();
3272
+ this.lockedChange = new EventEmitter();
3273
+ this.stickyChange = new EventEmitter();
3274
+ this.columnRangeChange = new EventEmitter();
3275
+ this.columnsContainer = new ColumnsContainer(() => []);
3157
3276
  }
3158
- }
3159
- HeaderTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3160
- HeaderTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: HeaderTemplateDirective, selector: "[kendoGridHeaderTemplate]", ngImport: i0 });
3161
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderTemplateDirective, decorators: [{
3162
- type: Directive,
3163
- args: [{
3164
- selector: '[kendoGridHeaderTemplate]'
3165
- }]
3166
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3167
- type: Optional
3168
- }] }]; } });
3169
-
3170
- /**
3171
- * Represents the column footer cell template of the Grid
3172
- * ([more information and example]({% slug templates_columns_grid %}#toc-footer-template)).
3173
- * Helps to customize the table footer cell for the column.
3174
- * To define a footer template, nest an `<ng-template>` tag with the
3175
- * [kendoGridFooterTemplate]({% slug api_grid_footertemplatedirective %}) directive inside the `<kendo-grid-column>` tag.
3176
- *
3177
- * The template context is set to the current column and the following additional fields are passed:
3178
- * * `column`&mdash;Defines an instance of the [ColumnComponent]({% slug api_grid_columncomponent %}) option.
3179
- * * `columnIndex`&mdash;Defines the current column index.
3180
- *
3181
- * For more information on how to display aggregates in the footer of the Grid,
3182
- * refer to the article on [aggregates]({% slug groupable_grid_with_aggregates %}).
3183
- *
3184
- * @example
3185
- * ```html
3186
- * <kendo-grid [data]="gridData" scrollable="none">
3187
- * <kendo-grid-column field="ProductName">
3188
- * <ng-template kendoGridFooterTemplate let-column let-columnIndex="columnIndex">
3189
- * {{column.field}}({{columnIndex}})
3190
- * </ng-template>
3191
- * </kendo-grid-column>
3192
- * </kendo-grid>
3193
- * ```
3194
- */
3195
- class FooterTemplateDirective {
3196
- constructor(templateRef) {
3197
- this.templateRef = templateRef;
3277
+ get lockedLeafColumns() {
3278
+ return this.columnsContainer.lockedLeafColumns;
3198
3279
  }
3199
- }
3200
- FooterTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FooterTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3201
- FooterTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FooterTemplateDirective, selector: "[kendoGridFooterTemplate]", ngImport: i0 });
3202
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FooterTemplateDirective, decorators: [{
3203
- type: Directive,
3204
- args: [{
3205
- selector: '[kendoGridFooterTemplate]'
3206
- }]
3207
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3208
- type: Optional
3209
- }] }]; } });
3210
-
3211
- /**
3212
- * Represents the template for the column menu in the Grid. Provides an option for
3213
- * customizing the content of the column menu for all or for specific columns.
3214
- * To define the content template, nest an `<ng-template>` tag with the
3215
- * `kendoGridColumnMenuTemplate` directive inside the `<kendo-grid>` or the `<kendo-grid-column>` component.
3216
- *
3217
- * The template context is passes through the following fields:
3218
- * - `service`&mdash;Represents the [ColumnMenuService]({% slug api_grid_columnmenuservice %}).
3219
- * - `column`&mdash;Represents the Grid column.
3220
- *
3221
- * @example
3222
- * ```html
3223
- * <kendo-grid [kendoGridBinding]="data" [sortable]="true" [columnMenu]="true">
3224
- * <ng-template kendoGridColumnMenuTemplate let-service="service">
3225
- * <kendo-grid-columnmenu-sort [service]="service"></kendo-grid-columnmenu-sort>
3226
- * </ng-template>
3227
- * <kendo-grid-column field="Field1">
3228
- * <ng-template kendoGridColumnMenuTemplate let-service="service">
3229
- * <kendo-grid-columnmenu-lock [service]="service"></kendo-grid-columnmenu-lock>
3230
- * <kendo-grid-columnmenu-sort [service]="service"></kendo-grid-columnmenu-sort>
3231
- * </ng-template>
3232
- * </kendo-grid-column>
3233
- * <kendo-grid-column field="Field2"></kendo-grid-column>
3234
- * </kendo-grid>
3235
- * ```
3236
- */
3237
- class ColumnMenuTemplateDirective {
3238
- constructor(templateRef) {
3239
- this.templateRef = templateRef;
3280
+ get nonLockedLeafColumns() {
3281
+ return this.columnsContainer.nonLockedLeafColumns;
3240
3282
  }
3241
- }
3242
- ColumnMenuTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnMenuTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3243
- ColumnMenuTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: ColumnMenuTemplateDirective, selector: "[kendoGridColumnMenuTemplate]", ngImport: i0 });
3244
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnMenuTemplateDirective, decorators: [{
3245
- type: Directive,
3246
- args: [{
3247
- selector: '[kendoGridColumnMenuTemplate]'
3248
- }]
3249
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3250
- type: Optional
3251
- }] }]; } });
3252
-
3253
- // Incremented each time the service is instantiated.
3254
- let sequence = 0;
3255
- /**
3256
- * @hidden
3257
- */
3258
- class IdService {
3259
- constructor() {
3260
- this.prefix = `k-grid${sequence++}`;
3283
+ get isLocked() {
3284
+ return this.lockedLeafColumns.length > 0;
3261
3285
  }
3262
- gridId() {
3263
- return this.prefix;
3286
+ get totalLevels() {
3287
+ return this.columnsContainer.totalLevels;
3264
3288
  }
3265
- cellId(rowIndex, colIndex) {
3266
- return `${this.prefix}-r${rowIndex}c${colIndex}`;
3289
+ get hiddenColumns() {
3290
+ if (!this.list) {
3291
+ return [];
3292
+ }
3293
+ return this.list().filter(column => !column.isVisible);
3267
3294
  }
3268
- selectionCheckboxId(itemIndex) {
3269
- return `${this.prefix}-checkbox${itemIndex}`;
3295
+ get leafNamedColumns() {
3296
+ const columns = expandColumns(this.list().filterSort(column => !column.isColumnGroup))
3297
+ .filter(column => column.matchesMedia && column.displayTitle);
3298
+ return orderBy(columns, [{ field: 'locked', dir: 'desc' }]);
3270
3299
  }
3271
- selectAllCheckboxId() {
3272
- return `${this.prefix}-select-all`;
3300
+ get unlockedRootCount() {
3301
+ return this.list().rootColumns().filter(column => !column.locked && column.isVisible).length;
3302
+ }
3303
+ stickyColumnsStyles(column) {
3304
+ if (!this.stickyColumns) {
3305
+ this.stickyColumns = this.list().rootColumns().filter(column => column.sticky && !column.locked && column.isVisible);
3306
+ }
3307
+ if (this.stickyColumns.length === 0) {
3308
+ return NO_STICKY;
3309
+ }
3310
+ const result = this.stickyColumns.reduce((acc, curr) => {
3311
+ if (curr.leafIndex < column.leafIndex) {
3312
+ acc.left += curr.width;
3313
+ }
3314
+ else if (curr.leafIndex > column.leafIndex) {
3315
+ acc.right += curr.width;
3316
+ }
3317
+ return acc;
3318
+ }, { left: 0, right: 0 });
3319
+ return {
3320
+ left: `${result.left}px`,
3321
+ right: `${result.right}px`
3322
+ };
3323
+ }
3324
+ init(columns, list) {
3325
+ this.columnsContainer = columns;
3326
+ this.list = list;
3327
+ this.stickyColumns = null;
3328
+ }
3329
+ changeVisibility(columns) {
3330
+ this.stickyColumns = null;
3331
+ this.visibilityChange.emit(columns);
3332
+ }
3333
+ changeLocked(columns) {
3334
+ this.stickyColumns = null;
3335
+ this.lockedChange.emit(columns);
3336
+ }
3337
+ changeStuck(columns) {
3338
+ this.stickyColumns = null;
3339
+ this.stickyChange.emit(columns);
3273
3340
  }
3274
3341
  }
3275
- IdService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: IdService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3276
- IdService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: IdService });
3277
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: IdService, decorators: [{
3342
+ ColumnInfoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnInfoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3343
+ ColumnInfoService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnInfoService });
3344
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnInfoService, decorators: [{
3278
3345
  type: Injectable
3279
- }], ctorParameters: function () { return []; } });
3346
+ }] });
3280
3347
 
3348
+ ;
3281
3349
  /**
3282
3350
  * @hidden
3283
3351
  */
3284
- const isSpanColumn = column => column.isSpanColumn;
3285
- /**
3286
- * @hidden
3287
- */
3288
- const isCheckboxColumn = column => column.isCheckboxColumn;
3289
- /**
3290
- * @hidden
3291
- */
3292
- const isRowReorderColumn = column => column.isRowReorderColumn;
3293
- const isColumnContainer = column => column.isColumnGroup || isSpanColumn(column);
3294
- /**
3295
- * The base class for the column components of the Grid.
3296
- */
3297
- class ColumnBase {
3298
- /**
3299
- * @hidden
3300
- */
3301
- constructor(parent, idService) {
3302
- this.parent = parent;
3303
- /**
3304
- * @hidden
3305
- */
3306
- this.matchesMedia = true;
3307
- /**
3308
- * The column index after reordering. The `orderIndex` is a read-only property. Setting this field does not affect column order.
3309
- *
3310
- * @default 0
3311
- */
3312
- this.orderIndex = 0;
3313
- /**
3314
- * @hidden
3315
- */
3316
- this.isColumnGroup = false;
3317
- /**
3318
- * @hidden
3319
- */
3320
- this.isSpanColumn = false;
3321
- /**
3322
- * Indicates whether the column is resizable.
3323
- * @default true
3324
- */
3325
- this.resizable = true;
3326
- /**
3327
- * Indicates whether the column is reorderable.
3328
- * @default true
3329
- */
3330
- this.reorderable = true;
3331
- /**
3332
- * The width (in pixels) below which the user is not able to resize the column by using the UI ([see example]({% slug resizing_columns_grid %}#toc-limiting-the-resizing)).
3333
- * The `autoFitColumn` and `autoFitColumns` methods have higher priority.
3334
- * @default 10
3335
- */
3336
- this.minResizableWidth = 10;
3337
- this._locked = false;
3338
- /**
3339
- * Determines whether the column will be always visible when scrolling the Grid horizontally.
3340
- *
3341
- * @default false
3342
- */
3343
- this.sticky = false;
3344
- /**
3345
- * Specifies if the column can be locked or unlocked from the column menu or by reordering the columns.
3346
- * @default true
3347
- */
3348
- this.lockable = true;
3349
- /**
3350
- * Specifies if the column can be stuck or unstuck from the column menu.
3351
- * @default true
3352
- */
3353
- this.stickable = true;
3354
- /**
3355
- * Specifies if the column menu will be shown for the column.
3356
- * @default true
3357
- */
3358
- this.columnMenu = true;
3359
- /**
3360
- * Specifies if the column will be included in the column-chooser list.
3361
- * @default true
3362
- */
3363
- this.includeInChooser = true;
3364
- /**
3365
- * @hidden
3366
- */
3367
- this.headerTemplates = new QueryList();
3368
- /**
3369
- * @hidden
3370
- */
3371
- this.columnMenuTemplates = new QueryList();
3372
- this.idService = idService;
3373
- if (parent && idService && parent.idService.gridId() === idService.gridId() && !isColumnContainer(parent)) {
3374
- throw new Error('Columns can be nested only inside ColumnGroupComponent');
3375
- }
3376
- }
3377
- /**
3378
- * @hidden
3379
- */
3380
- set leafIndex(value) {
3381
- this._leafIndex = value;
3352
+ class CellSelectionAggregateService {
3353
+ constructor(ctx, dataChanges, columnInfoService) {
3354
+ this.ctx = ctx;
3355
+ this.dataChanges = dataChanges;
3356
+ this.columnInfoService = columnInfoService;
3357
+ this.selectedItems = [];
3358
+ this.groupedAggregates = { dates: [], numbers: [], booleans: [] };
3359
+ this.aggregates = {
3360
+ sum: null,
3361
+ average: null,
3362
+ min: null,
3363
+ max: null,
3364
+ count: null,
3365
+ isTrue: null,
3366
+ isFalse: null,
3367
+ earliest: null,
3368
+ latest: null
3369
+ };
3382
3370
  }
3383
- /**
3384
- * @hidden
3385
- */
3386
- get leafIndex() {
3387
- return this._leafIndex;
3371
+ isAggregateIncluded(aggregate) {
3372
+ const { cellAggregates } = this.ctx.grid.selectable;
3373
+ if (typeof cellAggregates !== 'boolean') {
3374
+ return cellAggregates?.includes(aggregate);
3375
+ }
3376
+ return true;
3388
3377
  }
3389
- /**
3390
- * The width of the column (in pixels).
3391
- */
3392
- set width(value) {
3393
- if (typeof value === 'string') {
3394
- const parsedValue = this._width = parseInt(value, 10);
3395
- if (isDevMode()) {
3396
- console.warn(`Expected numeric value for column width, but got a string "${value}". Treating as ${parsedValue}px.`);
3378
+ init() {
3379
+ if (this.ctx.grid.selectable.cellAggregates) {
3380
+ this.data = this.dataChanges.data ? this.dataChanges.data : this.ctx.grid.data;
3381
+ if (this.isAggregateIncluded('count')) {
3382
+ this.aggregates['count'] = 0;
3383
+ }
3384
+ const selectionDirective = this.ctx.grid.selectionDirective;
3385
+ if (selectionDirective && !this.isRowSelection) {
3386
+ this.selectedItems = selectionDirective.selectedKeys;
3397
3387
  }
3398
- }
3399
- else {
3400
- this._width = value;
3401
3388
  }
3402
3389
  }
3403
- get width() { return this._width; }
3404
- /**
3405
- * Toggles the locked (frozen) state of the columns ([more information and example]({% slug locked_columns_grid %})).
3406
- *
3407
- * @default false
3408
- *
3409
- */
3410
- set locked(value) {
3411
- this._locked = value;
3390
+ onSelectionChange(selectionArgs) {
3391
+ this.handleSelectedItems(selectionArgs);
3392
+ this.nullifyAggregates();
3393
+ this.handleAggregateChanges();
3394
+ return this.aggregates;
3412
3395
  }
3413
- get locked() {
3414
- return this._locked;
3396
+ get isRowSelection() {
3397
+ return typeof this.ctx.grid.selectable === 'boolean' || !this.ctx.grid.selectable.cell;
3415
3398
  }
3416
- /**
3417
- * @hidden
3418
- */
3419
- get level() {
3420
- if (this.parent && isSpanColumn(this.parent)) {
3421
- return this.parent.level;
3399
+ handleAggregateChanges() {
3400
+ const lockedColumns = this.columnInfoService.lockedLeafColumns.toArray();
3401
+ const nonLockedColumns = this.columnInfoService.nonLockedLeafColumns.toArray();
3402
+ const selectedItemsLength = this.selectedItems.length;
3403
+ const columns = [...lockedColumns, ...nonLockedColumns];
3404
+ const fields = columns.map(col => col.field);
3405
+ if (this.isAggregateIncluded('count')) {
3406
+ this.aggregates['count'] = this.isRowSelection ? (selectedItemsLength * columns.length) : selectedItemsLength;
3422
3407
  }
3423
- return this.parent ? this.parent.level + 1 : 0;
3424
- }
3425
- /**
3426
- * @hidden
3427
- */
3428
- get isLocked() {
3429
- return this.parent ? this.parent.isLocked : this.locked;
3408
+ this.selectedItems.forEach((item) => {
3409
+ if (this.isRowSelection) {
3410
+ fields.forEach((field) => {
3411
+ const cellValue = item.dataItem;
3412
+ if (cellValue && cellValue.hasOwnProperty(field)) {
3413
+ const cellValue = item.dataItem[field];
3414
+ this.groupAggregates(cellValue);
3415
+ }
3416
+ });
3417
+ }
3418
+ else if (!this.isRowSelection) {
3419
+ const itemKey = this.data[item.itemKey];
3420
+ const field = fields[item.columnKey];
3421
+ if (itemKey && itemKey.hasOwnProperty(field)) {
3422
+ const cellValue = itemKey[fields[item.columnKey]];
3423
+ this.groupAggregates(cellValue);
3424
+ }
3425
+ }
3426
+ });
3427
+ this.calculateAggregates();
3430
3428
  }
3431
- /**
3432
- * @hidden
3433
- */
3434
- get colspan() {
3435
- return 1;
3429
+ groupAggregates(aggregate) {
3430
+ if (typeof aggregate === 'number') {
3431
+ this.groupedAggregates.numbers.push(aggregate);
3432
+ }
3433
+ else if (typeof aggregate === 'boolean') {
3434
+ this.groupedAggregates.booleans.push(aggregate);
3435
+ }
3436
+ else if (aggregate instanceof Date) {
3437
+ this.groupedAggregates.dates.push(aggregate);
3438
+ }
3436
3439
  }
3437
- /**
3438
- * @hidden
3439
- */
3440
- rowspan(totalColumnLevels) {
3441
- return this.level < totalColumnLevels ? (totalColumnLevels - this.level) + 1 : 1;
3440
+ calculateAggregates() {
3441
+ if (this.groupedAggregates.numbers.length > 0) {
3442
+ if (this.isAggregateIncluded('min')) {
3443
+ this.aggregates['min'] = Math.min(...this.groupedAggregates.numbers);
3444
+ }
3445
+ if (this.isAggregateIncluded('max')) {
3446
+ this.aggregates['max'] = Math.max(...this.groupedAggregates.numbers);
3447
+ }
3448
+ if (this.isAggregateIncluded('sum')) {
3449
+ this.aggregates['sum'] = this.groupedAggregates.numbers.reduce((acc, curr) => acc += curr, 0);
3450
+ }
3451
+ if (this.isAggregateIncluded('average')) {
3452
+ this.aggregates['average'] = this.aggregates['sum'] / this.groupedAggregates.numbers.length;
3453
+ }
3454
+ }
3455
+ if (this.groupedAggregates.booleans.length > 0) {
3456
+ if (this.isAggregateIncluded('isTrue')) {
3457
+ const isTrueCount = this.groupedAggregates.booleans.filter(bool => bool).length;
3458
+ this.aggregates['isTrue'] = isTrueCount > 0 ? isTrueCount : null;
3459
+ }
3460
+ if (this.isAggregateIncluded('isFalse')) {
3461
+ const isFalseCount = this.groupedAggregates.booleans.length - this.aggregates['isTrue'];
3462
+ this.aggregates['isFalse'] = isFalseCount > 0 ? isFalseCount : null;
3463
+ }
3464
+ }
3465
+ if (this.groupedAggregates.dates.length > 0) {
3466
+ if (this.isAggregateIncluded('earliest')) {
3467
+ this.aggregates['earliest'] = new Date(Math.min(...this.groupedAggregates.dates));
3468
+ }
3469
+ if (this.isAggregateIncluded('latest')) {
3470
+ this.aggregates['latest'] = new Date(Math.max(...this.groupedAggregates.dates));
3471
+ }
3472
+ }
3442
3473
  }
3443
- /**
3444
- * @hidden
3445
- */
3446
- get headerTemplateRef() {
3447
- const template = this.headerTemplates.first;
3448
- return template ? template.templateRef : undefined;
3474
+ handleSelectedItems(selectionArgs) {
3475
+ const rowOrCellSelect = `${this.isRowSelection ? 'selectedRows' : 'selectedCells'}`;
3476
+ const rowOrCellDeselect = `${this.isRowSelection ? 'deselectedRows' : 'deselectedCells'}`;
3477
+ const selectedItems = selectionArgs[rowOrCellSelect];
3478
+ const deselectedItems = selectionArgs[rowOrCellDeselect];
3479
+ if (!this.isRowSelection) {
3480
+ // Needed when we have column groups with cell selection, the deselected items are duplicated
3481
+ deselectedItems.forEach((item, index) => {
3482
+ if (index + 1 < deselectedItems.length) {
3483
+ if (item.itemKey === deselectedItems[index + 1].itemKey
3484
+ && item.columnKey === deselectedItems[index + 1].columnKey) {
3485
+ deselectedItems.splice(index, 1);
3486
+ }
3487
+ }
3488
+ });
3489
+ }
3490
+ if (selectedItems.length > 0) {
3491
+ selectedItems.forEach((item) => {
3492
+ this.selectedItems = [...this.selectedItems, item];
3493
+ });
3494
+ }
3495
+ if (deselectedItems.length > 0) {
3496
+ if (this.isRowSelection) {
3497
+ deselectedItems.forEach((row) => {
3498
+ this.selectedItems = this.selectedItems.filter((elem) => elem.dataItem !== row.dataItem);
3499
+ });
3500
+ }
3501
+ else {
3502
+ deselectedItems.forEach((cell) => {
3503
+ const index = this.selectedItems.findIndex((elem) => elem.itemKey === cell.itemKey && elem.columnKey === cell.columnKey);
3504
+ this.selectedItems.splice(index, 1);
3505
+ });
3506
+ }
3507
+ }
3449
3508
  }
3450
- /**
3451
- * @hidden
3452
- */
3453
- get footerTemplateRef() {
3454
- return this.footerTemplate ? this.footerTemplate.templateRef : undefined;
3455
- }
3456
- /**
3457
- * @hidden
3458
- */
3459
- get columnMenuTemplateRef() {
3460
- const template = this.columnMenuTemplates.first;
3461
- return template ? template.templateRef : null;
3462
- }
3463
- /**
3464
- * @hidden
3465
- */
3466
- get displayTitle() {
3467
- return this.title;
3468
- }
3469
- /**
3470
- * @hidden
3471
- */
3472
- get isVisible() {
3473
- return !this.hidden && this.matchesMedia;
3509
+ nullifyAggregates() {
3510
+ this.groupedAggregates = { dates: [], numbers: [], booleans: [] };
3511
+ this.aggregates['count'] = null;
3512
+ this.aggregates['sum'] = this.aggregates['average'] = null;
3513
+ this.aggregates['max'] = this.aggregates['min'] = null;
3514
+ this.aggregates['isFalse'] = this.aggregates['isTrue'] = null;
3515
+ this.aggregates['earliest'] = this.aggregates['latest'] = null;
3474
3516
  }
3475
3517
  }
3476
- ColumnBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnBase, deps: [{ token: ColumnBase }, { token: IdService }], target: i0.ɵɵFactoryTarget.Component });
3477
- ColumnBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ColumnBase, selector: "kendo-grid-column-base", inputs: { resizable: "resizable", reorderable: "reorderable", minResizableWidth: "minResizableWidth", maxResizableWidth: "maxResizableWidth", title: "title", width: "width", autoSize: "autoSize", locked: "locked", sticky: "sticky", hidden: "hidden", media: "media", lockable: "lockable", stickable: "stickable", columnMenu: "columnMenu", includeInChooser: "includeInChooser", style: "style", headerStyle: "headerStyle", filterStyle: "filterStyle", footerStyle: "footerStyle", cssClass: ["class", "cssClass"], headerClass: "headerClass", filterClass: "filterClass", footerClass: "footerClass" }, queries: [{ propertyName: "footerTemplate", first: true, predicate: FooterTemplateDirective, descendants: true }, { propertyName: "headerTemplates", predicate: HeaderTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], ngImport: i0, template: ``, isInline: true });
3478
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnBase, decorators: [{
3479
- type: Component,
3480
- args: [{
3481
- selector: 'kendo-grid-column-base',
3482
- template: ``
3483
- }]
3484
- }], ctorParameters: function () { return [{ type: ColumnBase }, { type: IdService }]; }, propDecorators: { resizable: [{
3485
- type: Input
3486
- }], reorderable: [{
3487
- type: Input
3488
- }], minResizableWidth: [{
3489
- type: Input
3490
- }], maxResizableWidth: [{
3491
- type: Input
3492
- }], title: [{
3493
- type: Input
3494
- }], width: [{
3495
- type: Input
3496
- }], autoSize: [{
3497
- type: Input
3498
- }], locked: [{
3499
- type: Input
3500
- }], sticky: [{
3501
- type: Input
3502
- }], hidden: [{
3503
- type: Input
3504
- }], media: [{
3505
- type: Input
3506
- }], lockable: [{
3507
- type: Input
3508
- }], stickable: [{
3509
- type: Input
3510
- }], columnMenu: [{
3511
- type: Input
3512
- }], includeInChooser: [{
3513
- type: Input
3514
- }], style: [{
3515
- type: Input
3516
- }], headerStyle: [{
3517
- type: Input
3518
- }], filterStyle: [{
3519
- type: Input
3520
- }], footerStyle: [{
3521
- type: Input
3522
- }], cssClass: [{
3523
- type: Input,
3524
- args: ['class']
3525
- }], headerClass: [{
3526
- type: Input
3527
- }], filterClass: [{
3528
- type: Input
3529
- }], footerClass: [{
3530
- type: Input
3531
- }], headerTemplates: [{
3532
- type: ContentChildren,
3533
- args: [HeaderTemplateDirective, { descendants: false }]
3534
- }], footerTemplate: [{
3535
- type: ContentChild,
3536
- args: [FooterTemplateDirective, { static: false }]
3537
- }], columnMenuTemplates: [{
3538
- type: ContentChildren,
3539
- args: [ColumnMenuTemplateDirective]
3540
- }] } });
3518
+ CellSelectionAggregateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionAggregateService, deps: [{ token: ContextService }, { token: LocalDataChangesService }, { token: ColumnInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
3519
+ CellSelectionAggregateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionAggregateService });
3520
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionAggregateService, decorators: [{
3521
+ type: Injectable
3522
+ }], ctorParameters: function () { return [{ type: ContextService }, { type: LocalDataChangesService }, { type: ColumnInfoService }]; } });
3541
3523
 
3542
3524
  /**
3543
- * Represents the filter-cell template ([see example]({% slug filter_row %}#toc-custom-filters)).
3525
+ * @hidden
3544
3526
  */
3545
- class FilterCellTemplateDirective {
3546
- constructor(templateRef) {
3547
- this.templateRef = templateRef;
3527
+ class SelectionService {
3528
+ constructor(domEvents, aggregateService, localDataChangesService, navigationService, ctxService) {
3529
+ this.domEvents = domEvents;
3530
+ this.aggregateService = aggregateService;
3531
+ this.localDataChangesService = localDataChangesService;
3532
+ this.navigationService = navigationService;
3533
+ this.ctxService = ctxService;
3534
+ this.changes = new EventEmitter();
3535
+ this.currentSelection = [];
3536
+ this.selectAllChecked = false;
3537
+ this.active = false;
3538
+ this.dragging = false;
3539
+ this.lastSelectionData = {};
3540
+ this.addSubscriptions();
3548
3541
  }
3549
- }
3550
- FilterCellTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterCellTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3551
- FilterCellTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FilterCellTemplateDirective, selector: "[kendoGridFilterCellTemplate]", ngImport: i0 });
3552
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterCellTemplateDirective, decorators: [{
3553
- type: Directive,
3554
- args: [{
3555
- selector: '[kendoGridFilterCellTemplate]'
3556
- }]
3557
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3558
- type: Optional
3559
- }] }]; } });
3560
-
3561
- /**
3562
- * Represents the filter-menu template
3563
- * ([see example]({% slug filter_menu %}#toc-custom-filters)).
3564
- */
3565
- class FilterMenuTemplateDirective {
3566
- constructor(templateRef) {
3567
- this.templateRef = templateRef;
3542
+ get enableMarquee() {
3543
+ const checkboxOnly = this.settings && typeof this.settings === 'object' && this.settings.checkboxOnly;
3544
+ if (!this.settings || checkboxOnly) {
3545
+ return false;
3546
+ }
3547
+ const selectableSettings = this.settings.selectable;
3548
+ const dragAndMultiple = typeof (selectableSettings) === 'object' &&
3549
+ isPresent(selectableSettings) &&
3550
+ selectableSettings.mode === 'multiple' &&
3551
+ selectableSettings.enabled !== false &&
3552
+ !selectableSettings.checkboxOnly &&
3553
+ selectableSettings.drag;
3554
+ return this.active && dragAndMultiple;
3568
3555
  }
3569
- }
3570
- FilterMenuTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterMenuTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3571
- FilterMenuTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FilterMenuTemplateDirective, selector: "[kendoGridFilterMenuTemplate]", ngImport: i0 });
3572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FilterMenuTemplateDirective, decorators: [{
3573
- type: Directive,
3574
- args: [{
3575
- selector: '[kendoGridFilterMenuTemplate]'
3576
- }]
3577
- }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
3578
- type: Optional
3579
- }] }]; } });
3580
-
3581
- /**
3582
- * @hidden
3583
- */
3584
- function isColumnComponent(column) {
3585
- return isPresent(column.field);
3586
- }
3587
- /**
3588
- * Represents the column of the Grid. [See example](slug:columns_config#toc-using-the-column-component)
3589
- *
3590
- * @example
3591
- * ```html
3592
- * <kendo-grid [data]="gridData">
3593
- * <kendo-grid-column field="ProductID" title="Product ID"></kendo-grid-column>
3594
- * <kendo-grid-column field="ProductName" title="Product Name"></kendo-grid-column>
3595
- * <kendo-grid-column field="UnitPrice" title="Unit Price"></kendo-grid-column>
3596
- * </kendo-grid>
3597
- * ```
3598
- */
3599
- class ColumnComponent extends ColumnBase {
3600
- constructor(parent, idService) {
3601
- super(parent, idService);
3602
- /**
3603
- * Allows the user to click the column headers and emits the `sortChange` event. [See example](slug:sorting_grid).
3604
- *
3605
- * @default true
3606
- */
3607
- this.sortable = true;
3608
- /**
3609
- * Determines if the column can be dragged to the group panel.
3610
- * If set to `false`, you can group the columns by the column field by using the API of the Grid.
3611
- *
3612
- * @default true
3613
- */
3614
- this.groupable = true;
3615
- /**
3616
- * Defines the editor type. [See example](slug:inline_editing_grid#toc-using-reactive-forms).
3617
- * Used when the column enters the edit mode.
3618
- *
3619
- * @default 'text'
3620
- */
3621
- this.editor = 'text';
3622
- /**
3623
- * Defines the filter type that is displayed inside the filter row. [See example](slug:filtering_grid#toc-filter-data-types).
3624
- *
3625
- * @default 'text'
3626
- */
3627
- this.filter = 'text';
3628
- /**
3629
- * Defines if a filter UI will be displayed for this column. [See example](slug:filtering_grid).
3630
- *
3631
- * @default true
3632
- */
3633
- this.filterable = true;
3634
- /**
3635
- * Defines whether the column is editable. [See example](slug:make_fields_uneditable_grid).
3636
- *
3637
- * @default true
3638
- */
3639
- this.editable = true;
3556
+ init(settings) {
3557
+ this.settings = settings;
3558
+ if (!isPresent(this.lastSelectionStartIndex)) {
3559
+ this.lastSelectionStartIndex = this.ctxService?.grid.selectionDirective?.rangeSelectionStartRow?.index || 0;
3560
+ this.lastSelectionData = this.ctxService?.grid.selectionDirective?.rangeSelectionStartRow?.dataItem || {};
3561
+ }
3562
+ this.currentSelection = [];
3563
+ if (settings.selectable && settings.selectable.enabled !== false) {
3564
+ const iterator = this.getIterator();
3565
+ this._selectAllState = true;
3566
+ let item = iterator.next();
3567
+ while (!item.done) {
3568
+ if (item.value && item.value.type === "data") {
3569
+ const rowArgs = {
3570
+ dataItem: item.value.data,
3571
+ index: item.value.index
3572
+ };
3573
+ if (settings.rowSelected(rowArgs)) {
3574
+ this.currentSelection[item.value.index] = rowArgs;
3575
+ }
3576
+ else {
3577
+ this._selectAllState = undefined;
3578
+ }
3579
+ }
3580
+ item = iterator.next();
3581
+ }
3582
+ if (this.currentSelection.length === 0) {
3583
+ this._selectAllState = false;
3584
+ }
3585
+ }
3586
+ }
3587
+ isSelected(index) {
3588
+ if (this.settings && this.active) {
3589
+ return this.options.enabled && isPresent(this.currentSelection[index]);
3590
+ }
3591
+ }
3592
+ handleClick(item, event) {
3593
+ if (this.dragging) {
3594
+ this.dragging = false;
3595
+ return;
3596
+ }
3597
+ let ev;
3598
+ const ctrlKey = event.ctrlKey || event.metaKey;
3599
+ if (this.options.mode === "single" && ctrlKey && this.isSelected(item.index)) {
3600
+ ev = this.toggle(item);
3601
+ }
3602
+ else if (this.options.mode === "multiple") {
3603
+ if (ctrlKey && !event.shiftKey) {
3604
+ ev = this.toggle(item);
3605
+ }
3606
+ else if (event.shiftKey) {
3607
+ ev = this.addAllTo(item, ctrlKey);
3608
+ }
3609
+ }
3610
+ if (!isPresent(ev)) {
3611
+ ev = this.select(item);
3612
+ this.currentSelection[item.index] = {
3613
+ dataItem: item.data,
3614
+ index: item.index
3615
+ };
3616
+ }
3617
+ if (!ev.selectedRows.length && !ev.deselectedRows.length) {
3618
+ return;
3619
+ }
3620
+ ev.ctrlKey = ctrlKey;
3621
+ ev.shiftKey = event.shiftKey;
3622
+ if (this.options.cellAggregates) {
3623
+ ev.cellAggregates = this.aggregateService.onSelectionChange(ev);
3624
+ }
3625
+ if (ev.shiftKey) {
3626
+ ev.rangeStartRow = { dataItem: this.lastSelectionData, index: this.lastSelectionStartIndex };
3627
+ ev.rangeEndRow = { dataItem: item.data, index: item.index };
3628
+ }
3629
+ this.changes.emit(ev);
3630
+ }
3631
+ toggle(item) {
3632
+ const selectedRows = [];
3633
+ const deselectedRows = [];
3634
+ this.lastSelectionStartIndex = item.index;
3635
+ this.lastSelectionData = item.data;
3636
+ const rowArgs = { dataItem: item.data, index: item.index };
3637
+ if (this.isSelected(item.index)) {
3638
+ deselectedRows.push(rowArgs);
3639
+ }
3640
+ else {
3641
+ selectedRows.push(rowArgs);
3642
+ }
3643
+ return {
3644
+ deselectedRows: deselectedRows,
3645
+ selectedRows: selectedRows
3646
+ };
3647
+ }
3648
+ toggleByIndex(index) {
3649
+ const iterator = this.getIterator();
3650
+ if (this.selectAllChecked && this.isSelected(index)) {
3651
+ this.selectAllChecked = false;
3652
+ }
3653
+ let item = iterator.next();
3654
+ while (!item.done) {
3655
+ if (item.value && item.value.type === "data" && item.value.index === index) {
3656
+ const itemToToggle = {
3657
+ data: item.value.data,
3658
+ index: item.value.index
3659
+ };
3660
+ if (this.isSelected(index) || this.options.mode === "multiple") {
3661
+ return this.toggle(itemToToggle);
3662
+ }
3663
+ else {
3664
+ return this.select(itemToToggle);
3665
+ }
3666
+ }
3667
+ item = iterator.next();
3668
+ }
3669
+ }
3670
+ select(item) {
3671
+ const deselectedRows = [];
3672
+ const selectedRows = [];
3673
+ this.lastSelectionStartIndex = item.index;
3674
+ this.lastSelectionData = item.data;
3675
+ if (!this.isSelected(item.index)) {
3676
+ selectedRows.push({ dataItem: item.data, index: item.index });
3677
+ }
3678
+ this.currentSelection.forEach((row) => {
3679
+ if (row.index !== item.index) {
3680
+ deselectedRows.push(row);
3681
+ }
3682
+ });
3683
+ return {
3684
+ deselectedRows: deselectedRows,
3685
+ selectedRows: selectedRows
3686
+ };
3687
+ }
3688
+ //Used to manually deselect removed items
3689
+ deselect(removedItem) {
3690
+ const iterator = this.getIterator();
3691
+ let item = iterator.next();
3692
+ while (!item.done) {
3693
+ if (item.value && item.value.type === "data" && item.value.data === removedItem) {
3694
+ const rowArgs = {
3695
+ dataItem: item.value.data,
3696
+ index: item.value.index
3697
+ };
3698
+ if (this.isSelected(rowArgs.index)) {
3699
+ const ev = {
3700
+ ctrlKey: false,
3701
+ deselectedRows: [rowArgs],
3702
+ selectedRows: []
3703
+ };
3704
+ this.changes.emit(ev);
3705
+ }
3706
+ }
3707
+ item = iterator.next();
3708
+ }
3709
+ }
3710
+ addAllTo(item, ctrlKey) {
3711
+ const selectedRows = [];
3712
+ const deselectedRows = [];
3713
+ const start = Math.min(this.lastSelectionStartIndex, item.index);
3714
+ const end = Math.max(this.lastSelectionStartIndex, item.index);
3715
+ const iterator = this.getIterator();
3716
+ let next = iterator.next();
3717
+ while (!next.done) {
3718
+ if (next.value && next.value.type === "data") {
3719
+ const idx = next.value.index;
3720
+ const rowArgs = { dataItem: next.value.data, index: idx };
3721
+ if ((idx < start || idx > end) && this.isSelected(idx) && !ctrlKey) {
3722
+ deselectedRows.push(rowArgs);
3723
+ }
3724
+ if ((idx >= start && idx <= end) && !this.isSelected(idx)) {
3725
+ selectedRows.push(rowArgs);
3726
+ }
3727
+ }
3728
+ next = iterator.next();
3729
+ }
3730
+ return {
3731
+ deselectedRows: deselectedRows,
3732
+ selectedRows: selectedRows
3733
+ };
3734
+ }
3735
+ updateAll(selectAllChecked) {
3736
+ this.selectAllChecked = selectAllChecked;
3737
+ const selectedRows = [];
3738
+ const deselectedRows = [];
3739
+ const iterator = this.getIterator();
3740
+ let next = iterator.next();
3741
+ while (!next.done) {
3742
+ if (next.value && next.value.type === "data") {
3743
+ const idx = next.value.index;
3744
+ const rowArgs = { dataItem: next.value.data, index: idx };
3745
+ if (this.isSelected(idx) && !selectAllChecked) {
3746
+ deselectedRows.push(rowArgs);
3747
+ }
3748
+ if (!this.isSelected(idx) && selectAllChecked) {
3749
+ selectedRows.push(rowArgs);
3750
+ }
3751
+ }
3752
+ next = iterator.next();
3753
+ }
3754
+ if (!selectedRows.length && !deselectedRows.length) {
3755
+ return;
3756
+ }
3757
+ const ev = {
3758
+ ctrlKey: true,
3759
+ deselectedRows: deselectedRows,
3760
+ selectedRows: selectedRows,
3761
+ shiftKey: true
3762
+ };
3763
+ if (this.options.cellAggregates) {
3764
+ ev.cellAggregates = this.aggregateService.onSelectionChange(ev);
3765
+ }
3766
+ this.changes.emit(ev);
3767
+ }
3768
+ selectRange(startIndex, endIndex) {
3769
+ const selectedRows = [];
3770
+ const deselectedRows = [];
3771
+ const start = Math.min(startIndex, endIndex);
3772
+ const end = Math.max(startIndex, endIndex);
3773
+ const iterator = this.getIterator();
3774
+ let next = iterator.next();
3775
+ while (!next.done) {
3776
+ if (next.value && next.value.type === "data") {
3777
+ const idx = next.value.index;
3778
+ const rowArgs = { dataItem: next.value.data, index: idx };
3779
+ if ((idx < start || idx > end) && this.isSelected(idx)) {
3780
+ deselectedRows.push(rowArgs);
3781
+ }
3782
+ if ((idx >= start && idx <= end) && !this.isSelected(idx)) {
3783
+ selectedRows.push(rowArgs);
3784
+ }
3785
+ }
3786
+ next = iterator.next();
3787
+ }
3788
+ let cellAggregates;
3789
+ if (this.options.cellAggregates) {
3790
+ cellAggregates = this.aggregateService.onSelectionChange({ selectedRows, deselectedRows });
3791
+ }
3792
+ return {
3793
+ deselectedRows: deselectedRows,
3794
+ selectedRows: selectedRows,
3795
+ cellAggregates
3796
+ };
3640
3797
  }
3641
- get templateRef() {
3642
- return this.template ? this.template.templateRef : undefined;
3798
+ get selectAllState() {
3799
+ return this._selectAllState;
3643
3800
  }
3644
- get groupHeaderTemplateRef() {
3645
- return this.groupHeaderTemplate ? this.groupHeaderTemplate.templateRef : undefined;
3801
+ get selected() {
3802
+ return this.currentSelection.map((item) => {
3803
+ return item.index;
3804
+ }).filter((n) => typeof n === "number");
3646
3805
  }
3647
- get groupHeaderColumnTemplateRef() {
3648
- return this.groupHeaderColumnTemplate ? this.groupHeaderColumnTemplate.templateRef : undefined;
3806
+ get options() {
3807
+ const defaultOptions = {
3808
+ cellAggregates: false,
3809
+ checkboxOnly: false,
3810
+ enabled: true,
3811
+ mode: "multiple"
3812
+ };
3813
+ if (!isPresent(this.settings)) {
3814
+ return defaultOptions;
3815
+ }
3816
+ if (typeof this.settings.selectable === 'boolean') {
3817
+ return {
3818
+ cellAggregates: false,
3819
+ checkboxOnly: false,
3820
+ enabled: this.settings.selectable,
3821
+ mode: "multiple"
3822
+ };
3823
+ }
3824
+ else {
3825
+ return Object.assign(defaultOptions, this.settings.selectable);
3826
+ }
3649
3827
  }
3650
- get groupFooterTemplateRef() {
3651
- return this.groupFooterTemplate ? this.groupFooterTemplate.templateRef : undefined;
3828
+ ngOnDestroy() {
3829
+ this.removeSubscriptions();
3652
3830
  }
3653
- get editTemplateRef() {
3654
- return this.editTemplate ? this.editTemplate.templateRef : undefined;
3831
+ targetArgs() {
3832
+ return {
3833
+ index: this.mouseDownEventArgs.rowIndex,
3834
+ dataItem: this.mouseDownEventArgs.dataItem
3835
+ };
3655
3836
  }
3656
- get filterCellTemplateRef() {
3657
- return this.filterCellTemplate ? this.filterCellTemplate.templateRef : undefined;
3837
+ addSubscriptions() {
3838
+ if (!this.cellClickSubscription) {
3839
+ this.cellClickSubscription = this.domEvents.cellClick.subscribe((args) => {
3840
+ if (this.options.enabled && !this.options.checkboxOnly && args.type !== 'contextmenu') {
3841
+ if (this.active) {
3842
+ this.handleClick({ index: args.rowIndex, data: args.dataItem }, args.originalEvent);
3843
+ }
3844
+ }
3845
+ });
3846
+ }
3847
+ if (!this.mousedownSubscription) {
3848
+ this.mousedownSubscription = this.domEvents.cellMousedown.subscribe((args) => {
3849
+ this.mouseDownEventArgs = args;
3850
+ if ((this.options.enabled && (!this.options.mode || this.options.mode === "multiple") &&
3851
+ !this.options.checkboxOnly && args.originalEvent.shiftKey)) {
3852
+ if (this.active) {
3853
+ args.originalEvent.preventDefault();
3854
+ this.navigationService.focusCellByElement(args.originalEvent.target);
3855
+ }
3856
+ }
3857
+ });
3858
+ }
3859
+ if (this.localDataChangesService && !this.dataChangedSubscription) {
3860
+ this.dataChangedSubscription = this.localDataChangesService.changes.subscribe((args) => {
3861
+ if (this.active) {
3862
+ if (isPresent(args.action) && args.action === 'remove') {
3863
+ this.deselect(args.item);
3864
+ }
3865
+ }
3866
+ });
3867
+ }
3658
3868
  }
3659
- get filterMenuTemplateRef() {
3660
- return this.filterMenuTemplate ? this.filterMenuTemplate.templateRef : undefined;
3869
+ getIterator() {
3870
+ const accessor = this.settings.view.accessor();
3871
+ if (!accessor) {
3872
+ return;
3873
+ }
3874
+ return accessor[iterator]();
3661
3875
  }
3662
- get displayTitle() {
3663
- return this.title === undefined ? this.field : this.title;
3876
+ removeSubscriptions() {
3877
+ if (this.cellClickSubscription) {
3878
+ this.cellClickSubscription.unsubscribe();
3879
+ this.cellClickSubscription = null;
3880
+ }
3881
+ if (this.mousedownSubscription) {
3882
+ this.mousedownSubscription.unsubscribe();
3883
+ this.mousedownSubscription = null;
3884
+ }
3885
+ if (this.dataChangedSubscription) {
3886
+ this.dataChangedSubscription.unsubscribe();
3887
+ this.dataChangedSubscription = null;
3888
+ }
3664
3889
  }
3665
3890
  }
3666
- ColumnComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3667
- ColumnComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ColumnComponent, selector: "kendo-grid-column", inputs: { field: "field", format: "format", sortable: "sortable", groupable: "groupable", editor: "editor", filter: "filter", filterable: "filterable", editable: "editable" }, providers: [
3668
- {
3669
- provide: ColumnBase,
3670
- useExisting: forwardRef(() => ColumnComponent)
3671
- }
3672
- ], queries: [{ propertyName: "template", first: true, predicate: CellTemplateDirective, descendants: true }, { propertyName: "groupHeaderTemplate", first: true, predicate: GroupHeaderTemplateDirective, descendants: true }, { propertyName: "groupHeaderColumnTemplate", first: true, predicate: GroupHeaderColumnTemplateDirective, descendants: true }, { propertyName: "groupFooterTemplate", first: true, predicate: GroupFooterTemplateDirective, descendants: true }, { propertyName: "editTemplate", first: true, predicate: EditTemplateDirective, descendants: true }, { propertyName: "filterCellTemplate", first: true, predicate: FilterCellTemplateDirective, descendants: true }, { propertyName: "filterMenuTemplate", first: true, predicate: FilterMenuTemplateDirective, descendants: true }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
3673
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnComponent, decorators: [{
3674
- type: Component,
3675
- args: [{
3676
- providers: [
3677
- {
3678
- provide: ColumnBase,
3679
- useExisting: forwardRef(() => ColumnComponent)
3680
- }
3681
- ],
3682
- selector: 'kendo-grid-column',
3683
- template: ``
3684
- }]
3685
- }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{
3686
- type: SkipSelf
3687
- }, {
3688
- type: Host
3689
- }, {
3690
- type: Optional
3691
- }] }, { type: IdService, decorators: [{
3692
- type: Optional
3693
- }] }]; }, propDecorators: { field: [{
3694
- type: Input
3695
- }], format: [{
3696
- type: Input
3697
- }], sortable: [{
3698
- type: Input
3699
- }], groupable: [{
3700
- type: Input
3701
- }], editor: [{
3702
- type: Input
3703
- }], filter: [{
3704
- type: Input
3705
- }], filterable: [{
3706
- type: Input
3707
- }], editable: [{
3708
- type: Input
3709
- }], template: [{
3710
- type: ContentChild,
3711
- args: [CellTemplateDirective, { static: false }]
3712
- }], groupHeaderTemplate: [{
3713
- type: ContentChild,
3714
- args: [GroupHeaderTemplateDirective, { static: false }]
3715
- }], groupHeaderColumnTemplate: [{
3716
- type: ContentChild,
3717
- args: [GroupHeaderColumnTemplateDirective, { static: false }]
3718
- }], groupFooterTemplate: [{
3719
- type: ContentChild,
3720
- args: [GroupFooterTemplateDirective, { static: false }]
3721
- }], editTemplate: [{
3722
- type: ContentChild,
3723
- args: [EditTemplateDirective, { static: false }]
3724
- }], filterCellTemplate: [{
3725
- type: ContentChild,
3726
- args: [FilterCellTemplateDirective, { static: false }]
3727
- }], filterMenuTemplate: [{
3728
- type: ContentChild,
3729
- args: [FilterMenuTemplateDirective, { static: false }]
3730
- }] } });
3891
+ SelectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionService, deps: [{ token: DomEventsService }, { token: CellSelectionAggregateService }, { token: LocalDataChangesService }, { token: NavigationService }, { token: ContextService }], target: i0.ɵɵFactoryTarget.Injectable });
3892
+ SelectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionService });
3893
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionService, decorators: [{
3894
+ type: Injectable
3895
+ }], ctorParameters: function () { return [{ type: DomEventsService }, { type: CellSelectionAggregateService }, { type: LocalDataChangesService }, { type: NavigationService }, { type: ContextService }]; } });
3731
3896
 
3732
3897
  /**
3733
3898
  * @hidden
3734
3899
  */
3735
- function isSpanColumnComponent(column) {
3736
- return column.isSpanColumn;
3737
- }
3738
- /**
3739
- * Represents a column which can be spanned over multiple data cells while the individual
3740
- * header and footer cells are retained ([see example]({% slug spanned_columns_grid %})).
3741
- * Enables you to achieve more flexible layout while keeping the built-in UI element for
3742
- * [sorting]({% slug sorting_grid %}), [filtering]({% slug filtering_grid %}), and
3743
- * [grouping]({% slug grouping_grid %}). Wrap the columns that will be
3744
- * merged inside the `<kendo-grid-span-column>` tag.
3745
- *
3746
- * ```html
3747
- * <kendo-grid-span-column>
3748
- * <kendo-grid-column field="field1"></kendo-grid-column>
3749
- * <kendo-grid-column field="field2"></kendo-grid-column>
3750
- * <ng-template kendoGridCellTemplate let-dataItem>
3751
- * <h5>{{ dataItem.field1 }}</h5>
3752
- * <p>{{ dataItem.field2 }}</p>
3753
- * </ng-template>
3754
- * </kendo-grid-span-column>
3755
- * ```
3756
- */
3757
- class SpanColumnComponent extends ColumnBase {
3758
- constructor(parent, idService) {
3759
- super(parent, idService);
3760
- /*
3761
- * @hidden
3762
- */
3763
- this.isSpanColumn = true;
3764
- this.template = new QueryList();
3765
- this.editTemplate = new QueryList();
3766
- /**
3767
- * @hidden
3768
- */
3769
- this.childColumns = new QueryList();
3770
- /**
3771
- * @hidden
3772
- */
3773
- this.includeInChooser = false;
3774
- this._editable = true;
3775
- if (parent && parent.isSpanColumn) {
3776
- throw new Error('SpanColumn cannot be nested inside another SpanColumn');
3900
+ class CellSelectionService {
3901
+ constructor(domEvents, aggregateService, localDataChangesService, navigationService) {
3902
+ this.domEvents = domEvents;
3903
+ this.aggregateService = aggregateService;
3904
+ this.localDataChangesService = localDataChangesService;
3905
+ this.navigationService = navigationService;
3906
+ this.changes = new EventEmitter();
3907
+ this.mouseUpEvent = new EventEmitter();
3908
+ this.currentSelection = [];
3909
+ this.active = false;
3910
+ this.dragging = false;
3911
+ this.dragSelectDeselect = false;
3912
+ this.lastSelectionItem = { itemKey: 0, columnKey: 0 };
3913
+ this.lastSelectionItemRowIndex = 0;
3914
+ this.lastSelectionItemColIndex = 0;
3915
+ this.addSubscriptions();
3916
+ }
3917
+ get enableMarquee() {
3918
+ const checkboxOnly = this.settings && typeof this.settings === 'object' && this.settings.checkboxOnly;
3919
+ if (!this.settings || checkboxOnly) {
3920
+ return false;
3921
+ }
3922
+ const selectableSettings = this.settings.selectable;
3923
+ const dragAndMultiple = typeof (selectableSettings) === 'object' &&
3924
+ isPresent(selectableSettings) &&
3925
+ selectableSettings.mode === 'multiple' &&
3926
+ selectableSettings.cell &&
3927
+ selectableSettings.enabled !== false &&
3928
+ selectableSettings.drag;
3929
+ return this.active && dragAndMultiple;
3930
+ }
3931
+ init(settings) {
3932
+ this.settings = settings;
3933
+ this.currentSelection = [];
3934
+ if (settings.selectable && settings.selectable.enabled !== false) {
3935
+ const iterator = this.getIterator();
3936
+ let item = iterator.next();
3937
+ while (!item.done) {
3938
+ if (item.value && item.value.type === "data") {
3939
+ const rowArgs = {
3940
+ dataItem: item.value.data,
3941
+ index: item.value.index
3942
+ };
3943
+ settings.columns.forEach(col => {
3944
+ const selectedCellArgs = settings.cellSelected(rowArgs, col, col.leafIndex);
3945
+ if (selectedCellArgs.selected) {
3946
+ this.currentSelection.push(selectedCellArgs.item);
3947
+ }
3948
+ });
3949
+ }
3950
+ item = iterator.next();
3951
+ }
3777
3952
  }
3778
3953
  }
3779
- /**
3780
- * Defines whether the edit template of the column will be rendered.
3781
- * To enable the editing functionality for a spanned column, set an edit template for it ([see example](slug:custom_reactive_editing_grid)).
3782
- * @default false
3783
- */
3784
- set editable(value) {
3785
- this._editable = value;
3786
- }
3787
- get editable() {
3788
- return isPresent(this.editTemplateRef) && this._editable;
3954
+ isCellSelected(item, col) {
3955
+ if (this.settings && this.active) {
3956
+ const selectedCellArgs = this.settings.cellSelected({ dataItem: item.data, index: item.index }, col, col.leafIndex);
3957
+ return this.options.enabled && selectedCellArgs.selected;
3958
+ }
3959
+ return false;
3789
3960
  }
3790
- /**
3791
- * @hidden
3792
- * added for backwards compitability
3793
- */
3794
- set width(_value) {
3961
+ handleClick(item, event) {
3962
+ if (this.dragging) {
3963
+ this.dragging = false;
3964
+ return;
3965
+ }
3966
+ let ev;
3967
+ const ctrlKey = event.ctrlKey || event.metaKey;
3968
+ if (this.options.mode === "single" && ctrlKey && this.isCellSelected(item, item.column)) {
3969
+ ev = this.toggle(item);
3970
+ }
3971
+ else if (this.options.mode === "multiple") {
3972
+ if (ctrlKey && !event.shiftKey) {
3973
+ ev = this.toggle(item);
3974
+ }
3975
+ else if (event.shiftKey) {
3976
+ const startRowIndex = Math.min(this.lastSelectionItemRowIndex, item.index);
3977
+ const startColIndex = Math.min(this.lastSelectionItemColIndex, item.column.leafIndex);
3978
+ const endRowIndex = Math.max(this.lastSelectionItemRowIndex, item.index);
3979
+ const endColIndex = Math.max(this.lastSelectionItemColIndex, item.column.leafIndex);
3980
+ ev = this.selectRange(startRowIndex, startColIndex, endRowIndex, endColIndex);
3981
+ }
3982
+ }
3983
+ if (!isPresent(ev)) {
3984
+ ev = this.select(item);
3985
+ this.currentSelection = [this.lastSelectionItem];
3986
+ }
3987
+ if (!ev.selectedCells.length && !ev.deselectedCells.length) {
3988
+ return;
3989
+ }
3990
+ ev.ctrlKey = ctrlKey;
3991
+ ev.shiftKey = event.shiftKey;
3992
+ if (this.options.cellAggregates && !event.shiftKey) {
3993
+ ev.cellAggregates = this.aggregateService.onSelectionChange(ev);
3994
+ }
3995
+ if (ev.shiftKey) {
3996
+ ev.rangeStartCell = this.lastSelectionItem;
3997
+ ev.rangeEndCell = {
3998
+ ...this.settings.cellSelected({ dataItem: item.data, index: item.index }, item.column, item.column.leafIndex).item
3999
+ };
4000
+ }
4001
+ this.changes.emit(ev);
3795
4002
  }
3796
- get width() {
3797
- return this.childColumns.reduce((total, column) => total + column.width, 0);
4003
+ toggle(item) {
4004
+ const selectedCells = [];
4005
+ const deselectedCells = [];
4006
+ this.lastSelectionItem =
4007
+ this.settings.cellSelected({ dataItem: item.data, index: item.index }, item.column, item.column.leafIndex).item;
4008
+ this.lastSelectionItemRowIndex = item.index;
4009
+ this.lastSelectionItemColIndex = item.column.leafIndex;
4010
+ if (this.isCellSelected(item, item.column)) {
4011
+ deselectedCells.push(this.lastSelectionItem);
4012
+ }
4013
+ else {
4014
+ selectedCells.push(this.lastSelectionItem);
4015
+ }
4016
+ return {
4017
+ deselectedCells,
4018
+ selectedCells
4019
+ };
3798
4020
  }
3799
- /**
3800
- * @hidden
3801
- */
3802
- get leafIndex() {
3803
- return this.childColumns.first.leafIndex;
4021
+ select(item) {
4022
+ const selectedCells = [];
4023
+ const deselectedCells = [];
4024
+ this.lastSelectionItem =
4025
+ this.settings.cellSelected({ dataItem: item.data, index: item.index }, item.column, item.column.leafIndex).item;
4026
+ this.lastSelectionItemRowIndex = item.index;
4027
+ this.lastSelectionItemColIndex = item.column.leafIndex;
4028
+ if (!this.isCellSelected(item, item.column)) {
4029
+ selectedCells.push(this.lastSelectionItem);
4030
+ }
4031
+ this.currentSelection.forEach((selectedItem) => {
4032
+ if (selectedItem.itemKey !== this.lastSelectionItem.itemKey || selectedItem.columnKey !== this.lastSelectionItem.columnKey) {
4033
+ deselectedCells.push(selectedItem);
4034
+ }
4035
+ });
4036
+ return {
4037
+ deselectedCells,
4038
+ selectedCells
4039
+ };
3804
4040
  }
3805
- /**
3806
- * @hidden
3807
- */
3808
- get templateRef() {
3809
- const template = this.template.first;
3810
- return template ? template.templateRef : undefined;
4041
+ //Used to manually deselect removed items
4042
+ deselect(removedItem) {
4043
+ const iterator = this.getIterator();
4044
+ let item = iterator.next();
4045
+ let rowArgs;
4046
+ while (!item.done) {
4047
+ if (item.value && item.value.type === "data" && item.value.data === removedItem) {
4048
+ rowArgs = {
4049
+ dataItem: item.value.data,
4050
+ index: item.value.index
4051
+ };
4052
+ break;
4053
+ }
4054
+ item = iterator.next();
4055
+ }
4056
+ if (rowArgs) {
4057
+ const cellsToRemove = this.currentSelection.filter(selectedItem => {
4058
+ const contender = this.settings.cellSelected(rowArgs, null, null).item;
4059
+ return selectedItem.itemKey === contender.itemKey;
4060
+ });
4061
+ if (cellsToRemove.length) {
4062
+ const ev = {
4063
+ ctrlKey: false,
4064
+ deselectedCells: cellsToRemove,
4065
+ selectedCells: []
4066
+ };
4067
+ this.changes.emit(ev);
4068
+ }
4069
+ }
3811
4070
  }
3812
- /**
3813
- * @hidden
3814
- */
3815
- get editTemplateRef() {
3816
- const editTemplate = this.editTemplate.first;
3817
- return editTemplate ? editTemplate.templateRef : undefined;
4071
+ selectRange(startRowIndex, startColIndex, endRowIndex, endColIndex) {
4072
+ const selectedCells = [];
4073
+ const deselectedCells = [];
4074
+ const selectionStartRow = Math.min(startRowIndex, endRowIndex);
4075
+ const selectionStartCol = Math.min(startColIndex, endColIndex);
4076
+ const selectionEndRow = Math.max(startRowIndex, endRowIndex);
4077
+ const selectionEndCol = Math.max(startColIndex, endColIndex);
4078
+ const iterator = this.getIterator();
4079
+ let next = iterator.next();
4080
+ while (!next.done) {
4081
+ if (next.value && next.value.type === "data") {
4082
+ const idx = next.value.index;
4083
+ const data = next.value.data;
4084
+ const rowArgs = {
4085
+ dataItem: data,
4086
+ index: idx
4087
+ };
4088
+ this.settings.columns.forEach(col => {
4089
+ const { item } = this.settings.cellSelected(rowArgs, col, col.leafIndex);
4090
+ const selected = this.isCellSelected(next.value, col);
4091
+ const isInRowRange = selectionStartRow <= idx && idx <= selectionEndRow;
4092
+ const isInColRange = selectionStartCol <= col.leafIndex && col.leafIndex <= selectionEndCol;
4093
+ const isInSelectionRect = isInRowRange && isInColRange;
4094
+ if (!isInSelectionRect && selected) {
4095
+ deselectedCells.push(item);
4096
+ }
4097
+ if (isInSelectionRect && !selected) {
4098
+ selectedCells.push(item);
4099
+ }
4100
+ });
4101
+ }
4102
+ next = iterator.next();
4103
+ }
4104
+ let cellAggregates;
4105
+ if (this.options.cellAggregates) {
4106
+ cellAggregates = this.aggregateService.onSelectionChange({ selectedCells, deselectedCells });
4107
+ }
4108
+ return {
4109
+ deselectedCells,
4110
+ selectedCells,
4111
+ cellAggregates
4112
+ };
3818
4113
  }
3819
- /**
3820
- * @hidden
3821
- */
3822
- get colspan() {
3823
- return this.childColumns.filter(c => c.isVisible).length;
4114
+ get options() {
4115
+ const defaultOptions = {
4116
+ cellAggregates: false,
4117
+ checkboxOnly: false,
4118
+ enabled: true,
4119
+ mode: "multiple"
4120
+ };
4121
+ if (!isPresent(this.settings)) {
4122
+ return defaultOptions;
4123
+ }
4124
+ if (typeof this.settings.selectable === 'boolean') {
4125
+ return {
4126
+ cellAggregates: false,
4127
+ checkboxOnly: false,
4128
+ enabled: this.settings.selectable,
4129
+ mode: "multiple"
4130
+ };
4131
+ }
4132
+ else {
4133
+ return Object.assign(defaultOptions, this.settings.selectable);
4134
+ }
3824
4135
  }
3825
- /**
3826
- * Toggles the locked (frozen) state of the columns ([see example](slug:locked_columns_grid)).
3827
- * @default false
3828
- */
3829
- set locked(value) {
3830
- this._locked = value;
4136
+ ngOnDestroy() {
4137
+ this.removeSubscriptions();
3831
4138
  }
3832
- get locked() {
3833
- return this._locked || this.childColumns.some(c => c.locked);
4139
+ addSubscriptions() {
4140
+ if (!this.cellClickSubscription) {
4141
+ this.cellClickSubscription = this.domEvents.cellClick.subscribe((args) => {
4142
+ if (this.options.enabled && !this.options.checkboxOnly && args.type !== 'contextmenu') {
4143
+ if (this.active) {
4144
+ this.handleClick({ index: args.rowIndex, data: args.dataItem, column: args.column }, args.originalEvent);
4145
+ }
4146
+ }
4147
+ });
4148
+ }
4149
+ if (!this.mousedownSubscription) {
4150
+ this.mousedownSubscription = this.domEvents.cellMousedown.subscribe((args) => {
4151
+ this.mouseDownEventArgs = args;
4152
+ if (this.options.enabled && (!this.options.mode || this.options.mode === "multiple") &&
4153
+ !this.options.checkboxOnly && args.originalEvent.shiftKey) {
4154
+ if (this.active) {
4155
+ args.originalEvent.preventDefault();
4156
+ this.navigationService.focusCellByElement(args.originalEvent.target);
4157
+ }
4158
+ }
4159
+ });
4160
+ }
4161
+ if (this.localDataChangesService && !this.dataChangedSubscription) {
4162
+ this.dataChangedSubscription = this.localDataChangesService.changes.subscribe((args) => {
4163
+ if (this.active) {
4164
+ if (isPresent(args.action) && args.action === 'remove') {
4165
+ this.deselect(args.item);
4166
+ }
4167
+ }
4168
+ });
4169
+ }
3834
4170
  }
3835
- get childrenArray() {
3836
- return this.childColumns.toArray();
4171
+ getIterator() {
4172
+ const accessor = this.settings.view.accessor();
4173
+ if (!accessor) {
4174
+ return;
4175
+ }
4176
+ return accessor[iterator]();
3837
4177
  }
3838
- get hasChildren() {
3839
- return this.childColumns.length > 0;
4178
+ removeSubscriptions() {
4179
+ if (this.cellClickSubscription) {
4180
+ this.cellClickSubscription.unsubscribe();
4181
+ this.cellClickSubscription = null;
4182
+ }
4183
+ if (this.mousedownSubscription) {
4184
+ this.mousedownSubscription.unsubscribe();
4185
+ this.mousedownSubscription = null;
4186
+ }
4187
+ if (this.dataChangedSubscription) {
4188
+ this.dataChangedSubscription.unsubscribe();
4189
+ this.dataChangedSubscription = null;
4190
+ }
3840
4191
  }
3841
4192
  }
3842
- SpanColumnComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SpanColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3843
- SpanColumnComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: SpanColumnComponent, selector: "kendo-grid-span-column", inputs: { editable: "editable", locked: "locked" }, providers: [
3844
- {
3845
- provide: ColumnBase,
3846
- useExisting: forwardRef(() => SpanColumnComponent)
3847
- }
3848
- ], queries: [{ propertyName: "template", predicate: CellTemplateDirective }, { propertyName: "editTemplate", predicate: EditTemplateDirective }, { propertyName: "childColumns", predicate: ColumnComponent }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
3849
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SpanColumnComponent, decorators: [{
3850
- type: Component,
3851
- args: [{
3852
- providers: [
3853
- {
3854
- provide: ColumnBase,
3855
- useExisting: forwardRef(() => SpanColumnComponent)
3856
- }
3857
- ],
3858
- selector: 'kendo-grid-span-column',
3859
- template: ``
3860
- }]
3861
- }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{
3862
- type: SkipSelf
3863
- }, {
3864
- type: Host
3865
- }, {
3866
- type: Optional
3867
- }] }, { type: IdService, decorators: [{
3868
- type: Optional
3869
- }] }]; }, propDecorators: { template: [{
3870
- type: ContentChildren,
3871
- args: [CellTemplateDirective, { descendants: false }]
3872
- }], editTemplate: [{
3873
- type: ContentChildren,
3874
- args: [EditTemplateDirective, { descendants: false }]
3875
- }], childColumns: [{
3876
- type: ContentChildren,
3877
- args: [ColumnComponent]
3878
- }], editable: [{
3879
- type: Input
3880
- }], locked: [{
3881
- type: Input
3882
- }] } });
4193
+ CellSelectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionService, deps: [{ token: DomEventsService }, { token: CellSelectionAggregateService }, { token: LocalDataChangesService }, { token: NavigationService }], target: i0.ɵɵFactoryTarget.Injectable });
4194
+ CellSelectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionService });
4195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellSelectionService, decorators: [{
4196
+ type: Injectable
4197
+ }], ctorParameters: function () { return [{ type: DomEventsService }, { type: CellSelectionAggregateService }, { type: LocalDataChangesService }, { type: NavigationService }]; } });
3883
4198
 
4199
+ const createElement$1 = () => {
4200
+ if (!isDocumentAvailable()) {
4201
+ return;
4202
+ }
4203
+ const marquee = document.createElement("div");
4204
+ marquee.className = "k-marquee";
4205
+ const marqueeColor = document.createElement("div");
4206
+ marqueeColor.className = "k-marquee-color";
4207
+ marquee.appendChild(marqueeColor);
4208
+ return marquee;
4209
+ };
4210
+ const POINTER_OFFSET = 2;
4211
+ const MINIMAL_DRAG_DISTANCE = 5;
4212
+ const offsets = {
4213
+ topLeft: { x: POINTER_OFFSET, y: POINTER_OFFSET },
4214
+ topRight: { x: -POINTER_OFFSET, y: POINTER_OFFSET },
4215
+ bottomLeft: { x: POINTER_OFFSET, y: -POINTER_OFFSET },
4216
+ bottomRight: { x: -POINTER_OFFSET, y: -POINTER_OFFSET }
4217
+ };
3884
4218
  /**
3885
4219
  * @hidden
3886
4220
  */
3887
- const expandColumns = (columns) => (columns.reduce((acc, column) => acc.concat(isSpanColumnComponent(column) ? column.childrenArray : [column]), []));
3888
- /**
3889
- * @hidden
3890
- */
3891
- const expandColumnsWithSpan = (columns) => (columns.reduce((acc, column) => acc.concat(isSpanColumnComponent(column) ?
3892
- [column].concat(column.childrenArray) :
3893
- [column]), []));
3894
- /**
3895
- * @hidden
3896
- */
3897
- const columnsToRender = (columns) => (expandColumns(columns).filter(x => x.isVisible));
3898
- const sumProp = (prop) => (array) => (array || []).reduce((prev, curr) => prev + (curr[prop] || 0), 0);
3899
- /**
3900
- * @hidden
3901
- */
3902
- const sumColumnWidths = sumProp('width');
3903
- /**
3904
- * @hidden
3905
- */
3906
- const columnsSpan = sumProp('colspan');
3907
- const validField = new RegExp(`^[$A-Z\_a-z][$A-Z\_a-z0-9\\.]*$`);
3908
- /**
3909
- * @hidden
3910
- */
3911
- const isValidFieldName = (fieldName) => !isNullOrEmptyString(fieldName) && validField.test(fieldName) &&
3912
- fieldName[0] !== "." && fieldName[fieldName.length - 1] !== ".";
3913
- /**
3914
- * @hidden
3915
- */
3916
- const children = column => column.children.filter(child => child !== column);
3917
- /**
3918
- * @hidden
3919
- */
3920
- const leafColumns = columns => {
3921
- return columns.reduce((acc, column) => {
3922
- if (column.isColumnGroup) {
3923
- acc = acc.concat(leafColumns(children(column)));
4221
+ class GridMarqueeDirective {
4222
+ constructor(draggable, selection, cellSelection, domEvents) {
4223
+ this.draggable = draggable;
4224
+ this.selection = selection;
4225
+ this.cellSelection = cellSelection;
4226
+ this.domEvents = domEvents;
4227
+ this.selectionStarted = false;
4228
+ }
4229
+ get webkitUserSelection() {
4230
+ return (this.cellSelection.enableMarquee || this.selection.enableMarquee) ? 'none' : null;
4231
+ }
4232
+ get userSelection() {
4233
+ return (this.cellSelection.enableMarquee || this.selection.enableMarquee);
4234
+ }
4235
+ ngOnInit() {
4236
+ this.subscriptions = (this.draggable.kendoPress.subscribe(this.start.bind(this)));
4237
+ this.subscriptions.add(this.draggable.kendoDrag.subscribe(this.moveMarquee.bind(this)));
4238
+ }
4239
+ ngOnDestroy() {
4240
+ this.subscriptions.unsubscribe();
4241
+ this.clean();
4242
+ }
4243
+ start(args) {
4244
+ const isInvalidTarget = args.originalEvent.target.matches('.k-grid-content, .k-grid-content-locked, .k-grid-aria-root, .k-checkbox');
4245
+ if (isInvalidTarget) {
4246
+ this.pressArgs = null;
4247
+ return;
3924
4248
  }
3925
- else if (column.isSpanColumn) {
3926
- acc = acc.concat(column.childrenArray);
4249
+ this.pressArgs = args;
4250
+ this.pressTarget = null;
4251
+ }
4252
+ moveMarquee(args) {
4253
+ if (!this.pressTarget) {
4254
+ this.pressTarget = this.cellSelection.active ? this.cellSelection.mouseDownEventArgs : this.selection.mouseDownEventArgs;
3927
4255
  }
3928
- else {
3929
- acc.push(column);
4256
+ const press = this.pressArgs;
4257
+ if (!press) {
4258
+ return;
3930
4259
  }
3931
- return acc;
3932
- }, []).filter(x => x.isVisible);
3933
- };
3934
- /**
3935
- * @hidden
3936
- */
3937
- const someLeafColumn = (callback, ...columns) => leafColumns(columns).some(callback);
3938
- /**
3939
- * @hidden
3940
- */
3941
- const resizableColumns = columns => columns.filter(column => isTruthy(column.resizable) && column.isVisible);
3942
- /**
3943
- * @hidden
3944
- */
3945
- const sortColumns = (columns) => orderBy(columns, [{ field: 'orderIndex', dir: 'asc' }]);
3946
- /**
3947
- * @hidden
3948
- */
3949
- const isInSpanColumn$1 = (column) => isTruthy(column.parent) && isSpanColumnComponent(column.parent);
3950
-
3951
- /**
3952
- * @hidden
3953
- */
3954
- function isColumnGroupComponent(column) {
3955
- return column.isColumnGroup;
3956
- }
3957
- /**
3958
- * Represents the column group header of the Grid
3959
- * ([more information and examples](slug:multicolumnheaders_columns_grid)).
3960
- *
3961
- * @example
3962
- * ```html
3963
- * <kendo-grid [data]="gridData">
3964
- * <kendo-grid-column-group title="Product Info">
3965
- * <kendo-grid-column field="ProductID"></kendo-grid-column>
3966
- * <kendo-grid-column field="ProductName"></kendo-grid-column>
3967
- * </kendo-grid-column-group>
3968
- * <kendo-grid-column field="UnitPrice"></kendo-grid-column>
3969
- * </kendo-grid>
3970
- * ```
3971
- */
3972
- class ColumnGroupComponent extends ColumnBase {
3973
- constructor(parent, idService) {
3974
- super(parent, idService);
3975
- this.parent = parent;
3976
- /**
3977
- * @hidden
3978
- */
3979
- this.includeInChooser = false;
3980
- /**
3981
- * @hidden
3982
- */
3983
- this.isColumnGroup = true;
3984
- /**
3985
- * @hidden
3986
- */
3987
- this.minResizableWidth = 10;
3988
- if (parent && parent.isSpanColumn) {
3989
- throw new Error('ColumnGroupComponent cannot be nested inside SpanColumnComponent');
4260
+ if (!this.selectionStarted) {
4261
+ const distance = Math.sqrt((args.pageX - press.pageX) ** 2 + (args.pageY - press.pageY) ** 2);
4262
+ if (distance > MINIMAL_DRAG_DISTANCE) {
4263
+ this.selectionStarted = true;
4264
+ this.dragEndSubscription = merge(this.domEvents.cellMouseup.pipe(take(1)), this.draggable.kendoRelease.pipe(delay(1), take(1)))
4265
+ .subscribe(this.endSelection.bind(this));
4266
+ }
4267
+ else {
4268
+ return;
4269
+ }
3990
4270
  }
3991
- }
3992
- /**
3993
- * @hidden
3994
- */
3995
- rowspan() {
3996
- return 1;
3997
- }
3998
- /**
3999
- * @hidden
4000
- */
4001
- get colspan() {
4002
- if (!this.children) {
4003
- return 1;
4271
+ this.initMarquee();
4272
+ const element = this.marqueeElement;
4273
+ const marqueeQuadrant = this.getMarqueeQuadrant(args.pageX, args.pageY, press.pageX, press.pageY);
4274
+ let left = Math.min(args.pageX, press.pageX);
4275
+ let top = Math.min(args.pageY, press.pageY);
4276
+ const width = Math.abs(args.pageX - press.pageX);
4277
+ const height = Math.abs(args.pageY - press.pageY);
4278
+ if (marqueeQuadrant) {
4279
+ left += offsets[marqueeQuadrant].x;
4280
+ top += offsets[marqueeQuadrant].y;
4004
4281
  }
4005
- return columnsSpan(this.children
4006
- .filter(child => child !== this && child.isVisible));
4282
+ element.style.left = `${left}px`;
4283
+ element.style.top = `${top}px`;
4284
+ element.style.width = `${width}px`;
4285
+ element.style.height = `${height}px`;
4007
4286
  }
4008
- /**
4009
- * @hidden
4010
- */
4011
- get leafIndex() {
4012
- return this.children ? (this.firstChild || {}).leafIndex : -1;
4287
+ endSelection(args) {
4288
+ if (args.type === 'mouseup' || args.type === 'touchend') {
4289
+ if (this.cellSelection.active) {
4290
+ this.cellSelection.dragging = true;
4291
+ this.cellSelection.changes.emit(this.cellSelection.selectRange(this.pressTarget.rowIndex, this.pressTarget.column.leafIndex, args.rowIndex, args.column.leafIndex));
4292
+ }
4293
+ else if (this.selection.active) {
4294
+ this.selection.dragging = true;
4295
+ this.selection.changes.emit(this.selection.selectRange(this.pressTarget.rowIndex, args.rowIndex));
4296
+ }
4297
+ }
4298
+ this.clean();
4013
4299
  }
4014
- get childrenArray() {
4015
- return this.children.filter(c => c !== this);
4300
+ clean() {
4301
+ if (this.marqueeElement) {
4302
+ document.body.removeChild(this.marqueeElement);
4303
+ this.marqueeElement = null;
4304
+ }
4305
+ if (this.dragEndSubscription) {
4306
+ this.dragEndSubscription.unsubscribe();
4307
+ }
4308
+ this.dragEndSubscription = null;
4309
+ this.pressTarget = null;
4310
+ this.pressArgs = null;
4311
+ this.selectionStarted = false;
4312
+ // eslint-disable-next-line no-unused-expressions
4313
+ this.cellSelection.active ? this.cellSelection.dragging = false : this.selection.dragging = false;
4016
4314
  }
4017
- get hasChildren() {
4018
- return Boolean(this.firstChild);
4315
+ initMarquee() {
4316
+ if (!isDocumentAvailable()) {
4317
+ return;
4318
+ }
4319
+ if (!this.marqueeElement) {
4320
+ this.marqueeElement = createElement$1();
4321
+ document.body.appendChild(this.marqueeElement);
4322
+ }
4019
4323
  }
4020
- get firstChild() {
4021
- return this.children.find(column => column !== this);
4324
+ getMarqueeQuadrant(pointerX, pointerY, startX, startY) {
4325
+ const leftHalf = pointerX < startX;
4326
+ const rightHalf = pointerX > startX;
4327
+ const topHalf = pointerY < startY;
4328
+ const bottomHalf = pointerY > startY;
4329
+ if (leftHalf && topHalf) {
4330
+ return 'topLeft';
4331
+ }
4332
+ if (leftHalf && bottomHalf) {
4333
+ return 'bottomLeft';
4334
+ }
4335
+ if (rightHalf && topHalf) {
4336
+ return 'topRight';
4337
+ }
4338
+ if (rightHalf && bottomHalf) {
4339
+ return 'bottomRight';
4340
+ }
4341
+ return null;
4022
4342
  }
4023
4343
  }
4024
- ColumnGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnGroupComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
4025
- ColumnGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ColumnGroupComponent, selector: "kendo-grid-column-group", providers: [
4026
- {
4027
- provide: ColumnBase,
4028
- useExisting: forwardRef(() => ColumnGroupComponent)
4029
- }
4030
- ], queries: [{ propertyName: "children", predicate: ColumnBase }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
4031
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnGroupComponent, decorators: [{
4032
- type: Component,
4344
+ GridMarqueeDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridMarqueeDirective, deps: [{ token: i1$1.DraggableDirective }, { token: SelectionService }, { token: CellSelectionService }, { token: DomEventsService }], target: i0.ɵɵFactoryTarget.Directive });
4345
+ GridMarqueeDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]", host: { properties: { "style.-webkit-user-select": "this.webkitUserSelection", "class.user-select-none": "this.userSelection" } }, ngImport: i0 });
4346
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridMarqueeDirective, decorators: [{
4347
+ type: Directive,
4033
4348
  args: [{
4034
- providers: [
4035
- {
4036
- provide: ColumnBase,
4037
- useExisting: forwardRef(() => ColumnGroupComponent)
4038
- }
4039
- ],
4040
- selector: 'kendo-grid-column-group',
4041
- template: ``
4349
+ selector: '[kendoGridSelectionMarquee]'
4042
4350
  }]
4043
- }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{
4044
- type: SkipSelf
4045
- }, {
4046
- type: Host
4047
- }, {
4048
- type: Optional
4049
- }] }, { type: IdService, decorators: [{
4050
- type: Optional
4051
- }] }]; }, propDecorators: { children: [{
4052
- type: ContentChildren,
4053
- args: [ColumnBase]
4351
+ }], ctorParameters: function () { return [{ type: i1$1.DraggableDirective }, { type: SelectionService }, { type: CellSelectionService }, { type: DomEventsService }]; }, propDecorators: { webkitUserSelection: [{
4352
+ type: HostBinding,
4353
+ args: ['style.-webkit-user-select']
4354
+ }], userSelection: [{
4355
+ type: HostBinding,
4356
+ args: ['class.user-select-none']
4054
4357
  }] } });
4055
4358
 
4359
+ /**
4360
+ * @hidden
4361
+ */
4362
+ class ZoneAwareEventEmitter extends EventEmitter {
4363
+ constructor(ngZone, isAsync = false) {
4364
+ super(isAsync);
4365
+ this.ngZone = ngZone;
4366
+ }
4367
+ subscribe(generatorOrNext, error, complete) {
4368
+ let schedulerFn;
4369
+ let errorFn = (_) => null;
4370
+ let completeFn = () => null;
4371
+ if (generatorOrNext && typeof generatorOrNext === 'object') {
4372
+ schedulerFn = (value) => { this.ngZone.run(() => generatorOrNext.next(value)); };
4373
+ if (generatorOrNext.error) {
4374
+ errorFn = (err) => { this.ngZone.run(() => generatorOrNext.error(err)); };
4375
+ }
4376
+ if (generatorOrNext.complete) {
4377
+ completeFn = () => { this.ngZone.run(() => generatorOrNext.complete()); };
4378
+ }
4379
+ }
4380
+ else {
4381
+ schedulerFn = (value) => { this.ngZone.run(() => generatorOrNext(value)); };
4382
+ if (error) {
4383
+ errorFn = (err) => { this.ngZone.run(() => error(err)); };
4384
+ }
4385
+ if (complete) {
4386
+ completeFn = () => { this.ngZone.run(() => complete()); };
4387
+ }
4388
+ }
4389
+ return super.subscribe(schedulerFn, errorFn, completeFn);
4390
+ }
4391
+ }
4392
+
4393
+ /**
4394
+ * @hidden
4395
+ */
4396
+ const packageMetadata = {
4397
+ name: '@progress/kendo-angular-grid',
4398
+ productName: 'Kendo UI for Angular',
4399
+ productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
4400
+ publishDate: 1686318734,
4401
+ version: '13.0.3-develop.2',
4402
+ licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
4403
+ };
4404
+
4056
4405
  /**
4057
4406
  * Represents the detail template of the Grid ([more information and examples]({% slug detailrowtemplate_grid %})).
4058
4407
  * To define the detail template, nest an `<ng-template>` tag with the `kendoGridDetailTemplate` directive inside a `<kendo-grid>` tag.
@@ -4705,108 +5054,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
4705
5054
  }], ctorParameters: function () { return [{ type: ContextService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { selectedKeys: [{
4706
5055
  type: Input
4707
5056
  }], rangeSelectionStartRow: [{
4708
- type: Input
4709
- }], rangeSelectionStartColumnIndex: [{
4710
- type: Input
4711
- }], selectionKey: [{
4712
- type: Input,
4713
- args: ["kendoGridSelectBy"]
4714
- }], columnKey: [{
4715
- type: Input
4716
- }], selectedKeysChange: [{
4717
- type: Output
4718
- }] } });
4719
-
4720
- const reset = (...lists) => {
4721
- let diff = false;
4722
- for (let idx = 0; idx < lists.length; idx++) {
4723
- const [list, columns] = lists[idx];
4724
- diff = diff || list.length !== columns.length;
4725
- list.reset(columns);
4726
- }
4727
- return diff;
4728
- };
4729
- /**
4730
- * @hidden
4731
- */
4732
- class ColumnsContainer {
4733
- constructor(columns) {
4734
- this.columns = columns;
4735
- this.allColumns = new QueryList();
4736
- this.leafColumns = new QueryList();
4737
- this.lockedColumns = new QueryList();
4738
- this.nonLockedColumns = new QueryList();
4739
- this.lockedLeafColumns = new QueryList();
4740
- this.nonLockedLeafColumns = new QueryList();
4741
- this.totalLevels = 0;
4742
- this.changes = new EventEmitter();
4743
- this.leafColumnsToRender = [];
4744
- this.lockedColumnsToRender = [];
4745
- this.nonLockedColumnsToRender = [];
4746
- this.hasGroupHeaderColumn = false;
4747
- this.hasGroupFooter = false;
4748
- this.hasFooter = false;
4749
- this.unlockedWidth = 0;
4750
- }
4751
- refresh() {
4752
- const currentLevels = this.totalLevels;
4753
- const leafColumns = new Array();
4754
- const lockedLeafColumns = new Array();
4755
- const nonLockedLeafColumns = new Array();
4756
- const lockedColumns = new Array();
4757
- const nonLockedColumns = new Array();
4758
- const allColumns = new Array();
4759
- const leafColumnsToRender = new Array();
4760
- const lockedColumnsToRender = new Array();
4761
- const nonLockedColumnsToRender = new Array();
4762
- let hasGroupHeaderColumn = false;
4763
- let hasGroupFooter = false;
4764
- let hasFooter = false;
4765
- let unlockedWidth = 0;
4766
- let leafIndex = 0;
4767
- this.totalLevels = 0;
4768
- this.columns().forEach(column => {
4769
- const containerLeafColumns = column.isLocked === true ? lockedLeafColumns : nonLockedLeafColumns;
4770
- const containerColumns = column.isLocked === true ? lockedColumns : nonLockedColumns;
4771
- const toRenderContainer = column.isLocked === true ? lockedColumnsToRender : nonLockedColumnsToRender;
4772
- if (!isColumnGroupComponent(column)) {
4773
- containerLeafColumns.push(column);
4774
- leafColumns.push(column);
4775
- leafColumnsToRender.push(...columnsToRender([column]));
4776
- toRenderContainer.push(...columnsToRender([column]));
4777
- hasGroupHeaderColumn = hasGroupHeaderColumn || someLeafColumn(leaf => Boolean(leaf.groupHeaderColumnTemplateRef), column);
4778
- hasGroupFooter = hasGroupFooter || someLeafColumn(leaf => Boolean(leaf.groupFooterTemplateRef), column);
4779
- hasFooter = hasFooter || someLeafColumn(leaf => Boolean(leaf.footerTemplateRef), column);
4780
- if (!column.isLocked) {
4781
- unlockedWidth += column.width || 0;
4782
- }
4783
- if (column.isSpanColumn) {
4784
- column.childColumns.forEach(c => {
4785
- c.leafIndex = leafIndex++;
4786
- });
4787
- }
4788
- else {
4789
- column.leafIndex = leafIndex++;
4790
- }
4791
- }
4792
- containerColumns.push(column);
4793
- allColumns.push(column);
4794
- this.totalLevels = column.level > this.totalLevels ? column.level : this.totalLevels;
4795
- });
4796
- this.hasGroupHeaderColumn = hasGroupHeaderColumn;
4797
- this.hasGroupFooter = hasGroupFooter;
4798
- this.hasFooter = hasFooter;
4799
- this.leafColumnsToRender = leafColumnsToRender;
4800
- this.lockedColumnsToRender = lockedColumnsToRender;
4801
- this.nonLockedColumnsToRender = nonLockedColumnsToRender;
4802
- this.unlockedWidth = unlockedWidth;
4803
- const changes = reset([this.leafColumns, leafColumns], [this.lockedLeafColumns, lockedLeafColumns], [this.nonLockedLeafColumns, nonLockedLeafColumns], [this.lockedColumns, lockedColumns], [this.allColumns, allColumns], [this.nonLockedColumns, nonLockedColumns]) || currentLevels !== this.totalLevels;
4804
- if (changes) {
4805
- this.changes.emit();
4806
- }
4807
- return changes;
4808
- }
4809
- }
5057
+ type: Input
5058
+ }], rangeSelectionStartColumnIndex: [{
5059
+ type: Input
5060
+ }], selectionKey: [{
5061
+ type: Input,
5062
+ args: ["kendoGridSelectBy"]
5063
+ }], columnKey: [{
5064
+ type: Input
5065
+ }], selectedKeysChange: [{
5066
+ type: Output
5067
+ }] } });
4810
5068
 
4811
5069
  const forEachColumn = (list, callback) => {
4812
5070
  list.forEach((column) => {
@@ -5975,89 +6233,6 @@ class NavigationMetadata {
5975
6233
  }
5976
6234
  }
5977
6235
 
5978
- const NO_STICKY = { left: '0px', right: '0px' };
5979
- /**
5980
- * @hidden
5981
- */
5982
- class ColumnInfoService {
5983
- constructor() {
5984
- this.visibilityChange = new EventEmitter();
5985
- this.lockedChange = new EventEmitter();
5986
- this.stickyChange = new EventEmitter();
5987
- this.columnRangeChange = new EventEmitter();
5988
- this.columnsContainer = new ColumnsContainer(() => []);
5989
- }
5990
- get lockedLeafColumns() {
5991
- return this.columnsContainer.lockedLeafColumns;
5992
- }
5993
- get nonLockedLeafColumns() {
5994
- return this.columnsContainer.nonLockedLeafColumns;
5995
- }
5996
- get isLocked() {
5997
- return this.lockedLeafColumns.length > 0;
5998
- }
5999
- get totalLevels() {
6000
- return this.columnsContainer.totalLevels;
6001
- }
6002
- get hiddenColumns() {
6003
- if (!this.list) {
6004
- return [];
6005
- }
6006
- return this.list().filter(column => !column.isVisible);
6007
- }
6008
- get leafNamedColumns() {
6009
- const columns = expandColumns(this.list().filterSort(column => !column.isColumnGroup))
6010
- .filter(column => column.matchesMedia && column.displayTitle);
6011
- return orderBy(columns, [{ field: 'locked', dir: 'desc' }]);
6012
- }
6013
- get unlockedRootCount() {
6014
- return this.list().rootColumns().filter(column => !column.locked && column.isVisible).length;
6015
- }
6016
- stickyColumnsStyles(column) {
6017
- if (!this.stickyColumns) {
6018
- this.stickyColumns = this.list().rootColumns().filter(column => column.sticky && !column.locked && column.isVisible);
6019
- }
6020
- if (this.stickyColumns.length === 0) {
6021
- return NO_STICKY;
6022
- }
6023
- const result = this.stickyColumns.reduce((acc, curr) => {
6024
- if (curr.leafIndex < column.leafIndex) {
6025
- acc.left += curr.width;
6026
- }
6027
- else if (curr.leafIndex > column.leafIndex) {
6028
- acc.right += curr.width;
6029
- }
6030
- return acc;
6031
- }, { left: 0, right: 0 });
6032
- return {
6033
- left: `${result.left}px`,
6034
- right: `${result.right}px`
6035
- };
6036
- }
6037
- init(columns, list) {
6038
- this.columnsContainer = columns;
6039
- this.list = list;
6040
- this.stickyColumns = null;
6041
- }
6042
- changeVisibility(columns) {
6043
- this.stickyColumns = null;
6044
- this.visibilityChange.emit(columns);
6045
- }
6046
- changeLocked(columns) {
6047
- this.stickyColumns = null;
6048
- this.lockedChange.emit(columns);
6049
- }
6050
- changeStuck(columns) {
6051
- this.stickyColumns = null;
6052
- this.stickyChange.emit(columns);
6053
- }
6054
- }
6055
- ColumnInfoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnInfoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6056
- ColumnInfoService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnInfoService });
6057
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ColumnInfoService, decorators: [{
6058
- type: Injectable
6059
- }] });
6060
-
6061
6236
  /**
6062
6237
  * @hidden
6063
6238
  */
@@ -15865,8 +16040,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
15865
16040
  * ```
15866
16041
  */
15867
16042
  class SelectionCheckboxDirective {
15868
- constructor(selectionService, el, renderer, ngZone) {
16043
+ constructor(selectionService, aggregateService, el, renderer, ngZone) {
15869
16044
  this.selectionService = selectionService;
16045
+ this.aggregateService = aggregateService;
15870
16046
  this.el = el;
15871
16047
  this.renderer = renderer;
15872
16048
  this.ngZone = ngZone;
@@ -15893,8 +16069,9 @@ class SelectionCheckboxDirective {
15893
16069
  const ev = this.selectionService.toggleByIndex(this.itemIndex);
15894
16070
  ev.ctrlKey = true;
15895
16071
  ev.shiftKey = false;
15896
- this.selectionService.aggregateChanges.emit(ev);
15897
- ev.cellAggregates = this.selectionService.aggregates;
16072
+ if (this.selectionService.options.cellAggregates) {
16073
+ ev.cellAggregates = this.aggregateService.onSelectionChange(ev);
16074
+ }
15898
16075
  this.selectionService.changes.emit(ev);
15899
16076
  });
15900
16077
  }
@@ -15911,14 +16088,14 @@ class SelectionCheckboxDirective {
15911
16088
  this.renderer.setProperty(this.el.nativeElement, 'checked', this.selectionService.isSelected(this.itemIndex));
15912
16089
  }
15913
16090
  }
15914
- SelectionCheckboxDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionCheckboxDirective, deps: [{ token: SelectionService }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
16091
+ SelectionCheckboxDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionCheckboxDirective, deps: [{ token: SelectionService }, { token: CellSelectionAggregateService }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
15915
16092
  SelectionCheckboxDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: SelectionCheckboxDirective, selector: "[kendoGridSelectionCheckbox]", inputs: { itemIndex: ["kendoGridSelectionCheckbox", "itemIndex"] }, host: { properties: { "attr.type": "this.type" } }, ngImport: i0 });
15916
16093
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: SelectionCheckboxDirective, decorators: [{
15917
16094
  type: Directive,
15918
16095
  args: [{
15919
16096
  selector: '[kendoGridSelectionCheckbox]'
15920
16097
  }]
15921
- }], ctorParameters: function () { return [{ type: SelectionService }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { itemIndex: [{
16098
+ }], ctorParameters: function () { return [{ type: SelectionService }, { type: CellSelectionAggregateService }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { itemIndex: [{
15922
16099
  type: Input,
15923
16100
  args: ['kendoGridSelectionCheckbox']
15924
16101
  }], type: [{
@@ -18648,191 +18825,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
18648
18825
  type: Input
18649
18826
  }] } });
18650
18827
 
18651
- /* eslint-disable @typescript-eslint/no-explicit-any */
18652
- ;
18653
18828
  /**
18654
18829
  * @hidden
18655
18830
  */
18656
18831
  class StatusBarComponent {
18657
- constructor(ctx, selectionService, dataChanges, columnInfoService, cellSelectionService) {
18658
- this.ctx = ctx;
18659
- this.selectionService = selectionService;
18660
- this.dataChanges = dataChanges;
18661
- this.columnInfoService = columnInfoService;
18662
- this.cellSelectionService = cellSelectionService;
18832
+ constructor(aggregateService) {
18833
+ this.aggregateService = aggregateService;
18663
18834
  this.hostClasses = true;
18664
- this.groupedAggregates = { dates: [], numbers: [], booleans: [] };
18665
- this.aggregates = {
18666
- sum: null,
18667
- average: null,
18668
- min: null,
18669
- max: null,
18670
- count: null,
18671
- isTrue: null,
18672
- isFalse: null,
18673
- earliest: null,
18674
- latest: null
18675
- };
18676
- this.subs = new Subscription();
18677
- this.selectedItems = [];
18678
18835
  }
18679
18836
  get isStatusBarTemplate() {
18680
18837
  return this.statusBarTemplate ? '' : 'none';
18681
18838
  }
18682
18839
  ngOnInit() {
18683
- if (this.selectableSettings.cellAggregates) {
18684
- this.data = this.dataChanges.data ? this.dataChanges.data : this.ctx.grid.data;
18685
- this.selectService = this.isRowSelection ? this.selectionService : this.cellSelectionService;
18686
- if (this.isAggregateIncluded('count')) {
18687
- this.aggregates['count'] = 0;
18688
- }
18689
- const selectionDirective = this.ctx.grid.selectionDirective;
18690
- if (selectionDirective && !this.isRowSelection) {
18691
- this.selectedItems = selectionDirective.selectedKeys;
18692
- }
18693
- this.subs.add(this.selectService.aggregateChanges.subscribe((selectionArgs) => this.onSelectionChange(selectionArgs)));
18694
- }
18695
- }
18696
- ngOnDestroy() {
18697
- this.subs.unsubscribe();
18698
- }
18699
- onSelectionChange(selectionArgs) {
18700
- this.handleSelectedItems(selectionArgs);
18701
- this.nullifyAggregates();
18702
- this.handleAggregateChanges();
18703
- this.selectService.aggregates = this.aggregates;
18704
- }
18705
- handleAggregateChanges() {
18706
- const lockedColumns = this.columnInfoService.lockedLeafColumns.toArray();
18707
- const nonLockedColumns = this.columnInfoService.nonLockedLeafColumns.toArray();
18708
- const selectedItemsLength = this.selectedItems.length;
18709
- const columns = [...lockedColumns, ...nonLockedColumns];
18710
- const fields = columns.map(col => col.field);
18711
- if (this.isAggregateIncluded('count')) {
18712
- this.aggregates['count'] = this.isRowSelection ? (selectedItemsLength * columns.length) : selectedItemsLength;
18713
- }
18714
- this.selectedItems.forEach((item) => {
18715
- if (this.isRowSelection) {
18716
- fields.forEach((field) => {
18717
- const cellValue = item.dataItem;
18718
- if (cellValue && cellValue.hasOwnProperty(field)) {
18719
- const cellValue = item.dataItem[field];
18720
- this.groupAggregates(cellValue);
18721
- }
18722
- });
18723
- }
18724
- else if (this.selectService.options.cell) {
18725
- const itemKey = this.data[item.itemKey];
18726
- const field = fields[item.columnKey];
18727
- if (itemKey && itemKey.hasOwnProperty(field)) {
18728
- const cellValue = itemKey[fields[item.columnKey]];
18729
- this.groupAggregates(cellValue);
18730
- }
18731
- }
18732
- });
18733
- this.calculateAggregates();
18734
- }
18735
- groupAggregates(aggregate) {
18736
- if (typeof aggregate === 'number') {
18737
- this.groupedAggregates.numbers.push(aggregate);
18738
- }
18739
- else if (typeof aggregate === 'boolean') {
18740
- this.groupedAggregates.booleans.push(aggregate);
18741
- }
18742
- else if (aggregate instanceof Date) {
18743
- this.groupedAggregates.dates.push(aggregate);
18744
- }
18745
- }
18746
- calculateAggregates() {
18747
- if (this.groupedAggregates.numbers.length > 0) {
18748
- if (this.isAggregateIncluded('min')) {
18749
- this.aggregates['min'] = Math.min(...this.groupedAggregates.numbers);
18750
- }
18751
- if (this.isAggregateIncluded('max')) {
18752
- this.aggregates['max'] = Math.max(...this.groupedAggregates.numbers);
18753
- }
18754
- if (this.isAggregateIncluded('sum')) {
18755
- this.aggregates['sum'] = this.groupedAggregates.numbers.reduce((acc, curr) => acc += curr, 0);
18756
- }
18757
- if (this.isAggregateIncluded('average')) {
18758
- this.aggregates['average'] = this.aggregates['sum'] / this.groupedAggregates.numbers.length;
18759
- }
18760
- }
18761
- if (this.groupedAggregates.booleans.length > 0) {
18762
- if (this.isAggregateIncluded('isTrue')) {
18763
- const isTrueCount = this.groupedAggregates.booleans.filter(bool => bool).length;
18764
- this.aggregates['isTrue'] = isTrueCount > 0 ? isTrueCount : null;
18765
- }
18766
- if (this.isAggregateIncluded('isFalse')) {
18767
- const isFalseCount = this.groupedAggregates.booleans.length - this.aggregates['isTrue'];
18768
- this.aggregates['isFalse'] = isFalseCount > 0 ? isFalseCount : null;
18769
- }
18770
- }
18771
- if (this.groupedAggregates.dates.length > 0) {
18772
- if (this.isAggregateIncluded('earliest')) {
18773
- this.aggregates['earliest'] = new Date(Math.min(...this.groupedAggregates.dates));
18774
- }
18775
- if (this.isAggregateIncluded('latest')) {
18776
- this.aggregates['latest'] = new Date(Math.max(...this.groupedAggregates.dates));
18777
- }
18778
- }
18779
- }
18780
- handleSelectedItems(selectionArgs) {
18781
- const rowOrCellSelect = `${this.isRowSelection ? 'selectedRows' : 'selectedCells'}`;
18782
- const rowOrCellDeselect = `${this.isRowSelection ? 'deselectedRows' : 'deselectedCells'}`;
18783
- const selectedItems = selectionArgs[rowOrCellSelect];
18784
- const deselectedItems = selectionArgs[rowOrCellDeselect];
18785
- if (!this.isRowSelection) {
18786
- // Needed when we have column groups with cell selection, the deselected items are duplicated
18787
- deselectedItems.forEach((item, index) => {
18788
- if (index + 1 < deselectedItems.length) {
18789
- if (item.itemKey === deselectedItems[index + 1].itemKey
18790
- && item.columnKey === deselectedItems[index + 1].columnKey) {
18791
- deselectedItems.splice(index, 1);
18792
- }
18793
- }
18794
- });
18795
- }
18796
- if (selectedItems.length > 0) {
18797
- selectedItems.forEach((item) => {
18798
- this.selectedItems = [...this.selectedItems, item];
18799
- });
18800
- }
18801
- if (deselectedItems.length > 0) {
18802
- if (this.isRowSelection) {
18803
- deselectedItems.forEach((row) => {
18804
- this.selectedItems = this.selectedItems.filter((elem) => elem.dataItem !== row.dataItem);
18805
- });
18806
- }
18807
- else {
18808
- deselectedItems.forEach((cell) => {
18809
- const index = this.selectedItems.findIndex((elem) => elem.itemKey === cell.itemKey && elem.columnKey === cell.columnKey);
18810
- this.selectedItems.splice(index, 1);
18811
- });
18812
- }
18813
- }
18814
- }
18815
- isAggregateIncluded(aggregate) {
18816
- const { cellAggregates } = this.selectService.options;
18817
- if (typeof cellAggregates !== 'boolean') {
18818
- return cellAggregates.includes(aggregate);
18819
- }
18820
- return true;
18821
- }
18822
- nullifyAggregates() {
18823
- this.groupedAggregates = { dates: [], numbers: [], booleans: [] };
18824
- this.aggregates['count'] = null;
18825
- this.aggregates['sum'] = this.aggregates['average'] = null;
18826
- this.aggregates['max'] = this.aggregates['min'] = null;
18827
- this.aggregates['isFalse'] = this.aggregates['isTrue'] = null;
18828
- this.aggregates['earliest'] = this.aggregates['latest'] = null;
18840
+ this.aggregateService.init();
18829
18841
  }
18830
- get isRowSelection() {
18831
- return typeof this.selectableSettings === 'boolean' || !this.selectableSettings.cell;
18842
+ get aggregates() {
18843
+ return this.aggregateService.aggregates;
18832
18844
  }
18833
18845
  }
18834
- StatusBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: StatusBarComponent, deps: [{ token: ContextService }, { token: SelectionService }, { token: LocalDataChangesService }, { token: ColumnInfoService }, { token: CellSelectionService }], target: i0.ɵɵFactoryTarget.Component });
18835
- StatusBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: { selectableSettings: "selectableSettings", statusBarTemplate: "statusBarTemplate" }, host: { properties: { "class.k-selection-aggregates": "this.hostClasses", "class.k-grid-selection-aggregates": "this.hostClasses", "style.display": "this.isStatusBarTemplate" } }, ngImport: i0, template: `
18846
+ StatusBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: StatusBarComponent, deps: [{ token: CellSelectionAggregateService }], target: i0.ɵɵFactoryTarget.Component });
18847
+ StatusBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: { statusBarTemplate: "statusBarTemplate" }, host: { properties: { "class.k-selection-aggregates": "this.hostClasses", "class.k-grid-selection-aggregates": "this.hostClasses", "style.display": "this.isStatusBarTemplate" } }, ngImport: i0, template: `
18836
18848
  <ng-template
18837
18849
  *ngIf="statusBarTemplate"
18838
18850
  [ngTemplateOutlet]="statusBarTemplate?.templateRef"
@@ -18851,7 +18863,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
18851
18863
  </ng-template>
18852
18864
  `
18853
18865
  }]
18854
- }], ctorParameters: function () { return [{ type: ContextService }, { type: SelectionService }, { type: LocalDataChangesService }, { type: ColumnInfoService }, { type: CellSelectionService }]; }, propDecorators: { hostClasses: [{
18866
+ }], ctorParameters: function () { return [{ type: CellSelectionAggregateService }]; }, propDecorators: { hostClasses: [{
18855
18867
  type: HostBinding,
18856
18868
  args: ['class.k-selection-aggregates']
18857
18869
  }, {
@@ -18860,8 +18872,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
18860
18872
  }], isStatusBarTemplate: [{
18861
18873
  type: HostBinding,
18862
18874
  args: ['style.display']
18863
- }], selectableSettings: [{
18864
- type: Input
18865
18875
  }], statusBarTemplate: [{
18866
18876
  type: Input
18867
18877
  }] } });
@@ -20967,6 +20977,7 @@ GridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
20967
20977
  NavigationService,
20968
20978
  FocusRoot,
20969
20979
  IdService,
20980
+ CellSelectionAggregateService,
20970
20981
  ScrollRequestService,
20971
20982
  SortService,
20972
20983
  ContextService,
@@ -21503,7 +21514,6 @@ GridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
21503
21514
  </div>
21504
21515
  <kendo-grid-status-bar
21505
21516
  *ngIf="showStatusBar"
21506
- [selectableSettings]="selectable"
21507
21517
  [statusBarTemplate]="statusBarTemplate">
21508
21518
  </kendo-grid-status-bar>
21509
21519
  <kendo-pager
@@ -21537,7 +21547,7 @@ GridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
21537
21547
  </kendo-icon-wrapper>
21538
21548
  {{hintText}}
21539
21549
  </ng-template>
21540
- `, isInline: true, components: [{ type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: ["position", "size", "navigable"] }, { type: PagerComponent, selector: "kendo-pager", inputs: ["total", "skip", "pageSize", "options", "size", "template"], outputs: ["pageChange"] }, { type: GroupPanelComponent, selector: "kendo-grid-group-panel", inputs: ["text", "navigable", "groups"], outputs: ["change"] }, { type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { type: HeaderComponent, selector: "[kendoGridHeader]", inputs: ["totalColumnLevels", "columns", "groups", "detailTemplate", "scrollable", "filterable", "sort", "filter", "sortable", "groupable", "lockedColumnsCount", "resizable", "reorderable", "columnMenu", "columnMenuTemplate", "totalColumnsCount", "tabIndex", "size"] }, { type: ListComponent, selector: "kendo-grid-list", inputs: ["data", "groups", "total", "rowHeight", "stickyRowHeight", "detailRowHeight", "take", "skip", "columns", "detailTemplate", "noRecordsTemplate", "selectable", "groupable", "filterable", "rowClass", "rowSticky", "loading", "trackBy", "virtualColumns", "isVirtual", "cellLoadingTemplate", "loadingTemplate", "sort", "size"], outputs: ["contentScroll", "pageChange", "scrollBottom"] }, { type: FooterComponent, selector: "[kendoGridFooter]", inputs: ["columns", "groups", "detailTemplate", "scrollable", "lockedColumnsCount", "logicalRowIndex"] }, { type: TableBodyComponent, selector: "[kendoGridTableBody]", inputs: ["columns", "allColumns", "groups", "detailTemplate", "noRecordsTemplate", "data", "skip", "selectable", "filterable", "noRecordsText", "isLocked", "isLoading", "isVirtual", "cellLoadingTemplate", "skipGroupDecoration", "showGroupFooters", "lockedColumnsCount", "totalColumnsCount", "virtualColumns", "trackBy", "rowSticky", "rowClass"] }, { type: LoadingComponent, selector: "[kendoGridLoading]", inputs: ["loadingTemplate"] }, { type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: ["selectableSettings", "statusBarTemplate"] }, { type: i3.IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }], directives: [{ type: LocalizedMessagesDirective, selector: "[kendoGridLocalizedMessages]" }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TableDirective, selector: "table", inputs: ["locked", "virtualColumns"] }, { type: GridTableDirective, selector: "[kendoGridTable]", inputs: ["size"] }, { type: ResizableContainerDirective, selector: "[kendoGridResizableContainer]", inputs: ["lockedWidth", "kendoGridResizableContainer"] }, { type: i41.DragTargetContainerDirective, selector: "[kendoDragTargetContainer]", inputs: ["hint", "dragTargetFilter", "dragHandle", "dragDelay", "threshold", "dragTargetId", "dragData", "dragDisabled", "mode"], outputs: ["onDragReady", "onPress", "onDragStart", "onDrag", "onRelease", "onDragEnd"], exportAs: ["kendoDragTargetContainer"] }, { type: i41.DropTargetContainerDirective, selector: "[kendoDropTargetContainer]", inputs: ["dropTargetFilter", "dropDisabled"], outputs: ["onDragEnter", "onDragOver", "onDragLeave", "onDrop"], exportAs: ["kendoDropTargetContainer"] }, { type: i1$1.DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]" }], encapsulation: i0.ViewEncapsulation.None });
21550
+ `, isInline: true, components: [{ type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: ["position", "size", "navigable"] }, { type: PagerComponent, selector: "kendo-pager", inputs: ["total", "skip", "pageSize", "options", "size", "template"], outputs: ["pageChange"] }, { type: GroupPanelComponent, selector: "kendo-grid-group-panel", inputs: ["text", "navigable", "groups"], outputs: ["change"] }, { type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { type: HeaderComponent, selector: "[kendoGridHeader]", inputs: ["totalColumnLevels", "columns", "groups", "detailTemplate", "scrollable", "filterable", "sort", "filter", "sortable", "groupable", "lockedColumnsCount", "resizable", "reorderable", "columnMenu", "columnMenuTemplate", "totalColumnsCount", "tabIndex", "size"] }, { type: ListComponent, selector: "kendo-grid-list", inputs: ["data", "groups", "total", "rowHeight", "stickyRowHeight", "detailRowHeight", "take", "skip", "columns", "detailTemplate", "noRecordsTemplate", "selectable", "groupable", "filterable", "rowClass", "rowSticky", "loading", "trackBy", "virtualColumns", "isVirtual", "cellLoadingTemplate", "loadingTemplate", "sort", "size"], outputs: ["contentScroll", "pageChange", "scrollBottom"] }, { type: FooterComponent, selector: "[kendoGridFooter]", inputs: ["columns", "groups", "detailTemplate", "scrollable", "lockedColumnsCount", "logicalRowIndex"] }, { type: TableBodyComponent, selector: "[kendoGridTableBody]", inputs: ["columns", "allColumns", "groups", "detailTemplate", "noRecordsTemplate", "data", "skip", "selectable", "filterable", "noRecordsText", "isLocked", "isLoading", "isVirtual", "cellLoadingTemplate", "skipGroupDecoration", "showGroupFooters", "lockedColumnsCount", "totalColumnsCount", "virtualColumns", "trackBy", "rowSticky", "rowClass"] }, { type: LoadingComponent, selector: "[kendoGridLoading]", inputs: ["loadingTemplate"] }, { type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: ["statusBarTemplate"] }, { type: i3.IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }], directives: [{ type: LocalizedMessagesDirective, selector: "[kendoGridLocalizedMessages]" }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TableDirective, selector: "table", inputs: ["locked", "virtualColumns"] }, { type: GridTableDirective, selector: "[kendoGridTable]", inputs: ["size"] }, { type: ResizableContainerDirective, selector: "[kendoGridResizableContainer]", inputs: ["lockedWidth", "kendoGridResizableContainer"] }, { type: i41.DragTargetContainerDirective, selector: "[kendoDragTargetContainer]", inputs: ["hint", "dragTargetFilter", "dragHandle", "dragDelay", "threshold", "dragTargetId", "dragData", "dragDisabled", "mode"], outputs: ["onDragReady", "onPress", "onDragStart", "onDrag", "onRelease", "onDragEnd"], exportAs: ["kendoDragTargetContainer"] }, { type: i41.DropTargetContainerDirective, selector: "[kendoDropTargetContainer]", inputs: ["dropTargetFilter", "dropDisabled"], outputs: ["onDragEnter", "onDragOver", "onDragLeave", "onDrop"], exportAs: ["kendoDropTargetContainer"] }, { type: i1$1.DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]" }], encapsulation: i0.ViewEncapsulation.None });
21541
21551
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridComponent, decorators: [{
21542
21552
  type: Component,
21543
21553
  args: [{
@@ -21581,6 +21591,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
21581
21591
  NavigationService,
21582
21592
  FocusRoot,
21583
21593
  IdService,
21594
+ CellSelectionAggregateService,
21584
21595
  ScrollRequestService,
21585
21596
  SortService,
21586
21597
  ContextService,
@@ -22119,7 +22130,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
22119
22130
  </div>
22120
22131
  <kendo-grid-status-bar
22121
22132
  *ngIf="showStatusBar"
22122
- [selectableSettings]="selectable"
22123
22133
  [statusBarTemplate]="statusBarTemplate">
22124
22134
  </kendo-grid-status-bar>
22125
22135
  <kendo-pager