@progress/kendo-angular-grid 20.1.0-develop.9 → 20.1.1-develop.1

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.
Files changed (33) hide show
  1. package/columns/column.component.d.ts +8 -1
  2. package/databinding.directive.d.ts +1 -1
  3. package/esm2022/columns/column.component.mjs +9 -1
  4. package/esm2022/common/clipboard.directive.mjs +3 -0
  5. package/esm2022/databinding.directive.mjs +1 -1
  6. package/esm2022/filtering/menu/filter-menu-container.component.mjs +120 -31
  7. package/esm2022/filtering/menu/filter-menu.component.mjs +4 -6
  8. package/esm2022/filtering/multicheckbox-filter.component.mjs +313 -0
  9. package/esm2022/grid.component.mjs +25 -12
  10. package/esm2022/index.mjs +1 -0
  11. package/esm2022/localization/messages.mjs +28 -1
  12. package/esm2022/package-metadata.mjs +2 -2
  13. package/esm2022/pdf/pdf.component.mjs +8 -3
  14. package/esm2022/rendering/cell.component.mjs +2 -2
  15. package/esm2022/rendering/common/field-accessor.pipe.mjs +1 -1
  16. package/esm2022/rendering/common/format.pipe.mjs +37 -0
  17. package/esm2022/rendering/header/header.component.mjs +1 -1
  18. package/esm2022/rendering/list.component.mjs +2 -2
  19. package/esm2022/rendering/table-body.component.mjs +4 -2
  20. package/esm2022/rendering/toolbar/tools/group-toolbar-tool.component.mjs +4 -3
  21. package/esm2022/row-reordering/row-reorder.service.mjs +3 -1
  22. package/esm2022/scrolling/scroller.service.mjs +0 -3
  23. package/fesm2022/progress-kendo-angular-grid.mjs +1969 -1502
  24. package/filtering/filterable.d.ts +23 -0
  25. package/filtering/menu/filter-menu-container.component.d.ts +5 -1
  26. package/filtering/menu/filter-menu.component.d.ts +3 -4
  27. package/filtering/multicheckbox-filter.component.d.ts +50 -0
  28. package/grid.component.d.ts +4 -6
  29. package/index.d.ts +1 -0
  30. package/localization/messages.d.ts +22 -1
  31. package/package.json +21 -21
  32. package/rendering/common/format.pipe.d.ts +17 -0
  33. package/schematics/ngAdd/index.js +4 -4
@@ -6,11 +6,11 @@ import * as i0 from '@angular/core';
6
6
  import { EventEmitter, Injectable, SecurityContext, InjectionToken, Optional, Inject, Directive, SkipSelf, Input, isDevMode, QueryList, Component, ContentChildren, ContentChild, forwardRef, Host, Output, HostBinding, Pipe, TemplateRef, ChangeDetectionStrategy, ViewChildren, ViewChild, Self, NgZone, HostListener, ElementRef, ViewContainerRef, ViewEncapsulation, inject, Injector, NgModule } from '@angular/core';
7
7
  import { merge, of, Subject, zip as zip$1, from, Subscription, interval, fromEvent, Observable, BehaviorSubject } from 'rxjs';
8
8
  import * as i1$3 from '@progress/kendo-angular-common';
9
- import { isDocumentAvailable, Keys, hasClasses as hasClasses$1, isPresent as isPresent$1, normalizeNumpadKeys, anyChanged, TemplateContextDirective, DraggableDirective, EventsOutsideAngularDirective, replaceMessagePlaceholder, isChanged as isChanged$1, KendoInput, guid, PrefixTemplateDirective, closest as closest$1, hasObservers, ResizeSensorComponent, isFirefox, firefoxMaxHeight, closestInScope as closestInScope$1, isFocusable as isFocusable$1, PreventableEvent as PreventableEvent$1, getLicenseMessage, shouldShowValidationUI, WatermarkOverlayComponent, ResizeBatchService } from '@progress/kendo-angular-common';
9
+ import { isDocumentAvailable, Keys, hasClasses as hasClasses$1, isPresent as isPresent$1, normalizeNumpadKeys, anyChanged, TemplateContextDirective, DraggableDirective, EventsOutsideAngularDirective, replaceMessagePlaceholder, isChanged as isChanged$1, KendoInput, guid, areObjectsEqual, PrefixTemplateDirective, closest as closest$1, hasObservers, ResizeSensorComponent, isFirefox, firefoxMaxHeight, closestInScope as closestInScope$1, isFocusable as isFocusable$1, getLicenseMessage, shouldShowValidationUI, WatermarkOverlayComponent, PreventableEvent as PreventableEvent$1, ResizeBatchService } from '@progress/kendo-angular-common';
10
10
  import * as i1 from '@angular/platform-browser';
11
11
  import * as i1$1 from '@progress/kendo-angular-icons';
12
12
  import { IconWrapperComponent, IconsService, KENDO_ICONS } from '@progress/kendo-angular-icons';
13
- import { plusIcon, cancelIcon, lockIcon, unlockIcon, caretAltDownIcon, caretAltRightIcon, caretAltLeftIcon, arrowLeftIcon, arrowRightIcon, sortDescSmallIcon, sortAscSmallIcon, filterClearIcon, filterIcon, searchIcon, checkIcon, arrowRotateCcwIcon, columnsIcon, pencilIcon, saveIcon, trashIcon, fileExcelIcon, filePdfIcon, sparklesIcon, chevronUpIcon, chevronDownIcon, chevronRightIcon, displayInlineFlexIcon, maxWidthIcon, stickIcon, unstickIcon, setColumnPositionIcon, slidersIcon, moreVerticalIcon, reorderIcon, minusIcon, insertMiddleIcon, xIcon, xCircleIcon, plusCircleIcon, chevronLeftIcon, tableWizardIcon, undoIcon, redoIcon, arrowsSwapIcon, groupIcon } from '@progress/kendo-svg-icons';
13
+ import { plusIcon, cancelIcon, lockIcon, unlockIcon, caretAltDownIcon, caretAltRightIcon, caretAltLeftIcon, arrowLeftIcon, arrowRightIcon, sortDescSmallIcon, sortAscSmallIcon, filterClearIcon, filterIcon, searchIcon, checkIcon, arrowRotateCcwIcon, columnsIcon, pencilIcon, saveIcon, trashIcon, fileExcelIcon, filePdfIcon, sparklesIcon, chevronUpIcon, chevronDownIcon, chevronRightIcon, displayInlineFlexIcon, maxWidthIcon, stickIcon, unstickIcon, setColumnPositionIcon, slidersIcon, moreVerticalIcon, reorderIcon, minusIcon, insertMiddleIcon, xIcon, xCircleIcon, plusCircleIcon, chevronLeftIcon, undoIcon, redoIcon, arrowsSwapIcon, groupIcon, tableWizardIcon } from '@progress/kendo-svg-icons';
14
14
  import { switchMap, take, map, filter, takeUntil, switchMapTo, delay, tap, throttleTime, debounceTime, distinctUntilChanged, skip, auditTime, bufferCount, flatMap } from 'rxjs/operators';
15
15
  import * as i1$2 from '@progress/kendo-angular-l10n';
16
16
  import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
@@ -32,7 +32,7 @@ import { NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule, FormControl, FormG
32
32
  import * as i2$1 from '@progress/kendo-angular-utils';
33
33
  import { DragTargetContainerDirective, DropTargetContainerDirective } from '@progress/kendo-angular-utils';
34
34
  import * as i4 from '@progress/kendo-angular-inputs';
35
- import { TextBoxComponent, NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, RadioButtonComponent, CheckBoxComponent, KENDO_FORMFIELD, KENDO_TEXTBOX, KENDO_NUMERICTEXTBOX, KENDO_CHECKBOX } from '@progress/kendo-angular-inputs';
35
+ import { TextBoxComponent, NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, RadioButtonComponent, CheckBoxComponent, TextBoxPrefixTemplateDirective, KENDO_FORMFIELD, KENDO_TEXTBOX, KENDO_NUMERICTEXTBOX, KENDO_CHECKBOX } from '@progress/kendo-angular-inputs';
36
36
  import * as i5 from '@progress/kendo-angular-dateinputs';
37
37
  import { DatePickerComponent, DatePickerCustomMessagesComponent, KENDO_DATEPICKER, CalendarDOMService, CenturyViewService, DecadeViewService, MonthViewService, YearViewService, NavigationService as NavigationService$1 } from '@progress/kendo-angular-dateinputs';
38
38
  import * as i54 from '@progress/kendo-angular-toolbar';
@@ -2869,6 +2869,12 @@ class ColumnComponent extends ColumnBase {
2869
2869
  * @default 'text'
2870
2870
  */
2871
2871
  filter = 'text';
2872
+ /**
2873
+ * Specifies the filter type for the filter menu UI.
2874
+ *
2875
+ * @default 'default'
2876
+ */
2877
+ filterVariant = 'default';
2872
2878
  /**
2873
2879
  * Shows or hides the filter UI for this column. [See example](slug:filtering_grid).
2874
2880
  *
@@ -2916,7 +2922,7 @@ class ColumnComponent extends ColumnBase {
2916
2922
  return this.title === undefined ? this.field : this.title;
2917
2923
  }
2918
2924
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
2919
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColumnComponent, isStandalone: true, selector: "kendo-grid-column", inputs: { field: "field", format: "format", sortable: "sortable", groupable: "groupable", editor: "editor", filter: "filter", filterable: "filterable", editable: "editable" }, providers: [
2925
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColumnComponent, isStandalone: true, selector: "kendo-grid-column", inputs: { field: "field", format: "format", sortable: "sortable", groupable: "groupable", editor: "editor", filter: "filter", filterVariant: "filterVariant", filterable: "filterable", editable: "editable" }, providers: [
2920
2926
  {
2921
2927
  provide: ColumnBase,
2922
2928
  useExisting: forwardRef(() => ColumnComponent)
@@ -2956,6 +2962,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
2956
2962
  type: Input
2957
2963
  }], filter: [{
2958
2964
  type: Input
2965
+ }], filterVariant: [{
2966
+ type: Input
2959
2967
  }], filterable: [{
2960
2968
  type: Input
2961
2969
  }], editable: [{
@@ -5485,7 +5493,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
5485
5493
  args: ['attr.aria-owns']
5486
5494
  }] } });
5487
5495
 
5488
- const FORMAT_REGEX = /\{\d+:?/;
5496
+ const FORMAT_REGEX$1 = /\{\d+:?/;
5489
5497
  /**
5490
5498
  * @hidden
5491
5499
  */
@@ -5506,7 +5514,7 @@ class FieldAccessorPipe {
5506
5514
  }
5507
5515
  formatValue(format, value) {
5508
5516
  const intl = this.intlService;
5509
- if (isString(format) && format.match(FORMAT_REGEX)) {
5517
+ if (isString(format) && FORMAT_REGEX$1.exec(format)) {
5510
5518
  return intl.format(format, value);
5511
5519
  }
5512
5520
  return intl.toString(value, format);
@@ -10677,6 +10685,344 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
10677
10685
  type: Input
10678
10686
  }] } });
10679
10687
 
10688
+ /**
10689
+ * @hidden
10690
+ */
10691
+ class LocalDataChangesService {
10692
+ changes = new EventEmitter();
10693
+ data;
10694
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalDataChangesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
10695
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalDataChangesService });
10696
+ }
10697
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalDataChangesService, decorators: [{
10698
+ type: Injectable
10699
+ }] });
10700
+
10701
+ const FORMAT_REGEX = /\{\d+:?/;
10702
+ /**
10703
+ * @hidden
10704
+ */
10705
+ class FormatPipe {
10706
+ intlService;
10707
+ constructor(intlService) {
10708
+ this.intlService = intlService;
10709
+ }
10710
+ transform(value, format) {
10711
+ const intl = this.intlService;
10712
+ if (isString(format) && FORMAT_REGEX.exec(format)) {
10713
+ return intl.format(format, value);
10714
+ }
10715
+ return intl.toString(value, format);
10716
+ }
10717
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormatPipe, deps: [{ token: i1$4.IntlService }], target: i0.ɵɵFactoryTarget.Pipe });
10718
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FormatPipe, isStandalone: true, name: "format", pure: false });
10719
+ }
10720
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormatPipe, decorators: [{
10721
+ type: Pipe,
10722
+ args: [{
10723
+ // eslint-disable-next-line @angular-eslint/pipe-prefix
10724
+ name: 'format',
10725
+ pure: false,
10726
+ standalone: true
10727
+ }]
10728
+ }], ctorParameters: function () { return [{ type: i1$4.IntlService }]; } });
10729
+
10730
+ /**
10731
+ * @hidden
10732
+ */
10733
+ class MultiCheckboxFilterComponent {
10734
+ ctx;
10735
+ dataChangesService;
10736
+ column;
10737
+ filterChange = new EventEmitter();
10738
+ filterInput;
10739
+ constructor(ctx, dataChangesService) {
10740
+ this.ctx = ctx;
10741
+ this.dataChangesService = dataChangesService;
10742
+ }
10743
+ listData = [];
10744
+ searchIcon = searchIcon;
10745
+ showSelectAll = true;
10746
+ currentlySelected = new Set();
10747
+ isSearched = false;
10748
+ currentFilter;
10749
+ filterChangeSub;
10750
+ baseListData = [];
10751
+ ngOnInit() {
10752
+ this.initializeData();
10753
+ this.currentFilter = this.ctx.grid?.filter ?? this.emptyFilter();
10754
+ this.updateSelectionFromFilter();
10755
+ if (this.currentFilter) {
10756
+ this.filterChange.emit(this.currentFilter);
10757
+ }
10758
+ }
10759
+ ngAfterViewInit() {
10760
+ if (this.filterInput) {
10761
+ this.filterChangeSub = this.filterInput.change.subscribe(this.onSearch.bind(this));
10762
+ }
10763
+ }
10764
+ ngOnDestroy() {
10765
+ if (this.filterChangeSub) {
10766
+ this.filterChangeSub.unsubscribe();
10767
+ this.filterChangeSub = null;
10768
+ }
10769
+ }
10770
+ isItemSelected(item) {
10771
+ return this.currentlySelected.has(item);
10772
+ }
10773
+ onSearch(value) {
10774
+ const searchValue = value;
10775
+ this.isSearched = searchValue.length > 0;
10776
+ this.showSelectAll = !this.isSearched;
10777
+ if (!searchValue) {
10778
+ this.listData = [...this.baseListData];
10779
+ }
10780
+ else {
10781
+ this.listData = filterBy(this.baseListData, { operator: 'contains', value: searchValue });
10782
+ }
10783
+ }
10784
+ handleCheckBoxChange(checkedState, value, selectAllChecked) {
10785
+ const field = this.column?.field;
10786
+ if (!field) {
10787
+ return;
10788
+ }
10789
+ if (!this.currentFilter) {
10790
+ this.currentFilter = this.emptyFilter();
10791
+ }
10792
+ const newFilter = this.currentFilter;
10793
+ const filters = [...newFilter.filters];
10794
+ const compositeIndex = this.getCompositeFilterIndex(newFilter);
10795
+ let fieldFilters = [];
10796
+ if (compositeIndex !== -1 && filters[compositeIndex].filters && !selectAllChecked) {
10797
+ fieldFilters = [...filters[compositeIndex].filters];
10798
+ }
10799
+ if (checkedState && selectAllChecked) {
10800
+ this.listData.forEach(item => {
10801
+ if (!fieldFilters.some(f => f.value === item)) {
10802
+ fieldFilters.push({ field, operator: 'eq', value: item });
10803
+ }
10804
+ });
10805
+ }
10806
+ else if (!checkedState && selectAllChecked) {
10807
+ fieldFilters = [];
10808
+ }
10809
+ else if (checkedState) {
10810
+ if (!fieldFilters.some(f => f.value === value)) {
10811
+ fieldFilters.push({ field, operator: 'eq', value });
10812
+ }
10813
+ }
10814
+ else {
10815
+ const idx = fieldFilters.findIndex(f => f.value === value);
10816
+ if (idx > -1) {
10817
+ fieldFilters.splice(idx, 1);
10818
+ }
10819
+ }
10820
+ if (fieldFilters.length === 0) {
10821
+ if (compositeIndex !== -1) {
10822
+ filters.splice(compositeIndex, 1);
10823
+ }
10824
+ }
10825
+ else {
10826
+ const block = { logic: 'or', filters: fieldFilters };
10827
+ if (compositeIndex !== -1) {
10828
+ filters[compositeIndex] = block;
10829
+ }
10830
+ else {
10831
+ filters.push(block);
10832
+ }
10833
+ }
10834
+ newFilter.logic = 'and';
10835
+ newFilter.filters = filters;
10836
+ this.currentFilter = newFilter;
10837
+ this.updateSelectionFromFilter();
10838
+ this.filterChange.emit(this.currentFilter);
10839
+ }
10840
+ get filteredGridData() {
10841
+ return filterBy(this.gridData, this.ctx.grid?.filter);
10842
+ }
10843
+ get selectAllChecked() {
10844
+ if (!this.listData || this.listData.length === 0) {
10845
+ return false;
10846
+ }
10847
+ const total = this.listData.length;
10848
+ const selectedInView = this.listData.filter(i => this.currentlySelected.has(i)).length;
10849
+ if (selectedInView === 0) {
10850
+ return false;
10851
+ }
10852
+ if (selectedInView === total) {
10853
+ return true;
10854
+ }
10855
+ return 'indeterminate';
10856
+ }
10857
+ get gridData() {
10858
+ let data = [];
10859
+ const isLocalData = isPresent$1(this.ctx?.dataBindingDirective);
10860
+ if (isPresent$1(this.normalizedFilterVariant.data)) {
10861
+ data = this.normalizedFilterVariant.data;
10862
+ }
10863
+ else if (isLocalData) {
10864
+ data = this.dataChangesService.data;
10865
+ }
10866
+ else {
10867
+ data = this.ctx.grid?.flatData;
10868
+ }
10869
+ return data || [];
10870
+ }
10871
+ get normalizedFilterVariant() {
10872
+ const defaultMultiCheckboxSettings = { variant: 'multiCheckbox', search: true };
10873
+ if (typeof this.column?.filterVariant === 'string') {
10874
+ return {
10875
+ variant: this.column.filterVariant,
10876
+ search: true
10877
+ };
10878
+ }
10879
+ return Object.assign(defaultMultiCheckboxSettings, this.column?.filterVariant);
10880
+ }
10881
+ get selectedItemsMessage() {
10882
+ const localizationMsg = this.messageFor('multiCheckboxFilterSelectedItemsCount') || '';
10883
+ return replaceMessagePlaceholder(localizationMsg, 'selectedItemsCount', this.currentlySelected.size.toString());
10884
+ }
10885
+ messageFor(key) {
10886
+ return this.ctx.localization.get(key);
10887
+ }
10888
+ getUniqueDateValues(data) {
10889
+ return data.reduce((acc, current) => {
10890
+ const value = current[this.column.field];
10891
+ if (value instanceof Date && acc.findIndex(d => d.getTime() === value.getTime()) === -1) {
10892
+ acc.push(value);
10893
+ }
10894
+ return acc;
10895
+ }, []);
10896
+ }
10897
+ initializeData() {
10898
+ if (!this.column) {
10899
+ this.baseListData = [];
10900
+ return;
10901
+ }
10902
+ const isDate = this.column.filter === 'date';
10903
+ if (isDate) {
10904
+ const dates = this.getUniqueDateValues(this.gridData);
10905
+ const sortedDates = [...dates].sort((a, b) => a - b);
10906
+ this.baseListData = sortedDates;
10907
+ }
10908
+ else {
10909
+ const field = this.column.field;
10910
+ const mapped = this.gridData.map(item => item?.[field]);
10911
+ this.baseListData = [...new Set(mapped)].sort((a, b) => {
10912
+ if (a > b) {
10913
+ return 1;
10914
+ }
10915
+ if (a < b) {
10916
+ return -1;
10917
+ }
10918
+ return 0;
10919
+ });
10920
+ }
10921
+ this.listData = [...this.baseListData];
10922
+ }
10923
+ emptyFilter() { return { filters: [], logic: 'and' }; }
10924
+ getCompositeFilterIndex(filter) {
10925
+ const field = this.column?.field;
10926
+ return filter.filters.findIndex((f) => f.filters?.length && f.filters[0].field === field);
10927
+ }
10928
+ updateSelectionFromFilter() {
10929
+ this.currentlySelected.clear();
10930
+ if (!this.currentFilter || !this.column?.field) {
10931
+ return;
10932
+ }
10933
+ const idx = this.getCompositeFilterIndex(this.currentFilter);
10934
+ if (idx === -1) {
10935
+ return;
10936
+ }
10937
+ const block = this.currentFilter.filters[idx];
10938
+ if (block && Array.isArray(block.filters)) {
10939
+ block.filters.forEach((f) => {
10940
+ if (f.field === this.column.field && f.operator === 'eq') {
10941
+ this.currentlySelected.add(f.value);
10942
+ }
10943
+ });
10944
+ }
10945
+ }
10946
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MultiCheckboxFilterComponent, deps: [{ token: ContextService }, { token: LocalDataChangesService }], target: i0.ɵɵFactoryTarget.Component });
10947
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: MultiCheckboxFilterComponent, isStandalone: true, selector: "kendo-grid-multicheckbox-filter", inputs: { column: "column" }, outputs: { filterChange: "filterChange" }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: FilterInputDirective, descendants: true }], ngImport: i0, template: `
10948
+ <kendo-textbox *ngIf="normalizedFilterVariant.search"
10949
+ kendoFilterInput
10950
+ class="k-searchbox"
10951
+ [placeholder]="messageFor('multiCheckboxFilterSearchPlaceholder')">
10952
+ <ng-template kendoTextBoxPrefixTemplate>
10953
+ <kendo-icon-wrapper innerCssClass="k-input-icon" name="search" [svgIcon]="searchIcon"></kendo-icon-wrapper>
10954
+ </ng-template>
10955
+ </kendo-textbox>
10956
+ <ul class="k-reset k-multicheck-wrap">
10957
+ <li class="k-item k-check-all-wrap" *ngIf="showSelectAll">
10958
+ <label class="k-label k-checkbox-label" role="option">
10959
+ <kendo-checkbox
10960
+ [checkedState]="selectAllChecked"
10961
+ (checkedStateChange)="handleCheckBoxChange($event, null, true)">
10962
+ </kendo-checkbox>
10963
+ <span>{{ messageFor('multiCheckboxFilterSelectAllLabel') }}</span>
10964
+ </label>
10965
+ </li>
10966
+ <li class="k-item" *ngFor="let item of listData">
10967
+ <label class="k-label k-checkbox-label" role="option">
10968
+ <kendo-checkbox
10969
+ [checkedState]="isItemSelected(item)"
10970
+ (checkedStateChange)="handleCheckBoxChange($event, item)">
10971
+ </kendo-checkbox>
10972
+ <span>{{ item | format: column.format }}</span>
10973
+ </label>
10974
+ </li>
10975
+ </ul>
10976
+ <div class="k-filter-selected-items">{{selectedItemsMessage}}</div>
10977
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CheckBoxComponent, selector: "kendo-checkbox", inputs: ["checkedState", "rounded"], outputs: ["checkedStateChange"], exportAs: ["kendoCheckBox"] }, { kind: "component", type: TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: TextBoxPrefixTemplateDirective, selector: "[kendoTextBoxPrefixTemplate]", inputs: ["showSeparator"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "pipe", type: FormatPipe, name: "format" }, { kind: "directive", type: FilterInputDirective, selector: "[kendoFilterInput]", inputs: ["filterDelay", "columnLabel", "value"] }] });
10978
+ }
10979
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MultiCheckboxFilterComponent, decorators: [{
10980
+ type: Component,
10981
+ args: [{
10982
+ selector: 'kendo-grid-multicheckbox-filter',
10983
+ template: `
10984
+ <kendo-textbox *ngIf="normalizedFilterVariant.search"
10985
+ kendoFilterInput
10986
+ class="k-searchbox"
10987
+ [placeholder]="messageFor('multiCheckboxFilterSearchPlaceholder')">
10988
+ <ng-template kendoTextBoxPrefixTemplate>
10989
+ <kendo-icon-wrapper innerCssClass="k-input-icon" name="search" [svgIcon]="searchIcon"></kendo-icon-wrapper>
10990
+ </ng-template>
10991
+ </kendo-textbox>
10992
+ <ul class="k-reset k-multicheck-wrap">
10993
+ <li class="k-item k-check-all-wrap" *ngIf="showSelectAll">
10994
+ <label class="k-label k-checkbox-label" role="option">
10995
+ <kendo-checkbox
10996
+ [checkedState]="selectAllChecked"
10997
+ (checkedStateChange)="handleCheckBoxChange($event, null, true)">
10998
+ </kendo-checkbox>
10999
+ <span>{{ messageFor('multiCheckboxFilterSelectAllLabel') }}</span>
11000
+ </label>
11001
+ </li>
11002
+ <li class="k-item" *ngFor="let item of listData">
11003
+ <label class="k-label k-checkbox-label" role="option">
11004
+ <kendo-checkbox
11005
+ [checkedState]="isItemSelected(item)"
11006
+ (checkedStateChange)="handleCheckBoxChange($event, item)">
11007
+ </kendo-checkbox>
11008
+ <span>{{ item | format: column.format }}</span>
11009
+ </label>
11010
+ </li>
11011
+ </ul>
11012
+ <div class="k-filter-selected-items">{{selectedItemsMessage}}</div>
11013
+ `,
11014
+ standalone: true,
11015
+ imports: [NgFor, NgIf, CheckBoxComponent, TextBoxComponent, TextBoxPrefixTemplateDirective, IconWrapperComponent, FormatPipe, FilterInputDirective]
11016
+ }]
11017
+ }], ctorParameters: function () { return [{ type: ContextService }, { type: LocalDataChangesService }]; }, propDecorators: { column: [{
11018
+ type: Input
11019
+ }], filterChange: [{
11020
+ type: Output
11021
+ }], filterInput: [{
11022
+ type: ViewChild,
11023
+ args: [FilterInputDirective]
11024
+ }] } });
11025
+
10680
11026
  const isNoValueOperator = operator => (operator === "isnull"
10681
11027
  || operator === "isnotnull"
10682
11028
  || operator === "isempty"
@@ -10761,11 +11107,11 @@ class FilterMenuContainerComponent {
10761
11107
  return this._childFilter;
10762
11108
  }
10763
11109
  resetButton;
10764
- filterButton;
10765
11110
  _childFilter;
10766
11111
  subscription;
10767
11112
  _templateContext = {};
10768
11113
  _filter;
11114
+ checkboxFilter;
10769
11115
  constructor(parentService, childService, ctx, cd, menuTabbingService, adaptiveGridService) {
10770
11116
  this.parentService = parentService;
10771
11117
  this.childService = childService;
@@ -10791,7 +11137,7 @@ class FilterMenuContainerComponent {
10791
11137
  this.menuTabbingService.lastFocusable = undefined;
10792
11138
  }
10793
11139
  get disabled() {
10794
- return !this.childFilter.filters.some(validFilters);
11140
+ return this.isMultiFilter ? this.areFiltersEqual : !this.childFilter.filters.some(validFilters);
10795
11141
  }
10796
11142
  get templateContext() {
10797
11143
  this._templateContext.column = this.column;
@@ -10804,15 +11150,20 @@ class FilterMenuContainerComponent {
10804
11150
  return isPresent(this.column) && isPresent(this.column.filterMenuTemplateRef);
10805
11151
  }
10806
11152
  submit() {
10807
- const filter = trimFilters(this.childFilter);
10808
- if (filter.filters.length) {
10809
- const root = this.filter || {
10810
- filters: [],
10811
- logic: "and"
10812
- };
10813
- removeFilter(root, this.column.field);
10814
- root.filters.push(filter);
10815
- this.parentService.filter(root);
11153
+ if (this.isMultiFilter) {
11154
+ this.parentService.filter(this.checkboxFilter);
11155
+ }
11156
+ else {
11157
+ const filter = trimFilters(this.childFilter);
11158
+ if (filter.filters.length) {
11159
+ const root = this.filter || {
11160
+ filters: [],
11161
+ logic: "and"
11162
+ };
11163
+ removeFilter(root, this.column.field);
11164
+ root.filters.push(filter);
11165
+ this.parentService.filter(root);
11166
+ }
10816
11167
  }
10817
11168
  this.close.emit();
10818
11169
  return false;
@@ -10840,29 +11191,100 @@ class FilterMenuContainerComponent {
10840
11191
  }
10841
11192
  }
10842
11193
  }
11194
+ onCheckboxFilterChange(filter) {
11195
+ this.checkboxFilter = filter;
11196
+ }
11197
+ getButtonIcon(buttonType, iconType) {
11198
+ if (!this.isMultiFilter) {
11199
+ return;
11200
+ }
11201
+ const icons = {
11202
+ filter: {
11203
+ icon: 'filter',
11204
+ svgIcon: filterIcon
11205
+ },
11206
+ reset: {
11207
+ icon: 'filter-clear',
11208
+ svgIcon: filterClearIcon
11209
+ }
11210
+ };
11211
+ return icons[buttonType]?.[iconType];
11212
+ }
10843
11213
  get clearText() {
10844
11214
  return this.ctx.localization.get("filterClearButton");
10845
11215
  }
10846
11216
  get filterText() {
10847
11217
  return this.ctx.localization.get("filterFilterButton");
10848
11218
  }
11219
+ get isMultiFilter() {
11220
+ if (!isPresent(this.column?.filterVariant)) {
11221
+ return false;
11222
+ }
11223
+ const filterVariant = this.column?.filterVariant;
11224
+ return isPresent(filterVariant) && (filterVariant === 'multiCheckbox' || typeof filterVariant === 'object' && filterVariant.variant === 'multiCheckbox');
11225
+ }
11226
+ get areFiltersEqual() {
11227
+ const checkboxFilter = this.checkboxFilter;
11228
+ const gridFilter = this.filter;
11229
+ const isComposite = (f) => !!f && Array.isArray(f.filters);
11230
+ // Treat undefined and "empty (no inner filters)" as equivalent
11231
+ const isEmptyComposite = (f) => isComposite(f) && f.filters.length === 0;
11232
+ if (!checkboxFilter && !gridFilter) {
11233
+ return true;
11234
+ }
11235
+ if ((!checkboxFilter && isEmptyComposite(gridFilter)) || (!gridFilter && isEmptyComposite(checkboxFilter))) {
11236
+ return true;
11237
+ }
11238
+ if (!checkboxFilter || !gridFilter) {
11239
+ return false;
11240
+ }
11241
+ const eq = (x, y) => {
11242
+ const xIsComp = isComposite(x);
11243
+ const yIsComp = isComposite(y);
11244
+ if (xIsComp !== yIsComp) {
11245
+ return false;
11246
+ }
11247
+ if (xIsComp) {
11248
+ const xLogic = x.logic || 'and';
11249
+ const yLogic = y.logic || 'and';
11250
+ if (xLogic !== yLogic) {
11251
+ return false;
11252
+ }
11253
+ if (x.filters.length !== y.filters.length) {
11254
+ return false;
11255
+ }
11256
+ for (let i = 0; i < x.filters.length; i++) {
11257
+ if (!eq(x.filters[i], y.filters[i])) {
11258
+ return false;
11259
+ }
11260
+ }
11261
+ return true;
11262
+ }
11263
+ return areObjectsEqual(x, y);
11264
+ };
11265
+ return eq(checkboxFilter, gridFilter);
11266
+ }
10849
11267
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterMenuContainerComponent, deps: [{ token: FilterService, skipSelf: true }, { token: FilterService }, { token: ContextService }, { token: i0.ChangeDetectorRef }, { token: MenuTabbingService }, { token: AdaptiveGridService }], target: i0.ɵɵFactoryTarget.Component });
10850
11268
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FilterMenuContainerComponent, isStandalone: true, selector: "kendo-grid-filter-menu-container", inputs: { column: "column", isLast: "isLast", isExpanded: "isExpanded", menuTabbingService: "menuTabbingService", filter: "filter", actionsClass: "actionsClass" }, outputs: { close: "close" }, providers: [
10851
11269
  FilterService,
10852
11270
  MenuTabbingService
10853
- ], viewQueries: [{ propertyName: "resetButton", first: true, predicate: ["resetButton"], descendants: true }, { propertyName: "filterButton", first: true, predicate: ["filterButton"], descendants: true }], ngImport: i0, template: `
11271
+ ], viewQueries: [{ propertyName: "resetButton", first: true, predicate: ["resetButton"], descendants: true }], ngImport: i0, template: `
10854
11272
  <form (submit)="submit()" (reset)="reset()"
10855
- class="k-filter-menu">
11273
+ class="k-filter-menu"
11274
+ [ngClass]="{'k-popup k-group k-reset': isMultiFilter && !ctx.grid?.isActionSheetExpanded}">
10856
11275
  <div class="k-filter-menu-container">
10857
11276
  <ng-container [ngSwitch]="hasTemplate">
10858
11277
  <ng-container *ngSwitchCase="false">
10859
- <ng-container
11278
+ <ng-container *ngIf="!isMultiFilter; else multiFilter"
10860
11279
  kendoFilterMenuHost
10861
11280
  [filterService]="childService"
10862
11281
  [column]="column"
10863
11282
  [filter]="childFilter"
10864
11283
  [menuTabbingService]="menuTabbingService">
10865
11284
  </ng-container>
11285
+ <ng-template #multiFilter>
11286
+ <kendo-grid-multicheckbox-filter style="display: contents;" [column]="column" (filterChange)="onCheckboxFilterChange($event)"></kendo-grid-multicheckbox-filter>
11287
+ </ng-template>
10866
11288
  </ng-container>
10867
11289
  <ng-container *ngSwitchCase="true">
10868
11290
  <ng-template
@@ -10874,20 +11296,24 @@ class FilterMenuContainerComponent {
10874
11296
  </ng-container>
10875
11297
  </ng-container>
10876
11298
  <div *ngIf="!ctx.grid?.isActionSheetExpanded" [ngClass]="actionsClass">
10877
- <button #filterButton
11299
+ <button #filterButton kendoButton
11300
+ themeColor="primary"
10878
11301
  type="submit"
10879
- class="k-button k-button-solid-primary k-button-solid k-button-md k-rounded-md k-button-rectangle"
11302
+ [ngClass]="{'k-button-rectangle': !isMultiFilter}"
10880
11303
  [disabled]="disabled"
11304
+ [icon]="getButtonIcon('filter', 'icon')"
11305
+ [svgIcon]="getButtonIcon('filter', 'svgIcon')"
10881
11306
  (keydown.tab)="onTab($event, 'filter')">{{filterText}}</button>
10882
- <button
10883
- #resetButton
11307
+ <button #resetButton kendoButton
10884
11308
  type="reset"
10885
- class="k-button k-button-solid-base k-button-solid k-button-md k-rounded-md k-button-rectangle"
11309
+ [ngClass]="{'k-button-rectangle': !isMultiFilter}"
11310
+ [icon]="getButtonIcon('reset', 'icon')"
11311
+ [svgIcon]="getButtonIcon('reset', 'svgIcon')"
10886
11312
  (keydown.tab)="onTab($event, 'reset')">{{clearText}}</button>
10887
11313
  </div>
10888
11314
  </div>
10889
11315
  </form>
10890
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: FilterMenuHostDirective, selector: "[kendoFilterMenuHost]", inputs: ["filterService", "menuTabbingService"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
11316
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: FilterMenuHostDirective, selector: "[kendoFilterMenuHost]", inputs: ["filterService", "menuTabbingService"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MultiCheckboxFilterComponent, selector: "kendo-grid-multicheckbox-filter", inputs: ["column"], outputs: ["filterChange"] }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }] });
10891
11317
  }
10892
11318
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterMenuContainerComponent, decorators: [{
10893
11319
  type: Component,
@@ -10899,17 +11325,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
10899
11325
  selector: 'kendo-grid-filter-menu-container',
10900
11326
  template: `
10901
11327
  <form (submit)="submit()" (reset)="reset()"
10902
- class="k-filter-menu">
11328
+ class="k-filter-menu"
11329
+ [ngClass]="{'k-popup k-group k-reset': isMultiFilter && !ctx.grid?.isActionSheetExpanded}">
10903
11330
  <div class="k-filter-menu-container">
10904
11331
  <ng-container [ngSwitch]="hasTemplate">
10905
11332
  <ng-container *ngSwitchCase="false">
10906
- <ng-container
11333
+ <ng-container *ngIf="!isMultiFilter; else multiFilter"
10907
11334
  kendoFilterMenuHost
10908
11335
  [filterService]="childService"
10909
11336
  [column]="column"
10910
11337
  [filter]="childFilter"
10911
11338
  [menuTabbingService]="menuTabbingService">
10912
11339
  </ng-container>
11340
+ <ng-template #multiFilter>
11341
+ <kendo-grid-multicheckbox-filter style="display: contents;" [column]="column" (filterChange)="onCheckboxFilterChange($event)"></kendo-grid-multicheckbox-filter>
11342
+ </ng-template>
10913
11343
  </ng-container>
10914
11344
  <ng-container *ngSwitchCase="true">
10915
11345
  <ng-template
@@ -10921,22 +11351,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
10921
11351
  </ng-container>
10922
11352
  </ng-container>
10923
11353
  <div *ngIf="!ctx.grid?.isActionSheetExpanded" [ngClass]="actionsClass">
10924
- <button #filterButton
11354
+ <button #filterButton kendoButton
11355
+ themeColor="primary"
10925
11356
  type="submit"
10926
- class="k-button k-button-solid-primary k-button-solid k-button-md k-rounded-md k-button-rectangle"
11357
+ [ngClass]="{'k-button-rectangle': !isMultiFilter}"
10927
11358
  [disabled]="disabled"
11359
+ [icon]="getButtonIcon('filter', 'icon')"
11360
+ [svgIcon]="getButtonIcon('filter', 'svgIcon')"
10928
11361
  (keydown.tab)="onTab($event, 'filter')">{{filterText}}</button>
10929
- <button
10930
- #resetButton
11362
+ <button #resetButton kendoButton
10931
11363
  type="reset"
10932
- class="k-button k-button-solid-base k-button-solid k-button-md k-rounded-md k-button-rectangle"
11364
+ [ngClass]="{'k-button-rectangle': !isMultiFilter}"
11365
+ [icon]="getButtonIcon('reset', 'icon')"
11366
+ [svgIcon]="getButtonIcon('reset', 'svgIcon')"
10933
11367
  (keydown.tab)="onTab($event, 'reset')">{{clearText}}</button>
10934
11368
  </div>
10935
11369
  </div>
10936
11370
  </form>
10937
11371
  `,
10938
11372
  standalone: true,
10939
- imports: [FormsModule, NgSwitch, NgSwitchCase, FilterMenuHostDirective, NgIf, NgTemplateOutlet, NgClass]
11373
+ imports: [FormsModule, NgSwitch, NgSwitchCase, FilterMenuHostDirective, NgIf, NgTemplateOutlet, NgClass, MultiCheckboxFilterComponent, ButtonComponent]
10940
11374
  }]
10941
11375
  }], ctorParameters: function () { return [{ type: FilterService, decorators: [{
10942
11376
  type: SkipSelf
@@ -10957,9 +11391,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
10957
11391
  }], resetButton: [{
10958
11392
  type: ViewChild,
10959
11393
  args: ['resetButton', { static: false }]
10960
- }], filterButton: [{
10961
- type: ViewChild,
10962
- args: ['filterButton', { static: false }]
10963
11394
  }] } });
10964
11395
 
10965
11396
  let id$1 = 0;
@@ -10975,7 +11406,6 @@ class FilterMenuComponent {
10975
11406
  renderer;
10976
11407
  cdr;
10977
11408
  adaptiveGridService;
10978
- zone;
10979
11409
  idService;
10980
11410
  filterIcon = filterIcon;
10981
11411
  /**
@@ -10993,7 +11423,7 @@ class FilterMenuComponent {
10993
11423
  tabIndex = '-1';
10994
11424
  popupRef;
10995
11425
  popupSubs;
10996
- constructor(filterService, popupService, ctx, navigationService, renderer, cdr, adaptiveGridService, zone, idService) {
11426
+ constructor(filterService, popupService, ctx, navigationService, renderer, cdr, adaptiveGridService, idService) {
10997
11427
  this.filterService = filterService;
10998
11428
  this.popupService = popupService;
10999
11429
  this.ctx = ctx;
@@ -11001,7 +11431,6 @@ class FilterMenuComponent {
11001
11431
  this.renderer = renderer;
11002
11432
  this.cdr = cdr;
11003
11433
  this.adaptiveGridService = adaptiveGridService;
11004
- this.zone = zone;
11005
11434
  this.idService = idService;
11006
11435
  }
11007
11436
  ngOnDestroy() {
@@ -11087,7 +11516,7 @@ class FilterMenuComponent {
11087
11516
  this.anchor.nativeElement.focus({ preventScroll: true });
11088
11517
  }
11089
11518
  }
11090
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterMenuComponent, deps: [{ token: FilterService }, { token: SinglePopupService }, { token: ContextService }, { token: NavigationService }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: AdaptiveGridService }, { token: i0.NgZone }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
11519
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterMenuComponent, deps: [{ token: FilterService }, { token: SinglePopupService }, { token: ContextService }, { token: NavigationService }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: AdaptiveGridService }, { token: IdService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
11091
11520
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FilterMenuComponent, isStandalone: true, selector: "kendo-grid-filter-menu", inputs: { column: "column", filter: "filter", tabIndex: "tabIndex" }, viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, static: true }, { propertyName: "template", first: true, predicate: ["template"], descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: `
11092
11521
  <a #anchor
11093
11522
  class="k-grid-filter-menu k-grid-header-menu"
@@ -11146,7 +11575,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
11146
11575
  standalone: true,
11147
11576
  imports: [IconWrapperComponent, FilterMenuContainerComponent],
11148
11577
  }]
11149
- }], ctorParameters: function () { return [{ type: FilterService }, { type: SinglePopupService }, { type: ContextService }, { type: NavigationService }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: AdaptiveGridService }, { type: i0.NgZone }, { type: IdService, decorators: [{
11578
+ }], ctorParameters: function () { return [{ type: FilterService }, { type: SinglePopupService }, { type: ContextService }, { type: NavigationService }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: AdaptiveGridService }, { type: IdService, decorators: [{
11150
11579
  type: Optional
11151
11580
  }] }]; }, propDecorators: { column: [{
11152
11581
  type: Input
@@ -16494,11 +16923,16 @@ class PDFComponent extends PDFExportComponent {
16494
16923
  overlayContent.scrollTop = content.scrollTop;
16495
16924
  overlayContent.scrollLeft = content.scrollLeft;
16496
16925
  if (!this.ctx?.grid?.isStacked) {
16497
- overlayQuery.header().scrollLeft = query.header().scrollLeft;
16926
+ const header = query.header();
16927
+ const overlayHeader = overlayQuery.header();
16928
+ if (header && overlayHeader) {
16929
+ overlayHeader.scrollLeft = header.scrollLeft;
16930
+ }
16498
16931
  }
16499
16932
  const footer = query.footer();
16500
- if (footer) {
16501
- overlayQuery.footer().scrollLeft = footer.scrollLeft;
16933
+ const overlayFooter = overlayQuery.footer();
16934
+ if (footer && overlayFooter) {
16935
+ overlayFooter.scrollLeft = footer.scrollLeft;
16502
16936
  }
16503
16937
  const lockedContent = query.content(true);
16504
16938
  if (lockedContent) {
@@ -17249,19 +17683,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
17249
17683
  args: ['dblclick']
17250
17684
  }] } });
17251
17685
 
17252
- /**
17253
- * @hidden
17254
- */
17255
- class LocalDataChangesService {
17256
- changes = new EventEmitter();
17257
- data;
17258
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalDataChangesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
17259
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalDataChangesService });
17260
- }
17261
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalDataChangesService, decorators: [{
17262
- type: Injectable
17263
- }] });
17264
-
17265
17686
  /**
17266
17687
  * @hidden
17267
17688
  */
@@ -18482,7 +18903,7 @@ class HeaderComponent {
18482
18903
  }
18483
18904
  onHeaderKeydown(column, args) {
18484
18905
  const code = normalizeNumpadKeys(args);
18485
- if (code === Keys.ArrowDown && args.altKey && this.showFilterMenu) {
18906
+ if (code === Keys.ArrowDown && args.altKey && this.showFilterMenu && this.isFilterable(column)) {
18486
18907
  args.preventDefault();
18487
18908
  args.stopImmediatePropagation();
18488
18909
  const filterMenu = this.filterMenus.find(fm => fm.column === column);
@@ -20181,7 +20602,7 @@ class CellComponent {
20181
20602
  </ng-container>
20182
20603
  </div>
20183
20604
  </div>
20184
- <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)">
20605
+ <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)" [attr.aria-expanded]="item.isExpanded">
20185
20606
  <div class="k-grid-stack-content">
20186
20607
  <button kendoButton
20187
20608
  fillMode="flat"
@@ -20389,7 +20810,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
20389
20810
  </ng-container>
20390
20811
  </div>
20391
20812
  </div>
20392
- <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)">
20813
+ <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)" [attr.aria-expanded]="item.isExpanded">
20393
20814
  <div class="k-grid-stack-content">
20394
20815
  <button kendoButton
20395
20816
  fillMode="flat"
@@ -21112,7 +21533,8 @@ class TableBodyComponent {
21112
21533
  [dataItem]="item.data"
21113
21534
  [detailExpandCell]="true"
21114
21535
  aria-selected="false"
21115
- role="gridcell">
21536
+ role="gridcell"
21537
+ [attr.aria-expanded]="item.isExpanded">
21116
21538
  <a
21117
21539
  *ngIf="detailTemplate.showIf(item.data, $any(item).index)"
21118
21540
  [attr.title]="detailButtonTitle(item)"
@@ -21432,7 +21854,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
21432
21854
  [dataItem]="item.data"
21433
21855
  [detailExpandCell]="true"
21434
21856
  aria-selected="false"
21435
- role="gridcell">
21857
+ role="gridcell"
21858
+ [attr.aria-expanded]="item.isExpanded">
21436
21859
  <a
21437
21860
  *ngIf="detailTemplate.showIf(item.data, $any(item).index)"
21438
21861
  [attr.title]="detailButtonTitle(item)"
@@ -22418,8 +22841,8 @@ const packageMetadata = {
22418
22841
  productName: 'Kendo UI for Angular',
22419
22842
  productCode: 'KENDOUIANGULAR',
22420
22843
  productCodes: ['KENDOUIANGULAR'],
22421
- publishDate: 1759490932,
22422
- version: '20.1.0-develop.9',
22844
+ publishDate: 1761222945,
22845
+ version: '20.1.1-develop.1',
22423
22846
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
22424
22847
  };
22425
22848
 
@@ -23582,7 +24005,9 @@ class RowReorderService {
23582
24005
  const draggedDataItem = draggedDragRow?.dataItem;
23583
24006
  isPresent$1(draggedDataItem) && columnFieldsArray.forEach(column => {
23584
24007
  const columnValue = draggedDataItem[column];
23585
- isPresent$1(columnValue) ? hintText += `${columnValue} ` : null;
24008
+ if (isPresent$1(columnValue)) {
24009
+ hintText += `${columnValue} `;
24010
+ }
23586
24011
  });
23587
24012
  return hintText.trim();
23588
24013
  }
@@ -24380,9 +24805,6 @@ class ScrollerService {
24380
24805
  const lastItemIndex = this.rowHeightService.index(scrollTop + offsetHeight);
24381
24806
  const overflow = Math.max(firstItemIndex + (this.virtualPageSize || this.take) - this.total, 0);
24382
24807
  firstItemIndex = Math.max(firstItemIndex - overflow, 0);
24383
- if (lastItemIndex < this.lastLoaded) {
24384
- this.lastLoaded = lastItemIndex;
24385
- }
24386
24808
  if (down) {
24387
24809
  const atBottom = scrollHeight - clientHeight - scrollTop < SCROLL_BOTTOM_THRESHOLD;
24388
24810
  if (atBottom) {
@@ -25578,7 +26000,7 @@ class ListComponent {
25578
26000
  <div></div>
25579
26001
  </div>
25580
26002
  </div>
25581
- <div
26003
+ <div
25582
26004
  #container
25583
26005
  class="k-grid-content k-virtual-content"
25584
26006
  [kendoGridResizableContainer]="lockedLeafColumns.length > 0"
@@ -25703,7 +26125,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
25703
26125
  <div></div>
25704
26126
  </div>
25705
26127
  </div>
25706
- <div
26128
+ <div
25707
26129
  #container
25708
26130
  class="k-grid-content k-virtual-content"
25709
26131
  [kendoGridResizableContainer]="lockedLeafColumns.length > 0"
@@ -26568,8 +26990,29 @@ class GridMessages extends ComponentMessages {
26568
26990
  * Sets the text for the external editing Dialog <b>Cancel</b> button.
26569
26991
  */
26570
26992
  externalEditingCancelText;
26993
+ /**
26994
+ * The placeholder text for the multi-checkbox filter search input
26995
+ */
26996
+ multiCheckboxFilterSearchPlaceholder;
26997
+ /**
26998
+ * The label for the multi-checkbox filter select all option
26999
+ */
27000
+ multiCheckboxFilterSelectAllLabel;
27001
+ /**
27002
+ * The text for the multi-checkbox filter selected items count
27003
+ *
27004
+ * The text includes the selected items count and a localizable string.
27005
+ * For 3 selected items the default text is `3 selected items`.
27006
+ *
27007
+ * To customize the text, use the `{selectedItemsCount}` placeholder and a custom localizable string.
27008
+ * For example, `{selectedItemsCount} items are selected`.
27009
+ *
27010
+ * The `{selectedItemsCount}` placeholder is replaced with the count of selected items,
27011
+ * and the message is rendered as `3 items are selected`.
27012
+ */
27013
+ multiCheckboxFilterSelectedItemsCount;
26571
27014
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GridMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
26572
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GridMessages, selector: "kendo-grid-messages-base", inputs: { groupPanelEmpty: "groupPanelEmpty", noRecords: "noRecords", pagerLabel: "pagerLabel", pagerFirstPage: "pagerFirstPage", pagerLastPage: "pagerLastPage", pagerPreviousPage: "pagerPreviousPage", pagerNextPage: "pagerNextPage", pagerPage: "pagerPage", pagerItemsPerPage: "pagerItemsPerPage", pagerOf: "pagerOf", pagerItems: "pagerItems", pagerPageNumberInputTitle: "pagerPageNumberInputTitle", pagerInputLabel: "pagerInputLabel", pagerSelectPage: "pagerSelectPage", filter: "filter", filterInputLabel: "filterInputLabel", filterMenuTitle: "filterMenuTitle", filterMenuOperatorsDropDownLabel: "filterMenuOperatorsDropDownLabel", filterMenuLogicDropDownLabel: "filterMenuLogicDropDownLabel", filterCellOperatorLabel: "filterCellOperatorLabel", booleanFilterCellLabel: "booleanFilterCellLabel", aiAssistantApplyButtonText: "aiAssistantApplyButtonText", aiAssistantToolbarToolText: "aiAssistantToolbarToolText", aiAssistantWindowTitle: "aiAssistantWindowTitle", aiAssistantWindowCloseTitle: "aiAssistantWindowCloseTitle", aiAssistantOutputCardTitle: "aiAssistantOutputCardTitle", aiAssistantOutputCardBodyContent: "aiAssistantOutputCardBodyContent", aiAssistantWindowMaximizeTitle: "aiAssistantWindowMaximizeTitle", aiAssistantWindowMinimizeTitle: "aiAssistantWindowMinimizeTitle", aiAssistantWindowRestoreTitle: "aiAssistantWindowRestoreTitle", filterEqOperator: "filterEqOperator", filterNotEqOperator: "filterNotEqOperator", filterIsNullOperator: "filterIsNullOperator", filterIsNotNullOperator: "filterIsNotNullOperator", filterIsEmptyOperator: "filterIsEmptyOperator", filterIsNotEmptyOperator: "filterIsNotEmptyOperator", filterStartsWithOperator: "filterStartsWithOperator", filterContainsOperator: "filterContainsOperator", filterNotContainsOperator: "filterNotContainsOperator", filterEndsWithOperator: "filterEndsWithOperator", filterGteOperator: "filterGteOperator", filterGtOperator: "filterGtOperator", filterLteOperator: "filterLteOperator", filterLtOperator: "filterLtOperator", filterIsTrue: "filterIsTrue", filterIsFalse: "filterIsFalse", filterBooleanAll: "filterBooleanAll", adaptiveFilterOperatorsTitle: "adaptiveFilterOperatorsTitle", filterAfterOrEqualOperator: "filterAfterOrEqualOperator", filterAfterOperator: "filterAfterOperator", filterBeforeOperator: "filterBeforeOperator", filterBeforeOrEqualOperator: "filterBeforeOrEqualOperator", filterFilterButton: "filterFilterButton", filterClearButton: "filterClearButton", adaptiveCloseButtonTitle: "adaptiveCloseButtonTitle", adaptiveBackButtonTitle: "adaptiveBackButtonTitle", filterAndLogic: "filterAndLogic", filterOrLogic: "filterOrLogic", filterToolbarToolText: "filterToolbarToolText", loading: "loading", gridLabel: "gridLabel", columnMenu: "columnMenu", setColumnPosition: "setColumnPosition", columns: "columns", columnChooserSelectedColumnsCount: "columnChooserSelectedColumnsCount", columnsSubtitle: "columnsSubtitle", adaptiveFilterTitle: "adaptiveFilterTitle", adaptiveSortTitle: "adaptiveSortTitle", adaptiveGroupTitle: "adaptiveGroupTitle", filterClearAllButton: "filterClearAllButton", groupClearButton: "groupClearButton", sortClearButton: "sortClearButton", sortDoneButton: "sortDoneButton", groupDoneButton: "groupDoneButton", lock: "lock", unlock: "unlock", stick: "stick", unstick: "unstick", sortable: "sortable", sortAscending: "sortAscending", sortDescending: "sortDescending", autosizeThisColumn: "autosizeThisColumn", autosizeAllColumns: "autosizeAllColumns", sortedAscending: "sortedAscending", sortedDescending: "sortedDescending", sortedDefault: "sortedDefault", sortToolbarToolText: "sortToolbarToolText", columnsApply: "columnsApply", columnsReset: "columnsReset", detailExpand: "detailExpand", detailCollapse: "detailCollapse", filterDateToday: "filterDateToday", filterDateToggle: "filterDateToggle", filterNumericDecrement: "filterNumericDecrement", filterNumericIncrement: "filterNumericIncrement", selectionCheckboxLabel: "selectionCheckboxLabel", selectAllCheckboxLabel: "selectAllCheckboxLabel", groupCollapse: "groupCollapse", groupExpand: "groupExpand", topToolbarLabel: "topToolbarLabel", bottomToolbarLabel: "bottomToolbarLabel", editToolbarToolText: "editToolbarToolText", saveToolbarToolText: "saveToolbarToolText", addToolbarToolText: "addToolbarToolText", cancelToolbarToolText: "cancelToolbarToolText", removeToolbarToolText: "removeToolbarToolText", excelExportToolbarToolText: "excelExportToolbarToolText", pdfExportToolbarToolText: "pdfExportToolbarToolText", groupPanelLabel: "groupPanelLabel", dragRowHandleLabel: "dragRowHandleLabel", columnMenuFilterTabTitle: "columnMenuFilterTabTitle", columnMenuGeneralTabTitle: "columnMenuGeneralTabTitle", columnMenuColumnsTabTitle: "columnMenuColumnsTabTitle", groupChipMenuPrevious: "groupChipMenuPrevious", groupChipMenuNext: "groupChipMenuNext", groupToolbarToolText: "groupToolbarToolText", formValidationErrorText: "formValidationErrorText", removeConfirmationDialogTitle: "removeConfirmationDialogTitle", removeConfirmationDialogContent: "removeConfirmationDialogContent", removeConfirmationDialogConfirmText: "removeConfirmationDialogConfirmText", removeConfirmationDialogRejectText: "removeConfirmationDialogRejectText", externalEditingTitle: "externalEditingTitle", externalEditingAddTitle: "externalEditingAddTitle", externalEditingSaveText: "externalEditingSaveText", externalEditingCancelText: "externalEditingCancelText" }, usesInheritance: true, ngImport: i0 });
27015
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GridMessages, selector: "kendo-grid-messages-base", inputs: { groupPanelEmpty: "groupPanelEmpty", noRecords: "noRecords", pagerLabel: "pagerLabel", pagerFirstPage: "pagerFirstPage", pagerLastPage: "pagerLastPage", pagerPreviousPage: "pagerPreviousPage", pagerNextPage: "pagerNextPage", pagerPage: "pagerPage", pagerItemsPerPage: "pagerItemsPerPage", pagerOf: "pagerOf", pagerItems: "pagerItems", pagerPageNumberInputTitle: "pagerPageNumberInputTitle", pagerInputLabel: "pagerInputLabel", pagerSelectPage: "pagerSelectPage", filter: "filter", filterInputLabel: "filterInputLabel", filterMenuTitle: "filterMenuTitle", filterMenuOperatorsDropDownLabel: "filterMenuOperatorsDropDownLabel", filterMenuLogicDropDownLabel: "filterMenuLogicDropDownLabel", filterCellOperatorLabel: "filterCellOperatorLabel", booleanFilterCellLabel: "booleanFilterCellLabel", aiAssistantApplyButtonText: "aiAssistantApplyButtonText", aiAssistantToolbarToolText: "aiAssistantToolbarToolText", aiAssistantWindowTitle: "aiAssistantWindowTitle", aiAssistantWindowCloseTitle: "aiAssistantWindowCloseTitle", aiAssistantOutputCardTitle: "aiAssistantOutputCardTitle", aiAssistantOutputCardBodyContent: "aiAssistantOutputCardBodyContent", aiAssistantWindowMaximizeTitle: "aiAssistantWindowMaximizeTitle", aiAssistantWindowMinimizeTitle: "aiAssistantWindowMinimizeTitle", aiAssistantWindowRestoreTitle: "aiAssistantWindowRestoreTitle", filterEqOperator: "filterEqOperator", filterNotEqOperator: "filterNotEqOperator", filterIsNullOperator: "filterIsNullOperator", filterIsNotNullOperator: "filterIsNotNullOperator", filterIsEmptyOperator: "filterIsEmptyOperator", filterIsNotEmptyOperator: "filterIsNotEmptyOperator", filterStartsWithOperator: "filterStartsWithOperator", filterContainsOperator: "filterContainsOperator", filterNotContainsOperator: "filterNotContainsOperator", filterEndsWithOperator: "filterEndsWithOperator", filterGteOperator: "filterGteOperator", filterGtOperator: "filterGtOperator", filterLteOperator: "filterLteOperator", filterLtOperator: "filterLtOperator", filterIsTrue: "filterIsTrue", filterIsFalse: "filterIsFalse", filterBooleanAll: "filterBooleanAll", adaptiveFilterOperatorsTitle: "adaptiveFilterOperatorsTitle", filterAfterOrEqualOperator: "filterAfterOrEqualOperator", filterAfterOperator: "filterAfterOperator", filterBeforeOperator: "filterBeforeOperator", filterBeforeOrEqualOperator: "filterBeforeOrEqualOperator", filterFilterButton: "filterFilterButton", filterClearButton: "filterClearButton", adaptiveCloseButtonTitle: "adaptiveCloseButtonTitle", adaptiveBackButtonTitle: "adaptiveBackButtonTitle", filterAndLogic: "filterAndLogic", filterOrLogic: "filterOrLogic", filterToolbarToolText: "filterToolbarToolText", loading: "loading", gridLabel: "gridLabel", columnMenu: "columnMenu", setColumnPosition: "setColumnPosition", columns: "columns", columnChooserSelectedColumnsCount: "columnChooserSelectedColumnsCount", columnsSubtitle: "columnsSubtitle", adaptiveFilterTitle: "adaptiveFilterTitle", adaptiveSortTitle: "adaptiveSortTitle", adaptiveGroupTitle: "adaptiveGroupTitle", filterClearAllButton: "filterClearAllButton", groupClearButton: "groupClearButton", sortClearButton: "sortClearButton", sortDoneButton: "sortDoneButton", groupDoneButton: "groupDoneButton", lock: "lock", unlock: "unlock", stick: "stick", unstick: "unstick", sortable: "sortable", sortAscending: "sortAscending", sortDescending: "sortDescending", autosizeThisColumn: "autosizeThisColumn", autosizeAllColumns: "autosizeAllColumns", sortedAscending: "sortedAscending", sortedDescending: "sortedDescending", sortedDefault: "sortedDefault", sortToolbarToolText: "sortToolbarToolText", columnsApply: "columnsApply", columnsReset: "columnsReset", detailExpand: "detailExpand", detailCollapse: "detailCollapse", filterDateToday: "filterDateToday", filterDateToggle: "filterDateToggle", filterNumericDecrement: "filterNumericDecrement", filterNumericIncrement: "filterNumericIncrement", selectionCheckboxLabel: "selectionCheckboxLabel", selectAllCheckboxLabel: "selectAllCheckboxLabel", groupCollapse: "groupCollapse", groupExpand: "groupExpand", topToolbarLabel: "topToolbarLabel", bottomToolbarLabel: "bottomToolbarLabel", editToolbarToolText: "editToolbarToolText", saveToolbarToolText: "saveToolbarToolText", addToolbarToolText: "addToolbarToolText", cancelToolbarToolText: "cancelToolbarToolText", removeToolbarToolText: "removeToolbarToolText", excelExportToolbarToolText: "excelExportToolbarToolText", pdfExportToolbarToolText: "pdfExportToolbarToolText", groupPanelLabel: "groupPanelLabel", dragRowHandleLabel: "dragRowHandleLabel", columnMenuFilterTabTitle: "columnMenuFilterTabTitle", columnMenuGeneralTabTitle: "columnMenuGeneralTabTitle", columnMenuColumnsTabTitle: "columnMenuColumnsTabTitle", groupChipMenuPrevious: "groupChipMenuPrevious", groupChipMenuNext: "groupChipMenuNext", groupToolbarToolText: "groupToolbarToolText", formValidationErrorText: "formValidationErrorText", removeConfirmationDialogTitle: "removeConfirmationDialogTitle", removeConfirmationDialogContent: "removeConfirmationDialogContent", removeConfirmationDialogConfirmText: "removeConfirmationDialogConfirmText", removeConfirmationDialogRejectText: "removeConfirmationDialogRejectText", externalEditingTitle: "externalEditingTitle", externalEditingAddTitle: "externalEditingAddTitle", externalEditingSaveText: "externalEditingSaveText", externalEditingCancelText: "externalEditingCancelText", multiCheckboxFilterSearchPlaceholder: "multiCheckboxFilterSearchPlaceholder", multiCheckboxFilterSelectAllLabel: "multiCheckboxFilterSelectAllLabel", multiCheckboxFilterSelectedItemsCount: "multiCheckboxFilterSelectedItemsCount" }, usesInheritance: true, ngImport: i0 });
26573
27016
  }
26574
27017
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GridMessages, decorators: [{
26575
27018
  type: Directive,
@@ -26827,6 +27270,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
26827
27270
  type: Input
26828
27271
  }], externalEditingCancelText: [{
26829
27272
  type: Input
27273
+ }], multiCheckboxFilterSearchPlaceholder: [{
27274
+ type: Input
27275
+ }], multiCheckboxFilterSelectAllLabel: [{
27276
+ type: Input
27277
+ }], multiCheckboxFilterSelectedItemsCount: [{
27278
+ type: Input
26830
27279
  }] } });
26831
27280
 
26832
27281
  /**
@@ -27848,11 +28297,12 @@ class GroupToolbarToolComponent {
27848
28297
  }
27849
28298
  }
27850
28299
  updateGroupedColumns() {
28300
+ const columns = this.ctx.grid['columnInfoService'].leafNamedColumns;
28301
+ const groupableColumns = columns.filter(column => column?.groupable);
27851
28302
  this.groupedColumns = this.group
27852
- .map(group => this.ctx.grid.columns.find(column => column?.field === group.field))
28303
+ .map(group => columns.find(column => column?.field === group.field))
27853
28304
  .filter(column => !!column);
27854
- this.ungroupedColumns = this.ctx.grid.columns.filter(column => column?.groupable &&
27855
- !this.groupedColumns.some(gc => gc?.field === column?.field));
28305
+ this.ungroupedColumns = groupableColumns.filter(column => !this.groupedColumns.some(gc => gc?.field === column?.field));
27856
28306
  }
27857
28307
  navigateToNextItem() {
27858
28308
  if (this.currentFocusedItemIndex < this.groupItems.length - 1) {
@@ -29205,1299 +29655,621 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
29205
29655
  args: [GroupToolbarToolComponent]
29206
29656
  }] } });
29207
29657
 
29208
- /**
29209
- * @hidden
29210
- */
29211
- const DEFAULT_AI_REQUEST_OPTIONS = {
29212
- headers: new HttpHeaders({
29213
- 'Content-Type': 'application/json'
29214
- }),
29215
- role: 'user',
29216
- method: 'POST',
29217
- responseType: 'json'
29658
+ const createControl = (source) => (acc, key) => {
29659
+ acc[key] = new FormControl(source[key]);
29660
+ return acc;
29218
29661
  };
29662
+ const validateColumnsField = (columns) => expandColumns(columns.toArray())
29663
+ .filter(isColumnComponent)
29664
+ .filter(({ field }) => !isValidFieldName(field))
29665
+ .forEach(({ field }) => console.warn(ColumnConfigurationErrorMessages.fieldName(field)));
29666
+ const handleExpandCollapseGroupsService = (service, expandEmitter, collapseEmitter, map) => (service.changes.pipe(filter(({ group, emit }) => emit && isPresent(group)))
29667
+ .subscribe((x) => x.expand ? expandEmitter.emit(map(x)) : collapseEmitter.emit(map(x))));
29668
+ const handleExpandCollapseDetailsService = (service, expandEmitter, collapseEmitter, map) => (service.changes.pipe(filter(({ dataItem }) => isPresent(dataItem)))
29669
+ .subscribe((x) => x.expand ? expandEmitter.emit(map(x)) : collapseEmitter.emit(map(x))));
29670
+ const isInEditedCell = (element, gridElement, isStacked = false) => (closest(element, matchesClasses('k-grid-edit-cell')) || (isStacked && closest(element, matchesClasses('k-grid-stack-edit-cell')))) &&
29671
+ closest(element, matchesNodeName('kendo-grid')) === gridElement;
29672
+ const NOTIFY_DELAY = 500;
29219
29673
  /**
29220
- * Represents the event data when the AI Assistant request completes successfully.
29674
+ * Represents the Kendo UI for Angular Data Grid component.
29675
+ *
29676
+ * Use the `kendo-grid` component to display and manage tabular data.
29677
+ *
29678
+ * @example
29679
+ * ```html
29680
+ * <kendo-grid [data]="gridData"></kendo-grid>
29681
+ * ```
29682
+ *
29683
+ * @remarks
29684
+ * Supported children components are:
29685
+ * {@link CheckboxColumnComponent},
29686
+ * {@link ColumnChooserComponent},
29687
+ * {@link ColumnComponent},
29688
+ * {@link ColumnGroupComponent},
29689
+ * {@link ColumnMenuAutoSizeAllColumnsComponent},
29690
+ * {@link ColumnMenuAutoSizeColumnComponent},
29691
+ * {@link ColumnMenuChooserComponent},
29692
+ * {@link ColumnMenuComponent},
29693
+ * {@link ColumnMenuFilterComponent},
29694
+ * {@link ColumnMenuItemComponent},
29695
+ * {@link ColumnMenuLockComponent},
29696
+ * {@link ColumnMenuPositionComponent},
29697
+ * {@link ColumnMenuSortComponent},
29698
+ * {@link ColumnMenuStickComponent},
29699
+ * {@link CommandColumnComponent},
29700
+ * {@link CustomMessagesComponent},
29701
+ * {@link ExcelComponent},
29702
+ * {@link GridSpacerComponent},
29703
+ * {@link PDFComponent},
29704
+ * {@link RowReorderColumnComponent},
29705
+ * {@link SpanColumnComponent},
29706
+ * {@link ToolBarComponent}.
29221
29707
  */
29222
- class GridToolbarAIResponseSuccessEvent extends PreventableEvent$1 {
29708
+ class GridComponent {
29709
+ supportService;
29710
+ selectionService;
29711
+ cellSelectionService;
29712
+ wrapper;
29713
+ groupInfoService;
29714
+ groupsService;
29715
+ changeNotification;
29716
+ detailsService;
29717
+ editService;
29718
+ filterService;
29719
+ pdfService;
29720
+ responsiveService;
29721
+ renderer;
29722
+ excelService;
29723
+ ngZone;
29724
+ scrollSyncService;
29725
+ domEvents;
29726
+ columnResizingService;
29727
+ changeDetectorRef;
29728
+ columnReorderService;
29729
+ columnInfoService;
29730
+ navigationService;
29731
+ sortService;
29732
+ scrollRequestService;
29733
+ localization;
29734
+ ctx;
29735
+ sizingService;
29736
+ adaptiveGridService;
29737
+ rowReorderService;
29738
+ dataMappingService;
29223
29739
  /**
29224
- * The HTTP response from the AI service.
29740
+ * Sets the data of the Grid. If you provide an array, the Grid gets the total count automatically.
29741
+ * ([more information and example]({% slug binding_grid %})).
29225
29742
  */
29226
- response;
29227
- constructor(response) {
29228
- super();
29229
- this.response = response;
29743
+ set data(value) {
29744
+ this._data = value;
29745
+ if (this.selectable && this.selectableSettings?.enabled && this.isVirtual) {
29746
+ this.blockArrowSelection = false;
29747
+ }
29748
+ if (this.notifyTimeout) {
29749
+ clearTimeout(this.notifyTimeout);
29750
+ this.notifyTimeout = null;
29751
+ }
29752
+ if (this.rowReorderable) {
29753
+ this.ngZone.runOutsideAngular(() => {
29754
+ this.notifyTimeout = setTimeout(() => {
29755
+ this.notifyReorderContainers();
29756
+ }, NOTIFY_DELAY);
29757
+ });
29758
+ }
29230
29759
  }
29231
- }
29232
- /**
29233
- * Represents the event data when the AI Assistant request completes with an error.
29234
- */
29235
- class GridToolbarAIResponseErrorEvent extends PreventableEvent$1 {
29236
- /**
29237
- * The HTTP error response from the AI service.
29238
- */
29239
- error;
29240
- constructor(error) {
29241
- super();
29242
- this.error = error;
29760
+ get data() {
29761
+ return this._data;
29243
29762
  }
29244
- }
29245
-
29246
- /**
29247
- * @hidden
29248
- * Converts date strings in a filter to Date objects.
29249
- */
29250
- const convertDateStringsInFilter = (filter) => {
29251
- if (!filter) {
29252
- return filter;
29763
+ get hintText() {
29764
+ return this.rowReorderService.getDefaultHintText(this.columnList, this.flatData);
29253
29765
  }
29254
- if (filter.filters && Array.isArray(filter.filters)) {
29255
- return {
29256
- ...filter,
29257
- filters: filter.filters.map(f => convertDateStringsInFilter(f))
29258
- };
29766
+ /**
29767
+ * @hidden
29768
+ */
29769
+ get customHintTemplate() {
29770
+ if (this.rowReorderable) {
29771
+ const allColumns = this.columnList.toArray();
29772
+ const rowReorderColumn = allColumns.find(column => column.isRowReorderColumn);
29773
+ return rowReorderColumn.rowDragHintTemplateRef;
29774
+ }
29259
29775
  }
29260
- if (filter.field && filter.value !== undefined) {
29261
- if (typeof filter.value === 'string' && isDateOperator(filter.operator)) {
29262
- const date = parseDate(filter.value);
29776
+ /**
29777
+ * @hidden
29778
+ */
29779
+ get hintContext() {
29780
+ if (this.customHintTemplate) {
29781
+ const draggedRow = this.rowReorderService?.getDraggedRow(this.flatData);
29263
29782
  return {
29264
- ...filter,
29265
- value: date || filter.value
29783
+ $implicit: draggedRow?.dataItem,
29784
+ rowIndex: draggedRow?.rowIndex
29266
29785
  };
29267
29786
  }
29268
29787
  }
29269
- return filter;
29270
- };
29271
- /**
29272
- * @hidden
29273
- */
29274
- const isDateOperator = (operator) => {
29275
- const dateOperators = [
29276
- 'eq', 'neq', 'lt', 'lte', 'gt', 'gte'
29277
- ];
29278
- return dateOperators.includes(operator);
29279
- };
29280
- /**
29281
- * @hidden
29282
- * Processes cell highlights for a specific filter and item.
29283
- */
29284
- const processCellHighlights = (filter, rowIndex, columns, highlightItems) => {
29285
- Object.keys(filter.cells).forEach((columnField) => {
29286
- const actualColumnIndex = Array.from(columns).findIndex((col) => col.field === columnField);
29287
- if (actualColumnIndex !== -1) {
29288
- highlightItems.push({
29289
- itemKey: rowIndex,
29290
- columnKey: actualColumnIndex,
29291
- });
29788
+ /**
29789
+ * Defines the page size used by the Grid pager.
29790
+ * Required for the [`paging`]({% slug paging_grid %}) feature.
29791
+ */
29792
+ pageSize;
29793
+ /**
29794
+ * Defines the height in pixels for the Grid when `scrollable` is set.
29795
+ * You can also set the height using `style.height` with units like `px`, `%`, `em`, or `rem`.
29796
+ */
29797
+ height;
29798
+ /**
29799
+ * Sets the `style.height` attribute of each Grid data or group header/footer row (`tr`) element in the DOM in pixels.
29800
+ * If some row cells have content that requires more space, the row automatically expands to fit the content.
29801
+ */
29802
+ rowHeight;
29803
+ /**
29804
+ * Enables or disables adaptive mode. Adaptive rendering is off by default.
29805
+ *
29806
+ * @default 'none'
29807
+ */
29808
+ adaptiveMode = 'none';
29809
+ /**
29810
+ * Sets the `style.height` attribute of each Grid detail row (`tr.k-detail-row`) element in the DOM in pixels.
29811
+ * If the detail row has content that requires more space, the row automatically expands to fit the content.
29812
+ */
29813
+ detailRowHeight;
29814
+ /**
29815
+ * Defines the number of records to skip in the pager.
29816
+ * Required for the [`paging`]({% slug paging_grid %}) feature.
29817
+ */
29818
+ get skip() {
29819
+ return this._skip;
29820
+ }
29821
+ set skip(value) {
29822
+ if (typeof value === 'number' && value >= 0) {
29823
+ this._skip = this.rowReorderService.skip = value;
29292
29824
  }
29293
- });
29294
- };
29295
- /**
29296
- * @hidden
29297
- * Processes filtered results and adds highlight items.
29298
- */
29299
- const processFilteredResults = (filteredResults, data, filter, columns, highlightItems) => {
29300
- filteredResults?.forEach((item) => {
29301
- const rowIndex = data.findIndex((dataItem) => dataItem === item);
29302
- if (filter.cells && Object.keys(filter.cells).length > 0) {
29303
- processCellHighlights(filter, rowIndex, columns, highlightItems);
29825
+ }
29826
+ /**
29827
+ * Defines the scroll mode for the Grid.
29828
+ *
29829
+ * @default 'scrollable'
29830
+ */
29831
+ scrollable = 'scrollable';
29832
+ /**
29833
+ * Enables the selection feature of the Grid. The `selectable` property can be set to `true`, `false`, or an object with additional settings.
29834
+ * [See example](slug:grid_row_selection).
29835
+ *
29836
+ * @default false
29837
+ */
29838
+ selectable = false;
29839
+ /**
29840
+ * Sets the descriptors for sorting the data ([see example](slug:manual_sorting_grid)).
29841
+ */
29842
+ set sort(value) {
29843
+ if (isArray(value)) {
29844
+ this._sort = value;
29304
29845
  }
29305
- else {
29306
- highlightItems.push({
29307
- itemKey: rowIndex,
29308
- });
29846
+ }
29847
+ get sort() {
29848
+ return this._sort;
29849
+ }
29850
+ /**
29851
+ * Specifies the sizing for Grid elements like tables, buttons, and inputs.
29852
+ *
29853
+ * @default 'medium'
29854
+ */
29855
+ set size(size) {
29856
+ this._size = size;
29857
+ if (size === 'none') {
29858
+ this.wrapper.nativeElement.classList.remove('k-grid-sm', 'k-grid-md');
29309
29859
  }
29310
- });
29311
- };
29312
- /**
29313
- * @hidden
29314
- * Highlights items in a grid based on the provided filters and columns.
29315
- * @param data - The data to be highlighted.
29316
- * @param filters - The composite highlight descriptors containing the filters and logic.
29317
- * @param columns - The columns of the grid.
29318
- * @returns An array of HighlightItem objects representing the highlighted items.
29319
- */
29320
- const highlightBy = (data, filters, columns) => {
29321
- const highlightItems = [];
29322
- filters.forEach((filter) => {
29323
- const processedFilters = filter.filters.map((filter) => convertDateStringsInFilter(filter));
29324
- const filteredResults = filterBy(data, {
29325
- logic: filter.logic || "and",
29326
- filters: processedFilters,
29327
- });
29328
- processFilteredResults(filteredResults, data, filter, columns, highlightItems);
29329
- });
29330
- return highlightItems;
29331
- };
29332
-
29333
- /**
29334
- * @hidden
29335
- */
29336
- class AiAssistantComponent {
29337
- http;
29338
- ctx;
29339
- columnInfoService;
29340
- aiPrompt;
29341
- activeView = 0;
29342
- requestUrl;
29343
- requestOptions;
29344
- aiPromptSettings;
29345
- aiToolDirective;
29346
- streaming = false;
29347
- disabledGenerateButton = false;
29348
- lastMessage;
29349
- requestData;
29350
- currentRequestSubscription = null;
29351
- //Remove this when the AI Assistant has a built-in loading indicator
29352
- loadingOutput = { id: 'k-loading-item', output: '', prompt: '' };
29353
- columns = [];
29354
- idCounter = 0;
29355
- constructor(http, ctx, columnInfoService) {
29356
- this.http = http;
29357
- this.ctx = ctx;
29358
- this.columnInfoService = columnInfoService;
29860
+ this.sizingService.changes.next(this.size);
29359
29861
  }
29360
- ngAfterViewInit() {
29361
- this.columns = this.columnInfoService.leafNamedColumns.map((col) => ({ field: col.field }));
29862
+ get size() {
29863
+ return this._size;
29362
29864
  }
29363
- ngOnDestroy() {
29364
- this.unsubscribeCurrentRequest();
29865
+ /**
29866
+ * A function that defines how to track changes for the data rows.
29867
+ * By default, the Grid tracks changes by the index of the data item.
29868
+ * Edited rows are tracked by reference.
29869
+ * [See example](slug:track_changes_grid).
29870
+ */
29871
+ trackBy = defaultTrackBy;
29872
+ /**
29873
+ * Sets the filter descriptor for the data ([see examples](slug:manual_filtering_grid)).
29874
+ */
29875
+ filter;
29876
+ /**
29877
+ * Sets the descriptors for grouping the data ([see example](slug:manual_grouping_grid)).
29878
+ */
29879
+ set group(value) {
29880
+ if (isArray(value)) {
29881
+ this._group = value;
29882
+ }
29365
29883
  }
29366
- message(message) {
29367
- return this.ctx.localization.get(message);
29884
+ get group() {
29885
+ return this._group;
29368
29886
  }
29369
- cancelRequest() {
29370
- this.aiToolDirective.cancelRequest.emit();
29371
- this.unsubscribeCurrentRequest();
29372
- this.streaming = false;
29887
+ /**
29888
+ * If `true`, renders only columns in the current viewport.
29889
+ *
29890
+ * @default false
29891
+ */
29892
+ virtualColumns = false;
29893
+ /**
29894
+ * @hidden
29895
+ */
29896
+ get showStatusBar() {
29897
+ return !!(this.selectable);
29373
29898
  }
29374
- onPromptRequest(ev) {
29375
- if (this.aiToolDirective.promptOutputs.length === 0) {
29376
- this.aiToolDirective.promptOutputs.push(this.loadingOutput);
29377
- }
29378
- this.unsubscribeCurrentRequest();
29379
- this.streaming = true;
29380
- this.activeView = 1;
29381
- if (ev.prompt) {
29382
- this.lastMessage = ev.prompt;
29383
- }
29384
- this.requestData = {
29385
- columns: this.columns,
29386
- promptMessage: ev.prompt,
29387
- url: this.requestUrl,
29388
- requestOptions: {
29389
- ...this.requestOptions
29390
- }
29391
- };
29392
- if (!this.requestOptions.body) {
29393
- const requestBody = {
29394
- role: this.requestData.requestOptions.role,
29395
- contents: [
29396
- {
29397
- text: this.requestData.promptMessage
29398
- }
29399
- ],
29400
- columns: this.requestData.columns
29401
- };
29402
- this.requestData.requestOptions.body = requestBody;
29403
- }
29404
- this.aiToolDirective.promptRequest.emit({ requestData: this.requestData, isRetry: ev.isRetry });
29405
- if (!this.requestUrl) {
29406
- return;
29407
- }
29408
- this.currentRequestSubscription = this.sendPromptRequest().subscribe((res) => {
29409
- if (res.body) {
29410
- this.processResponse(res);
29411
- this.streaming = false;
29412
- }
29413
- this.currentRequestSubscription = null;
29414
- }, (error) => {
29415
- this.handleError(error);
29416
- this.streaming = false;
29417
- this.currentRequestSubscription = null;
29418
- });
29899
+ /**
29900
+ * @hidden
29901
+ */
29902
+ get showTopToolbar() {
29903
+ return this.toolbarTemplate && ['top', 'both'].indexOf(this.toolbarTemplate.position) > -1;
29419
29904
  }
29420
- sendPromptRequest() {
29421
- const request = new HttpRequest(this.requestData.requestOptions.method, this.requestData.url, this.requestData.requestOptions.body, this.requestData.requestOptions);
29422
- return this.http.request(request);
29905
+ /**
29906
+ * @hidden
29907
+ */
29908
+ get showBottomToolbar() {
29909
+ return this.toolbarTemplate && ['bottom', 'both'].indexOf(this.toolbarTemplate.position) > -1;
29423
29910
  }
29424
- processResponse(response) {
29425
- if (this.aiToolDirective.autoClose) {
29426
- this.aiToolDirective.emitOpenClose = true;
29427
- this.aiToolDirective.toggleWindow();
29428
- }
29429
- const responseBody = response.body;
29430
- const responseSuccessEvent = new GridToolbarAIResponseSuccessEvent(response);
29431
- this.aiToolDirective.responseSuccess.emit(responseSuccessEvent);
29432
- if (responseSuccessEvent.isDefaultPrevented()) {
29433
- this.deleteLoadingOutput();
29434
- return;
29435
- }
29436
- const isFilterable = Boolean(this.ctx.grid.filterable);
29437
- const isSortable = Boolean(this.ctx.grid.sortable);
29438
- const isGroupable = Boolean(this.ctx.grid.groupable);
29439
- if (isFilterable && responseBody.filter) {
29440
- this.processFilterResponse(responseBody.filter);
29441
- }
29442
- if (isSortable && responseBody.sort) {
29443
- this.processArrayResponse(responseBody.sort, this.ctx.grid.currentState.sort || [], (item) => item.field, (mergedArray) => this.ctx.grid.sortChange.next(mergedArray));
29444
- }
29445
- if (isGroupable && responseBody.group) {
29446
- this.processArrayResponse(responseBody.group, this.ctx.grid.currentState.group || [], (item) => item.field, (mergedArray) => this.ctx.grid.groupChange.next(mergedArray));
29447
- }
29448
- if (this.ctx.highlightDirective && responseBody.highlight) {
29449
- this.processHighlightResponse(responseBody.highlight);
29450
- }
29451
- const responseContentStart = [`${this.ctx.localization.get('aiAssistantOutputCardBodyContent')} \n`];
29452
- const responseContentBody = responseBody.messages
29453
- .map((output, idx) => `${idx + 1} ${output}`)
29454
- .join('\n');
29455
- const output = {
29456
- id: this.idCounter++,
29457
- title: this.ctx.localization.get('aiAssistantOutputCardTitle'),
29458
- prompt: this.lastMessage,
29459
- output: responseContentStart.concat(responseContentBody).join(''),
29460
- };
29461
- this.deleteLoadingOutput();
29462
- this.aiToolDirective.promptOutputs.unshift(output);
29911
+ /**
29912
+ * @hidden
29913
+ */
29914
+ get isLocked() {
29915
+ return (this.lockedLeafColumns.length > 0 && !this.isStacked);
29463
29916
  }
29464
- handleError(error) {
29465
- const responseErrorEvent = new GridToolbarAIResponseErrorEvent(error);
29466
- this.aiToolDirective.responseError.emit(responseErrorEvent);
29467
- if (responseErrorEvent.isDefaultPrevented()) {
29468
- this.deleteLoadingOutput();
29469
- return;
29470
- }
29471
- const output = {
29472
- id: this.idCounter++,
29473
- prompt: this.lastMessage,
29474
- output: error.message
29475
- };
29476
- this.deleteLoadingOutput();
29477
- this.aiToolDirective.promptOutputs.unshift(output);
29917
+ /**
29918
+ * @hidden
29919
+ */
29920
+ get showTopPager() {
29921
+ const position = this.pageable.position;
29922
+ return this.pageable !== false && ['top', 'both'].indexOf(position) > -1;
29478
29923
  }
29479
- deleteLoadingOutput() {
29480
- if (this.aiToolDirective.promptOutputs[0]?.id === this.loadingOutput.id) {
29481
- this.aiToolDirective.promptOutputs.splice(0, 1);
29482
- }
29924
+ /**
29925
+ * @hidden
29926
+ */
29927
+ get showBottomPager() {
29928
+ const position = this.pageable.position;
29929
+ return this.pageable !== false && position !== 'top';
29483
29930
  }
29484
- unsubscribeCurrentRequest() {
29485
- if (this.currentRequestSubscription) {
29486
- this.currentRequestSubscription.unsubscribe();
29487
- this.currentRequestSubscription = null;
29488
- }
29931
+ /**
29932
+ * @hidden
29933
+ */
29934
+ get hasPager() {
29935
+ return this.showTopPager || this.showBottomPager;
29489
29936
  }
29490
- processArrayResponse(newItems, currentItems, getField, updateGrid) {
29491
- if (newItems?.length === 0) {
29492
- updateGrid([]);
29493
- }
29494
- else if (newItems?.length) {
29495
- let mergedArray = [...newItems];
29496
- const newFields = newItems.map(getField);
29497
- const existingItemsToKeep = currentItems.filter(item => !newFields.includes(getField(item)));
29498
- mergedArray = [...mergedArray, ...existingItemsToKeep];
29499
- updateGrid(mergedArray);
29500
- }
29937
+ /**
29938
+ * @hidden
29939
+ */
29940
+ get showGroupPanel() {
29941
+ const isGroupable = this.groupable && this.groupable.enabled !== false;
29942
+ const isGrouped = this.group?.length > 0;
29943
+ return this.isStacked ? isGroupable && isGrouped : isGroupable;
29501
29944
  }
29502
- processHighlightResponse(highlight) {
29503
- if (highlight.length === 0) {
29504
- this.ctx.highlightDirective['setState']([]);
29505
- return;
29506
- }
29507
- const highlightedItems = highlightBy(this.ctx.dataBindingDirective['originalData'], highlight, this.columns);
29508
- this.ctx.highlightDirective['setState'](highlightedItems);
29945
+ /**
29946
+ * @hidden
29947
+ */
29948
+ get groupableEmptyText() {
29949
+ return this.groupable.emptyText;
29509
29950
  }
29510
- processFilterResponse(filter) {
29511
- const processedFilter = convertDateStringsInFilter(filter);
29512
- const clearFilter = Object.keys(processedFilter).length === 0;
29513
- if (clearFilter) {
29514
- this.ctx.grid.filterChange.next(undefined);
29515
- }
29516
- else if (processedFilter?.filters.length) {
29517
- const currentFilter = this.ctx.grid.currentState.filter;
29518
- let mergedFilter = processedFilter;
29519
- if (currentFilter && currentFilter.filters?.length > 0) {
29520
- mergedFilter = {
29521
- logic: 'and',
29522
- filters: [
29523
- currentFilter,
29524
- processedFilter
29525
- ]
29526
- };
29527
- }
29528
- this.ctx.grid.filterChange.next(mergedFilter);
29529
- }
29951
+ /**
29952
+ * @hidden
29953
+ */
29954
+ get marqueeSelection() {
29955
+ return this.selectionService.enableMarquee || this.cellSelectionService.enableMarquee;
29530
29956
  }
29531
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiAssistantComponent, deps: [{ token: i1$8.HttpClient }, { token: ContextService }, { token: ColumnInfoService }], target: i0.ɵɵFactoryTarget.Component });
29532
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AiAssistantComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "aiPrompt", first: true, predicate: AIPromptComponent, descendants: true }], ngImport: i0, template: `
29533
- <kendo-aiprompt
29534
- #aiPrompt
29535
- [promptSuggestions]="aiPromptSettings?.promptSuggestions"
29536
- [showOutputRating]="aiPromptSettings?.showOutputRating"
29537
- [streaming]="streaming"
29538
- [speechToTextButton]="aiPromptSettings?.speechToTextButton"
29539
- [(activeView)]="activeView"
29540
- [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon"
29541
- [generateButtonIcon]="aiPromptSettings?.generateButtonIcon"
29542
- [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0"
29543
- [promptOutputs]="aiPromptSettings?.promptOutputs"
29544
- [textAreaSettings]="aiPromptSettings?.textAreaSettings"
29545
- (promptRequest)="onPromptRequest($event)"
29546
- (promptRequestCancel)="cancelRequest()"
29547
- >
29548
- <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view>
29549
- <kendo-aiprompt-output-view></kendo-aiprompt-output-view>
29550
- <ng-template *ngIf="streaming && aiPrompt.streaming" kendoAIPromptOutputTemplate let-output>
29551
- <div class="k-card">
29552
- <div class="k-card-header">
29553
- <div class="k-card-title">
29554
- <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span>
29555
- </div>
29556
- <div class="k-card-subtitle">
29557
- <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
29558
- </div>
29559
- </div>
29560
- <div class="k-card-body">
29561
- <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span>
29562
- </div>
29563
- <div class="k-card-actions">
29564
- <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
29565
- </div>
29566
- </div>
29567
- </ng-template>
29568
- <ng-template *ngIf="!(streaming && aiPrompt.streaming)" kendoAIPromptOutputBodyTemplate let-output>
29569
- <p>{{output.output}}</p>
29570
- </ng-template>
29571
- <kendo-aiprompt-messages
29572
- [generateOutput]="message('aiAssistantApplyButtonText')"
29573
- ></kendo-aiprompt-messages>
29574
- </kendo-aiprompt>
29575
- `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AIPromptComponent, selector: "kendo-aiprompt", inputs: ["activeView", "promptCommands", "promptSuggestions", "promptOutputs", "showOutputRating", "streaming", "speechToTextButton", "textAreaSettings", "generateButtonSVGIcon", "generateButtonIcon", "disabledGenerateButton"], outputs: ["activeViewChange", "promptRequest", "commandExecute", "outputCopy", "outputRatingChange", "promptRequestCancel"], exportAs: ["kendoAIPrompt"] }, { kind: "component", type: AIPromptCustomMessagesComponent, selector: "kendo-aiprompt-messages" }, { kind: "component", type: PromptViewComponent, selector: "kendo-aiprompt-prompt-view" }, { kind: "component", type: OutputViewComponent, selector: "kendo-aiprompt-output-view" }, { kind: "directive", type: AIPromptOutputTemplateDirective, selector: "[kendoAIPromptOutputTemplate]" }, { kind: "directive", type: AIPromptOutputBodyTemplateDirective, selector: "[kendoAIPromptOutputBodyTemplate]" }] });
29576
- }
29577
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiAssistantComponent, decorators: [{
29578
- type: Component,
29579
- args: [{
29580
- standalone: true,
29581
- imports: [NgIf, AIPromptComponent, AIPromptCustomMessagesComponent, PromptViewComponent, OutputViewComponent, AIPromptOutputTemplateDirective, AIPromptOutputBodyTemplateDirective],
29582
- template: `
29583
- <kendo-aiprompt
29584
- #aiPrompt
29585
- [promptSuggestions]="aiPromptSettings?.promptSuggestions"
29586
- [showOutputRating]="aiPromptSettings?.showOutputRating"
29587
- [streaming]="streaming"
29588
- [speechToTextButton]="aiPromptSettings?.speechToTextButton"
29589
- [(activeView)]="activeView"
29590
- [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon"
29591
- [generateButtonIcon]="aiPromptSettings?.generateButtonIcon"
29592
- [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0"
29593
- [promptOutputs]="aiPromptSettings?.promptOutputs"
29594
- [textAreaSettings]="aiPromptSettings?.textAreaSettings"
29595
- (promptRequest)="onPromptRequest($event)"
29596
- (promptRequestCancel)="cancelRequest()"
29597
- >
29598
- <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view>
29599
- <kendo-aiprompt-output-view></kendo-aiprompt-output-view>
29600
- <ng-template *ngIf="streaming && aiPrompt.streaming" kendoAIPromptOutputTemplate let-output>
29601
- <div class="k-card">
29602
- <div class="k-card-header">
29603
- <div class="k-card-title">
29604
- <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span>
29605
- </div>
29606
- <div class="k-card-subtitle">
29607
- <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
29608
- </div>
29609
- </div>
29610
- <div class="k-card-body">
29611
- <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span>
29612
- </div>
29613
- <div class="k-card-actions">
29614
- <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
29615
- </div>
29616
- </div>
29617
- </ng-template>
29618
- <ng-template *ngIf="!(streaming && aiPrompt.streaming)" kendoAIPromptOutputBodyTemplate let-output>
29619
- <p>{{output.output}}</p>
29620
- </ng-template>
29621
- <kendo-aiprompt-messages
29622
- [generateOutput]="message('aiAssistantApplyButtonText')"
29623
- ></kendo-aiprompt-messages>
29624
- </kendo-aiprompt>
29625
- `
29626
- }]
29627
- }], ctorParameters: function () { return [{ type: i1$8.HttpClient }, { type: ContextService }, { type: ColumnInfoService }]; }, propDecorators: { aiPrompt: [{
29628
- type: ViewChild,
29629
- args: [AIPromptComponent]
29630
- }] } });
29631
-
29632
- /**
29633
- * Represents an AI Assistant tool of the Grid.
29634
- * Use this directive on any `kendo-toolbar-button` inside a ToolbarComponent in the Grid.
29635
- *
29636
- * @example
29637
- * ```html-no-run
29638
- * <kendo-grid>
29639
- * <kendo-toolbar>
29640
- * <kendo-toolbar-button kendoGridAIAssistantTool></kendo-toolbar-button>
29641
- * </kendo-toolbar>
29642
- * </kendo-grid>
29643
- * ```
29644
- * @remarks
29645
- * Applied to: {@link ToolBarButtonComponent}.
29646
- */
29647
- class AIAssistantToolbarDirective extends ToolbarToolBase {
29648
- windowService;
29649
- host;
29650
- ctx;
29651
- zone;
29652
- refresh;
29653
29957
  /**
29654
- * The URL to which the AI Assistant tool sends the AI request.
29655
- * - When you set this property, the AI Assistant tool sends and handles an HTTP request to the provided `requestUrl`. You can handle the `promptRequest` event to modify the request options before the tool sends it.
29656
- * - When you do not set this property, the AI Assistant tool does not send an HTTP request. You should handle the `promptRequest` event to send and handle a custom HTTP request.
29958
+ * @hidden
29657
29959
  */
29658
- requestUrl;
29960
+ get isAdaptiveModeEnabled() {
29961
+ return this.adaptiveMode === 'auto';
29962
+ }
29659
29963
  /**
29660
- * Configures the request options that the AI Assistant tool sends with the AI request.
29964
+ * @hidden
29661
29965
  *
29662
- * @default { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), role: 'user', method: 'POST', responseType: 'json', withCredentials: false }
29966
+ * The `isOpen` property is used to determine if a Grid Popup or ActionSheet is open.
29663
29967
  */
29664
- requestOptions;
29968
+ get isOpen() {
29969
+ return isPresent(this.adaptiveGridService.popupRef) || this.isActionSheetExpanded;
29970
+ }
29665
29971
  /**
29666
- * Configures the initial settings for the AI Assistant Window when opened.
29972
+ * @hidden
29667
29973
  */
29668
- aiWindowSettings;
29974
+ get isActionSheetExpanded() {
29975
+ return Boolean(this.adaptiveRenderer?.actionSheet?.expanded);
29976
+ }
29669
29977
  /**
29670
- * Configures the initial settings for the AI Prompt component that the AI Assistant Window component uses when opened.
29978
+ * @hidden
29671
29979
  */
29672
- aiPromptSettings;
29980
+ gridData = () => { return this.flatData; };
29673
29981
  /**
29674
- * Determines whether to close the AI Assistant Window automatically after a successful request.
29675
- * @default true
29982
+ * Enables the [filtering](slug:filtering_grid) feature of the Grid for columns with a `field` option.
29983
+ *
29984
+ * @default false
29676
29985
  */
29677
- autoClose = true;
29986
+ filterable = false;
29678
29987
  /**
29679
- * Determines whether to keep the AI Prompt's outputs after closing the AI Assistant Window.
29988
+ * Enables [sorting]({% slug sorting_grid %}) feature of the Grid for columns with a `field` option.
29680
29989
  * @default false
29681
29990
  */
29682
- keepOutputHistory = false;
29991
+ sortable = false;
29683
29992
  /**
29684
- * Emits an event before the AI Assistant tool sends the AI request.
29685
- * - When you provide a `requestUrl`, you can handle the event to modify the request options.
29686
- * - When you do not provide a `requestUrl`, you can handle the event to perform an entirely custom request.
29993
+ * Configures the Grid pager ([see example](slug:paging_grid_settings)).
29994
+ * @default false
29687
29995
  */
29688
- promptRequest = new EventEmitter();
29996
+ pageable = false;
29997
+ get normalizedPageableSettings() {
29998
+ return normalize(this.pageable);
29999
+ }
29689
30000
  /**
29690
- * Emits an event when the user clicks the cancel button.
30001
+ * If `true`, allows grouping by dragging column headers ([see example]({% slug grouping_grid %})).
30002
+ *
30003
+ * @default false
29691
30004
  */
29692
- cancelRequest = new EventEmitter();
30005
+ groupable = false;
29693
30006
  /**
29694
- * Emits an event when the AI Assistant tool completes the AI request successfully.
29695
- * The event contains the response from the AI service and is preventable to allow stopping the default response handling.
30007
+ * Determines if the Grid can be resized.
30008
+ *
30009
+ * @default false
29696
30010
  */
29697
- responseSuccess = new EventEmitter();
30011
+ gridResizable = false;
29698
30012
  /**
29699
- * Emits an event when the AI Assistant tool completes the AI request with an error.
29700
- * The event contains the error response from the AI service and is preventable to allow stopping the default error handling.
30013
+ * Enables row reordering feature of the Grid ([see example]({% slug reordering_rows_grid %})).
30014
+ *
30015
+ * @default false
29701
30016
  */
29702
- responseError = new EventEmitter();
30017
+ set rowReorderable(value) {
30018
+ this._rowReorderable = value;
30019
+ if (value) {
30020
+ this.rowReorderSubscription = this.rowReorderService.rowReorder.subscribe(args => {
30021
+ this.ngZone.run(() => {
30022
+ this.rowReorder.emit(args);
30023
+ });
30024
+ });
30025
+ }
30026
+ else {
30027
+ this.rowReorderSubscription?.unsubscribe();
30028
+ }
30029
+ }
30030
+ get rowReorderable() {
30031
+ return this._rowReorderable;
30032
+ }
29703
30033
  /**
29704
- * Emits an event when the AI Assistant tool closes.
30034
+ * By default, navigation is enabled. To disable, set to `false`.
30035
+ * To enable navigation for specific sections, provide a [`GridNavigableSection`](slug:api_grid_gridnavigablesection).
29705
30036
  */
29706
- close = new EventEmitter();
30037
+ set navigable(value) {
30038
+ if (typeof value === 'boolean') {
30039
+ this._navigable = value ? ['table', 'pager', 'toolbar'] : [];
30040
+ this.ctx.navigable = value;
30041
+ return;
30042
+ }
30043
+ else {
30044
+ this.ctx.navigable = value.includes('table');
30045
+ }
30046
+ this._navigable = value;
30047
+ }
30048
+ get navigable() {
30049
+ return this._navigable;
30050
+ }
29707
30051
  /**
29708
- * Emits an event when the AI Assistant tool opens.
30052
+ * If `true`, resizes columns during initialization to fit headers and content.
30053
+ * Columns with `autoSize` set to `false` are excluded.
30054
+ * [See example](slug:resizing_columns_grid).
30055
+ *
30056
+ * @default false
29709
30057
  */
29710
- open = new EventEmitter();
29711
- tableWizardIcon = tableWizardIcon;
29712
- emitOpenClose = false;
29713
- promptOutputs = [];
29714
- windowRef;
29715
- subs = new Subscription();
29716
- defaultAiPromptSettings = {
29717
- speechToTextButton: true,
29718
- generateButtonSVGIcon: this.tableWizardIcon,
29719
- generateButtonIcon: 'table-wizard'
29720
- };
29721
- constructor(windowService, host, ctx, zone, refresh, cdr) {
29722
- super(host, ToolbarToolName.aiAssistant, ctx, zone, cdr);
29723
- this.windowService = windowService;
29724
- this.host = host;
29725
- this.ctx = ctx;
29726
- this.zone = zone;
29727
- this.refresh = refresh;
29728
- this.host.rounded = 'full';
29729
- this.host.themeColor = 'primary';
29730
- this.host.showText = 'never';
29731
- }
29732
- ngOnInit() {
29733
- this.subs.add(this.host.click.subscribe(() => this.onClick()));
29734
- const hasToolbarIcon = isPresent$1(this.host.toolbarOptions.icon) && this.host.toolbarOptions.icon !== '';
29735
- const hasOverflowIcon = isPresent$1(this.host.overflowOptions.icon) && this.host.overflowOptions.icon !== '';
29736
- const hasIcon = hasToolbarIcon && hasOverflowIcon;
29737
- const hasSvgIcon = isPresent$1(this.host.toolbarOptions.svgIcon) && isPresent$1(this.host.overflowOptions.svgIcon);
29738
- if (!hasIcon) {
29739
- this.host.icon = 'sparkles';
29740
- }
29741
- if (!hasSvgIcon) {
29742
- this.host.svgIcon = sparklesIcon;
29743
- }
29744
- this.requestOptions = { ...DEFAULT_AI_REQUEST_OPTIONS, ...this.requestOptions };
29745
- }
29746
- ngAfterViewInit() {
29747
- super.ngAfterViewInit();
29748
- this.zone.onStable.pipe(take(1)).subscribe(() => {
29749
- this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
29750
- this.buttonElement?.setAttribute('aria-expanded', 'false');
29751
- const needsTitle = this.host.showText !== 'always' && this.host.showText !== 'toolbar';
29752
- if (needsTitle && !this.host.title) {
29753
- this.buttonElement?.setAttribute('title', this.ctx.localization.get('aiAssistantToolbarToolText'));
29754
- }
29755
- });
29756
- this.subs.add(this.refresh.onRefresh.pipe(filter((tool) => tool === this.host)).subscribe((tool) => {
29757
- if (tool.overflows && this.windowRef) {
29758
- this.windowRef.close();
29759
- }
29760
- }));
29761
- }
29762
- ngOnDestroy() {
29763
- super.ngOnDestroy();
29764
- this.subs.unsubscribe();
29765
- this.promptOutputs = [];
29766
- }
30058
+ autoSize = false;
29767
30059
  /**
29768
- * @hidden
30060
+ * Sets a function to apply custom CSS classes to each data row ([see example](slug:styling_grid_rows)).
29769
30061
  */
29770
- onClick() {
29771
- this.emitOpenClose = true;
29772
- this.toggleWindow();
30062
+ set rowClass(fn) {
30063
+ if (isDevMode() && typeof fn !== 'function') {
30064
+ throw new Error(GridConfigurationErrorMessages.functionType('rowClass', fn));
30065
+ }
30066
+ this._rowClass = fn;
30067
+ }
30068
+ get rowClass() {
30069
+ return this._rowClass;
29773
30070
  }
29774
30071
  /**
29775
- * Toggles the AI Assistant window.
30072
+ * Sets a function to determine if a data row is sticky (always visible after scrolling).
29776
30073
  */
29777
- toggleWindow() {
29778
- if (!this.windowRef) {
29779
- this.openWindow();
30074
+ set rowSticky(fn) {
30075
+ if (isDevMode() && isPresent(fn) && typeof fn !== 'function') {
30076
+ throw new Error(GridConfigurationErrorMessages.functionType('rowSticky', fn));
29780
30077
  }
29781
- else {
29782
- this.closeWindow();
30078
+ if (isPresent(fn)) {
30079
+ this._rowSticky = fn;
29783
30080
  }
29784
30081
  }
29785
- openWindow() {
29786
- if (!this.keepOutputHistory) {
29787
- this.promptOutputs = [];
29788
- }
29789
- const defaultWindowWidth = 437;
29790
- const rtl = this.ctx.localization.rtl;
29791
- const defaultWindowSettings = {
29792
- left: rtl ? this.buttonElement.offsetLeft - (this.aiWindowSettings.width || defaultWindowWidth) : this.buttonElement.offsetLeft + this.buttonElement.offsetWidth,
29793
- top: this.buttonElement.offsetTop + this.buttonElement.offsetHeight,
29794
- width: defaultWindowWidth,
29795
- title: this.ctx.localization.get('aiAssistantWindowTitle'),
29796
- cssClass: 'k-grid-assistant-window',
29797
- content: AiAssistantComponent,
29798
- autoFocusedElement: '.k-input-inner',
29799
- appendTo: this.ctx.grid.windowContainer
29800
- };
29801
- this.aiWindowSettings = {
29802
- ...defaultWindowSettings,
29803
- ...this.aiWindowSettings
29804
- };
29805
- this.windowRef = this.windowService.open(this.aiWindowSettings);
29806
- this.windowRef.window.instance.messages = {
29807
- closeTitle: this.ctx.localization.get('aiAssistantWindowCloseTitle'),
29808
- maximizeTitle: this.ctx.localization.get('aiAssistantWindowMaximizeTitle'),
29809
- minimizeTitle: this.ctx.localization.get('aiAssistantWindowMinimizeTitle'),
29810
- restoreTitle: this.ctx.localization.get('aiAssistantWindowRestoreTitle')
29811
- };
29812
- const aiPrompt = this.windowRef.content.instance;
29813
- aiPrompt.requestUrl = this.requestUrl;
29814
- aiPrompt.requestOptions = this.requestOptions;
29815
- aiPrompt.aiToolDirective = this;
29816
- aiPrompt.disabledGenerateButton = this.aiPromptSettings?.disabledGenerateButton;
29817
- aiPrompt.streaming = this.aiPromptSettings?.streaming || false;
29818
- aiPrompt.activeView = this.aiPromptSettings?.activeView || 0;
29819
- aiPrompt.aiPromptSettings = { ...this.defaultAiPromptSettings, ...this.aiPromptSettings };
29820
- if (!aiPrompt.aiPromptSettings.promptOutputs) {
29821
- aiPrompt.aiPromptSettings.promptOutputs = this.promptOutputs;
29822
- }
29823
- if (this.emitOpenClose) {
29824
- this.zone.onStable.pipe(take(1)).subscribe(() => {
29825
- const event = {
29826
- aiWindow: this.windowRef.window.instance,
29827
- aiPrompt: this.windowRef.content.instance.aiPrompt
29828
- };
29829
- this.open.emit(event);
29830
- this.emitOpenClose = false;
29831
- });
29832
- }
29833
- this.subs.add(this.windowRef.window.instance.close.subscribe(() => {
29834
- this.emitOpenClose = true;
29835
- this.closeWindow(true);
29836
- }));
29837
- this.host.selected = true;
30082
+ get rowSticky() {
30083
+ return this._rowSticky;
29838
30084
  }
29839
- closeWindow(focusAnchor = false) {
29840
- this.windowRef.close();
29841
- if (this.emitOpenClose) {
29842
- this.close.emit();
29843
- this.emitOpenClose = false;
30085
+ /**
30086
+ * Sets a function to determine if a data row is selected ([see example]({% slug grid_selection_custom %}#toc-setting-the-selected-rows)).
30087
+ */
30088
+ set rowSelected(fn) {
30089
+ if (isDevMode() && typeof fn !== 'function') {
30090
+ throw new Error(GridConfigurationErrorMessages.functionType('rowSelected', fn));
29844
30091
  }
29845
- this.windowRef = null;
29846
- this.buttonElement?.setAttribute('aria-expanded', 'false');
29847
- this.buttonElement?.removeAttribute('aria-controls');
29848
- this.host.selected = false;
29849
- focusAnchor && this.buttonElement?.focus();
30092
+ this._rowSelected = fn;
30093
+ }
30094
+ get rowSelected() {
30095
+ return this._rowSelected;
29850
30096
  }
29851
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIAssistantToolbarDirective, deps: [{ token: i1$7.WindowService }, { token: i54.ToolBarButtonComponent }, { token: ContextService }, { token: i0.NgZone }, { token: i54.RefreshService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
29852
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: AIAssistantToolbarDirective, isStandalone: true, selector: "[kendoGridAIAssistantTool]", inputs: { requestUrl: "requestUrl", requestOptions: "requestOptions", aiWindowSettings: "aiWindowSettings", aiPromptSettings: "aiPromptSettings", autoClose: "autoClose", keepOutputHistory: "keepOutputHistory" }, outputs: { promptRequest: "promptRequest", cancelRequest: "cancelRequest", responseSuccess: "responseSuccess", responseError: "responseError", close: "close", open: "open" }, usesInheritance: true, ngImport: i0 });
29853
- }
29854
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIAssistantToolbarDirective, decorators: [{
29855
- type: Directive,
29856
- args: [{
29857
- selector: '[kendoGridAIAssistantTool]',
29858
- standalone: true
29859
- }]
29860
- }], ctorParameters: function () { return [{ type: i1$7.WindowService }, { type: i54.ToolBarButtonComponent }, { type: ContextService }, { type: i0.NgZone }, { type: i54.RefreshService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { requestUrl: [{
29861
- type: Input
29862
- }], requestOptions: [{
29863
- type: Input
29864
- }], aiWindowSettings: [{
29865
- type: Input
29866
- }], aiPromptSettings: [{
29867
- type: Input
29868
- }], autoClose: [{
29869
- type: Input
29870
- }], keepOutputHistory: [{
29871
- type: Input
29872
- }], promptRequest: [{
29873
- type: Output
29874
- }], cancelRequest: [{
29875
- type: Output
29876
- }], responseSuccess: [{
29877
- type: Output
29878
- }], responseError: [{
29879
- type: Output
29880
- }], close: [{
29881
- type: Output
29882
- }], open: [{
29883
- type: Output
29884
- }] } });
29885
-
29886
- const createControl = (source) => (acc, key) => {
29887
- acc[key] = new FormControl(source[key]);
29888
- return acc;
29889
- };
29890
- const validateColumnsField = (columns) => expandColumns(columns.toArray())
29891
- .filter(isColumnComponent)
29892
- .filter(({ field }) => !isValidFieldName(field))
29893
- .forEach(({ field }) => console.warn(ColumnConfigurationErrorMessages.fieldName(field)));
29894
- const handleExpandCollapseGroupsService = (service, expandEmitter, collapseEmitter, map) => (service.changes.pipe(filter(({ group, emit }) => emit && isPresent(group)))
29895
- .subscribe((x) => x.expand ? expandEmitter.emit(map(x)) : collapseEmitter.emit(map(x))));
29896
- const handleExpandCollapseDetailsService = (service, expandEmitter, collapseEmitter, map) => (service.changes.pipe(filter(({ dataItem }) => isPresent(dataItem)))
29897
- .subscribe((x) => x.expand ? expandEmitter.emit(map(x)) : collapseEmitter.emit(map(x))));
29898
- const isInEditedCell = (element, gridElement, isStacked = false) => (closest(element, matchesClasses('k-grid-edit-cell')) || (isStacked && closest(element, matchesClasses('k-grid-stack-edit-cell')))) &&
29899
- closest(element, matchesNodeName('kendo-grid')) === gridElement;
29900
- const NOTIFY_DELAY = 500;
29901
- /**
29902
- * Represents the Kendo UI for Angular Data Grid component.
29903
- *
29904
- * Use the `kendo-grid` component to display and manage tabular data.
29905
- *
29906
- * @example
29907
- * ```html
29908
- * <kendo-grid [data]="gridData"></kendo-grid>
29909
- * ```
29910
- *
29911
- * @remarks
29912
- * Supported children components are:
29913
- * {@link CheckboxColumnComponent},
29914
- * {@link ColumnChooserComponent},
29915
- * {@link ColumnComponent},
29916
- * {@link ColumnGroupComponent},
29917
- * {@link ColumnMenuAutoSizeAllColumnsComponent},
29918
- * {@link ColumnMenuAutoSizeColumnComponent},
29919
- * {@link ColumnMenuChooserComponent},
29920
- * {@link ColumnMenuComponent},
29921
- * {@link ColumnMenuFilterComponent},
29922
- * {@link ColumnMenuItemComponent},
29923
- * {@link ColumnMenuLockComponent},
29924
- * {@link ColumnMenuPositionComponent},
29925
- * {@link ColumnMenuSortComponent},
29926
- * {@link ColumnMenuStickComponent},
29927
- * {@link CommandColumnComponent},
29928
- * {@link CustomMessagesComponent},
29929
- * {@link ExcelComponent},
29930
- * {@link GridSpacerComponent},
29931
- * {@link PDFComponent},
29932
- * {@link RowReorderColumnComponent},
29933
- * {@link SpanColumnComponent},
29934
- * {@link ToolBarComponent}.
29935
- */
29936
- class GridComponent {
29937
- supportService;
29938
- selectionService;
29939
- cellSelectionService;
29940
- wrapper;
29941
- groupInfoService;
29942
- groupsService;
29943
- changeNotification;
29944
- detailsService;
29945
- editService;
29946
- filterService;
29947
- pdfService;
29948
- responsiveService;
29949
- renderer;
29950
- excelService;
29951
- ngZone;
29952
- scrollSyncService;
29953
- domEvents;
29954
- columnResizingService;
29955
- changeDetectorRef;
29956
- columnReorderService;
29957
- columnInfoService;
29958
- navigationService;
29959
- sortService;
29960
- scrollRequestService;
29961
- localization;
29962
- ctx;
29963
- sizingService;
29964
- adaptiveGridService;
29965
- rowReorderService;
29966
- dataMappingService;
29967
30097
  /**
29968
- * Sets the data of the Grid. If you provide an array, the Grid gets the total count automatically.
29969
- * ([more information and example]({% slug binding_grid %})).
30098
+ * Sets a function to determine if a data row is selectable.
29970
30099
  */
29971
- set data(value) {
29972
- this._data = value;
29973
- if (this.selectable && this.selectableSettings?.enabled && this.isVirtual) {
29974
- this.blockArrowSelection = false;
29975
- }
29976
- if (this.notifyTimeout) {
29977
- clearTimeout(this.notifyTimeout);
29978
- this.notifyTimeout = null;
29979
- }
29980
- if (this.rowReorderable) {
29981
- this.ngZone.runOutsideAngular(() => {
29982
- this.notifyTimeout = setTimeout(() => {
29983
- this.notifyReorderContainers();
29984
- }, NOTIFY_DELAY);
29985
- });
30100
+ set isRowSelectable(fn) {
30101
+ if (isDevMode() && typeof fn !== 'function') {
30102
+ throw new Error(GridConfigurationErrorMessages.functionType('isRowSelectable', fn));
29986
30103
  }
30104
+ this._isRowSelectable = fn;
29987
30105
  }
29988
- get data() {
29989
- return this._data;
29990
- }
29991
- get hintText() {
29992
- return this.rowReorderService.getDefaultHintText(this.columnList, this.flatData);
30106
+ get isRowSelectable() {
30107
+ return this._isRowSelectable;
29993
30108
  }
29994
30109
  /**
29995
- * @hidden
30110
+ * Sets a function to determine if a data cell is selected.
30111
+ * The function returns an object with `selected` and `item` properties ([see example]({% slug grid_selection_custom %}#toc-setting-the-selected-cells)).
29996
30112
  */
29997
- get customHintTemplate() {
29998
- if (this.rowReorderable) {
29999
- const allColumns = this.columnList.toArray();
30000
- const rowReorderColumn = allColumns.find(column => column.isRowReorderColumn);
30001
- return rowReorderColumn.rowDragHintTemplateRef;
30113
+ set cellSelected(fn) {
30114
+ if (isDevMode() && typeof fn !== 'function') {
30115
+ throw new Error(GridConfigurationErrorMessages.functionType('cellSelected', fn));
30002
30116
  }
30117
+ this._cellSelected = fn;
30118
+ }
30119
+ get cellSelected() {
30120
+ return this._cellSelected;
30003
30121
  }
30004
30122
  /**
30005
- * @hidden
30123
+ * Returns the currently focused cell (if any).
30006
30124
  */
30007
- get hintContext() {
30008
- if (this.customHintTemplate) {
30009
- const draggedRow = this.rowReorderService?.getDraggedRow(this.flatData);
30010
- return {
30011
- $implicit: draggedRow?.dataItem,
30012
- rowIndex: draggedRow?.rowIndex
30013
- };
30014
- }
30125
+ get activeCell() {
30126
+ return this.navigationService.activeCell;
30015
30127
  }
30016
30128
  /**
30017
- * Defines the page size used by the Grid pager.
30018
- * Required for the [`paging`]({% slug paging_grid %}) feature.
30129
+ * Returns the currently focused row (if any).
30019
30130
  */
30020
- pageSize;
30131
+ get activeRow() {
30132
+ return this.navigationService.activeRow;
30133
+ }
30021
30134
  /**
30022
- * Defines the height in pixels for the Grid when `scrollable` is set.
30023
- * You can also set the height using `style.height` with units like `px`, `%`, `em`, or `rem`.
30135
+ * Returns the current Grid selection.
30136
+ *
30137
+ * @hidden
30024
30138
  */
30025
- height;
30139
+ get selection() {
30140
+ return (this.selectable || this.selectionDirective) ?
30141
+ this.defaultSelection ? this.defaultSelection.stateToArray() : this.selectionDirective.stateToArray() :
30142
+ [];
30143
+ }
30026
30144
  /**
30027
- * Sets the `style.height` attribute of each Grid data or group header/footer row (`tr`) element in the DOM in pixels.
30028
- * If some row cells have content that requires more space, the row automatically expands to fit the content.
30145
+ * Gets the current `GridState`, including data operations and column state.
30146
+ * Use this to store and restore the Grid state.
30029
30147
  */
30030
- rowHeight;
30148
+ get currentState() {
30149
+ return {
30150
+ filter: this.filter,
30151
+ group: this.group,
30152
+ sort: this.sort,
30153
+ skip: this.skip,
30154
+ take: this.pageSize,
30155
+ columnsState: this.columns.toArray().flatMap(recursiveColumnsFlatMap),
30156
+ currentData: structuredClone(this.data)
30157
+ };
30158
+ }
30031
30159
  /**
30032
- * Enables or disables adaptive mode. Adaptive rendering is off by default.
30160
+ * If `true`, allows resizing columns by dragging header cell edges ([see example]({% slug resizing_columns_grid %})).
30033
30161
  *
30034
- * @default 'none'
30162
+ * @default false
30035
30163
  */
30036
- adaptiveMode = 'none';
30164
+ resizable = false;
30037
30165
  /**
30038
- * Sets the `style.height` attribute of each Grid detail row (`tr.k-detail-row`) element in the DOM in pixels.
30039
- * If the detail row has content that requires more space, the row automatically expands to fit the content.
30166
+ * If `true`, allows reordering columns by dragging header cells ([see example]({% slug reordering_columns_grid %})).
30167
+ *
30168
+ * @default false
30040
30169
  */
30041
- detailRowHeight;
30170
+ reorderable = false;
30042
30171
  /**
30043
- * Defines the number of records to skip in the pager.
30044
- * Required for the [`paging`]({% slug paging_grid %}) feature.
30172
+ * If `true`, displays the Grid loading indicator ([see example]({% slug binding_grid %})).
30173
+ *
30174
+ * @default false
30045
30175
  */
30046
- get skip() {
30047
- return this._skip;
30176
+ set loading(value) {
30177
+ this._loading = value;
30178
+ this.rowReorderable && this.notifyReorderContainers();
30048
30179
  }
30049
- set skip(value) {
30050
- if (typeof value === 'number' && value >= 0) {
30051
- this._skip = this.rowReorderService.skip = value;
30052
- }
30180
+ get loading() {
30181
+ return this._loading;
30053
30182
  }
30054
30183
  /**
30055
- * Defines the scroll mode for the Grid.
30184
+ * If `true`, displays the column menu for columns ([see example]({% slug columnmenu_grid %})).
30056
30185
  *
30057
- * @default 'scrollable'
30186
+ * @default false
30058
30187
  */
30059
- scrollable = 'scrollable';
30188
+ columnMenu = false;
30060
30189
  /**
30061
- * Enables the selection feature of the Grid. The `selectable` property can be set to `true`, `false`, or an object with additional settings.
30062
- * [See example](slug:grid_row_selection).
30190
+ * If `true`, hides the Grid header. The header is visible by default.
30191
+ * The header includes column headers and the [filter row](slug:filter_row).
30063
30192
  *
30064
30193
  * @default false
30065
30194
  */
30066
- selectable = false;
30195
+ hideHeader = false;
30067
30196
  /**
30068
- * Sets the descriptors for sorting the data ([see example]({% slug sorting_grid %})).
30197
+ * Specifies if the currently inactive toolbar tools will be visible. Applicable when the toolbar is configured using the `<kendo-toolbar>` component. By default, such tools are hidden.
30198
+ *
30199
+ * @default false
30069
30200
  */
30070
- set sort(value) {
30071
- if (isArray(value)) {
30072
- this._sort = value;
30073
- }
30201
+ showInactiveTools = false;
30202
+ /**
30203
+ * Sets a function to determine if a specific row is expanded.
30204
+ */
30205
+ set isDetailExpanded(callback) {
30206
+ this.detailsService.userCallback = callback;
30074
30207
  }
30075
- get sort() {
30076
- return this._sort;
30208
+ get isDetailExpanded() {
30209
+ return this.detailsService.userCallback;
30077
30210
  }
30078
30211
  /**
30079
- * Specifies the sizing for Grid elements like tables, buttons, and inputs.
30080
- *
30081
- * @default 'medium'
30212
+ * Sets a function to determine if a specific group row is expanded.
30082
30213
  */
30083
- set size(size) {
30084
- this._size = size;
30085
- if (size === 'none') {
30086
- this.wrapper.nativeElement.classList.remove('k-grid-sm', 'k-grid-md');
30087
- }
30088
- this.sizingService.changes.next(this.size);
30214
+ set isGroupExpanded(callback) {
30215
+ this.groupsService.userCallback = callback;
30216
+ this.groupable = isPresent(callback);
30089
30217
  }
30090
- get size() {
30091
- return this._size;
30218
+ get isGroupExpanded() {
30219
+ return this.groupsService.userCallback;
30092
30220
  }
30093
30221
  /**
30094
- * A function that defines how to track changes for the data rows.
30095
- * By default, the Grid tracks changes by the index of the data item.
30096
- * Edited rows are tracked by reference.
30097
- * [See example](slug:track_changes_grid).
30222
+ * Sets the Grid data layout display mode.
30223
+ *
30224
+ * @default 'columns'
30098
30225
  */
30099
- trackBy = defaultTrackBy;
30226
+ dataLayoutMode = 'columns';
30100
30227
  /**
30101
- * Sets the filter descriptor for the data ([see examples]({% slug filtering_grid %})).
30228
+ * Fires when the Grid data is filtered through the UI and the filter descriptor changes.
30102
30229
  */
30103
- filter;
30230
+ filterChange = new EventEmitter();
30104
30231
  /**
30105
- * Sets the descriptors for grouping the data ([see example]({% slug grouping_grid %})).
30232
+ * Fires when the page is changed through the UI ([see example]({% slug paging_grid %})).
30106
30233
  */
30107
- set group(value) {
30108
- if (isArray(value)) {
30109
- this._group = value;
30110
- }
30111
- }
30112
- get group() {
30113
- return this._group;
30114
- }
30234
+ pageChange = new EventEmitter();
30115
30235
  /**
30116
- * If `true`, renders only columns in the current viewport.
30117
- *
30118
- * @default false
30236
+ * Fires when the Grid data is grouped through the UI and the group descriptors change ([see example]({% slug grouping_grid %})).
30119
30237
  */
30120
- virtualColumns = false;
30238
+ groupChange;
30121
30239
  /**
30122
- * @hidden
30240
+ * Fires when the Grid data is sorted through the UI and the sort descriptors change ([see example]({% slug sorting_grid %})).
30123
30241
  */
30124
- get showStatusBar() {
30125
- return !!(this.selectable);
30126
- }
30242
+ sortChange = new EventEmitter();
30127
30243
  /**
30128
- * @hidden
30244
+ * Fires when the Grid selection changes through the UI.
30129
30245
  */
30130
- get showTopToolbar() {
30131
- return this.toolbarTemplate && ['top', 'both'].indexOf(this.toolbarTemplate.position) > -1;
30132
- }
30246
+ selectionChange = new EventEmitter();
30133
30247
  /**
30134
- * @hidden
30248
+ * Fires when a row is reordered through the UI.
30135
30249
  */
30136
- get showBottomToolbar() {
30137
- return this.toolbarTemplate && ['bottom', 'both'].indexOf(this.toolbarTemplate.position) > -1;
30138
- }
30250
+ rowReorder = new EventEmitter();
30139
30251
  /**
30140
- * @hidden
30252
+ * Fires when the data state of the Grid is changed.
30141
30253
  */
30142
- get isLocked() {
30143
- return (this.lockedLeafColumns.length > 0 && !this.isStacked);
30144
- }
30254
+ dataStateChange = new EventEmitter();
30145
30255
  /**
30146
- * @hidden
30256
+ * Fires when the data or columns state of the Grid is changed.
30147
30257
  */
30148
- get showTopPager() {
30149
- const position = this.pageable.position;
30150
- return this.pageable !== false && ['top', 'both'].indexOf(position) > -1;
30151
- }
30258
+ gridStateChange = new EventEmitter();
30152
30259
  /**
30153
- * @hidden
30260
+ * Fires when a group is expanded through the UI.
30154
30261
  */
30155
- get showBottomPager() {
30156
- const position = this.pageable.position;
30157
- return this.pageable !== false && position !== 'top';
30158
- }
30262
+ groupExpand = new EventEmitter();
30159
30263
  /**
30160
- * @hidden
30264
+ * Fires when a group is collapsed through the UI.
30161
30265
  */
30162
- get hasPager() {
30163
- return this.showTopPager || this.showBottomPager;
30164
- }
30266
+ groupCollapse = new EventEmitter();
30165
30267
  /**
30166
- * @hidden
30268
+ * Fires when a detail row is expanded through the UI.
30167
30269
  */
30168
- get showGroupPanel() {
30169
- const isGroupable = this.groupable && this.groupable.enabled !== false;
30170
- const isGrouped = this.group?.length > 0;
30171
- return this.isStacked ? isGroupable && isGrouped : isGroupable;
30172
- }
30270
+ detailExpand = new EventEmitter();
30173
30271
  /**
30174
- * @hidden
30175
- */
30176
- get groupableEmptyText() {
30177
- return this.groupable.emptyText;
30178
- }
30179
- /**
30180
- * @hidden
30181
- */
30182
- get marqueeSelection() {
30183
- return this.selectionService.enableMarquee || this.cellSelectionService.enableMarquee;
30184
- }
30185
- /**
30186
- * @hidden
30187
- */
30188
- get isAdaptiveModeEnabled() {
30189
- return this.adaptiveMode === 'auto';
30190
- }
30191
- /**
30192
- * @hidden
30193
- *
30194
- * The `isOpen` property is used to determine if a Grid Popup or ActionSheet is open.
30195
- */
30196
- get isOpen() {
30197
- return isPresent(this.adaptiveGridService.popupRef) || this.isActionSheetExpanded;
30198
- }
30199
- /**
30200
- * @hidden
30201
- */
30202
- get isActionSheetExpanded() {
30203
- return Boolean(this.adaptiveRenderer?.actionSheet?.expanded);
30204
- }
30205
- /**
30206
- * @hidden
30207
- */
30208
- gridData = () => { return this.flatData; };
30209
- /**
30210
- * Enables the [filtering](slug:filtering_grid) feature of the Grid for columns with a `field` option.
30211
- *
30212
- * @default false
30213
- */
30214
- filterable = false;
30215
- /**
30216
- * Enables [sorting]({% slug sorting_grid %}) feature of the Grid for columns with a `field` option.
30217
- * @default false
30218
- */
30219
- sortable = false;
30220
- /**
30221
- * Configures the Grid pager ([see example](slug:paging_grid_settings)).
30222
- * @default false
30223
- */
30224
- pageable = false;
30225
- get normalizedPageableSettings() {
30226
- return normalize(this.pageable);
30227
- }
30228
- /**
30229
- * If `true`, allows grouping by dragging column headers ([see example]({% slug grouping_grid %})).
30230
- *
30231
- * @default false
30232
- */
30233
- groupable = false;
30234
- /**
30235
- * Determines if the Grid can be resized.
30236
- *
30237
- * @default false
30238
- */
30239
- gridResizable = false;
30240
- /**
30241
- * Enables row reordering feature of the Grid ([see example]({% slug reordering_rows_grid %})).
30242
- *
30243
- * @default false
30244
- */
30245
- set rowReorderable(value) {
30246
- this._rowReorderable = value;
30247
- if (value) {
30248
- this.rowReorderSubscription = this.rowReorderService.rowReorder.subscribe(args => {
30249
- this.ngZone.run(() => {
30250
- this.rowReorder.emit(args);
30251
- });
30252
- });
30253
- }
30254
- else {
30255
- this.rowReorderSubscription?.unsubscribe();
30256
- }
30257
- }
30258
- get rowReorderable() {
30259
- return this._rowReorderable;
30260
- }
30261
- /**
30262
- * By default, navigation is enabled. To disable, set to `false`.
30263
- * To enable navigation for specific sections, provide a [`GridNavigableSection`](slug:api_grid_gridnavigablesection).
30264
- */
30265
- set navigable(value) {
30266
- if (typeof value === 'boolean') {
30267
- this._navigable = value ? ['table', 'pager', 'toolbar'] : [];
30268
- this.ctx.navigable = value;
30269
- return;
30270
- }
30271
- else {
30272
- this.ctx.navigable = value.includes('table');
30273
- }
30274
- this._navigable = value;
30275
- }
30276
- get navigable() {
30277
- return this._navigable;
30278
- }
30279
- /**
30280
- * If `true`, resizes columns during initialization to fit headers and content.
30281
- * Columns with `autoSize` set to `false` are excluded.
30282
- * [See example](slug:resizing_columns_grid).
30283
- *
30284
- * @default false
30285
- */
30286
- autoSize = false;
30287
- /**
30288
- * Sets a function to apply custom CSS classes to each data row ([see example](slug:styling_grid_rows)).
30289
- */
30290
- set rowClass(fn) {
30291
- if (isDevMode() && typeof fn !== 'function') {
30292
- throw new Error(GridConfigurationErrorMessages.functionType('rowClass', fn));
30293
- }
30294
- this._rowClass = fn;
30295
- }
30296
- get rowClass() {
30297
- return this._rowClass;
30298
- }
30299
- /**
30300
- * Sets a function to determine if a data row is sticky (always visible after scrolling).
30301
- */
30302
- set rowSticky(fn) {
30303
- if (isDevMode() && isPresent(fn) && typeof fn !== 'function') {
30304
- throw new Error(GridConfigurationErrorMessages.functionType('rowSticky', fn));
30305
- }
30306
- if (isPresent(fn)) {
30307
- this._rowSticky = fn;
30308
- }
30309
- }
30310
- get rowSticky() {
30311
- return this._rowSticky;
30312
- }
30313
- /**
30314
- * Sets a function to determine if a data row is selected ([see example]({% slug grid_selection_custom %}#toc-setting-the-selected-rows)).
30315
- */
30316
- set rowSelected(fn) {
30317
- if (isDevMode() && typeof fn !== 'function') {
30318
- throw new Error(GridConfigurationErrorMessages.functionType('rowSelected', fn));
30319
- }
30320
- this._rowSelected = fn;
30321
- }
30322
- get rowSelected() {
30323
- return this._rowSelected;
30324
- }
30325
- /**
30326
- * Sets a function to determine if a data row is selectable.
30327
- */
30328
- set isRowSelectable(fn) {
30329
- if (isDevMode() && typeof fn !== 'function') {
30330
- throw new Error(GridConfigurationErrorMessages.functionType('isRowSelectable', fn));
30331
- }
30332
- this._isRowSelectable = fn;
30333
- }
30334
- get isRowSelectable() {
30335
- return this._isRowSelectable;
30336
- }
30337
- /**
30338
- * Sets a function to determine if a data cell is selected.
30339
- * The function returns an object with `selected` and `item` properties ([see example]({% slug grid_selection_custom %}#toc-setting-the-selected-cells)).
30340
- */
30341
- set cellSelected(fn) {
30342
- if (isDevMode() && typeof fn !== 'function') {
30343
- throw new Error(GridConfigurationErrorMessages.functionType('cellSelected', fn));
30344
- }
30345
- this._cellSelected = fn;
30346
- }
30347
- get cellSelected() {
30348
- return this._cellSelected;
30349
- }
30350
- /**
30351
- * Returns the currently focused cell (if any).
30352
- */
30353
- get activeCell() {
30354
- return this.navigationService.activeCell;
30355
- }
30356
- /**
30357
- * Returns the currently focused row (if any).
30358
- */
30359
- get activeRow() {
30360
- return this.navigationService.activeRow;
30361
- }
30362
- /**
30363
- * Returns the current Grid selection.
30364
- *
30365
- * @hidden
30366
- */
30367
- get selection() {
30368
- return (this.selectable || this.selectionDirective) ?
30369
- this.defaultSelection ? this.defaultSelection.stateToArray() : this.selectionDirective.stateToArray() :
30370
- [];
30371
- }
30372
- /**
30373
- * Gets the current `GridState`, including data operations and column state.
30374
- * Use this to store and restore the Grid state.
30375
- */
30376
- get currentState() {
30377
- return {
30378
- filter: this.filter,
30379
- group: this.group,
30380
- sort: this.sort,
30381
- skip: this.skip,
30382
- take: this.pageSize,
30383
- columnsState: this.columns.toArray().flatMap(recursiveColumnsFlatMap),
30384
- currentData: structuredClone(this.data)
30385
- };
30386
- }
30387
- /**
30388
- * If `true`, allows resizing columns by dragging header cell edges ([see example]({% slug resizing_columns_grid %})).
30389
- *
30390
- * @default false
30391
- */
30392
- resizable = false;
30393
- /**
30394
- * If `true`, allows reordering columns by dragging header cells ([see example]({% slug reordering_columns_grid %})).
30395
- *
30396
- * @default false
30397
- */
30398
- reorderable = false;
30399
- /**
30400
- * If `true`, displays the Grid loading indicator ([see example]({% slug binding_grid %})).
30401
- *
30402
- * @default false
30403
- */
30404
- set loading(value) {
30405
- this._loading = value;
30406
- this.rowReorderable && this.notifyReorderContainers();
30407
- }
30408
- get loading() {
30409
- return this._loading;
30410
- }
30411
- /**
30412
- * If `true`, displays the column menu for columns ([see example]({% slug columnmenu_grid %})).
30413
- *
30414
- * @default false
30415
- */
30416
- columnMenu = false;
30417
- /**
30418
- * If `true`, hides the Grid header. The header is visible by default.
30419
- * The header includes column headers and the [filter row](slug:filter_row).
30420
- *
30421
- * @default false
30422
- */
30423
- hideHeader = false;
30424
- /**
30425
- * Specifies if the currently inactive toolbar tools will be visible. Applicable when the toolbar is configured using the `<kendo-toolbar>` component. By default, such tools are hidden.
30426
- *
30427
- * @default false
30428
- */
30429
- showInactiveTools = false;
30430
- /**
30431
- * Sets a function to determine if a specific row is expanded.
30432
- */
30433
- set isDetailExpanded(callback) {
30434
- this.detailsService.userCallback = callback;
30435
- }
30436
- get isDetailExpanded() {
30437
- return this.detailsService.userCallback;
30438
- }
30439
- /**
30440
- * Sets a function to determine if a specific group row is expanded.
30441
- */
30442
- set isGroupExpanded(callback) {
30443
- this.groupsService.userCallback = callback;
30444
- this.groupable = isPresent(callback);
30445
- }
30446
- get isGroupExpanded() {
30447
- return this.groupsService.userCallback;
30448
- }
30449
- /**
30450
- * Sets the Grid data layout display mode.
30451
- *
30452
- * @default 'columns'
30453
- */
30454
- dataLayoutMode = 'columns';
30455
- /**
30456
- * Fires when the Grid data is filtered through the UI and the filter descriptor changes.
30457
- */
30458
- filterChange = new EventEmitter();
30459
- /**
30460
- * Fires when the page is changed through the UI ([see example]({% slug paging_grid %})).
30461
- */
30462
- pageChange = new EventEmitter();
30463
- /**
30464
- * Fires when the Grid data is grouped through the UI and the group descriptors change ([see example]({% slug grouping_grid %})).
30465
- */
30466
- groupChange;
30467
- /**
30468
- * Fires when the Grid data is sorted through the UI and the sort descriptors change ([see example]({% slug sorting_grid %})).
30469
- */
30470
- sortChange = new EventEmitter();
30471
- /**
30472
- * Fires when the Grid selection changes through the UI.
30473
- */
30474
- selectionChange = new EventEmitter();
30475
- /**
30476
- * Fires when a row is reordered through the UI.
30477
- */
30478
- rowReorder = new EventEmitter();
30479
- /**
30480
- * Fires when the data state of the Grid is changed.
30481
- */
30482
- dataStateChange = new EventEmitter();
30483
- /**
30484
- * Fires when the data or columns state of the Grid is changed.
30485
- */
30486
- gridStateChange = new EventEmitter();
30487
- /**
30488
- * Fires when a group is expanded through the UI.
30489
- */
30490
- groupExpand = new EventEmitter();
30491
- /**
30492
- * Fires when a group is collapsed through the UI.
30493
- */
30494
- groupCollapse = new EventEmitter();
30495
- /**
30496
- * Fires when a detail row is expanded through the UI.
30497
- */
30498
- detailExpand = new EventEmitter();
30499
- /**
30500
- * Fires when a detail row is collapsed through the UI.
30272
+ * Fires when a detail row is collapsed through the UI.
30501
30273
  */
30502
30274
  detailCollapse = new EventEmitter();
30503
30275
  /**
@@ -30677,7 +30449,6 @@ class GridComponent {
30677
30449
  this._customToolbarTemplate = customToolbarTemplate;
30678
30450
  }
30679
30451
  columnMenuTemplates;
30680
- aiAssistantToolbarTool;
30681
30452
  lockedHeader;
30682
30453
  header;
30683
30454
  footer = new QueryList();
@@ -32247,7 +32018,7 @@ class GridComponent {
32247
32018
  ColumnMenuService,
32248
32019
  MenuTabbingService,
32249
32020
  DataMappingService
32250
- ], queries: [{ propertyName: "aiAssistantToolbarTool", first: true, predicate: AIAssistantToolbarDirective, descendants: true }, { propertyName: "columns", predicate: ColumnBase }, { propertyName: "detailTemplateChildren", predicate: DetailTemplateDirective }, { propertyName: "cellLoadingTemplateChildren", predicate: CellLoadingTemplateDirective }, { propertyName: "loadingTemplateChildren", predicate: LoadingTemplateDirective }, { propertyName: "statusBarTemplateChildren", predicate: StatusBarTemplateDirective }, { propertyName: "noRecordsTemplateChildren", predicate: NoRecordsTemplateDirective }, { propertyName: "pagerTemplateChildren", predicate: PagerTemplateDirective }, { propertyName: "toolbarTemplateChildren", predicate: ToolbarTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], viewQueries: [{ propertyName: "lockedHeader", first: true, predicate: ["lockedHeader"], descendants: true }, { propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "ariaRoot", first: true, predicate: ["ariaRoot"], descendants: true, static: true }, { propertyName: "dragTargetContainer", first: true, predicate: DragTargetContainerDirective, descendants: true }, { propertyName: "dropTargetContainer", first: true, predicate: DropTargetContainerDirective, descendants: true }, { propertyName: "dialogContainer", first: true, predicate: ["dialogContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "windowContainer", first: true, predicate: ["windowContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "listComponent", first: true, predicate: ListComponent, descendants: true }, { propertyName: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
32021
+ ], queries: [{ propertyName: "columns", predicate: ColumnBase }, { propertyName: "detailTemplateChildren", predicate: DetailTemplateDirective }, { propertyName: "cellLoadingTemplateChildren", predicate: CellLoadingTemplateDirective }, { propertyName: "loadingTemplateChildren", predicate: LoadingTemplateDirective }, { propertyName: "statusBarTemplateChildren", predicate: StatusBarTemplateDirective }, { propertyName: "noRecordsTemplateChildren", predicate: NoRecordsTemplateDirective }, { propertyName: "pagerTemplateChildren", predicate: PagerTemplateDirective }, { propertyName: "toolbarTemplateChildren", predicate: ToolbarTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], viewQueries: [{ propertyName: "lockedHeader", first: true, predicate: ["lockedHeader"], descendants: true }, { propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "ariaRoot", first: true, predicate: ["ariaRoot"], descendants: true, static: true }, { propertyName: "dragTargetContainer", first: true, predicate: DragTargetContainerDirective, descendants: true }, { propertyName: "dropTargetContainer", first: true, predicate: DropTargetContainerDirective, descendants: true }, { propertyName: "dialogContainer", first: true, predicate: ["dialogContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "windowContainer", first: true, predicate: ["windowContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "listComponent", first: true, predicate: ListComponent, descendants: true }, { propertyName: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
32251
32022
  <ng-container kendoGridLocalizedMessages
32252
32023
  i18n-groupPanelEmpty="kendo.grid.groupPanelEmpty|The label visible in the Grid group panel when it is empty"
32253
32024
  groupPanelEmpty="Drag a column header and drop it here to group by that column"
@@ -32623,6 +32394,15 @@ class GridComponent {
32623
32394
 
32624
32395
  i18n-columnChooserSelectedColumnsCount="kendo.grid.columnChooserSelectedColumnsCount|The text displayed in the Column Chooser for the number of selected columns"
32625
32396
  columnChooserSelectedColumnsCount="{{ '{selectedColumnsCount} Selected items' }}"
32397
+
32398
+ i18n-multiCheckboxFilterSearchPlaceholder="kendo.grid.multiCheckboxFilterSearchPlaceholder|The placeholder text for the multi-checkbox filter search input"
32399
+ multiCheckboxFilterSearchPlaceholder="Search..."
32400
+
32401
+ i18n-multiCheckboxFilterSelectAllLabel="kendo.grid.multiCheckboxFilterSelectAllLabel|The label for the multi-checkbox filter select all option"
32402
+ multiCheckboxFilterSelectAllLabel="Select all"
32403
+
32404
+ i18n-multiCheckboxFilterSelectedItemsCount="kendo.grid.multiCheckboxFilterSelectedItemsCount|The text for the multi-checkbox filter selected items count"
32405
+ multiCheckboxFilterSelectedItemsCount="{{ '{selectedItemsCount} selected items' }}"
32626
32406
  >
32627
32407
  </ng-container>
32628
32408
  <kendo-grid-toolbar
@@ -33041,10 +32821,10 @@ class GridComponent {
33041
32821
  </kendo-pager-info>
33042
32822
  </ng-template>
33043
32823
  <div #dialogContainer></div>
32824
+ <div #windowContainer></div>
33044
32825
 
33045
32826
  <kendo-grid-adaptive-renderer *ngIf="isAdaptiveModeEnabled"></kendo-grid-adaptive-renderer>
33046
32827
  <kendo-resize-sensor *ngIf="isVirtual" (resize)="onResize()"></kendo-resize-sensor>
33047
- <div *ngIf="aiAssistantToolbarTool" #windowContainer></div>
33048
32828
 
33049
32829
  <div kendoWatermarkOverlay *ngIf="showLicenseWatermark" [licenseMessage]="licenseMessage"></div>
33050
32830
  `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoGridLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: ["position", "size", "navigable"] }, { kind: "component", type: GroupPanelComponent, selector: "kendo-grid-group-panel", inputs: ["text", "navigable", "groups"], outputs: ["change"] }, { kind: "directive", type: TableDirective, selector: "[kendoGridResizableTable]", inputs: ["locked", "virtualColumns"] }, { kind: "directive", type: GridTableDirective, selector: "[kendoGridTable]", inputs: ["size"] }, { kind: "component", type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { kind: "component", type: HeaderComponent, selector: "[kendoGridHeader]", inputs: ["totalColumnLevels", "columns", "groups", "detailTemplate", "scrollable", "filterable", "sort", "filter", "sortable", "groupable", "lockedColumnsCount", "resizable", "reorderable", "columnMenu", "columnMenuTemplate", "totalColumnsCount", "totalColumns", "tabIndex", "size"] }, { kind: "directive", type: ResizableContainerDirective, selector: "[kendoGridResizableContainer]", inputs: ["lockedWidth", "kendoGridResizableContainer"] }, { kind: "component", type: ListComponent, selector: "kendo-grid-list", inputs: ["data", "groups", "total", "rowHeight", "detailRowHeight", "take", "skip", "columns", "detailTemplate", "noRecordsTemplate", "selectable", "groupable", "filterable", "rowClass", "rowSticky", "loading", "trackBy", "virtualColumns", "isVirtual", "cellLoadingTemplate", "loadingTemplate", "sort", "size"], outputs: ["contentScroll", "pageChange", "scrollBottom"] }, { kind: "directive", type: DragTargetContainerDirective, selector: "[kendoDragTargetContainer]", inputs: ["hint", "dragTargetFilter", "dragHandle", "dragDelay", "threshold", "dragTargetId", "dragData", "dragDisabled", "mode", "cursorStyle", "hintContext"], outputs: ["onDragReady", "onPress", "onDragStart", "onDrag", "onRelease", "onDragEnd"], exportAs: ["kendoDragTargetContainer"] }, { kind: "directive", type: DropTargetContainerDirective, selector: "[kendoDropTargetContainer]", inputs: ["dropTargetFilter", "dropDisabled"], outputs: ["onDragEnter", "onDragOver", "onDragLeave", "onDrop"], exportAs: ["kendoDropTargetContainer"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]" }, { kind: "component", type: FooterComponent, selector: "[kendoGridFooter]", inputs: ["columns", "groups", "detailTemplate", "scrollable", "lockedColumnsCount", "logicalRowIndex", "totalColumns", "totalColumnsCount"] }, { kind: "component", type: TableBodyComponent, selector: "[kendoGridTableBody]", inputs: ["columns", "allColumns", "groups", "detailTemplate", "noRecordsTemplate", "rowsToRender", "skip", "selectable", "filterable", "noRecordsText", "isLocked", "isLoading", "isVirtual", "cellLoadingTemplate", "skipGroupDecoration", "lockedColumnsCount", "totalColumnsCount", "virtualColumns", "trackBy", "rowSticky", "totalColumns", "rowClass", "rowHeight", "detailRowHeight"] }, { kind: "component", type: LoadingComponent, selector: "[kendoGridLoading]", inputs: ["loadingTemplate"] }, { kind: "component", type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: ["statusBarTemplate"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: WatermarkOverlayComponent, selector: "div[kendoWatermarkOverlay]", inputs: ["licenseMessage"] }, { kind: "component", type: i53.CustomMessagesComponent, selector: "kendo-datapager-messages, kendo-pager-messages" }, { kind: "component", type: i53.PagerInfoComponent, selector: "kendo-datapager-info, kendo-pager-info" }, { kind: "component", type: i53.PagerInputComponent, selector: "kendo-datapager-input, kendo-pager-input", inputs: ["showPageText", "size"] }, { kind: "component", type: i53.PagerNextButtonsComponent, selector: "kendo-datapager-next-buttons, kendo-pager-next-buttons", inputs: ["size"] }, { kind: "component", type: i53.PagerNumericButtonsComponent, selector: "kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons", inputs: ["buttonCount", "size"] }, { kind: "component", type: i53.PagerPageSizesComponent, selector: "kendo-datapager-page-sizes, kendo-pager-page-sizes", inputs: ["showItemsText", "pageSizes", "size", "adaptiveMode"] }, { kind: "component", type: i53.PagerPrevButtonsComponent, selector: "kendo-datapager-prev-buttons, kendo-pager-prev-buttons", inputs: ["size"] }, { kind: "directive", type: i53.PagerTemplateDirective, selector: "[kendoDataPagerTemplate], [kendoPagerTemplate]" }, { kind: "component", type: i53.PagerComponent, selector: "kendo-datapager, kendo-pager", inputs: ["externalTemplate", "total", "skip", "pageSize", "buttonCount", "info", "type", "pageSizeValues", "previousNext", "navigable", "size", "responsive", "adaptiveMode"], outputs: ["pageChange", "pageSizeChange", "pagerInputVisibilityChange", "pageTextVisibilityChange", "itemsTextVisibilityChange"], exportAs: ["kendoDataPager", "kendoPager"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AdaptiveRendererComponent, selector: "kendo-grid-adaptive-renderer" }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }], encapsulation: i0.ViewEncapsulation.None });
@@ -33483,6 +33263,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
33483
33263
 
33484
33264
  i18n-columnChooserSelectedColumnsCount="kendo.grid.columnChooserSelectedColumnsCount|The text displayed in the Column Chooser for the number of selected columns"
33485
33265
  columnChooserSelectedColumnsCount="{{ '{selectedColumnsCount} Selected items' }}"
33266
+
33267
+ i18n-multiCheckboxFilterSearchPlaceholder="kendo.grid.multiCheckboxFilterSearchPlaceholder|The placeholder text for the multi-checkbox filter search input"
33268
+ multiCheckboxFilterSearchPlaceholder="Search..."
33269
+
33270
+ i18n-multiCheckboxFilterSelectAllLabel="kendo.grid.multiCheckboxFilterSelectAllLabel|The label for the multi-checkbox filter select all option"
33271
+ multiCheckboxFilterSelectAllLabel="Select all"
33272
+
33273
+ i18n-multiCheckboxFilterSelectedItemsCount="kendo.grid.multiCheckboxFilterSelectedItemsCount|The text for the multi-checkbox filter selected items count"
33274
+ multiCheckboxFilterSelectedItemsCount="{{ '{selectedItemsCount} selected items' }}"
33486
33275
  >
33487
33276
  </ng-container>
33488
33277
  <kendo-grid-toolbar
@@ -33901,10 +33690,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
33901
33690
  </kendo-pager-info>
33902
33691
  </ng-template>
33903
33692
  <div #dialogContainer></div>
33693
+ <div #windowContainer></div>
33904
33694
 
33905
33695
  <kendo-grid-adaptive-renderer *ngIf="isAdaptiveModeEnabled"></kendo-grid-adaptive-renderer>
33906
33696
  <kendo-resize-sensor *ngIf="isVirtual" (resize)="onResize()"></kendo-resize-sensor>
33907
- <div *ngIf="aiAssistantToolbarTool" #windowContainer></div>
33908
33697
 
33909
33698
  <div kendoWatermarkOverlay *ngIf="showLicenseWatermark" [licenseMessage]="licenseMessage"></div>
33910
33699
  `,
@@ -34113,9 +33902,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
34113
33902
  }], columnMenuTemplates: [{
34114
33903
  type: ContentChildren,
34115
33904
  args: [ColumnMenuTemplateDirective]
34116
- }], aiAssistantToolbarTool: [{
34117
- type: ContentChild,
34118
- args: [AIAssistantToolbarDirective]
34119
33905
  }], lockedHeader: [{
34120
33906
  type: ViewChild,
34121
33907
  args: ['lockedHeader']
@@ -34199,7 +33985,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
34199
33985
  * [sorting]({% slug sorting_grid %}), and [grouping]({% slug grouping_grid %}).
34200
33986
  *
34201
33987
  * Use this directive with local data and enable the Grid data operations with minimal configuration.
34202
- * ([More information and examples]({% slug local_data_grid %}#toc-using-the-data-binding-directive)).
33988
+ * ([More information and examples]({% slug local_data_grid %}#toc-automatic-data-processing)).
34203
33989
  *
34204
33990
  * @example
34205
33991
  * ```html
@@ -35576,6 +35362,9 @@ class GridClipboardDirective {
35576
35362
  const isPaste = operationType === 'paste';
35577
35363
  const pastedData = args.clipboardData.getData('text');
35578
35364
  const visibleCols = this.host.columns.toArray().filter(c => c.isVisible);
35365
+ if (visibleCols.some(c => c.orderIndex > 0)) { // columns have been reordered
35366
+ visibleCols.sort((a, b) => a.orderIndex - b.orderIndex);
35367
+ }
35579
35368
  const data = isPaste ?
35580
35369
  {
35581
35370
  dataString: pastedData,
@@ -37190,325 +36979,1003 @@ class CancelCommandToolbarDirective extends ToolbarEditingToolBase {
37190
36979
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CancelCommandToolbarDirective, deps: [{ token: EditService }, { token: i54.ToolBarButtonComponent }, { token: SelectionService }, { token: ContextService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
37191
36980
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CancelCommandToolbarDirective, isStandalone: true, selector: "[kendoGridCancelTool]", usesInheritance: true, ngImport: i0 });
37192
36981
  }
37193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CancelCommandToolbarDirective, decorators: [{
37194
- type: Directive,
36982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CancelCommandToolbarDirective, decorators: [{
36983
+ type: Directive,
36984
+ args: [{
36985
+ selector: '[kendoGridCancelTool]',
36986
+ standalone: true
36987
+ }]
36988
+ }], ctorParameters: function () { return [{ type: EditService }, { type: i54.ToolBarButtonComponent }, { type: SelectionService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; } });
36989
+
36990
+ let incrementingId = 0;
36991
+ /**
36992
+ * Represents the toolbar tool for grouping columns of the Grid.
36993
+ * Use this directive on any `kendo-toolbar-button` inside a ToolbarComponent in the Grid.
36994
+ * When you click the toolbar button with this directive, the `group` event is triggered.
36995
+ *
36996
+ * @example
36997
+ * ```html
36998
+ * <kendo-grid>
36999
+ * <kendo-toolbar>
37000
+ * <kendo-toolbar-button text="Group" kendoGridGroupTool></kendo-toolbar-button>
37001
+ * </kendo-toolbar>
37002
+ * </kendo-grid>
37003
+ * ```
37004
+ * @remarks
37005
+ * Applied to: {@link ToolBarButtonComponent}.
37006
+ */
37007
+ class GroupCommandToolbarDirective {
37008
+ host;
37009
+ popupService;
37010
+ ctx;
37011
+ ngZone;
37012
+ renderer;
37013
+ adaptiveGridService;
37014
+ popupRef;
37015
+ nextId = incrementingId++;
37016
+ toolSubs = new Subscription();
37017
+ popupSubs;
37018
+ actionSheetCloseSub;
37019
+ removeClickListener;
37020
+ constructor(host, popupService, ctx, ngZone, renderer, adaptiveGridService) {
37021
+ this.host = host;
37022
+ this.popupService = popupService;
37023
+ this.ctx = ctx;
37024
+ this.ngZone = ngZone;
37025
+ this.renderer = renderer;
37026
+ this.adaptiveGridService = adaptiveGridService;
37027
+ }
37028
+ ngOnInit() {
37029
+ this.toolSubs = this.host.click.subscribe(e => this.onClick(e));
37030
+ this.toolSubs.add(this.ctx.grid.groupChange.subscribe(group => {
37031
+ this.host.showBadge = this.isGroupingApplied(group);
37032
+ }));
37033
+ this.host.hasBadgeContainer = true;
37034
+ this.host.showBadge = this.isGroupingApplied(this.ctx.grid.group);
37035
+ const hasToolbarIcon = isPresent$1(this.host.toolbarOptions.icon) && this.host.toolbarOptions.icon !== '';
37036
+ const hasOverflowIcon = isPresent$1(this.host.overflowOptions.icon) && this.host.overflowOptions.icon !== '';
37037
+ const hasIcon = hasToolbarIcon && hasOverflowIcon;
37038
+ const hasSvgIcon = isPresent$1(this.host.toolbarOptions.svgIcon) && isPresent$1(this.host.overflowOptions.svgIcon);
37039
+ if (!hasIcon) {
37040
+ this.host.icon = 'group';
37041
+ }
37042
+ if (!hasSvgIcon) {
37043
+ this.host.svgIcon = groupIcon;
37044
+ }
37045
+ }
37046
+ ngAfterViewInit() {
37047
+ if (!isPresent$1(this.host.text)) {
37048
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => {
37049
+ this.host.text = this.ctx.localization.get(`groupToolbarToolText`);
37050
+ });
37051
+ }
37052
+ this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
37053
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37054
+ this.buttonElement?.setAttribute('title', this.ctx.localization.get('groupToolbarToolText'));
37055
+ }
37056
+ ngOnDestroy() {
37057
+ if (this.toolSubs) {
37058
+ this.toolSubs.unsubscribe();
37059
+ }
37060
+ if (this.popupSubs) {
37061
+ this.popupSubs.unsubscribe();
37062
+ }
37063
+ if (this.popupRef) {
37064
+ this.popupRef.close();
37065
+ this.popupRef = null;
37066
+ }
37067
+ if (this.actionSheetCloseSub) {
37068
+ this.actionSheetCloseSub.unsubscribe();
37069
+ this.actionSheetCloseSub = null;
37070
+ }
37071
+ if (this.removeClickListener) {
37072
+ this.removeClickListener();
37073
+ this.removeClickListener = null;
37074
+ }
37075
+ }
37076
+ onClick(e) {
37077
+ e.preventDefault();
37078
+ if (this.ctx.grid.adaptiveMode === 'auto' && this.adaptiveGridService.windowSize !== 'large') {
37079
+ if (!this.ctx.grid.isActionSheetExpanded) {
37080
+ this.adaptiveGridService.viewType = 'groupToolbarTool';
37081
+ this.ctx.grid.adaptiveRenderer.actionSheet.toggle(true);
37082
+ this.host.selected = true;
37083
+ this.actionSheetCloseSub = this.ctx.grid.adaptiveRenderer.actionSheet.collapse.subscribe(() => this.host.selected = false);
37084
+ }
37085
+ }
37086
+ else {
37087
+ if (this.popupRef) {
37088
+ this.closePopup();
37089
+ return;
37090
+ }
37091
+ this.openPopup();
37092
+ }
37093
+ }
37094
+ openPopup() {
37095
+ const direction = this.ctx.localization.rtl ? 'right' : 'left';
37096
+ this.popupRef = this.popupService.open({
37097
+ anchor: this.buttonElement,
37098
+ content: GroupToolbarToolComponent,
37099
+ popupClass: 'k-grid-columnmenu-popup',
37100
+ positionMode: 'absolute',
37101
+ anchorAlign: { vertical: 'bottom', horizontal: direction },
37102
+ popupAlign: { vertical: 'top', horizontal: direction }
37103
+ });
37104
+ this.adaptiveGridService.popupRef = this.popupRef;
37105
+ this.setPopupAttributes();
37106
+ this.host.selected = true;
37107
+ this.ngZone.runOutsideAngular(() => {
37108
+ if (!isDocumentAvailable()) {
37109
+ return;
37110
+ }
37111
+ this.removeClickListener = this.renderer.listen('document', 'click', (e) => {
37112
+ if (this.popupRef && !closest$1(e.target, node => node === this.popupRef.popupElement || node === this.buttonElement)) {
37113
+ this.ngZone.run(() => {
37114
+ this.closePopup();
37115
+ });
37116
+ }
37117
+ });
37118
+ });
37119
+ this.popupSubs = this.popupRef.popup.instance.anchorViewportLeave.subscribe(() => {
37120
+ this.popupSubs?.unsubscribe();
37121
+ this.popupSubs = null;
37122
+ this.closePopup();
37123
+ });
37124
+ this.initPopupProperties();
37125
+ }
37126
+ setPopupAttributes() {
37127
+ const popupElement = this.popupRef.popupElement;
37128
+ const popupId = `k-group-tool-${this.nextId}-popup`;
37129
+ const popupAriaElement = popupElement.querySelector('.k-popup');
37130
+ this.renderer.setAttribute(popupElement, 'dir', this.ctx.localization.rtl ? 'rtl' : 'ltr');
37131
+ this.renderer.setAttribute(popupAriaElement, 'id', popupId);
37132
+ this.renderer.setAttribute(popupAriaElement, 'role', 'dialog');
37133
+ this.buttonElement?.setAttribute('aria-expanded', 'true');
37134
+ this.buttonElement?.setAttribute('aria-controls', popupId);
37135
+ }
37136
+ initPopupProperties() {
37137
+ this.popupRef.content.instance.ctx = this.ctx;
37138
+ this.popupRef.content.instance.hostButton = this.host;
37139
+ this.popupSubs.add(this.popupRef.content.instance.groupClear.subscribe(() => {
37140
+ this.closePopup();
37141
+ }));
37142
+ this.popupSubs.add(this.popupRef.content.instance.close.subscribe(() => {
37143
+ this.closePopup();
37144
+ }));
37145
+ }
37146
+ closePopup() {
37147
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37148
+ this.buttonElement?.removeAttribute('aria-controls');
37149
+ this.host.selected = false;
37150
+ if (this.popupRef) {
37151
+ this.popupRef.close();
37152
+ this.popupRef = null;
37153
+ }
37154
+ if (this.popupSubs) {
37155
+ this.popupSubs.unsubscribe();
37156
+ this.popupSubs = null;
37157
+ }
37158
+ if (this.removeClickListener) {
37159
+ this.removeClickListener();
37160
+ this.removeClickListener = null;
37161
+ }
37162
+ }
37163
+ get buttonElement() {
37164
+ return this.host.getButton();
37165
+ }
37166
+ isGroupingApplied(group) {
37167
+ return isPresent$1(group) && group.length > 0;
37168
+ }
37169
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupCommandToolbarDirective, deps: [{ token: i54.ToolBarButtonComponent }, { token: i2.PopupService }, { token: ContextService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: AdaptiveGridService }], target: i0.ɵɵFactoryTarget.Directive });
37170
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GroupCommandToolbarDirective, isStandalone: true, selector: "[kendoGridGroupTool]", ngImport: i0 });
37171
+ }
37172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupCommandToolbarDirective, decorators: [{
37173
+ type: Directive,
37174
+ args: [{
37175
+ selector: '[kendoGridGroupTool]',
37176
+ standalone: true
37177
+ }]
37178
+ }], ctorParameters: function () { return [{ type: i54.ToolBarButtonComponent }, { type: i2.PopupService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: AdaptiveGridService }]; } });
37179
+
37180
+ /**
37181
+ * Stores the row and cell highlight state of the Grid.
37182
+ *
37183
+ * @example
37184
+ * ```typescript
37185
+ * <kendo-grid kendoGridHighlight="ProductID"></kendo-grid>
37186
+ *
37187
+ * <kendo-grid [kendoGridHighlight]="myKey"></kendo-grid>
37188
+ * ```
37189
+ * @remarks
37190
+ * Applied to: {@link GridComponent}.
37191
+ */
37192
+ class HighlightDirective {
37193
+ ctx;
37194
+ /**
37195
+ * Stores the highlighted items keys.
37196
+ * @default []
37197
+ */
37198
+ highlightedKeys = [];
37199
+ /**
37200
+ * Sets the item key to store in `highlightedKeys`. The Grid uses the row index as the default item key.
37201
+ */
37202
+ highlightItemKey;
37203
+ /**
37204
+ * Sets the column key for a data cell. The Grid uses the column index as the default column key.
37205
+ */
37206
+ highlightColumnKey;
37207
+ rowHighlightState = new Set();
37208
+ cellHighlightState = new PairSet();
37209
+ constructor(ctx) {
37210
+ this.ctx = ctx;
37211
+ this.ctx.highlightDirective = this;
37212
+ }
37213
+ ngOnChanges(changes) {
37214
+ if (isPresent$1(changes['highlightedKeys'])) {
37215
+ this.setState(this.highlightedKeys);
37216
+ }
37217
+ }
37218
+ ngOnDestroy() {
37219
+ this.reset();
37220
+ this.ctx.highlightDirective = null;
37221
+ }
37222
+ /**
37223
+ * @hidden
37224
+ */
37225
+ isRowHighlighted(row) {
37226
+ return this.rowHighlightState.has(this.getItemKey(row));
37227
+ }
37228
+ /**
37229
+ * @hidden
37230
+ */
37231
+ isCellHighlighted(row, column, colIndex) {
37232
+ const highlightItem = this.getHighlightItem(row, column, colIndex);
37233
+ return this.cellHighlightState.has(highlightItem.itemKey, highlightItem.columnKey);
37234
+ }
37235
+ getItemKey(row) {
37236
+ if (this.highlightItemKey) {
37237
+ if (typeof this.highlightItemKey === "string") {
37238
+ return row.data?.[this.highlightItemKey];
37239
+ }
37240
+ if (typeof this.highlightItemKey === "function") {
37241
+ return this.highlightItemKey(row);
37242
+ }
37243
+ }
37244
+ return row.index;
37245
+ }
37246
+ getHighlightItem(row, col, colIndex) {
37247
+ const itemIdentifiers = {};
37248
+ itemIdentifiers.itemKey = this.getItemKey(row);
37249
+ if (!isPresent$1(col) && !isPresent$1(colIndex)) {
37250
+ return itemIdentifiers;
37251
+ }
37252
+ if (this.highlightColumnKey) {
37253
+ if (typeof this.highlightColumnKey === "string") {
37254
+ itemIdentifiers.columnKey = row.dataItem[this.highlightColumnKey];
37255
+ }
37256
+ if (typeof this.highlightColumnKey === "function") {
37257
+ itemIdentifiers.columnKey = this.highlightColumnKey(col, colIndex);
37258
+ }
37259
+ }
37260
+ return {
37261
+ itemKey: itemIdentifiers.itemKey,
37262
+ columnKey: itemIdentifiers.columnKey ? itemIdentifiers.columnKey : colIndex
37263
+ };
37264
+ }
37265
+ setState(highlightedKeys) {
37266
+ this.reset();
37267
+ if (!highlightedKeys || highlightedKeys.length === 0) {
37268
+ return;
37269
+ }
37270
+ const rowHighlights = highlightedKeys.filter(item => !isPresent$1(item.columnKey));
37271
+ const cellHighlights = highlightedKeys.filter(item => isPresent$1(item.columnKey));
37272
+ if (cellHighlights.length > 0) {
37273
+ this.cellHighlightState = new PairSet(cellHighlights, 'itemKey', 'columnKey');
37274
+ }
37275
+ if (rowHighlights.length > 0) {
37276
+ rowHighlights.forEach(item => {
37277
+ this.rowHighlightState.add(item.itemKey);
37278
+ });
37279
+ }
37280
+ }
37281
+ reset() {
37282
+ this.rowHighlightState.clear();
37283
+ this.cellHighlightState.clear();
37284
+ }
37285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, deps: [{ token: ContextService }], target: i0.ɵɵFactoryTarget.Directive });
37286
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: HighlightDirective, isStandalone: true, selector: "[kendoGridHighlight]", inputs: { highlightedKeys: "highlightedKeys", highlightItemKey: ["kendoGridHighlight", "highlightItemKey"], highlightColumnKey: "highlightColumnKey" }, usesOnChanges: true, ngImport: i0 });
37287
+ }
37288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, decorators: [{
37289
+ type: Directive,
37290
+ args: [{
37291
+ selector: '[kendoGridHighlight]',
37292
+ standalone: true
37293
+ }]
37294
+ }], ctorParameters: function () { return [{ type: ContextService }]; }, propDecorators: { highlightedKeys: [{
37295
+ type: Input
37296
+ }], highlightItemKey: [{
37297
+ type: Input,
37298
+ args: ["kendoGridHighlight"]
37299
+ }], highlightColumnKey: [{
37300
+ type: Input
37301
+ }] } });
37302
+
37303
+ /**
37304
+ * @hidden
37305
+ */
37306
+ const DEFAULT_AI_REQUEST_OPTIONS = {
37307
+ headers: new HttpHeaders({
37308
+ 'Content-Type': 'application/json'
37309
+ }),
37310
+ role: 'user',
37311
+ method: 'POST',
37312
+ responseType: 'json'
37313
+ };
37314
+ /**
37315
+ * Represents the event data when the AI Assistant request completes successfully.
37316
+ */
37317
+ class GridToolbarAIResponseSuccessEvent extends PreventableEvent$1 {
37318
+ /**
37319
+ * The HTTP response from the AI service.
37320
+ */
37321
+ response;
37322
+ constructor(response) {
37323
+ super();
37324
+ this.response = response;
37325
+ }
37326
+ }
37327
+ /**
37328
+ * Represents the event data when the AI Assistant request completes with an error.
37329
+ */
37330
+ class GridToolbarAIResponseErrorEvent extends PreventableEvent$1 {
37331
+ /**
37332
+ * The HTTP error response from the AI service.
37333
+ */
37334
+ error;
37335
+ constructor(error) {
37336
+ super();
37337
+ this.error = error;
37338
+ }
37339
+ }
37340
+
37341
+ /**
37342
+ * @hidden
37343
+ * Converts date strings in a filter to Date objects.
37344
+ */
37345
+ const convertDateStringsInFilter = (filter) => {
37346
+ if (!filter) {
37347
+ return filter;
37348
+ }
37349
+ if (filter.filters && Array.isArray(filter.filters)) {
37350
+ return {
37351
+ ...filter,
37352
+ filters: filter.filters.map(f => convertDateStringsInFilter(f))
37353
+ };
37354
+ }
37355
+ if (filter.field && filter.value !== undefined) {
37356
+ if (typeof filter.value === 'string' && isDateOperator(filter.operator)) {
37357
+ const date = parseDate(filter.value);
37358
+ return {
37359
+ ...filter,
37360
+ value: date || filter.value
37361
+ };
37362
+ }
37363
+ }
37364
+ return filter;
37365
+ };
37366
+ /**
37367
+ * @hidden
37368
+ */
37369
+ const isDateOperator = (operator) => {
37370
+ const dateOperators = [
37371
+ 'eq', 'neq', 'lt', 'lte', 'gt', 'gte'
37372
+ ];
37373
+ return dateOperators.includes(operator);
37374
+ };
37375
+ /**
37376
+ * @hidden
37377
+ * Processes cell highlights for a specific filter and item.
37378
+ */
37379
+ const processCellHighlights = (filter, rowIndex, columns, highlightItems) => {
37380
+ Object.keys(filter.cells).forEach((columnField) => {
37381
+ const actualColumnIndex = Array.from(columns).findIndex((col) => col.field === columnField);
37382
+ if (actualColumnIndex !== -1) {
37383
+ highlightItems.push({
37384
+ itemKey: rowIndex,
37385
+ columnKey: actualColumnIndex,
37386
+ });
37387
+ }
37388
+ });
37389
+ };
37390
+ /**
37391
+ * @hidden
37392
+ * Processes filtered results and adds highlight items.
37393
+ */
37394
+ const processFilteredResults = (filteredResults, data, filter, columns, highlightItems) => {
37395
+ filteredResults?.forEach((item) => {
37396
+ const rowIndex = data.findIndex((dataItem) => dataItem === item);
37397
+ if (filter.cells && Object.keys(filter.cells).length > 0) {
37398
+ processCellHighlights(filter, rowIndex, columns, highlightItems);
37399
+ }
37400
+ else {
37401
+ highlightItems.push({
37402
+ itemKey: rowIndex,
37403
+ });
37404
+ }
37405
+ });
37406
+ };
37407
+ /**
37408
+ * @hidden
37409
+ * Highlights items in a grid based on the provided filters and columns.
37410
+ * @param data - The data to be highlighted.
37411
+ * @param filters - The composite highlight descriptors containing the filters and logic.
37412
+ * @param columns - The columns of the grid.
37413
+ * @returns An array of HighlightItem objects representing the highlighted items.
37414
+ */
37415
+ const highlightBy = (data, filters, columns) => {
37416
+ const highlightItems = [];
37417
+ filters.forEach((filter) => {
37418
+ const processedFilters = filter.filters.map((filter) => convertDateStringsInFilter(filter));
37419
+ const filteredResults = filterBy(data, {
37420
+ logic: filter.logic || "and",
37421
+ filters: processedFilters,
37422
+ });
37423
+ processFilteredResults(filteredResults, data, filter, columns, highlightItems);
37424
+ });
37425
+ return highlightItems;
37426
+ };
37427
+
37428
+ /**
37429
+ * @hidden
37430
+ */
37431
+ class AiAssistantComponent {
37432
+ http;
37433
+ ctx;
37434
+ columnInfoService;
37435
+ aiPrompt;
37436
+ activeView = 0;
37437
+ requestUrl;
37438
+ requestOptions;
37439
+ aiPromptSettings;
37440
+ aiToolDirective;
37441
+ streaming = false;
37442
+ disabledGenerateButton = false;
37443
+ lastMessage;
37444
+ requestData;
37445
+ currentRequestSubscription = null;
37446
+ //Remove this when the AI Assistant has a built-in loading indicator
37447
+ loadingOutput = { id: 'k-loading-item', output: '', prompt: '' };
37448
+ columns = [];
37449
+ idCounter = 0;
37450
+ constructor(http, ctx, columnInfoService) {
37451
+ this.http = http;
37452
+ this.ctx = ctx;
37453
+ this.columnInfoService = columnInfoService;
37454
+ }
37455
+ ngAfterViewInit() {
37456
+ this.columns = this.columnInfoService.leafNamedColumns.map((col) => ({ field: col.field }));
37457
+ }
37458
+ ngOnDestroy() {
37459
+ this.unsubscribeCurrentRequest();
37460
+ }
37461
+ message(message) {
37462
+ return this.ctx.localization.get(message);
37463
+ }
37464
+ cancelRequest() {
37465
+ this.aiToolDirective.cancelRequest.emit();
37466
+ this.unsubscribeCurrentRequest();
37467
+ this.streaming = false;
37468
+ }
37469
+ onPromptRequest(ev) {
37470
+ if (this.aiToolDirective.promptOutputs.length === 0) {
37471
+ this.aiToolDirective.promptOutputs.push(this.loadingOutput);
37472
+ }
37473
+ this.unsubscribeCurrentRequest();
37474
+ this.streaming = true;
37475
+ this.activeView = 1;
37476
+ if (ev.prompt) {
37477
+ this.lastMessage = ev.prompt;
37478
+ }
37479
+ this.requestData = {
37480
+ columns: this.columns,
37481
+ promptMessage: ev.prompt,
37482
+ url: this.requestUrl,
37483
+ requestOptions: {
37484
+ ...this.requestOptions
37485
+ }
37486
+ };
37487
+ if (!this.requestOptions.body) {
37488
+ const requestBody = {
37489
+ role: this.requestData.requestOptions.role,
37490
+ contents: [
37491
+ {
37492
+ text: this.requestData.promptMessage
37493
+ }
37494
+ ],
37495
+ columns: this.requestData.columns
37496
+ };
37497
+ this.requestData.requestOptions.body = requestBody;
37498
+ }
37499
+ this.aiToolDirective.promptRequest.emit({ requestData: this.requestData, isRetry: ev.isRetry });
37500
+ if (!this.requestUrl) {
37501
+ return;
37502
+ }
37503
+ this.currentRequestSubscription = this.sendPromptRequest().subscribe((res) => {
37504
+ if (res.body) {
37505
+ this.processResponse(res);
37506
+ this.streaming = false;
37507
+ }
37508
+ this.currentRequestSubscription = null;
37509
+ }, (error) => {
37510
+ this.handleError(error);
37511
+ this.streaming = false;
37512
+ this.currentRequestSubscription = null;
37513
+ });
37514
+ }
37515
+ sendPromptRequest() {
37516
+ const request = new HttpRequest(this.requestData.requestOptions.method, this.requestData.url, this.requestData.requestOptions.body, this.requestData.requestOptions);
37517
+ return this.http.request(request);
37518
+ }
37519
+ processResponse(response) {
37520
+ if (this.aiToolDirective.autoClose) {
37521
+ this.aiToolDirective.emitOpenClose = true;
37522
+ this.aiToolDirective.toggleWindow();
37523
+ }
37524
+ const responseBody = response.body;
37525
+ const responseSuccessEvent = new GridToolbarAIResponseSuccessEvent(response);
37526
+ this.aiToolDirective.responseSuccess.emit(responseSuccessEvent);
37527
+ if (responseSuccessEvent.isDefaultPrevented()) {
37528
+ this.deleteLoadingOutput();
37529
+ return;
37530
+ }
37531
+ const isFilterable = Boolean(this.ctx.grid.filterable);
37532
+ const isSortable = Boolean(this.ctx.grid.sortable);
37533
+ const isGroupable = Boolean(this.ctx.grid.groupable);
37534
+ if (isFilterable && responseBody.filter) {
37535
+ this.processFilterResponse(responseBody.filter);
37536
+ }
37537
+ if (isSortable && responseBody.sort) {
37538
+ this.processArrayResponse(responseBody.sort, this.ctx.grid.currentState.sort || [], (item) => item.field, (mergedArray) => this.ctx.grid.sortChange.next(mergedArray));
37539
+ }
37540
+ if (isGroupable && responseBody.group) {
37541
+ this.processArrayResponse(responseBody.group, this.ctx.grid.currentState.group || [], (item) => item.field, (mergedArray) => this.ctx.grid.groupChange.next(mergedArray));
37542
+ }
37543
+ if (this.ctx.highlightDirective && responseBody.highlight) {
37544
+ this.processHighlightResponse(responseBody.highlight);
37545
+ }
37546
+ const responseContentStart = [`${this.ctx.localization.get('aiAssistantOutputCardBodyContent')} \n`];
37547
+ const responseContentBody = responseBody.messages
37548
+ .map((output, idx) => `${idx + 1} ${output}`)
37549
+ .join('\n');
37550
+ const output = {
37551
+ id: this.idCounter++,
37552
+ title: this.ctx.localization.get('aiAssistantOutputCardTitle'),
37553
+ prompt: this.lastMessage,
37554
+ output: responseContentStart.concat(responseContentBody).join(''),
37555
+ };
37556
+ this.deleteLoadingOutput();
37557
+ this.aiToolDirective.promptOutputs.unshift(output);
37558
+ }
37559
+ handleError(error) {
37560
+ const responseErrorEvent = new GridToolbarAIResponseErrorEvent(error);
37561
+ this.aiToolDirective.responseError.emit(responseErrorEvent);
37562
+ if (responseErrorEvent.isDefaultPrevented()) {
37563
+ this.deleteLoadingOutput();
37564
+ return;
37565
+ }
37566
+ const output = {
37567
+ id: this.idCounter++,
37568
+ prompt: this.lastMessage,
37569
+ output: error.message
37570
+ };
37571
+ this.deleteLoadingOutput();
37572
+ this.aiToolDirective.promptOutputs.unshift(output);
37573
+ }
37574
+ deleteLoadingOutput() {
37575
+ if (this.aiToolDirective.promptOutputs[0]?.id === this.loadingOutput.id) {
37576
+ this.aiToolDirective.promptOutputs.splice(0, 1);
37577
+ }
37578
+ }
37579
+ unsubscribeCurrentRequest() {
37580
+ if (this.currentRequestSubscription) {
37581
+ this.currentRequestSubscription.unsubscribe();
37582
+ this.currentRequestSubscription = null;
37583
+ }
37584
+ }
37585
+ processArrayResponse(newItems, currentItems, getField, updateGrid) {
37586
+ if (newItems?.length === 0) {
37587
+ updateGrid([]);
37588
+ }
37589
+ else if (newItems?.length) {
37590
+ let mergedArray = [...newItems];
37591
+ const newFields = newItems.map(getField);
37592
+ const existingItemsToKeep = currentItems.filter(item => !newFields.includes(getField(item)));
37593
+ mergedArray = [...mergedArray, ...existingItemsToKeep];
37594
+ updateGrid(mergedArray);
37595
+ }
37596
+ }
37597
+ processHighlightResponse(highlight) {
37598
+ if (highlight.length === 0) {
37599
+ this.ctx.highlightDirective['setState']([]);
37600
+ return;
37601
+ }
37602
+ const highlightedItems = highlightBy(this.ctx.dataBindingDirective['originalData'], highlight, this.columns);
37603
+ this.ctx.highlightDirective['setState'](highlightedItems);
37604
+ }
37605
+ processFilterResponse(filter) {
37606
+ const processedFilter = convertDateStringsInFilter(filter);
37607
+ const clearFilter = Object.keys(processedFilter).length === 0;
37608
+ if (clearFilter) {
37609
+ this.ctx.grid.filterChange.next(undefined);
37610
+ }
37611
+ else if (processedFilter?.filters.length) {
37612
+ const currentFilter = this.ctx.grid.currentState.filter;
37613
+ let mergedFilter = processedFilter;
37614
+ if (currentFilter && currentFilter.filters?.length > 0) {
37615
+ mergedFilter = {
37616
+ logic: 'and',
37617
+ filters: [
37618
+ currentFilter,
37619
+ processedFilter
37620
+ ]
37621
+ };
37622
+ }
37623
+ this.ctx.grid.filterChange.next(mergedFilter);
37624
+ }
37625
+ }
37626
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiAssistantComponent, deps: [{ token: i1$8.HttpClient }, { token: ContextService }, { token: ColumnInfoService }], target: i0.ɵɵFactoryTarget.Component });
37627
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AiAssistantComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "aiPrompt", first: true, predicate: AIPromptComponent, descendants: true }], ngImport: i0, template: `
37628
+ <kendo-aiprompt
37629
+ #aiPrompt
37630
+ [promptSuggestions]="aiPromptSettings?.promptSuggestions"
37631
+ [showOutputRating]="aiPromptSettings?.showOutputRating"
37632
+ [streaming]="streaming"
37633
+ [speechToTextButton]="aiPromptSettings?.speechToTextButton"
37634
+ [(activeView)]="activeView"
37635
+ [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon"
37636
+ [generateButtonIcon]="aiPromptSettings?.generateButtonIcon"
37637
+ [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0"
37638
+ [promptOutputs]="aiPromptSettings?.promptOutputs"
37639
+ [textAreaSettings]="aiPromptSettings?.textAreaSettings"
37640
+ (promptRequest)="onPromptRequest($event)"
37641
+ (promptRequestCancel)="cancelRequest()"
37642
+ >
37643
+ <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view>
37644
+ <kendo-aiprompt-output-view></kendo-aiprompt-output-view>
37645
+ <ng-template *ngIf="streaming && aiPrompt.streaming" kendoAIPromptOutputTemplate let-output>
37646
+ <div class="k-card">
37647
+ <div class="k-card-header">
37648
+ <div class="k-card-title">
37649
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span>
37650
+ </div>
37651
+ <div class="k-card-subtitle">
37652
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37653
+ </div>
37654
+ </div>
37655
+ <div class="k-card-body">
37656
+ <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span>
37657
+ </div>
37658
+ <div class="k-card-actions">
37659
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37660
+ </div>
37661
+ </div>
37662
+ </ng-template>
37663
+ <ng-template *ngIf="!(streaming && aiPrompt.streaming)" kendoAIPromptOutputBodyTemplate let-output>
37664
+ <p>{{output.output}}</p>
37665
+ </ng-template>
37666
+ <kendo-aiprompt-messages
37667
+ [generateOutput]="message('aiAssistantApplyButtonText')"
37668
+ ></kendo-aiprompt-messages>
37669
+ </kendo-aiprompt>
37670
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AIPromptComponent, selector: "kendo-aiprompt", inputs: ["activeView", "promptCommands", "promptSuggestions", "promptOutputs", "showOutputRating", "streaming", "speechToTextButton", "textAreaSettings", "generateButtonSVGIcon", "generateButtonIcon", "disabledGenerateButton"], outputs: ["activeViewChange", "promptRequest", "commandExecute", "outputCopy", "outputRatingChange", "promptRequestCancel"], exportAs: ["kendoAIPrompt"] }, { kind: "component", type: AIPromptCustomMessagesComponent, selector: "kendo-aiprompt-messages" }, { kind: "component", type: PromptViewComponent, selector: "kendo-aiprompt-prompt-view" }, { kind: "component", type: OutputViewComponent, selector: "kendo-aiprompt-output-view" }, { kind: "directive", type: AIPromptOutputTemplateDirective, selector: "[kendoAIPromptOutputTemplate]" }, { kind: "directive", type: AIPromptOutputBodyTemplateDirective, selector: "[kendoAIPromptOutputBodyTemplate]" }] });
37671
+ }
37672
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiAssistantComponent, decorators: [{
37673
+ type: Component,
37195
37674
  args: [{
37196
- selector: '[kendoGridCancelTool]',
37197
- standalone: true
37675
+ standalone: true,
37676
+ imports: [NgIf, AIPromptComponent, AIPromptCustomMessagesComponent, PromptViewComponent, OutputViewComponent, AIPromptOutputTemplateDirective, AIPromptOutputBodyTemplateDirective],
37677
+ template: `
37678
+ <kendo-aiprompt
37679
+ #aiPrompt
37680
+ [promptSuggestions]="aiPromptSettings?.promptSuggestions"
37681
+ [showOutputRating]="aiPromptSettings?.showOutputRating"
37682
+ [streaming]="streaming"
37683
+ [speechToTextButton]="aiPromptSettings?.speechToTextButton"
37684
+ [(activeView)]="activeView"
37685
+ [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon"
37686
+ [generateButtonIcon]="aiPromptSettings?.generateButtonIcon"
37687
+ [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0"
37688
+ [promptOutputs]="aiPromptSettings?.promptOutputs"
37689
+ [textAreaSettings]="aiPromptSettings?.textAreaSettings"
37690
+ (promptRequest)="onPromptRequest($event)"
37691
+ (promptRequestCancel)="cancelRequest()"
37692
+ >
37693
+ <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view>
37694
+ <kendo-aiprompt-output-view></kendo-aiprompt-output-view>
37695
+ <ng-template *ngIf="streaming && aiPrompt.streaming" kendoAIPromptOutputTemplate let-output>
37696
+ <div class="k-card">
37697
+ <div class="k-card-header">
37698
+ <div class="k-card-title">
37699
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span>
37700
+ </div>
37701
+ <div class="k-card-subtitle">
37702
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37703
+ </div>
37704
+ </div>
37705
+ <div class="k-card-body">
37706
+ <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span>
37707
+ </div>
37708
+ <div class="k-card-actions">
37709
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37710
+ </div>
37711
+ </div>
37712
+ </ng-template>
37713
+ <ng-template *ngIf="!(streaming && aiPrompt.streaming)" kendoAIPromptOutputBodyTemplate let-output>
37714
+ <p>{{output.output}}</p>
37715
+ </ng-template>
37716
+ <kendo-aiprompt-messages
37717
+ [generateOutput]="message('aiAssistantApplyButtonText')"
37718
+ ></kendo-aiprompt-messages>
37719
+ </kendo-aiprompt>
37720
+ `
37198
37721
  }]
37199
- }], ctorParameters: function () { return [{ type: EditService }, { type: i54.ToolBarButtonComponent }, { type: SelectionService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; } });
37722
+ }], ctorParameters: function () { return [{ type: i1$8.HttpClient }, { type: ContextService }, { type: ColumnInfoService }]; }, propDecorators: { aiPrompt: [{
37723
+ type: ViewChild,
37724
+ args: [AIPromptComponent]
37725
+ }] } });
37200
37726
 
37201
- let incrementingId = 0;
37202
37727
  /**
37203
- * Represents the toolbar tool for grouping columns of the Grid.
37728
+ * Represents an AI Assistant tool of the Grid.
37204
37729
  * Use this directive on any `kendo-toolbar-button` inside a ToolbarComponent in the Grid.
37205
- * When you click the toolbar button with this directive, the `group` event is triggered.
37206
37730
  *
37207
37731
  * @example
37208
- * ```html
37732
+ * ```html-no-run
37209
37733
  * <kendo-grid>
37210
37734
  * <kendo-toolbar>
37211
- * <kendo-toolbar-button text="Group" kendoGridGroupTool></kendo-toolbar-button>
37735
+ * <kendo-toolbar-button kendoGridAIAssistantTool></kendo-toolbar-button>
37212
37736
  * </kendo-toolbar>
37213
37737
  * </kendo-grid>
37214
37738
  * ```
37215
37739
  * @remarks
37216
37740
  * Applied to: {@link ToolBarButtonComponent}.
37217
37741
  */
37218
- class GroupCommandToolbarDirective {
37742
+ class AIAssistantToolbarDirective extends ToolbarToolBase {
37743
+ windowService;
37219
37744
  host;
37220
- popupService;
37221
37745
  ctx;
37222
- ngZone;
37223
- renderer;
37224
- adaptiveGridService;
37225
- popupRef;
37226
- nextId = incrementingId++;
37227
- toolSubs = new Subscription();
37228
- popupSubs;
37229
- actionSheetCloseSub;
37230
- removeClickListener;
37231
- constructor(host, popupService, ctx, ngZone, renderer, adaptiveGridService) {
37746
+ zone;
37747
+ refresh;
37748
+ /**
37749
+ * The URL to which the AI Assistant tool sends the AI request.
37750
+ * - When you set this property, the AI Assistant tool sends and handles an HTTP request to the provided `requestUrl`. You can handle the `promptRequest` event to modify the request options before the tool sends it.
37751
+ * - When you do not set this property, the AI Assistant tool does not send an HTTP request. You should handle the `promptRequest` event to send and handle a custom HTTP request.
37752
+ */
37753
+ requestUrl;
37754
+ /**
37755
+ * Configures the request options that the AI Assistant tool sends with the AI request.
37756
+ *
37757
+ * @default { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), role: 'user', method: 'POST', responseType: 'json', withCredentials: false }
37758
+ */
37759
+ requestOptions;
37760
+ /**
37761
+ * Configures the initial settings for the AI Assistant Window when opened.
37762
+ */
37763
+ aiWindowSettings;
37764
+ /**
37765
+ * Configures the initial settings for the AI Prompt component that the AI Assistant Window component uses when opened.
37766
+ */
37767
+ aiPromptSettings;
37768
+ /**
37769
+ * Determines whether to close the AI Assistant Window automatically after a successful request.
37770
+ * @default true
37771
+ */
37772
+ autoClose = true;
37773
+ /**
37774
+ * Determines whether to keep the AI Prompt's outputs after closing the AI Assistant Window.
37775
+ * @default false
37776
+ */
37777
+ keepOutputHistory = false;
37778
+ /**
37779
+ * Emits an event before the AI Assistant tool sends the AI request.
37780
+ * - When you provide a `requestUrl`, you can handle the event to modify the request options.
37781
+ * - When you do not provide a `requestUrl`, you can handle the event to perform an entirely custom request.
37782
+ */
37783
+ promptRequest = new EventEmitter();
37784
+ /**
37785
+ * Emits an event when the user clicks the cancel button.
37786
+ */
37787
+ cancelRequest = new EventEmitter();
37788
+ /**
37789
+ * Emits an event when the AI Assistant tool completes the AI request successfully.
37790
+ * The event contains the response from the AI service and is preventable to allow stopping the default response handling.
37791
+ */
37792
+ responseSuccess = new EventEmitter();
37793
+ /**
37794
+ * Emits an event when the AI Assistant tool completes the AI request with an error.
37795
+ * The event contains the error response from the AI service and is preventable to allow stopping the default error handling.
37796
+ */
37797
+ responseError = new EventEmitter();
37798
+ /**
37799
+ * Emits an event when the AI Assistant tool closes.
37800
+ */
37801
+ close = new EventEmitter();
37802
+ /**
37803
+ * Emits an event when the AI Assistant tool opens.
37804
+ */
37805
+ open = new EventEmitter();
37806
+ tableWizardIcon = tableWizardIcon;
37807
+ emitOpenClose = false;
37808
+ promptOutputs = [];
37809
+ windowRef;
37810
+ subs = new Subscription();
37811
+ defaultAiPromptSettings = {
37812
+ speechToTextButton: true,
37813
+ generateButtonSVGIcon: this.tableWizardIcon,
37814
+ generateButtonIcon: 'table-wizard'
37815
+ };
37816
+ constructor(windowService, host, ctx, zone, refresh, cdr) {
37817
+ super(host, ToolbarToolName.aiAssistant, ctx, zone, cdr);
37818
+ this.windowService = windowService;
37232
37819
  this.host = host;
37233
- this.popupService = popupService;
37234
37820
  this.ctx = ctx;
37235
- this.ngZone = ngZone;
37236
- this.renderer = renderer;
37237
- this.adaptiveGridService = adaptiveGridService;
37821
+ this.zone = zone;
37822
+ this.refresh = refresh;
37823
+ this.host.rounded = 'full';
37824
+ this.host.themeColor = 'primary';
37825
+ this.host.showText = 'never';
37238
37826
  }
37239
37827
  ngOnInit() {
37240
- this.toolSubs = this.host.click.subscribe(e => this.onClick(e));
37241
- this.toolSubs.add(this.ctx.grid.groupChange.subscribe(group => {
37242
- this.host.showBadge = this.isGroupingApplied(group);
37243
- }));
37244
- this.host.hasBadgeContainer = true;
37245
- this.host.showBadge = this.isGroupingApplied(this.ctx.grid.group);
37828
+ this.subs.add(this.host.click.subscribe(() => this.onClick()));
37246
37829
  const hasToolbarIcon = isPresent$1(this.host.toolbarOptions.icon) && this.host.toolbarOptions.icon !== '';
37247
37830
  const hasOverflowIcon = isPresent$1(this.host.overflowOptions.icon) && this.host.overflowOptions.icon !== '';
37248
37831
  const hasIcon = hasToolbarIcon && hasOverflowIcon;
37249
37832
  const hasSvgIcon = isPresent$1(this.host.toolbarOptions.svgIcon) && isPresent$1(this.host.overflowOptions.svgIcon);
37250
37833
  if (!hasIcon) {
37251
- this.host.icon = 'group';
37834
+ this.host.icon = 'sparkles';
37252
37835
  }
37253
37836
  if (!hasSvgIcon) {
37254
- this.host.svgIcon = groupIcon;
37837
+ this.host.svgIcon = sparklesIcon;
37255
37838
  }
37839
+ this.requestOptions = { ...DEFAULT_AI_REQUEST_OPTIONS, ...this.requestOptions };
37256
37840
  }
37257
37841
  ngAfterViewInit() {
37258
- if (!isPresent$1(this.host.text)) {
37259
- this.ngZone.onStable.pipe(take(1)).subscribe(() => {
37260
- this.host.text = this.ctx.localization.get(`groupToolbarToolText`);
37261
- });
37262
- }
37263
- this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
37264
- this.buttonElement?.setAttribute('aria-expanded', 'false');
37265
- this.buttonElement?.setAttribute('title', this.ctx.localization.get('groupToolbarToolText'));
37266
- }
37267
- ngOnDestroy() {
37268
- if (this.toolSubs) {
37269
- this.toolSubs.unsubscribe();
37270
- }
37271
- if (this.popupSubs) {
37272
- this.popupSubs.unsubscribe();
37273
- }
37274
- if (this.popupRef) {
37275
- this.popupRef.close();
37276
- this.popupRef = null;
37277
- }
37278
- if (this.actionSheetCloseSub) {
37279
- this.actionSheetCloseSub.unsubscribe();
37280
- this.actionSheetCloseSub = null;
37281
- }
37282
- if (this.removeClickListener) {
37283
- this.removeClickListener();
37284
- this.removeClickListener = null;
37285
- }
37286
- }
37287
- onClick(e) {
37288
- e.preventDefault();
37289
- if (this.ctx.grid.adaptiveMode === 'auto' && this.adaptiveGridService.windowSize !== 'large') {
37290
- if (!this.ctx.grid.isActionSheetExpanded) {
37291
- this.adaptiveGridService.viewType = 'groupToolbarTool';
37292
- this.ctx.grid.adaptiveRenderer.actionSheet.toggle(true);
37293
- this.host.selected = true;
37294
- this.actionSheetCloseSub = this.ctx.grid.adaptiveRenderer.actionSheet.collapse.subscribe(() => this.host.selected = false);
37295
- }
37296
- }
37297
- else {
37298
- if (this.popupRef) {
37299
- this.closePopup();
37300
- return;
37842
+ super.ngAfterViewInit();
37843
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
37844
+ this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
37845
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37846
+ const needsTitle = this.host.showText !== 'always' && this.host.showText !== 'toolbar';
37847
+ if (needsTitle && !this.host.title) {
37848
+ this.buttonElement?.setAttribute('title', this.ctx.localization.get('aiAssistantToolbarToolText'));
37301
37849
  }
37302
- this.openPopup();
37303
- }
37304
- }
37305
- openPopup() {
37306
- const direction = this.ctx.localization.rtl ? 'right' : 'left';
37307
- this.popupRef = this.popupService.open({
37308
- anchor: this.buttonElement,
37309
- content: GroupToolbarToolComponent,
37310
- popupClass: 'k-grid-columnmenu-popup',
37311
- positionMode: 'absolute',
37312
- anchorAlign: { vertical: 'bottom', horizontal: direction },
37313
- popupAlign: { vertical: 'top', horizontal: direction }
37314
37850
  });
37315
- this.adaptiveGridService.popupRef = this.popupRef;
37316
- this.setPopupAttributes();
37317
- this.host.selected = true;
37318
- this.ngZone.runOutsideAngular(() => {
37319
- if (!isDocumentAvailable()) {
37320
- return;
37851
+ this.subs.add(this.refresh.onRefresh.pipe(filter((tool) => tool === this.host)).subscribe((tool) => {
37852
+ if (tool.overflows && this.windowRef) {
37853
+ this.windowRef.close();
37321
37854
  }
37322
- this.removeClickListener = this.renderer.listen('document', 'click', (e) => {
37323
- if (this.popupRef && !closest$1(e.target, node => node === this.popupRef.popupElement || node === this.buttonElement)) {
37324
- this.ngZone.run(() => {
37325
- this.closePopup();
37326
- });
37327
- }
37328
- });
37329
- });
37330
- this.popupSubs = this.popupRef.popup.instance.anchorViewportLeave.subscribe(() => {
37331
- this.popupSubs?.unsubscribe();
37332
- this.popupSubs = null;
37333
- this.closePopup();
37334
- });
37335
- this.initPopupProperties();
37336
- }
37337
- setPopupAttributes() {
37338
- const popupElement = this.popupRef.popupElement;
37339
- const popupId = `k-group-tool-${this.nextId}-popup`;
37340
- const popupAriaElement = popupElement.querySelector('.k-popup');
37341
- this.renderer.setAttribute(popupElement, 'dir', this.ctx.localization.rtl ? 'rtl' : 'ltr');
37342
- this.renderer.setAttribute(popupAriaElement, 'id', popupId);
37343
- this.renderer.setAttribute(popupAriaElement, 'role', 'dialog');
37344
- this.buttonElement?.setAttribute('aria-expanded', 'true');
37345
- this.buttonElement?.setAttribute('aria-controls', popupId);
37346
- }
37347
- initPopupProperties() {
37348
- this.popupRef.content.instance.ctx = this.ctx;
37349
- this.popupRef.content.instance.hostButton = this.host;
37350
- this.popupSubs.add(this.popupRef.content.instance.groupClear.subscribe(() => {
37351
- this.closePopup();
37352
37855
  }));
37353
- this.popupSubs.add(this.popupRef.content.instance.close.subscribe(() => {
37354
- this.closePopup();
37355
- }));
37356
- }
37357
- closePopup() {
37358
- this.buttonElement?.setAttribute('aria-expanded', 'false');
37359
- this.buttonElement?.removeAttribute('aria-controls');
37360
- this.host.selected = false;
37361
- if (this.popupRef) {
37362
- this.popupRef.close();
37363
- this.popupRef = null;
37364
- }
37365
- if (this.popupSubs) {
37366
- this.popupSubs.unsubscribe();
37367
- this.popupSubs = null;
37368
- }
37369
- if (this.removeClickListener) {
37370
- this.removeClickListener();
37371
- this.removeClickListener = null;
37372
- }
37373
- }
37374
- get buttonElement() {
37375
- return this.host.getButton();
37376
- }
37377
- isGroupingApplied(group) {
37378
- return isPresent$1(group) && group.length > 0;
37379
- }
37380
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupCommandToolbarDirective, deps: [{ token: i54.ToolBarButtonComponent }, { token: i2.PopupService }, { token: ContextService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: AdaptiveGridService }], target: i0.ɵɵFactoryTarget.Directive });
37381
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GroupCommandToolbarDirective, isStandalone: true, selector: "[kendoGridGroupTool]", ngImport: i0 });
37382
- }
37383
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupCommandToolbarDirective, decorators: [{
37384
- type: Directive,
37385
- args: [{
37386
- selector: '[kendoGridGroupTool]',
37387
- standalone: true
37388
- }]
37389
- }], ctorParameters: function () { return [{ type: i54.ToolBarButtonComponent }, { type: i2.PopupService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: AdaptiveGridService }]; } });
37390
-
37391
- /**
37392
- * Stores the row and cell highlight state of the Grid.
37393
- *
37394
- * @example
37395
- * ```typescript
37396
- * <kendo-grid kendoGridHighlight="ProductID"></kendo-grid>
37397
- *
37398
- * <kendo-grid [kendoGridHighlight]="myKey"></kendo-grid>
37399
- * ```
37400
- * @remarks
37401
- * Applied to: {@link GridComponent}.
37402
- */
37403
- class HighlightDirective {
37404
- ctx;
37405
- /**
37406
- * Stores the highlighted items keys.
37407
- * @default []
37408
- */
37409
- highlightedKeys = [];
37410
- /**
37411
- * Sets the item key to store in `highlightedKeys`. The Grid uses the row index as the default item key.
37412
- */
37413
- highlightItemKey;
37414
- /**
37415
- * Sets the column key for a data cell. The Grid uses the column index as the default column key.
37416
- */
37417
- highlightColumnKey;
37418
- rowHighlightState = new Set();
37419
- cellHighlightState = new PairSet();
37420
- constructor(ctx) {
37421
- this.ctx = ctx;
37422
- this.ctx.highlightDirective = this;
37423
- }
37424
- ngOnChanges(changes) {
37425
- if (isPresent$1(changes['highlightedKeys'])) {
37426
- this.setState(this.highlightedKeys);
37427
- }
37428
37856
  }
37429
37857
  ngOnDestroy() {
37430
- this.reset();
37431
- this.ctx.highlightDirective = null;
37858
+ super.ngOnDestroy();
37859
+ this.subs.unsubscribe();
37860
+ this.promptOutputs = [];
37432
37861
  }
37433
37862
  /**
37434
37863
  * @hidden
37435
37864
  */
37436
- isRowHighlighted(row) {
37437
- return this.rowHighlightState.has(this.getItemKey(row));
37865
+ onClick() {
37866
+ this.emitOpenClose = true;
37867
+ this.toggleWindow();
37438
37868
  }
37439
37869
  /**
37440
- * @hidden
37870
+ * Toggles the AI Assistant window.
37441
37871
  */
37442
- isCellHighlighted(row, column, colIndex) {
37443
- const highlightItem = this.getHighlightItem(row, column, colIndex);
37444
- return this.cellHighlightState.has(highlightItem.itemKey, highlightItem.columnKey);
37445
- }
37446
- getItemKey(row) {
37447
- if (this.highlightItemKey) {
37448
- if (typeof this.highlightItemKey === "string") {
37449
- return row.data?.[this.highlightItemKey];
37450
- }
37451
- if (typeof this.highlightItemKey === "function") {
37452
- return this.highlightItemKey(row);
37453
- }
37454
- }
37455
- return row.index;
37456
- }
37457
- getHighlightItem(row, col, colIndex) {
37458
- const itemIdentifiers = {};
37459
- itemIdentifiers.itemKey = this.getItemKey(row);
37460
- if (!isPresent$1(col) && !isPresent$1(colIndex)) {
37461
- return itemIdentifiers;
37872
+ toggleWindow() {
37873
+ if (!this.windowRef) {
37874
+ this.openWindow();
37462
37875
  }
37463
- if (this.highlightColumnKey) {
37464
- if (typeof this.highlightColumnKey === "string") {
37465
- itemIdentifiers.columnKey = row.dataItem[this.highlightColumnKey];
37466
- }
37467
- if (typeof this.highlightColumnKey === "function") {
37468
- itemIdentifiers.columnKey = this.highlightColumnKey(col, colIndex);
37469
- }
37876
+ else {
37877
+ this.closeWindow();
37470
37878
  }
37471
- return {
37472
- itemKey: itemIdentifiers.itemKey,
37473
- columnKey: itemIdentifiers.columnKey ? itemIdentifiers.columnKey : colIndex
37474
- };
37475
37879
  }
37476
- setState(highlightedKeys) {
37477
- this.reset();
37478
- if (!highlightedKeys || highlightedKeys.length === 0) {
37479
- return;
37880
+ openWindow() {
37881
+ if (!this.keepOutputHistory) {
37882
+ this.promptOutputs = [];
37480
37883
  }
37481
- const rowHighlights = highlightedKeys.filter(item => !isPresent$1(item.columnKey));
37482
- const cellHighlights = highlightedKeys.filter(item => isPresent$1(item.columnKey));
37483
- if (cellHighlights.length > 0) {
37484
- this.cellHighlightState = new PairSet(cellHighlights, 'itemKey', 'columnKey');
37884
+ const defaultWindowWidth = 437;
37885
+ const rtl = this.ctx.localization.rtl;
37886
+ const defaultWindowSettings = {
37887
+ left: rtl ? this.buttonElement.offsetLeft - (this.aiWindowSettings.width || defaultWindowWidth) : this.buttonElement.offsetLeft + this.buttonElement.offsetWidth,
37888
+ top: this.buttonElement.offsetTop + this.buttonElement.offsetHeight,
37889
+ width: defaultWindowWidth,
37890
+ title: this.ctx.localization.get('aiAssistantWindowTitle'),
37891
+ cssClass: 'k-grid-assistant-window',
37892
+ content: AiAssistantComponent,
37893
+ autoFocusedElement: '.k-input-inner',
37894
+ appendTo: this.ctx.grid.windowContainer
37895
+ };
37896
+ this.aiWindowSettings = {
37897
+ ...defaultWindowSettings,
37898
+ ...this.aiWindowSettings
37899
+ };
37900
+ this.windowRef = this.windowService.open(this.aiWindowSettings);
37901
+ this.windowRef.window.instance.messages = {
37902
+ closeTitle: this.ctx.localization.get('aiAssistantWindowCloseTitle'),
37903
+ maximizeTitle: this.ctx.localization.get('aiAssistantWindowMaximizeTitle'),
37904
+ minimizeTitle: this.ctx.localization.get('aiAssistantWindowMinimizeTitle'),
37905
+ restoreTitle: this.ctx.localization.get('aiAssistantWindowRestoreTitle')
37906
+ };
37907
+ const aiPrompt = this.windowRef.content.instance;
37908
+ aiPrompt.requestUrl = this.requestUrl;
37909
+ aiPrompt.requestOptions = this.requestOptions;
37910
+ aiPrompt.aiToolDirective = this;
37911
+ aiPrompt.disabledGenerateButton = this.aiPromptSettings?.disabledGenerateButton;
37912
+ aiPrompt.streaming = this.aiPromptSettings?.streaming || false;
37913
+ aiPrompt.activeView = this.aiPromptSettings?.activeView || 0;
37914
+ aiPrompt.aiPromptSettings = { ...this.defaultAiPromptSettings, ...this.aiPromptSettings };
37915
+ if (!aiPrompt.aiPromptSettings.promptOutputs) {
37916
+ aiPrompt.aiPromptSettings.promptOutputs = this.promptOutputs;
37485
37917
  }
37486
- if (rowHighlights.length > 0) {
37487
- rowHighlights.forEach(item => {
37488
- this.rowHighlightState.add(item.itemKey);
37918
+ if (this.emitOpenClose) {
37919
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
37920
+ const event = {
37921
+ aiWindow: this.windowRef.window.instance,
37922
+ aiPrompt: this.windowRef.content.instance.aiPrompt
37923
+ };
37924
+ this.open.emit(event);
37925
+ this.emitOpenClose = false;
37489
37926
  });
37490
37927
  }
37928
+ this.subs.add(this.windowRef.window.instance.close.subscribe(() => {
37929
+ this.emitOpenClose = true;
37930
+ this.closeWindow(true);
37931
+ }));
37932
+ this.host.selected = true;
37491
37933
  }
37492
- reset() {
37493
- this.rowHighlightState.clear();
37494
- this.cellHighlightState.clear();
37934
+ closeWindow(focusAnchor = false) {
37935
+ this.windowRef.close();
37936
+ if (this.emitOpenClose) {
37937
+ this.close.emit();
37938
+ this.emitOpenClose = false;
37939
+ }
37940
+ this.windowRef = null;
37941
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37942
+ this.buttonElement?.removeAttribute('aria-controls');
37943
+ this.host.selected = false;
37944
+ focusAnchor && this.buttonElement?.focus();
37495
37945
  }
37496
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, deps: [{ token: ContextService }], target: i0.ɵɵFactoryTarget.Directive });
37497
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: HighlightDirective, isStandalone: true, selector: "[kendoGridHighlight]", inputs: { highlightedKeys: "highlightedKeys", highlightItemKey: ["kendoGridHighlight", "highlightItemKey"], highlightColumnKey: "highlightColumnKey" }, usesOnChanges: true, ngImport: i0 });
37946
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIAssistantToolbarDirective, deps: [{ token: i1$7.WindowService }, { token: i54.ToolBarButtonComponent }, { token: ContextService }, { token: i0.NgZone }, { token: i54.RefreshService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
37947
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: AIAssistantToolbarDirective, isStandalone: true, selector: "[kendoGridAIAssistantTool]", inputs: { requestUrl: "requestUrl", requestOptions: "requestOptions", aiWindowSettings: "aiWindowSettings", aiPromptSettings: "aiPromptSettings", autoClose: "autoClose", keepOutputHistory: "keepOutputHistory" }, outputs: { promptRequest: "promptRequest", cancelRequest: "cancelRequest", responseSuccess: "responseSuccess", responseError: "responseError", close: "close", open: "open" }, usesInheritance: true, ngImport: i0 });
37498
37948
  }
37499
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, decorators: [{
37949
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIAssistantToolbarDirective, decorators: [{
37500
37950
  type: Directive,
37501
37951
  args: [{
37502
- selector: '[kendoGridHighlight]',
37952
+ selector: '[kendoGridAIAssistantTool]',
37503
37953
  standalone: true
37504
37954
  }]
37505
- }], ctorParameters: function () { return [{ type: ContextService }]; }, propDecorators: { highlightedKeys: [{
37955
+ }], ctorParameters: function () { return [{ type: i1$7.WindowService }, { type: i54.ToolBarButtonComponent }, { type: ContextService }, { type: i0.NgZone }, { type: i54.RefreshService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { requestUrl: [{
37506
37956
  type: Input
37507
- }], highlightItemKey: [{
37508
- type: Input,
37509
- args: ["kendoGridHighlight"]
37510
- }], highlightColumnKey: [{
37957
+ }], requestOptions: [{
37958
+ type: Input
37959
+ }], aiWindowSettings: [{
37960
+ type: Input
37961
+ }], aiPromptSettings: [{
37511
37962
  type: Input
37963
+ }], autoClose: [{
37964
+ type: Input
37965
+ }], keepOutputHistory: [{
37966
+ type: Input
37967
+ }], promptRequest: [{
37968
+ type: Output
37969
+ }], cancelRequest: [{
37970
+ type: Output
37971
+ }], responseSuccess: [{
37972
+ type: Output
37973
+ }], responseError: [{
37974
+ type: Output
37975
+ }], close: [{
37976
+ type: Output
37977
+ }], open: [{
37978
+ type: Output
37512
37979
  }] } });
37513
37980
 
37514
37981
  /**
@@ -38089,5 +38556,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
38089
38556
  * Generated bundle index. Do not edit.
38090
38557
  */
38091
38558
 
38092
- export { AIAssistantToolbarDirective, AddCommandDirective, AddCommandToolbarDirective, AfterEqFilterOperatorComponent, AfterFilterOperatorComponent, AutoCompleteFilterCellComponent, BaseFilterCellComponent, BeforeEqFilterOperatorComponent, BeforeFilterOperatorComponent, BooleanFilterCellComponent, BooleanFilterComponent, BooleanFilterMenuComponent, BooleanFilterRadioButtonDirective, BrowserSupportService, CELL_CONTEXT, CancelCommandDirective, CancelCommandToolbarDirective, CellCloseEvent, CellComponent, CellLoadingTemplateDirective, CellSelectionAggregateService, CellSelectionService, CellTemplateDirective, ChangeNotificationService, CheckboxColumnComponent, ColGroupComponent, ColumnBase, ColumnChooserComponent, ColumnChooserToolbarDirective, ColumnComponent, ColumnGroupComponent, ColumnHandleDirective, ColumnInfoService, ColumnListComponent, ColumnLockedChangeEvent, ColumnMenuAutoSizeAllColumnsComponent, ColumnMenuAutoSizeColumnComponent, ColumnMenuChooserComponent, ColumnMenuComponent, ColumnMenuContainerComponent, ColumnMenuFilterComponent, ColumnMenuItemComponent, ColumnMenuItemContentTemplateDirective, ColumnMenuItemDirective, ColumnMenuLockComponent, ColumnMenuPositionComponent, ColumnMenuService, ColumnMenuSortComponent, ColumnMenuStickComponent, ColumnMenuTemplateDirective, ColumnReorderEvent, ColumnReorderService, ColumnResizingService, ColumnStickyChangeEvent, ColumnVisibilityChangeEvent, ColumnsContainer, CommandColumnComponent, ContainsFilterOperatorComponent, ContextService, CustomMessagesComponent, DEFAULT_AI_REQUEST_OPTIONS, DEFAULT_SCROLLER_FACTORY, DataBindingDirective, DateFilterCellComponent, DateFilterComponent, DateFilterMenuComponent, DateFilterMenuInputComponent, DetailCollapseEvent, DetailExpandEvent, DetailTemplateDirective, DetailsService, DoesNotContainFilterOperatorComponent, DomEventsService, DragAndDropService, DragHintService, DropCueService, EditCommandDirective, EditCommandToolbarDirective, EditService as EditServiceClass, EditTemplateDirective, EditingDirectiveBase, EndsWithFilterOperatorComponent, EqualFilterOperatorComponent, ExcelCommandDirective, ExcelCommandToolbarDirective, ExcelComponent, ExcelExportEvent, ExcelModule, ExcelService, ExpandDetailsDirective, ExpandGroupDirective, ExternalEditingDirective, FieldAccessorPipe, FilterCellComponent, FilterCellHostDirective, FilterCellOperatorsComponent, FilterCellTemplateDirective, FilterCellWrapperComponent, FilterCommandToolbarDirective, FilterInputDirective, FilterMenuComponent, FilterMenuContainerComponent, FilterMenuDropDownListDirective, FilterMenuHostDirective, FilterMenuInputWrapperComponent, FilterMenuTemplateDirective, FilterRowComponent, FilterService, FocusRoot, FocusableDirective, FooterComponent, FooterTemplateDirective, GreaterFilterOperatorComponent, GreaterOrEqualToFilterOperatorComponent, GridClipboardDirective, GridComponent, GridModule, GridSpacerComponent, GridTableDirective, GridToolbarAIResponseErrorEvent, GridToolbarAIResponseSuccessEvent, GridToolbarFocusableDirective, GridToolbarNavigationService, GroupCommandToolbarDirective, GroupFooterTemplateDirective, GroupHeaderColumnTemplateDirective, GroupHeaderComponent, GroupHeaderTemplateDirective, GroupInfoService, GroupPanelComponent, GroupsService, HeaderComponent, HeaderTemplateDirective, HighlightDirective, IdService, InCellEditingDirective, IsEmptyFilterOperatorComponent, IsNotEmptyFilterOperatorComponent, IsNotNullFilterOperatorComponent, IsNullFilterOperatorComponent, KENDO_GRID, KENDO_GRID_BODY_EXPORTS, KENDO_GRID_COLUMN_DRAGANDDROP, KENDO_GRID_COLUMN_MENU_DECLARATIONS, KENDO_GRID_COLUMN_MENU_EXPORTS, KENDO_GRID_DECLARATIONS, KENDO_GRID_EXCEL_EXPORT, KENDO_GRID_EXPORTS, KENDO_GRID_FILTER_MENU, KENDO_GRID_FILTER_MENU_EXPORTS, KENDO_GRID_FILTER_OPERATORS, KENDO_GRID_FILTER_ROW, KENDO_GRID_FILTER_ROW_EXPORTS, KENDO_GRID_FILTER_SHARED, KENDO_GRID_FOOTER_EXPORTS, KENDO_GRID_GROUP_EXPORTS, KENDO_GRID_HEADER_EXPORTS, KENDO_GRID_PDF_EXPORT, KENDO_GRID_SHARED, LessFilterOperatorComponent, LessOrEqualToFilterOperatorComponent, ListComponent, LoadingComponent, LoadingTemplateDirective, LocalDataChangesService, LogicalCellDirective, LogicalRowDirective, MenuTabbingService, NavigationService, NoRecordsTemplateDirective, NotEqualFilterOperatorComponent, NumericFilterCellComponent, NumericFilterComponent, NumericFilterMenuComponent, NumericFilterMenuInputComponent, PDFCommandDirective, PDFCommandToolbarDirective, PDFComponent, PDFMarginComponent, PDFModule, PDFService, PDFTemplateDirective, PopupCloseEvent, ReactiveEditingDirective, RedoCommandToolbarDirective, RemoveCommandDirective, RemoveCommandToolbarDirective, ResizableContainerDirective, ResizeService, ResponsiveService, RowDragHandleTemplateDirective, RowDragHintTemplateDirective, RowEditingDirectiveBase, RowReorderColumnComponent, RowReorderService, SaveCommandDirective, SaveCommandToolbarDirective, ScrollRequestService, ScrollSyncService, SelectAllCheckboxDirective, SelectAllToolbarToolComponent, SelectionCheckboxDirective, SelectionDirective, SelectionService, SinglePopupService, SizingOptionsService, Skip, SortCommandToolbarDirective, SortService, SpanColumnComponent, StartsWithFilterOperatorComponent, StatusBarTemplateDirective, StringFilterCellComponent, StringFilterComponent, StringFilterMenuComponent, StringFilterMenuInputComponent, SuspendService, TableBodyComponent, TableDirective, TemplateEditingDirective, ToolbarComponent, ToolbarTemplateDirective, UndoCommandToolbarDirective, UndoRedoDirective, UndoRedoEvent, defaultTrackBy, hasFilterMenu, hasFilterRow, isFilterable };
38559
+ export { AIAssistantToolbarDirective, AddCommandDirective, AddCommandToolbarDirective, AfterEqFilterOperatorComponent, AfterFilterOperatorComponent, AutoCompleteFilterCellComponent, BaseFilterCellComponent, BeforeEqFilterOperatorComponent, BeforeFilterOperatorComponent, BooleanFilterCellComponent, BooleanFilterComponent, BooleanFilterMenuComponent, BooleanFilterRadioButtonDirective, BrowserSupportService, CELL_CONTEXT, CancelCommandDirective, CancelCommandToolbarDirective, CellCloseEvent, CellComponent, CellLoadingTemplateDirective, CellSelectionAggregateService, CellSelectionService, CellTemplateDirective, ChangeNotificationService, CheckboxColumnComponent, ColGroupComponent, ColumnBase, ColumnChooserComponent, ColumnChooserToolbarDirective, ColumnComponent, ColumnGroupComponent, ColumnHandleDirective, ColumnInfoService, ColumnListComponent, ColumnLockedChangeEvent, ColumnMenuAutoSizeAllColumnsComponent, ColumnMenuAutoSizeColumnComponent, ColumnMenuChooserComponent, ColumnMenuComponent, ColumnMenuContainerComponent, ColumnMenuFilterComponent, ColumnMenuItemComponent, ColumnMenuItemContentTemplateDirective, ColumnMenuItemDirective, ColumnMenuLockComponent, ColumnMenuPositionComponent, ColumnMenuService, ColumnMenuSortComponent, ColumnMenuStickComponent, ColumnMenuTemplateDirective, ColumnReorderEvent, ColumnReorderService, ColumnResizingService, ColumnStickyChangeEvent, ColumnVisibilityChangeEvent, ColumnsContainer, CommandColumnComponent, ContainsFilterOperatorComponent, ContextService, CustomMessagesComponent, DEFAULT_AI_REQUEST_OPTIONS, DEFAULT_SCROLLER_FACTORY, DataBindingDirective, DateFilterCellComponent, DateFilterComponent, DateFilterMenuComponent, DateFilterMenuInputComponent, DetailCollapseEvent, DetailExpandEvent, DetailTemplateDirective, DetailsService, DoesNotContainFilterOperatorComponent, DomEventsService, DragAndDropService, DragHintService, DropCueService, EditCommandDirective, EditCommandToolbarDirective, EditService as EditServiceClass, EditTemplateDirective, EditingDirectiveBase, EndsWithFilterOperatorComponent, EqualFilterOperatorComponent, ExcelCommandDirective, ExcelCommandToolbarDirective, ExcelComponent, ExcelExportEvent, ExcelModule, ExcelService, ExpandDetailsDirective, ExpandGroupDirective, ExternalEditingDirective, FieldAccessorPipe, FilterCellComponent, FilterCellHostDirective, FilterCellOperatorsComponent, FilterCellTemplateDirective, FilterCellWrapperComponent, FilterCommandToolbarDirective, FilterInputDirective, FilterMenuComponent, FilterMenuContainerComponent, FilterMenuDropDownListDirective, FilterMenuHostDirective, FilterMenuInputWrapperComponent, FilterMenuTemplateDirective, FilterRowComponent, FilterService, FocusRoot, FocusableDirective, FooterComponent, FooterTemplateDirective, GreaterFilterOperatorComponent, GreaterOrEqualToFilterOperatorComponent, GridClipboardDirective, GridComponent, GridModule, GridSpacerComponent, GridTableDirective, GridToolbarAIResponseErrorEvent, GridToolbarAIResponseSuccessEvent, GridToolbarFocusableDirective, GridToolbarNavigationService, GroupCommandToolbarDirective, GroupFooterTemplateDirective, GroupHeaderColumnTemplateDirective, GroupHeaderComponent, GroupHeaderTemplateDirective, GroupInfoService, GroupPanelComponent, GroupsService, HeaderComponent, HeaderTemplateDirective, HighlightDirective, IdService, InCellEditingDirective, IsEmptyFilterOperatorComponent, IsNotEmptyFilterOperatorComponent, IsNotNullFilterOperatorComponent, IsNullFilterOperatorComponent, KENDO_GRID, KENDO_GRID_BODY_EXPORTS, KENDO_GRID_COLUMN_DRAGANDDROP, KENDO_GRID_COLUMN_MENU_DECLARATIONS, KENDO_GRID_COLUMN_MENU_EXPORTS, KENDO_GRID_DECLARATIONS, KENDO_GRID_EXCEL_EXPORT, KENDO_GRID_EXPORTS, KENDO_GRID_FILTER_MENU, KENDO_GRID_FILTER_MENU_EXPORTS, KENDO_GRID_FILTER_OPERATORS, KENDO_GRID_FILTER_ROW, KENDO_GRID_FILTER_ROW_EXPORTS, KENDO_GRID_FILTER_SHARED, KENDO_GRID_FOOTER_EXPORTS, KENDO_GRID_GROUP_EXPORTS, KENDO_GRID_HEADER_EXPORTS, KENDO_GRID_PDF_EXPORT, KENDO_GRID_SHARED, LessFilterOperatorComponent, LessOrEqualToFilterOperatorComponent, ListComponent, LoadingComponent, LoadingTemplateDirective, LocalDataChangesService, LogicalCellDirective, LogicalRowDirective, MenuTabbingService, MultiCheckboxFilterComponent, NavigationService, NoRecordsTemplateDirective, NotEqualFilterOperatorComponent, NumericFilterCellComponent, NumericFilterComponent, NumericFilterMenuComponent, NumericFilterMenuInputComponent, PDFCommandDirective, PDFCommandToolbarDirective, PDFComponent, PDFMarginComponent, PDFModule, PDFService, PDFTemplateDirective, PopupCloseEvent, ReactiveEditingDirective, RedoCommandToolbarDirective, RemoveCommandDirective, RemoveCommandToolbarDirective, ResizableContainerDirective, ResizeService, ResponsiveService, RowDragHandleTemplateDirective, RowDragHintTemplateDirective, RowEditingDirectiveBase, RowReorderColumnComponent, RowReorderService, SaveCommandDirective, SaveCommandToolbarDirective, ScrollRequestService, ScrollSyncService, SelectAllCheckboxDirective, SelectAllToolbarToolComponent, SelectionCheckboxDirective, SelectionDirective, SelectionService, SinglePopupService, SizingOptionsService, Skip, SortCommandToolbarDirective, SortService, SpanColumnComponent, StartsWithFilterOperatorComponent, StatusBarTemplateDirective, StringFilterCellComponent, StringFilterComponent, StringFilterMenuComponent, StringFilterMenuInputComponent, SuspendService, TableBodyComponent, TableDirective, TemplateEditingDirective, ToolbarComponent, ToolbarTemplateDirective, UndoCommandToolbarDirective, UndoRedoDirective, UndoRedoEvent, defaultTrackBy, hasFilterMenu, hasFilterRow, isFilterable };
38093
38560