@progress/kendo-angular-grid 20.1.0-develop.8 → 20.1.0

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 (30) hide show
  1. package/columns/column.component.d.ts +8 -1
  2. package/esm2022/columns/column.component.mjs +9 -1
  3. package/esm2022/common/clipboard.directive.mjs +3 -0
  4. package/esm2022/filtering/menu/filter-menu-container.component.mjs +120 -31
  5. package/esm2022/filtering/menu/filter-menu.component.mjs +4 -6
  6. package/esm2022/filtering/multicheckbox-filter.component.mjs +313 -0
  7. package/esm2022/grid.component.mjs +25 -12
  8. package/esm2022/index.mjs +1 -0
  9. package/esm2022/localization/messages.mjs +28 -1
  10. package/esm2022/package-metadata.mjs +2 -2
  11. package/esm2022/pdf/pdf.component.mjs +8 -3
  12. package/esm2022/rendering/cell.component.mjs +2 -2
  13. package/esm2022/rendering/common/field-accessor.pipe.mjs +1 -1
  14. package/esm2022/rendering/common/format.pipe.mjs +37 -0
  15. package/esm2022/rendering/header/header.component.mjs +1 -1
  16. package/esm2022/rendering/list.component.mjs +2 -2
  17. package/esm2022/rendering/table-body.component.mjs +4 -2
  18. package/esm2022/rendering/toolbar/tools/group-toolbar-tool.component.mjs +4 -3
  19. package/esm2022/scrolling/scroller.service.mjs +0 -3
  20. package/fesm2022/progress-kendo-angular-grid.mjs +1965 -1500
  21. package/filtering/filterable.d.ts +23 -0
  22. package/filtering/menu/filter-menu-container.component.d.ts +5 -1
  23. package/filtering/menu/filter-menu.component.d.ts +3 -4
  24. package/filtering/multicheckbox-filter.component.d.ts +50 -0
  25. package/grid.component.d.ts +4 -6
  26. package/index.d.ts +1 -0
  27. package/localization/messages.d.ts +22 -1
  28. package/package.json +21 -21
  29. package/rendering/common/format.pipe.d.ts +17 -0
  30. 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 [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 [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: 1759482491,
22422
- version: '20.1.0-develop.8',
22844
+ publishDate: 1761117321,
22845
+ version: '20.1.0',
22423
22846
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
22424
22847
  };
22425
22848
 
@@ -24380,9 +24803,6 @@ class ScrollerService {
24380
24803
  const lastItemIndex = this.rowHeightService.index(scrollTop + offsetHeight);
24381
24804
  const overflow = Math.max(firstItemIndex + (this.virtualPageSize || this.take) - this.total, 0);
24382
24805
  firstItemIndex = Math.max(firstItemIndex - overflow, 0);
24383
- if (lastItemIndex < this.lastLoaded) {
24384
- this.lastLoaded = lastItemIndex;
24385
- }
24386
24806
  if (down) {
24387
24807
  const atBottom = scrollHeight - clientHeight - scrollTop < SCROLL_BOTTOM_THRESHOLD;
24388
24808
  if (atBottom) {
@@ -25578,7 +25998,7 @@ class ListComponent {
25578
25998
  <div></div>
25579
25999
  </div>
25580
26000
  </div>
25581
- <div
26001
+ <div
25582
26002
  #container
25583
26003
  class="k-grid-content k-virtual-content"
25584
26004
  [kendoGridResizableContainer]="lockedLeafColumns.length > 0"
@@ -25703,7 +26123,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
25703
26123
  <div></div>
25704
26124
  </div>
25705
26125
  </div>
25706
- <div
26126
+ <div
25707
26127
  #container
25708
26128
  class="k-grid-content k-virtual-content"
25709
26129
  [kendoGridResizableContainer]="lockedLeafColumns.length > 0"
@@ -26568,8 +26988,29 @@ class GridMessages extends ComponentMessages {
26568
26988
  * Sets the text for the external editing Dialog <b>Cancel</b> button.
26569
26989
  */
26570
26990
  externalEditingCancelText;
26991
+ /**
26992
+ * The placeholder text for the multi-checkbox filter search input
26993
+ */
26994
+ multiCheckboxFilterSearchPlaceholder;
26995
+ /**
26996
+ * The label for the multi-checkbox filter select all option
26997
+ */
26998
+ multiCheckboxFilterSelectAllLabel;
26999
+ /**
27000
+ * The text for the multi-checkbox filter selected items count
27001
+ *
27002
+ * The text includes the selected items count and a localizable string.
27003
+ * For 3 selected items the default text is `3 selected items`.
27004
+ *
27005
+ * To customize the text, use the `{selectedItemsCount}` placeholder and a custom localizable string.
27006
+ * For example, `{selectedItemsCount} items are selected`.
27007
+ *
27008
+ * The `{selectedItemsCount}` placeholder is replaced with the count of selected items,
27009
+ * and the message is rendered as `3 items are selected`.
27010
+ */
27011
+ multiCheckboxFilterSelectedItemsCount;
26571
27012
  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 });
27013
+ 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
27014
  }
26574
27015
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GridMessages, decorators: [{
26575
27016
  type: Directive,
@@ -26827,6 +27268,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
26827
27268
  type: Input
26828
27269
  }], externalEditingCancelText: [{
26829
27270
  type: Input
27271
+ }], multiCheckboxFilterSearchPlaceholder: [{
27272
+ type: Input
27273
+ }], multiCheckboxFilterSelectAllLabel: [{
27274
+ type: Input
27275
+ }], multiCheckboxFilterSelectedItemsCount: [{
27276
+ type: Input
26830
27277
  }] } });
26831
27278
 
26832
27279
  /**
@@ -27848,11 +28295,12 @@ class GroupToolbarToolComponent {
27848
28295
  }
27849
28296
  }
27850
28297
  updateGroupedColumns() {
28298
+ const columns = this.ctx.grid['columnInfoService'].leafNamedColumns;
28299
+ const groupableColumns = columns.filter(column => column?.groupable);
27851
28300
  this.groupedColumns = this.group
27852
- .map(group => this.ctx.grid.columns.find(column => column?.field === group.field))
28301
+ .map(group => columns.find(column => column?.field === group.field))
27853
28302
  .filter(column => !!column);
27854
- this.ungroupedColumns = this.ctx.grid.columns.filter(column => column?.groupable &&
27855
- !this.groupedColumns.some(gc => gc?.field === column?.field));
28303
+ this.ungroupedColumns = groupableColumns.filter(column => !this.groupedColumns.some(gc => gc?.field === column?.field));
27856
28304
  }
27857
28305
  navigateToNextItem() {
27858
28306
  if (this.currentFocusedItemIndex < this.groupItems.length - 1) {
@@ -29205,1299 +29653,621 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
29205
29653
  args: [GroupToolbarToolComponent]
29206
29654
  }] } });
29207
29655
 
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'
29656
+ const createControl = (source) => (acc, key) => {
29657
+ acc[key] = new FormControl(source[key]);
29658
+ return acc;
29218
29659
  };
29660
+ const validateColumnsField = (columns) => expandColumns(columns.toArray())
29661
+ .filter(isColumnComponent)
29662
+ .filter(({ field }) => !isValidFieldName(field))
29663
+ .forEach(({ field }) => console.warn(ColumnConfigurationErrorMessages.fieldName(field)));
29664
+ const handleExpandCollapseGroupsService = (service, expandEmitter, collapseEmitter, map) => (service.changes.pipe(filter(({ group, emit }) => emit && isPresent(group)))
29665
+ .subscribe((x) => x.expand ? expandEmitter.emit(map(x)) : collapseEmitter.emit(map(x))));
29666
+ const handleExpandCollapseDetailsService = (service, expandEmitter, collapseEmitter, map) => (service.changes.pipe(filter(({ dataItem }) => isPresent(dataItem)))
29667
+ .subscribe((x) => x.expand ? expandEmitter.emit(map(x)) : collapseEmitter.emit(map(x))));
29668
+ const isInEditedCell = (element, gridElement, isStacked = false) => (closest(element, matchesClasses('k-grid-edit-cell')) || (isStacked && closest(element, matchesClasses('k-grid-stack-edit-cell')))) &&
29669
+ closest(element, matchesNodeName('kendo-grid')) === gridElement;
29670
+ const NOTIFY_DELAY = 500;
29219
29671
  /**
29220
- * Represents the event data when the AI Assistant request completes successfully.
29672
+ * Represents the Kendo UI for Angular Data Grid component.
29673
+ *
29674
+ * Use the `kendo-grid` component to display and manage tabular data.
29675
+ *
29676
+ * @example
29677
+ * ```html
29678
+ * <kendo-grid [data]="gridData"></kendo-grid>
29679
+ * ```
29680
+ *
29681
+ * @remarks
29682
+ * Supported children components are:
29683
+ * {@link CheckboxColumnComponent},
29684
+ * {@link ColumnChooserComponent},
29685
+ * {@link ColumnComponent},
29686
+ * {@link ColumnGroupComponent},
29687
+ * {@link ColumnMenuAutoSizeAllColumnsComponent},
29688
+ * {@link ColumnMenuAutoSizeColumnComponent},
29689
+ * {@link ColumnMenuChooserComponent},
29690
+ * {@link ColumnMenuComponent},
29691
+ * {@link ColumnMenuFilterComponent},
29692
+ * {@link ColumnMenuItemComponent},
29693
+ * {@link ColumnMenuLockComponent},
29694
+ * {@link ColumnMenuPositionComponent},
29695
+ * {@link ColumnMenuSortComponent},
29696
+ * {@link ColumnMenuStickComponent},
29697
+ * {@link CommandColumnComponent},
29698
+ * {@link CustomMessagesComponent},
29699
+ * {@link ExcelComponent},
29700
+ * {@link GridSpacerComponent},
29701
+ * {@link PDFComponent},
29702
+ * {@link RowReorderColumnComponent},
29703
+ * {@link SpanColumnComponent},
29704
+ * {@link ToolBarComponent}.
29221
29705
  */
29222
- class GridToolbarAIResponseSuccessEvent extends PreventableEvent$1 {
29706
+ class GridComponent {
29707
+ supportService;
29708
+ selectionService;
29709
+ cellSelectionService;
29710
+ wrapper;
29711
+ groupInfoService;
29712
+ groupsService;
29713
+ changeNotification;
29714
+ detailsService;
29715
+ editService;
29716
+ filterService;
29717
+ pdfService;
29718
+ responsiveService;
29719
+ renderer;
29720
+ excelService;
29721
+ ngZone;
29722
+ scrollSyncService;
29723
+ domEvents;
29724
+ columnResizingService;
29725
+ changeDetectorRef;
29726
+ columnReorderService;
29727
+ columnInfoService;
29728
+ navigationService;
29729
+ sortService;
29730
+ scrollRequestService;
29731
+ localization;
29732
+ ctx;
29733
+ sizingService;
29734
+ adaptiveGridService;
29735
+ rowReorderService;
29736
+ dataMappingService;
29223
29737
  /**
29224
- * The HTTP response from the AI service.
29738
+ * Sets the data of the Grid. If you provide an array, the Grid gets the total count automatically.
29739
+ * ([more information and example]({% slug binding_grid %})).
29225
29740
  */
29226
- response;
29227
- constructor(response) {
29228
- super();
29229
- this.response = response;
29741
+ set data(value) {
29742
+ this._data = value;
29743
+ if (this.selectable && this.selectableSettings?.enabled && this.isVirtual) {
29744
+ this.blockArrowSelection = false;
29745
+ }
29746
+ if (this.notifyTimeout) {
29747
+ clearTimeout(this.notifyTimeout);
29748
+ this.notifyTimeout = null;
29749
+ }
29750
+ if (this.rowReorderable) {
29751
+ this.ngZone.runOutsideAngular(() => {
29752
+ this.notifyTimeout = setTimeout(() => {
29753
+ this.notifyReorderContainers();
29754
+ }, NOTIFY_DELAY);
29755
+ });
29756
+ }
29230
29757
  }
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;
29758
+ get data() {
29759
+ return this._data;
29243
29760
  }
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;
29761
+ get hintText() {
29762
+ return this.rowReorderService.getDefaultHintText(this.columnList, this.flatData);
29253
29763
  }
29254
- if (filter.filters && Array.isArray(filter.filters)) {
29255
- return {
29256
- ...filter,
29257
- filters: filter.filters.map(f => convertDateStringsInFilter(f))
29258
- };
29764
+ /**
29765
+ * @hidden
29766
+ */
29767
+ get customHintTemplate() {
29768
+ if (this.rowReorderable) {
29769
+ const allColumns = this.columnList.toArray();
29770
+ const rowReorderColumn = allColumns.find(column => column.isRowReorderColumn);
29771
+ return rowReorderColumn.rowDragHintTemplateRef;
29772
+ }
29259
29773
  }
29260
- if (filter.field && filter.value !== undefined) {
29261
- if (typeof filter.value === 'string' && isDateOperator(filter.operator)) {
29262
- const date = parseDate(filter.value);
29774
+ /**
29775
+ * @hidden
29776
+ */
29777
+ get hintContext() {
29778
+ if (this.customHintTemplate) {
29779
+ const draggedRow = this.rowReorderService?.getDraggedRow(this.flatData);
29263
29780
  return {
29264
- ...filter,
29265
- value: date || filter.value
29781
+ $implicit: draggedRow?.dataItem,
29782
+ rowIndex: draggedRow?.rowIndex
29266
29783
  };
29267
29784
  }
29268
29785
  }
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
- });
29786
+ /**
29787
+ * Defines the page size used by the Grid pager.
29788
+ * Required for the [`paging`]({% slug paging_grid %}) feature.
29789
+ */
29790
+ pageSize;
29791
+ /**
29792
+ * Defines the height in pixels for the Grid when `scrollable` is set.
29793
+ * You can also set the height using `style.height` with units like `px`, `%`, `em`, or `rem`.
29794
+ */
29795
+ height;
29796
+ /**
29797
+ * Sets the `style.height` attribute of each Grid data or group header/footer row (`tr`) element in the DOM in pixels.
29798
+ * If some row cells have content that requires more space, the row automatically expands to fit the content.
29799
+ */
29800
+ rowHeight;
29801
+ /**
29802
+ * Enables or disables adaptive mode. Adaptive rendering is off by default.
29803
+ *
29804
+ * @default 'none'
29805
+ */
29806
+ adaptiveMode = 'none';
29807
+ /**
29808
+ * Sets the `style.height` attribute of each Grid detail row (`tr.k-detail-row`) element in the DOM in pixels.
29809
+ * If the detail row has content that requires more space, the row automatically expands to fit the content.
29810
+ */
29811
+ detailRowHeight;
29812
+ /**
29813
+ * Defines the number of records to skip in the pager.
29814
+ * Required for the [`paging`]({% slug paging_grid %}) feature.
29815
+ */
29816
+ get skip() {
29817
+ return this._skip;
29818
+ }
29819
+ set skip(value) {
29820
+ if (typeof value === 'number' && value >= 0) {
29821
+ this._skip = this.rowReorderService.skip = value;
29292
29822
  }
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);
29823
+ }
29824
+ /**
29825
+ * Defines the scroll mode for the Grid.
29826
+ *
29827
+ * @default 'scrollable'
29828
+ */
29829
+ scrollable = 'scrollable';
29830
+ /**
29831
+ * Enables the selection feature of the Grid. The `selectable` property can be set to `true`, `false`, or an object with additional settings.
29832
+ * [See example](slug:grid_row_selection).
29833
+ *
29834
+ * @default false
29835
+ */
29836
+ selectable = false;
29837
+ /**
29838
+ * Sets the descriptors for sorting the data ([see example](slug:manual_sorting_grid)).
29839
+ */
29840
+ set sort(value) {
29841
+ if (isArray(value)) {
29842
+ this._sort = value;
29304
29843
  }
29305
- else {
29306
- highlightItems.push({
29307
- itemKey: rowIndex,
29308
- });
29844
+ }
29845
+ get sort() {
29846
+ return this._sort;
29847
+ }
29848
+ /**
29849
+ * Specifies the sizing for Grid elements like tables, buttons, and inputs.
29850
+ *
29851
+ * @default 'medium'
29852
+ */
29853
+ set size(size) {
29854
+ this._size = size;
29855
+ if (size === 'none') {
29856
+ this.wrapper.nativeElement.classList.remove('k-grid-sm', 'k-grid-md');
29309
29857
  }
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;
29858
+ this.sizingService.changes.next(this.size);
29359
29859
  }
29360
- ngAfterViewInit() {
29361
- this.columns = this.columnInfoService.leafNamedColumns.map((col) => ({ field: col.field }));
29860
+ get size() {
29861
+ return this._size;
29362
29862
  }
29363
- ngOnDestroy() {
29364
- this.unsubscribeCurrentRequest();
29863
+ /**
29864
+ * A function that defines how to track changes for the data rows.
29865
+ * By default, the Grid tracks changes by the index of the data item.
29866
+ * Edited rows are tracked by reference.
29867
+ * [See example](slug:track_changes_grid).
29868
+ */
29869
+ trackBy = defaultTrackBy;
29870
+ /**
29871
+ * Sets the filter descriptor for the data ([see examples](slug:manual_filtering_grid)).
29872
+ */
29873
+ filter;
29874
+ /**
29875
+ * Sets the descriptors for grouping the data ([see example](slug:manual_grouping_grid)).
29876
+ */
29877
+ set group(value) {
29878
+ if (isArray(value)) {
29879
+ this._group = value;
29880
+ }
29365
29881
  }
29366
- message(message) {
29367
- return this.ctx.localization.get(message);
29882
+ get group() {
29883
+ return this._group;
29368
29884
  }
29369
- cancelRequest() {
29370
- this.aiToolDirective.cancelRequest.emit();
29371
- this.unsubscribeCurrentRequest();
29372
- this.streaming = false;
29885
+ /**
29886
+ * If `true`, renders only columns in the current viewport.
29887
+ *
29888
+ * @default false
29889
+ */
29890
+ virtualColumns = false;
29891
+ /**
29892
+ * @hidden
29893
+ */
29894
+ get showStatusBar() {
29895
+ return !!(this.selectable);
29373
29896
  }
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
- });
29897
+ /**
29898
+ * @hidden
29899
+ */
29900
+ get showTopToolbar() {
29901
+ return this.toolbarTemplate && ['top', 'both'].indexOf(this.toolbarTemplate.position) > -1;
29419
29902
  }
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);
29903
+ /**
29904
+ * @hidden
29905
+ */
29906
+ get showBottomToolbar() {
29907
+ return this.toolbarTemplate && ['bottom', 'both'].indexOf(this.toolbarTemplate.position) > -1;
29423
29908
  }
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);
29909
+ /**
29910
+ * @hidden
29911
+ */
29912
+ get isLocked() {
29913
+ return (this.lockedLeafColumns.length > 0 && !this.isStacked);
29463
29914
  }
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);
29915
+ /**
29916
+ * @hidden
29917
+ */
29918
+ get showTopPager() {
29919
+ const position = this.pageable.position;
29920
+ return this.pageable !== false && ['top', 'both'].indexOf(position) > -1;
29478
29921
  }
29479
- deleteLoadingOutput() {
29480
- if (this.aiToolDirective.promptOutputs[0]?.id === this.loadingOutput.id) {
29481
- this.aiToolDirective.promptOutputs.splice(0, 1);
29482
- }
29922
+ /**
29923
+ * @hidden
29924
+ */
29925
+ get showBottomPager() {
29926
+ const position = this.pageable.position;
29927
+ return this.pageable !== false && position !== 'top';
29483
29928
  }
29484
- unsubscribeCurrentRequest() {
29485
- if (this.currentRequestSubscription) {
29486
- this.currentRequestSubscription.unsubscribe();
29487
- this.currentRequestSubscription = null;
29488
- }
29929
+ /**
29930
+ * @hidden
29931
+ */
29932
+ get hasPager() {
29933
+ return this.showTopPager || this.showBottomPager;
29489
29934
  }
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
- }
29935
+ /**
29936
+ * @hidden
29937
+ */
29938
+ get showGroupPanel() {
29939
+ const isGroupable = this.groupable && this.groupable.enabled !== false;
29940
+ const isGrouped = this.group?.length > 0;
29941
+ return this.isStacked ? isGroupable && isGrouped : isGroupable;
29501
29942
  }
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);
29943
+ /**
29944
+ * @hidden
29945
+ */
29946
+ get groupableEmptyText() {
29947
+ return this.groupable.emptyText;
29509
29948
  }
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
- }
29949
+ /**
29950
+ * @hidden
29951
+ */
29952
+ get marqueeSelection() {
29953
+ return this.selectionService.enableMarquee || this.cellSelectionService.enableMarquee;
29530
29954
  }
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
29955
  /**
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.
29956
+ * @hidden
29657
29957
  */
29658
- requestUrl;
29958
+ get isAdaptiveModeEnabled() {
29959
+ return this.adaptiveMode === 'auto';
29960
+ }
29659
29961
  /**
29660
- * Configures the request options that the AI Assistant tool sends with the AI request.
29962
+ * @hidden
29661
29963
  *
29662
- * @default { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), role: 'user', method: 'POST', responseType: 'json', withCredentials: false }
29964
+ * The `isOpen` property is used to determine if a Grid Popup or ActionSheet is open.
29663
29965
  */
29664
- requestOptions;
29966
+ get isOpen() {
29967
+ return isPresent(this.adaptiveGridService.popupRef) || this.isActionSheetExpanded;
29968
+ }
29665
29969
  /**
29666
- * Configures the initial settings for the AI Assistant Window when opened.
29970
+ * @hidden
29667
29971
  */
29668
- aiWindowSettings;
29972
+ get isActionSheetExpanded() {
29973
+ return Boolean(this.adaptiveRenderer?.actionSheet?.expanded);
29974
+ }
29669
29975
  /**
29670
- * Configures the initial settings for the AI Prompt component that the AI Assistant Window component uses when opened.
29976
+ * @hidden
29671
29977
  */
29672
- aiPromptSettings;
29978
+ gridData = () => { return this.flatData; };
29673
29979
  /**
29674
- * Determines whether to close the AI Assistant Window automatically after a successful request.
29675
- * @default true
29980
+ * Enables the [filtering](slug:filtering_grid) feature of the Grid for columns with a `field` option.
29981
+ *
29982
+ * @default false
29676
29983
  */
29677
- autoClose = true;
29984
+ filterable = false;
29678
29985
  /**
29679
- * Determines whether to keep the AI Prompt's outputs after closing the AI Assistant Window.
29986
+ * Enables [sorting]({% slug sorting_grid %}) feature of the Grid for columns with a `field` option.
29680
29987
  * @default false
29681
29988
  */
29682
- keepOutputHistory = false;
29989
+ sortable = false;
29683
29990
  /**
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.
29991
+ * Configures the Grid pager ([see example](slug:paging_grid_settings)).
29992
+ * @default false
29687
29993
  */
29688
- promptRequest = new EventEmitter();
29994
+ pageable = false;
29995
+ get normalizedPageableSettings() {
29996
+ return normalize(this.pageable);
29997
+ }
29689
29998
  /**
29690
- * Emits an event when the user clicks the cancel button.
29999
+ * If `true`, allows grouping by dragging column headers ([see example]({% slug grouping_grid %})).
30000
+ *
30001
+ * @default false
29691
30002
  */
29692
- cancelRequest = new EventEmitter();
30003
+ groupable = false;
29693
30004
  /**
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.
30005
+ * Determines if the Grid can be resized.
30006
+ *
30007
+ * @default false
29696
30008
  */
29697
- responseSuccess = new EventEmitter();
30009
+ gridResizable = false;
29698
30010
  /**
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.
30011
+ * Enables row reordering feature of the Grid ([see example]({% slug reordering_rows_grid %})).
30012
+ *
30013
+ * @default false
29701
30014
  */
29702
- responseError = new EventEmitter();
30015
+ set rowReorderable(value) {
30016
+ this._rowReorderable = value;
30017
+ if (value) {
30018
+ this.rowReorderSubscription = this.rowReorderService.rowReorder.subscribe(args => {
30019
+ this.ngZone.run(() => {
30020
+ this.rowReorder.emit(args);
30021
+ });
30022
+ });
30023
+ }
30024
+ else {
30025
+ this.rowReorderSubscription?.unsubscribe();
30026
+ }
30027
+ }
30028
+ get rowReorderable() {
30029
+ return this._rowReorderable;
30030
+ }
29703
30031
  /**
29704
- * Emits an event when the AI Assistant tool closes.
30032
+ * By default, navigation is enabled. To disable, set to `false`.
30033
+ * To enable navigation for specific sections, provide a [`GridNavigableSection`](slug:api_grid_gridnavigablesection).
29705
30034
  */
29706
- close = new EventEmitter();
30035
+ set navigable(value) {
30036
+ if (typeof value === 'boolean') {
30037
+ this._navigable = value ? ['table', 'pager', 'toolbar'] : [];
30038
+ this.ctx.navigable = value;
30039
+ return;
30040
+ }
30041
+ else {
30042
+ this.ctx.navigable = value.includes('table');
30043
+ }
30044
+ this._navigable = value;
30045
+ }
30046
+ get navigable() {
30047
+ return this._navigable;
30048
+ }
29707
30049
  /**
29708
- * Emits an event when the AI Assistant tool opens.
30050
+ * If `true`, resizes columns during initialization to fit headers and content.
30051
+ * Columns with `autoSize` set to `false` are excluded.
30052
+ * [See example](slug:resizing_columns_grid).
30053
+ *
30054
+ * @default false
29709
30055
  */
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
- }
30056
+ autoSize = false;
29767
30057
  /**
29768
- * @hidden
30058
+ * Sets a function to apply custom CSS classes to each data row ([see example](slug:styling_grid_rows)).
29769
30059
  */
29770
- onClick() {
29771
- this.emitOpenClose = true;
29772
- this.toggleWindow();
30060
+ set rowClass(fn) {
30061
+ if (isDevMode() && typeof fn !== 'function') {
30062
+ throw new Error(GridConfigurationErrorMessages.functionType('rowClass', fn));
30063
+ }
30064
+ this._rowClass = fn;
30065
+ }
30066
+ get rowClass() {
30067
+ return this._rowClass;
29773
30068
  }
29774
30069
  /**
29775
- * Toggles the AI Assistant window.
30070
+ * Sets a function to determine if a data row is sticky (always visible after scrolling).
29776
30071
  */
29777
- toggleWindow() {
29778
- if (!this.windowRef) {
29779
- this.openWindow();
30072
+ set rowSticky(fn) {
30073
+ if (isDevMode() && isPresent(fn) && typeof fn !== 'function') {
30074
+ throw new Error(GridConfigurationErrorMessages.functionType('rowSticky', fn));
29780
30075
  }
29781
- else {
29782
- this.closeWindow();
30076
+ if (isPresent(fn)) {
30077
+ this._rowSticky = fn;
29783
30078
  }
29784
30079
  }
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;
30080
+ get rowSticky() {
30081
+ return this._rowSticky;
29838
30082
  }
29839
- closeWindow(focusAnchor = false) {
29840
- this.windowRef.close();
29841
- if (this.emitOpenClose) {
29842
- this.close.emit();
29843
- this.emitOpenClose = false;
30083
+ /**
30084
+ * Sets a function to determine if a data row is selected ([see example]({% slug grid_selection_custom %}#toc-setting-the-selected-rows)).
30085
+ */
30086
+ set rowSelected(fn) {
30087
+ if (isDevMode() && typeof fn !== 'function') {
30088
+ throw new Error(GridConfigurationErrorMessages.functionType('rowSelected', fn));
29844
30089
  }
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();
30090
+ this._rowSelected = fn;
30091
+ }
30092
+ get rowSelected() {
30093
+ return this._rowSelected;
29850
30094
  }
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
30095
  /**
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 %})).
30096
+ * Sets a function to determine if a data row is selectable.
29970
30097
  */
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
- });
30098
+ set isRowSelectable(fn) {
30099
+ if (isDevMode() && typeof fn !== 'function') {
30100
+ throw new Error(GridConfigurationErrorMessages.functionType('isRowSelectable', fn));
29986
30101
  }
30102
+ this._isRowSelectable = fn;
29987
30103
  }
29988
- get data() {
29989
- return this._data;
29990
- }
29991
- get hintText() {
29992
- return this.rowReorderService.getDefaultHintText(this.columnList, this.flatData);
30104
+ get isRowSelectable() {
30105
+ return this._isRowSelectable;
29993
30106
  }
29994
30107
  /**
29995
- * @hidden
30108
+ * Sets a function to determine if a data cell is selected.
30109
+ * The function returns an object with `selected` and `item` properties ([see example]({% slug grid_selection_custom %}#toc-setting-the-selected-cells)).
29996
30110
  */
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;
30111
+ set cellSelected(fn) {
30112
+ if (isDevMode() && typeof fn !== 'function') {
30113
+ throw new Error(GridConfigurationErrorMessages.functionType('cellSelected', fn));
30002
30114
  }
30115
+ this._cellSelected = fn;
30116
+ }
30117
+ get cellSelected() {
30118
+ return this._cellSelected;
30003
30119
  }
30004
30120
  /**
30005
- * @hidden
30121
+ * Returns the currently focused cell (if any).
30006
30122
  */
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
- }
30123
+ get activeCell() {
30124
+ return this.navigationService.activeCell;
30015
30125
  }
30016
30126
  /**
30017
- * Defines the page size used by the Grid pager.
30018
- * Required for the [`paging`]({% slug paging_grid %}) feature.
30127
+ * Returns the currently focused row (if any).
30019
30128
  */
30020
- pageSize;
30129
+ get activeRow() {
30130
+ return this.navigationService.activeRow;
30131
+ }
30021
30132
  /**
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`.
30133
+ * Returns the current Grid selection.
30134
+ *
30135
+ * @hidden
30024
30136
  */
30025
- height;
30137
+ get selection() {
30138
+ return (this.selectable || this.selectionDirective) ?
30139
+ this.defaultSelection ? this.defaultSelection.stateToArray() : this.selectionDirective.stateToArray() :
30140
+ [];
30141
+ }
30026
30142
  /**
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.
30143
+ * Gets the current `GridState`, including data operations and column state.
30144
+ * Use this to store and restore the Grid state.
30029
30145
  */
30030
- rowHeight;
30146
+ get currentState() {
30147
+ return {
30148
+ filter: this.filter,
30149
+ group: this.group,
30150
+ sort: this.sort,
30151
+ skip: this.skip,
30152
+ take: this.pageSize,
30153
+ columnsState: this.columns.toArray().flatMap(recursiveColumnsFlatMap),
30154
+ currentData: structuredClone(this.data)
30155
+ };
30156
+ }
30031
30157
  /**
30032
- * Enables or disables adaptive mode. Adaptive rendering is off by default.
30158
+ * If `true`, allows resizing columns by dragging header cell edges ([see example]({% slug resizing_columns_grid %})).
30033
30159
  *
30034
- * @default 'none'
30160
+ * @default false
30035
30161
  */
30036
- adaptiveMode = 'none';
30162
+ resizable = false;
30037
30163
  /**
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.
30164
+ * If `true`, allows reordering columns by dragging header cells ([see example]({% slug reordering_columns_grid %})).
30165
+ *
30166
+ * @default false
30040
30167
  */
30041
- detailRowHeight;
30168
+ reorderable = false;
30042
30169
  /**
30043
- * Defines the number of records to skip in the pager.
30044
- * Required for the [`paging`]({% slug paging_grid %}) feature.
30170
+ * If `true`, displays the Grid loading indicator ([see example]({% slug binding_grid %})).
30171
+ *
30172
+ * @default false
30045
30173
  */
30046
- get skip() {
30047
- return this._skip;
30174
+ set loading(value) {
30175
+ this._loading = value;
30176
+ this.rowReorderable && this.notifyReorderContainers();
30048
30177
  }
30049
- set skip(value) {
30050
- if (typeof value === 'number' && value >= 0) {
30051
- this._skip = this.rowReorderService.skip = value;
30052
- }
30178
+ get loading() {
30179
+ return this._loading;
30053
30180
  }
30054
30181
  /**
30055
- * Defines the scroll mode for the Grid.
30182
+ * If `true`, displays the column menu for columns ([see example]({% slug columnmenu_grid %})).
30056
30183
  *
30057
- * @default 'scrollable'
30184
+ * @default false
30058
30185
  */
30059
- scrollable = 'scrollable';
30186
+ columnMenu = false;
30060
30187
  /**
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).
30188
+ * If `true`, hides the Grid header. The header is visible by default.
30189
+ * The header includes column headers and the [filter row](slug:filter_row).
30063
30190
  *
30064
30191
  * @default false
30065
30192
  */
30066
- selectable = false;
30193
+ hideHeader = false;
30067
30194
  /**
30068
- * Sets the descriptors for sorting the data ([see example]({% slug sorting_grid %})).
30195
+ * 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.
30196
+ *
30197
+ * @default false
30069
30198
  */
30070
- set sort(value) {
30071
- if (isArray(value)) {
30072
- this._sort = value;
30073
- }
30199
+ showInactiveTools = false;
30200
+ /**
30201
+ * Sets a function to determine if a specific row is expanded.
30202
+ */
30203
+ set isDetailExpanded(callback) {
30204
+ this.detailsService.userCallback = callback;
30074
30205
  }
30075
- get sort() {
30076
- return this._sort;
30206
+ get isDetailExpanded() {
30207
+ return this.detailsService.userCallback;
30077
30208
  }
30078
30209
  /**
30079
- * Specifies the sizing for Grid elements like tables, buttons, and inputs.
30080
- *
30081
- * @default 'medium'
30210
+ * Sets a function to determine if a specific group row is expanded.
30082
30211
  */
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);
30212
+ set isGroupExpanded(callback) {
30213
+ this.groupsService.userCallback = callback;
30214
+ this.groupable = isPresent(callback);
30089
30215
  }
30090
- get size() {
30091
- return this._size;
30216
+ get isGroupExpanded() {
30217
+ return this.groupsService.userCallback;
30092
30218
  }
30093
30219
  /**
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).
30220
+ * Sets the Grid data layout display mode.
30221
+ *
30222
+ * @default 'columns'
30098
30223
  */
30099
- trackBy = defaultTrackBy;
30224
+ dataLayoutMode = 'columns';
30100
30225
  /**
30101
- * Sets the filter descriptor for the data ([see examples]({% slug filtering_grid %})).
30226
+ * Fires when the Grid data is filtered through the UI and the filter descriptor changes.
30102
30227
  */
30103
- filter;
30228
+ filterChange = new EventEmitter();
30104
30229
  /**
30105
- * Sets the descriptors for grouping the data ([see example]({% slug grouping_grid %})).
30230
+ * Fires when the page is changed through the UI ([see example]({% slug paging_grid %})).
30106
30231
  */
30107
- set group(value) {
30108
- if (isArray(value)) {
30109
- this._group = value;
30110
- }
30111
- }
30112
- get group() {
30113
- return this._group;
30114
- }
30232
+ pageChange = new EventEmitter();
30115
30233
  /**
30116
- * If `true`, renders only columns in the current viewport.
30117
- *
30118
- * @default false
30234
+ * Fires when the Grid data is grouped through the UI and the group descriptors change ([see example]({% slug grouping_grid %})).
30119
30235
  */
30120
- virtualColumns = false;
30236
+ groupChange;
30121
30237
  /**
30122
- * @hidden
30238
+ * Fires when the Grid data is sorted through the UI and the sort descriptors change ([see example]({% slug sorting_grid %})).
30123
30239
  */
30124
- get showStatusBar() {
30125
- return !!(this.selectable);
30126
- }
30240
+ sortChange = new EventEmitter();
30127
30241
  /**
30128
- * @hidden
30242
+ * Fires when the Grid selection changes through the UI.
30129
30243
  */
30130
- get showTopToolbar() {
30131
- return this.toolbarTemplate && ['top', 'both'].indexOf(this.toolbarTemplate.position) > -1;
30132
- }
30244
+ selectionChange = new EventEmitter();
30133
30245
  /**
30134
- * @hidden
30246
+ * Fires when a row is reordered through the UI.
30135
30247
  */
30136
- get showBottomToolbar() {
30137
- return this.toolbarTemplate && ['bottom', 'both'].indexOf(this.toolbarTemplate.position) > -1;
30138
- }
30248
+ rowReorder = new EventEmitter();
30139
30249
  /**
30140
- * @hidden
30250
+ * Fires when the data state of the Grid is changed.
30141
30251
  */
30142
- get isLocked() {
30143
- return (this.lockedLeafColumns.length > 0 && !this.isStacked);
30144
- }
30252
+ dataStateChange = new EventEmitter();
30145
30253
  /**
30146
- * @hidden
30254
+ * Fires when the data or columns state of the Grid is changed.
30147
30255
  */
30148
- get showTopPager() {
30149
- const position = this.pageable.position;
30150
- return this.pageable !== false && ['top', 'both'].indexOf(position) > -1;
30151
- }
30256
+ gridStateChange = new EventEmitter();
30152
30257
  /**
30153
- * @hidden
30258
+ * Fires when a group is expanded through the UI.
30154
30259
  */
30155
- get showBottomPager() {
30156
- const position = this.pageable.position;
30157
- return this.pageable !== false && position !== 'top';
30158
- }
30260
+ groupExpand = new EventEmitter();
30159
30261
  /**
30160
- * @hidden
30262
+ * Fires when a group is collapsed through the UI.
30161
30263
  */
30162
- get hasPager() {
30163
- return this.showTopPager || this.showBottomPager;
30164
- }
30264
+ groupCollapse = new EventEmitter();
30165
30265
  /**
30166
- * @hidden
30266
+ * Fires when a detail row is expanded through the UI.
30167
30267
  */
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
- }
30268
+ detailExpand = new EventEmitter();
30173
30269
  /**
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.
30270
+ * Fires when a detail row is collapsed through the UI.
30501
30271
  */
30502
30272
  detailCollapse = new EventEmitter();
30503
30273
  /**
@@ -30677,7 +30447,6 @@ class GridComponent {
30677
30447
  this._customToolbarTemplate = customToolbarTemplate;
30678
30448
  }
30679
30449
  columnMenuTemplates;
30680
- aiAssistantToolbarTool;
30681
30450
  lockedHeader;
30682
30451
  header;
30683
30452
  footer = new QueryList();
@@ -32247,7 +32016,7 @@ class GridComponent {
32247
32016
  ColumnMenuService,
32248
32017
  MenuTabbingService,
32249
32018
  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: `
32019
+ ], 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
32020
  <ng-container kendoGridLocalizedMessages
32252
32021
  i18n-groupPanelEmpty="kendo.grid.groupPanelEmpty|The label visible in the Grid group panel when it is empty"
32253
32022
  groupPanelEmpty="Drag a column header and drop it here to group by that column"
@@ -32623,6 +32392,15 @@ class GridComponent {
32623
32392
 
32624
32393
  i18n-columnChooserSelectedColumnsCount="kendo.grid.columnChooserSelectedColumnsCount|The text displayed in the Column Chooser for the number of selected columns"
32625
32394
  columnChooserSelectedColumnsCount="{{ '{selectedColumnsCount} Selected items' }}"
32395
+
32396
+ i18n-multiCheckboxFilterSearchPlaceholder="kendo.grid.multiCheckboxFilterSearchPlaceholder|The placeholder text for the multi-checkbox filter search input"
32397
+ multiCheckboxFilterSearchPlaceholder="Search..."
32398
+
32399
+ i18n-multiCheckboxFilterSelectAllLabel="kendo.grid.multiCheckboxFilterSelectAllLabel|The label for the multi-checkbox filter select all option"
32400
+ multiCheckboxFilterSelectAllLabel="Select all"
32401
+
32402
+ i18n-multiCheckboxFilterSelectedItemsCount="kendo.grid.multiCheckboxFilterSelectedItemsCount|The text for the multi-checkbox filter selected items count"
32403
+ multiCheckboxFilterSelectedItemsCount="{{ '{selectedItemsCount} selected items' }}"
32626
32404
  >
32627
32405
  </ng-container>
32628
32406
  <kendo-grid-toolbar
@@ -33041,10 +32819,10 @@ class GridComponent {
33041
32819
  </kendo-pager-info>
33042
32820
  </ng-template>
33043
32821
  <div #dialogContainer></div>
32822
+ <div #windowContainer></div>
33044
32823
 
33045
32824
  <kendo-grid-adaptive-renderer *ngIf="isAdaptiveModeEnabled"></kendo-grid-adaptive-renderer>
33046
32825
  <kendo-resize-sensor *ngIf="isVirtual" (resize)="onResize()"></kendo-resize-sensor>
33047
- <div *ngIf="aiAssistantToolbarTool" #windowContainer></div>
33048
32826
 
33049
32827
  <div kendoWatermarkOverlay *ngIf="showLicenseWatermark" [licenseMessage]="licenseMessage"></div>
33050
32828
  `, 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 +33261,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
33483
33261
 
33484
33262
  i18n-columnChooserSelectedColumnsCount="kendo.grid.columnChooserSelectedColumnsCount|The text displayed in the Column Chooser for the number of selected columns"
33485
33263
  columnChooserSelectedColumnsCount="{{ '{selectedColumnsCount} Selected items' }}"
33264
+
33265
+ i18n-multiCheckboxFilterSearchPlaceholder="kendo.grid.multiCheckboxFilterSearchPlaceholder|The placeholder text for the multi-checkbox filter search input"
33266
+ multiCheckboxFilterSearchPlaceholder="Search..."
33267
+
33268
+ i18n-multiCheckboxFilterSelectAllLabel="kendo.grid.multiCheckboxFilterSelectAllLabel|The label for the multi-checkbox filter select all option"
33269
+ multiCheckboxFilterSelectAllLabel="Select all"
33270
+
33271
+ i18n-multiCheckboxFilterSelectedItemsCount="kendo.grid.multiCheckboxFilterSelectedItemsCount|The text for the multi-checkbox filter selected items count"
33272
+ multiCheckboxFilterSelectedItemsCount="{{ '{selectedItemsCount} selected items' }}"
33486
33273
  >
33487
33274
  </ng-container>
33488
33275
  <kendo-grid-toolbar
@@ -33901,10 +33688,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
33901
33688
  </kendo-pager-info>
33902
33689
  </ng-template>
33903
33690
  <div #dialogContainer></div>
33691
+ <div #windowContainer></div>
33904
33692
 
33905
33693
  <kendo-grid-adaptive-renderer *ngIf="isAdaptiveModeEnabled"></kendo-grid-adaptive-renderer>
33906
33694
  <kendo-resize-sensor *ngIf="isVirtual" (resize)="onResize()"></kendo-resize-sensor>
33907
- <div *ngIf="aiAssistantToolbarTool" #windowContainer></div>
33908
33695
 
33909
33696
  <div kendoWatermarkOverlay *ngIf="showLicenseWatermark" [licenseMessage]="licenseMessage"></div>
33910
33697
  `,
@@ -34113,9 +33900,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
34113
33900
  }], columnMenuTemplates: [{
34114
33901
  type: ContentChildren,
34115
33902
  args: [ColumnMenuTemplateDirective]
34116
- }], aiAssistantToolbarTool: [{
34117
- type: ContentChild,
34118
- args: [AIAssistantToolbarDirective]
34119
33903
  }], lockedHeader: [{
34120
33904
  type: ViewChild,
34121
33905
  args: ['lockedHeader']
@@ -35576,6 +35360,9 @@ class GridClipboardDirective {
35576
35360
  const isPaste = operationType === 'paste';
35577
35361
  const pastedData = args.clipboardData.getData('text');
35578
35362
  const visibleCols = this.host.columns.toArray().filter(c => c.isVisible);
35363
+ if (visibleCols.some(c => c.orderIndex > 0)) { // columns have been reordered
35364
+ visibleCols.sort((a, b) => a.orderIndex - b.orderIndex);
35365
+ }
35579
35366
  const data = isPaste ?
35580
35367
  {
35581
35368
  dataString: pastedData,
@@ -37190,325 +36977,1003 @@ class CancelCommandToolbarDirective extends ToolbarEditingToolBase {
37190
36977
  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
36978
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CancelCommandToolbarDirective, isStandalone: true, selector: "[kendoGridCancelTool]", usesInheritance: true, ngImport: i0 });
37192
36979
  }
37193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CancelCommandToolbarDirective, decorators: [{
37194
- type: Directive,
36980
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CancelCommandToolbarDirective, decorators: [{
36981
+ type: Directive,
36982
+ args: [{
36983
+ selector: '[kendoGridCancelTool]',
36984
+ standalone: true
36985
+ }]
36986
+ }], ctorParameters: function () { return [{ type: EditService }, { type: i54.ToolBarButtonComponent }, { type: SelectionService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; } });
36987
+
36988
+ let incrementingId = 0;
36989
+ /**
36990
+ * Represents the toolbar tool for grouping columns of the Grid.
36991
+ * Use this directive on any `kendo-toolbar-button` inside a ToolbarComponent in the Grid.
36992
+ * When you click the toolbar button with this directive, the `group` event is triggered.
36993
+ *
36994
+ * @example
36995
+ * ```html
36996
+ * <kendo-grid>
36997
+ * <kendo-toolbar>
36998
+ * <kendo-toolbar-button text="Group" kendoGridGroupTool></kendo-toolbar-button>
36999
+ * </kendo-toolbar>
37000
+ * </kendo-grid>
37001
+ * ```
37002
+ * @remarks
37003
+ * Applied to: {@link ToolBarButtonComponent}.
37004
+ */
37005
+ class GroupCommandToolbarDirective {
37006
+ host;
37007
+ popupService;
37008
+ ctx;
37009
+ ngZone;
37010
+ renderer;
37011
+ adaptiveGridService;
37012
+ popupRef;
37013
+ nextId = incrementingId++;
37014
+ toolSubs = new Subscription();
37015
+ popupSubs;
37016
+ actionSheetCloseSub;
37017
+ removeClickListener;
37018
+ constructor(host, popupService, ctx, ngZone, renderer, adaptiveGridService) {
37019
+ this.host = host;
37020
+ this.popupService = popupService;
37021
+ this.ctx = ctx;
37022
+ this.ngZone = ngZone;
37023
+ this.renderer = renderer;
37024
+ this.adaptiveGridService = adaptiveGridService;
37025
+ }
37026
+ ngOnInit() {
37027
+ this.toolSubs = this.host.click.subscribe(e => this.onClick(e));
37028
+ this.toolSubs.add(this.ctx.grid.groupChange.subscribe(group => {
37029
+ this.host.showBadge = this.isGroupingApplied(group);
37030
+ }));
37031
+ this.host.hasBadgeContainer = true;
37032
+ this.host.showBadge = this.isGroupingApplied(this.ctx.grid.group);
37033
+ const hasToolbarIcon = isPresent$1(this.host.toolbarOptions.icon) && this.host.toolbarOptions.icon !== '';
37034
+ const hasOverflowIcon = isPresent$1(this.host.overflowOptions.icon) && this.host.overflowOptions.icon !== '';
37035
+ const hasIcon = hasToolbarIcon && hasOverflowIcon;
37036
+ const hasSvgIcon = isPresent$1(this.host.toolbarOptions.svgIcon) && isPresent$1(this.host.overflowOptions.svgIcon);
37037
+ if (!hasIcon) {
37038
+ this.host.icon = 'group';
37039
+ }
37040
+ if (!hasSvgIcon) {
37041
+ this.host.svgIcon = groupIcon;
37042
+ }
37043
+ }
37044
+ ngAfterViewInit() {
37045
+ if (!isPresent$1(this.host.text)) {
37046
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => {
37047
+ this.host.text = this.ctx.localization.get(`groupToolbarToolText`);
37048
+ });
37049
+ }
37050
+ this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
37051
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37052
+ this.buttonElement?.setAttribute('title', this.ctx.localization.get('groupToolbarToolText'));
37053
+ }
37054
+ ngOnDestroy() {
37055
+ if (this.toolSubs) {
37056
+ this.toolSubs.unsubscribe();
37057
+ }
37058
+ if (this.popupSubs) {
37059
+ this.popupSubs.unsubscribe();
37060
+ }
37061
+ if (this.popupRef) {
37062
+ this.popupRef.close();
37063
+ this.popupRef = null;
37064
+ }
37065
+ if (this.actionSheetCloseSub) {
37066
+ this.actionSheetCloseSub.unsubscribe();
37067
+ this.actionSheetCloseSub = null;
37068
+ }
37069
+ if (this.removeClickListener) {
37070
+ this.removeClickListener();
37071
+ this.removeClickListener = null;
37072
+ }
37073
+ }
37074
+ onClick(e) {
37075
+ e.preventDefault();
37076
+ if (this.ctx.grid.adaptiveMode === 'auto' && this.adaptiveGridService.windowSize !== 'large') {
37077
+ if (!this.ctx.grid.isActionSheetExpanded) {
37078
+ this.adaptiveGridService.viewType = 'groupToolbarTool';
37079
+ this.ctx.grid.adaptiveRenderer.actionSheet.toggle(true);
37080
+ this.host.selected = true;
37081
+ this.actionSheetCloseSub = this.ctx.grid.adaptiveRenderer.actionSheet.collapse.subscribe(() => this.host.selected = false);
37082
+ }
37083
+ }
37084
+ else {
37085
+ if (this.popupRef) {
37086
+ this.closePopup();
37087
+ return;
37088
+ }
37089
+ this.openPopup();
37090
+ }
37091
+ }
37092
+ openPopup() {
37093
+ const direction = this.ctx.localization.rtl ? 'right' : 'left';
37094
+ this.popupRef = this.popupService.open({
37095
+ anchor: this.buttonElement,
37096
+ content: GroupToolbarToolComponent,
37097
+ popupClass: 'k-grid-columnmenu-popup',
37098
+ positionMode: 'absolute',
37099
+ anchorAlign: { vertical: 'bottom', horizontal: direction },
37100
+ popupAlign: { vertical: 'top', horizontal: direction }
37101
+ });
37102
+ this.adaptiveGridService.popupRef = this.popupRef;
37103
+ this.setPopupAttributes();
37104
+ this.host.selected = true;
37105
+ this.ngZone.runOutsideAngular(() => {
37106
+ if (!isDocumentAvailable()) {
37107
+ return;
37108
+ }
37109
+ this.removeClickListener = this.renderer.listen('document', 'click', (e) => {
37110
+ if (this.popupRef && !closest$1(e.target, node => node === this.popupRef.popupElement || node === this.buttonElement)) {
37111
+ this.ngZone.run(() => {
37112
+ this.closePopup();
37113
+ });
37114
+ }
37115
+ });
37116
+ });
37117
+ this.popupSubs = this.popupRef.popup.instance.anchorViewportLeave.subscribe(() => {
37118
+ this.popupSubs?.unsubscribe();
37119
+ this.popupSubs = null;
37120
+ this.closePopup();
37121
+ });
37122
+ this.initPopupProperties();
37123
+ }
37124
+ setPopupAttributes() {
37125
+ const popupElement = this.popupRef.popupElement;
37126
+ const popupId = `k-group-tool-${this.nextId}-popup`;
37127
+ const popupAriaElement = popupElement.querySelector('.k-popup');
37128
+ this.renderer.setAttribute(popupElement, 'dir', this.ctx.localization.rtl ? 'rtl' : 'ltr');
37129
+ this.renderer.setAttribute(popupAriaElement, 'id', popupId);
37130
+ this.renderer.setAttribute(popupAriaElement, 'role', 'dialog');
37131
+ this.buttonElement?.setAttribute('aria-expanded', 'true');
37132
+ this.buttonElement?.setAttribute('aria-controls', popupId);
37133
+ }
37134
+ initPopupProperties() {
37135
+ this.popupRef.content.instance.ctx = this.ctx;
37136
+ this.popupRef.content.instance.hostButton = this.host;
37137
+ this.popupSubs.add(this.popupRef.content.instance.groupClear.subscribe(() => {
37138
+ this.closePopup();
37139
+ }));
37140
+ this.popupSubs.add(this.popupRef.content.instance.close.subscribe(() => {
37141
+ this.closePopup();
37142
+ }));
37143
+ }
37144
+ closePopup() {
37145
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37146
+ this.buttonElement?.removeAttribute('aria-controls');
37147
+ this.host.selected = false;
37148
+ if (this.popupRef) {
37149
+ this.popupRef.close();
37150
+ this.popupRef = null;
37151
+ }
37152
+ if (this.popupSubs) {
37153
+ this.popupSubs.unsubscribe();
37154
+ this.popupSubs = null;
37155
+ }
37156
+ if (this.removeClickListener) {
37157
+ this.removeClickListener();
37158
+ this.removeClickListener = null;
37159
+ }
37160
+ }
37161
+ get buttonElement() {
37162
+ return this.host.getButton();
37163
+ }
37164
+ isGroupingApplied(group) {
37165
+ return isPresent$1(group) && group.length > 0;
37166
+ }
37167
+ 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 });
37168
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GroupCommandToolbarDirective, isStandalone: true, selector: "[kendoGridGroupTool]", ngImport: i0 });
37169
+ }
37170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupCommandToolbarDirective, decorators: [{
37171
+ type: Directive,
37172
+ args: [{
37173
+ selector: '[kendoGridGroupTool]',
37174
+ standalone: true
37175
+ }]
37176
+ }], ctorParameters: function () { return [{ type: i54.ToolBarButtonComponent }, { type: i2.PopupService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: AdaptiveGridService }]; } });
37177
+
37178
+ /**
37179
+ * Stores the row and cell highlight state of the Grid.
37180
+ *
37181
+ * @example
37182
+ * ```typescript
37183
+ * <kendo-grid kendoGridHighlight="ProductID"></kendo-grid>
37184
+ *
37185
+ * <kendo-grid [kendoGridHighlight]="myKey"></kendo-grid>
37186
+ * ```
37187
+ * @remarks
37188
+ * Applied to: {@link GridComponent}.
37189
+ */
37190
+ class HighlightDirective {
37191
+ ctx;
37192
+ /**
37193
+ * Stores the highlighted items keys.
37194
+ * @default []
37195
+ */
37196
+ highlightedKeys = [];
37197
+ /**
37198
+ * Sets the item key to store in `highlightedKeys`. The Grid uses the row index as the default item key.
37199
+ */
37200
+ highlightItemKey;
37201
+ /**
37202
+ * Sets the column key for a data cell. The Grid uses the column index as the default column key.
37203
+ */
37204
+ highlightColumnKey;
37205
+ rowHighlightState = new Set();
37206
+ cellHighlightState = new PairSet();
37207
+ constructor(ctx) {
37208
+ this.ctx = ctx;
37209
+ this.ctx.highlightDirective = this;
37210
+ }
37211
+ ngOnChanges(changes) {
37212
+ if (isPresent$1(changes['highlightedKeys'])) {
37213
+ this.setState(this.highlightedKeys);
37214
+ }
37215
+ }
37216
+ ngOnDestroy() {
37217
+ this.reset();
37218
+ this.ctx.highlightDirective = null;
37219
+ }
37220
+ /**
37221
+ * @hidden
37222
+ */
37223
+ isRowHighlighted(row) {
37224
+ return this.rowHighlightState.has(this.getItemKey(row));
37225
+ }
37226
+ /**
37227
+ * @hidden
37228
+ */
37229
+ isCellHighlighted(row, column, colIndex) {
37230
+ const highlightItem = this.getHighlightItem(row, column, colIndex);
37231
+ return this.cellHighlightState.has(highlightItem.itemKey, highlightItem.columnKey);
37232
+ }
37233
+ getItemKey(row) {
37234
+ if (this.highlightItemKey) {
37235
+ if (typeof this.highlightItemKey === "string") {
37236
+ return row.data?.[this.highlightItemKey];
37237
+ }
37238
+ if (typeof this.highlightItemKey === "function") {
37239
+ return this.highlightItemKey(row);
37240
+ }
37241
+ }
37242
+ return row.index;
37243
+ }
37244
+ getHighlightItem(row, col, colIndex) {
37245
+ const itemIdentifiers = {};
37246
+ itemIdentifiers.itemKey = this.getItemKey(row);
37247
+ if (!isPresent$1(col) && !isPresent$1(colIndex)) {
37248
+ return itemIdentifiers;
37249
+ }
37250
+ if (this.highlightColumnKey) {
37251
+ if (typeof this.highlightColumnKey === "string") {
37252
+ itemIdentifiers.columnKey = row.dataItem[this.highlightColumnKey];
37253
+ }
37254
+ if (typeof this.highlightColumnKey === "function") {
37255
+ itemIdentifiers.columnKey = this.highlightColumnKey(col, colIndex);
37256
+ }
37257
+ }
37258
+ return {
37259
+ itemKey: itemIdentifiers.itemKey,
37260
+ columnKey: itemIdentifiers.columnKey ? itemIdentifiers.columnKey : colIndex
37261
+ };
37262
+ }
37263
+ setState(highlightedKeys) {
37264
+ this.reset();
37265
+ if (!highlightedKeys || highlightedKeys.length === 0) {
37266
+ return;
37267
+ }
37268
+ const rowHighlights = highlightedKeys.filter(item => !isPresent$1(item.columnKey));
37269
+ const cellHighlights = highlightedKeys.filter(item => isPresent$1(item.columnKey));
37270
+ if (cellHighlights.length > 0) {
37271
+ this.cellHighlightState = new PairSet(cellHighlights, 'itemKey', 'columnKey');
37272
+ }
37273
+ if (rowHighlights.length > 0) {
37274
+ rowHighlights.forEach(item => {
37275
+ this.rowHighlightState.add(item.itemKey);
37276
+ });
37277
+ }
37278
+ }
37279
+ reset() {
37280
+ this.rowHighlightState.clear();
37281
+ this.cellHighlightState.clear();
37282
+ }
37283
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, deps: [{ token: ContextService }], target: i0.ɵɵFactoryTarget.Directive });
37284
+ 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 });
37285
+ }
37286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, decorators: [{
37287
+ type: Directive,
37288
+ args: [{
37289
+ selector: '[kendoGridHighlight]',
37290
+ standalone: true
37291
+ }]
37292
+ }], ctorParameters: function () { return [{ type: ContextService }]; }, propDecorators: { highlightedKeys: [{
37293
+ type: Input
37294
+ }], highlightItemKey: [{
37295
+ type: Input,
37296
+ args: ["kendoGridHighlight"]
37297
+ }], highlightColumnKey: [{
37298
+ type: Input
37299
+ }] } });
37300
+
37301
+ /**
37302
+ * @hidden
37303
+ */
37304
+ const DEFAULT_AI_REQUEST_OPTIONS = {
37305
+ headers: new HttpHeaders({
37306
+ 'Content-Type': 'application/json'
37307
+ }),
37308
+ role: 'user',
37309
+ method: 'POST',
37310
+ responseType: 'json'
37311
+ };
37312
+ /**
37313
+ * Represents the event data when the AI Assistant request completes successfully.
37314
+ */
37315
+ class GridToolbarAIResponseSuccessEvent extends PreventableEvent$1 {
37316
+ /**
37317
+ * The HTTP response from the AI service.
37318
+ */
37319
+ response;
37320
+ constructor(response) {
37321
+ super();
37322
+ this.response = response;
37323
+ }
37324
+ }
37325
+ /**
37326
+ * Represents the event data when the AI Assistant request completes with an error.
37327
+ */
37328
+ class GridToolbarAIResponseErrorEvent extends PreventableEvent$1 {
37329
+ /**
37330
+ * The HTTP error response from the AI service.
37331
+ */
37332
+ error;
37333
+ constructor(error) {
37334
+ super();
37335
+ this.error = error;
37336
+ }
37337
+ }
37338
+
37339
+ /**
37340
+ * @hidden
37341
+ * Converts date strings in a filter to Date objects.
37342
+ */
37343
+ const convertDateStringsInFilter = (filter) => {
37344
+ if (!filter) {
37345
+ return filter;
37346
+ }
37347
+ if (filter.filters && Array.isArray(filter.filters)) {
37348
+ return {
37349
+ ...filter,
37350
+ filters: filter.filters.map(f => convertDateStringsInFilter(f))
37351
+ };
37352
+ }
37353
+ if (filter.field && filter.value !== undefined) {
37354
+ if (typeof filter.value === 'string' && isDateOperator(filter.operator)) {
37355
+ const date = parseDate(filter.value);
37356
+ return {
37357
+ ...filter,
37358
+ value: date || filter.value
37359
+ };
37360
+ }
37361
+ }
37362
+ return filter;
37363
+ };
37364
+ /**
37365
+ * @hidden
37366
+ */
37367
+ const isDateOperator = (operator) => {
37368
+ const dateOperators = [
37369
+ 'eq', 'neq', 'lt', 'lte', 'gt', 'gte'
37370
+ ];
37371
+ return dateOperators.includes(operator);
37372
+ };
37373
+ /**
37374
+ * @hidden
37375
+ * Processes cell highlights for a specific filter and item.
37376
+ */
37377
+ const processCellHighlights = (filter, rowIndex, columns, highlightItems) => {
37378
+ Object.keys(filter.cells).forEach((columnField) => {
37379
+ const actualColumnIndex = Array.from(columns).findIndex((col) => col.field === columnField);
37380
+ if (actualColumnIndex !== -1) {
37381
+ highlightItems.push({
37382
+ itemKey: rowIndex,
37383
+ columnKey: actualColumnIndex,
37384
+ });
37385
+ }
37386
+ });
37387
+ };
37388
+ /**
37389
+ * @hidden
37390
+ * Processes filtered results and adds highlight items.
37391
+ */
37392
+ const processFilteredResults = (filteredResults, data, filter, columns, highlightItems) => {
37393
+ filteredResults?.forEach((item) => {
37394
+ const rowIndex = data.findIndex((dataItem) => dataItem === item);
37395
+ if (filter.cells && Object.keys(filter.cells).length > 0) {
37396
+ processCellHighlights(filter, rowIndex, columns, highlightItems);
37397
+ }
37398
+ else {
37399
+ highlightItems.push({
37400
+ itemKey: rowIndex,
37401
+ });
37402
+ }
37403
+ });
37404
+ };
37405
+ /**
37406
+ * @hidden
37407
+ * Highlights items in a grid based on the provided filters and columns.
37408
+ * @param data - The data to be highlighted.
37409
+ * @param filters - The composite highlight descriptors containing the filters and logic.
37410
+ * @param columns - The columns of the grid.
37411
+ * @returns An array of HighlightItem objects representing the highlighted items.
37412
+ */
37413
+ const highlightBy = (data, filters, columns) => {
37414
+ const highlightItems = [];
37415
+ filters.forEach((filter) => {
37416
+ const processedFilters = filter.filters.map((filter) => convertDateStringsInFilter(filter));
37417
+ const filteredResults = filterBy(data, {
37418
+ logic: filter.logic || "and",
37419
+ filters: processedFilters,
37420
+ });
37421
+ processFilteredResults(filteredResults, data, filter, columns, highlightItems);
37422
+ });
37423
+ return highlightItems;
37424
+ };
37425
+
37426
+ /**
37427
+ * @hidden
37428
+ */
37429
+ class AiAssistantComponent {
37430
+ http;
37431
+ ctx;
37432
+ columnInfoService;
37433
+ aiPrompt;
37434
+ activeView = 0;
37435
+ requestUrl;
37436
+ requestOptions;
37437
+ aiPromptSettings;
37438
+ aiToolDirective;
37439
+ streaming = false;
37440
+ disabledGenerateButton = false;
37441
+ lastMessage;
37442
+ requestData;
37443
+ currentRequestSubscription = null;
37444
+ //Remove this when the AI Assistant has a built-in loading indicator
37445
+ loadingOutput = { id: 'k-loading-item', output: '', prompt: '' };
37446
+ columns = [];
37447
+ idCounter = 0;
37448
+ constructor(http, ctx, columnInfoService) {
37449
+ this.http = http;
37450
+ this.ctx = ctx;
37451
+ this.columnInfoService = columnInfoService;
37452
+ }
37453
+ ngAfterViewInit() {
37454
+ this.columns = this.columnInfoService.leafNamedColumns.map((col) => ({ field: col.field }));
37455
+ }
37456
+ ngOnDestroy() {
37457
+ this.unsubscribeCurrentRequest();
37458
+ }
37459
+ message(message) {
37460
+ return this.ctx.localization.get(message);
37461
+ }
37462
+ cancelRequest() {
37463
+ this.aiToolDirective.cancelRequest.emit();
37464
+ this.unsubscribeCurrentRequest();
37465
+ this.streaming = false;
37466
+ }
37467
+ onPromptRequest(ev) {
37468
+ if (this.aiToolDirective.promptOutputs.length === 0) {
37469
+ this.aiToolDirective.promptOutputs.push(this.loadingOutput);
37470
+ }
37471
+ this.unsubscribeCurrentRequest();
37472
+ this.streaming = true;
37473
+ this.activeView = 1;
37474
+ if (ev.prompt) {
37475
+ this.lastMessage = ev.prompt;
37476
+ }
37477
+ this.requestData = {
37478
+ columns: this.columns,
37479
+ promptMessage: ev.prompt,
37480
+ url: this.requestUrl,
37481
+ requestOptions: {
37482
+ ...this.requestOptions
37483
+ }
37484
+ };
37485
+ if (!this.requestOptions.body) {
37486
+ const requestBody = {
37487
+ role: this.requestData.requestOptions.role,
37488
+ contents: [
37489
+ {
37490
+ text: this.requestData.promptMessage
37491
+ }
37492
+ ],
37493
+ columns: this.requestData.columns
37494
+ };
37495
+ this.requestData.requestOptions.body = requestBody;
37496
+ }
37497
+ this.aiToolDirective.promptRequest.emit({ requestData: this.requestData, isRetry: ev.isRetry });
37498
+ if (!this.requestUrl) {
37499
+ return;
37500
+ }
37501
+ this.currentRequestSubscription = this.sendPromptRequest().subscribe((res) => {
37502
+ if (res.body) {
37503
+ this.processResponse(res);
37504
+ this.streaming = false;
37505
+ }
37506
+ this.currentRequestSubscription = null;
37507
+ }, (error) => {
37508
+ this.handleError(error);
37509
+ this.streaming = false;
37510
+ this.currentRequestSubscription = null;
37511
+ });
37512
+ }
37513
+ sendPromptRequest() {
37514
+ const request = new HttpRequest(this.requestData.requestOptions.method, this.requestData.url, this.requestData.requestOptions.body, this.requestData.requestOptions);
37515
+ return this.http.request(request);
37516
+ }
37517
+ processResponse(response) {
37518
+ if (this.aiToolDirective.autoClose) {
37519
+ this.aiToolDirective.emitOpenClose = true;
37520
+ this.aiToolDirective.toggleWindow();
37521
+ }
37522
+ const responseBody = response.body;
37523
+ const responseSuccessEvent = new GridToolbarAIResponseSuccessEvent(response);
37524
+ this.aiToolDirective.responseSuccess.emit(responseSuccessEvent);
37525
+ if (responseSuccessEvent.isDefaultPrevented()) {
37526
+ this.deleteLoadingOutput();
37527
+ return;
37528
+ }
37529
+ const isFilterable = Boolean(this.ctx.grid.filterable);
37530
+ const isSortable = Boolean(this.ctx.grid.sortable);
37531
+ const isGroupable = Boolean(this.ctx.grid.groupable);
37532
+ if (isFilterable && responseBody.filter) {
37533
+ this.processFilterResponse(responseBody.filter);
37534
+ }
37535
+ if (isSortable && responseBody.sort) {
37536
+ this.processArrayResponse(responseBody.sort, this.ctx.grid.currentState.sort || [], (item) => item.field, (mergedArray) => this.ctx.grid.sortChange.next(mergedArray));
37537
+ }
37538
+ if (isGroupable && responseBody.group) {
37539
+ this.processArrayResponse(responseBody.group, this.ctx.grid.currentState.group || [], (item) => item.field, (mergedArray) => this.ctx.grid.groupChange.next(mergedArray));
37540
+ }
37541
+ if (this.ctx.highlightDirective && responseBody.highlight) {
37542
+ this.processHighlightResponse(responseBody.highlight);
37543
+ }
37544
+ const responseContentStart = [`${this.ctx.localization.get('aiAssistantOutputCardBodyContent')} \n`];
37545
+ const responseContentBody = responseBody.messages
37546
+ .map((output, idx) => `${idx + 1} ${output}`)
37547
+ .join('\n');
37548
+ const output = {
37549
+ id: this.idCounter++,
37550
+ title: this.ctx.localization.get('aiAssistantOutputCardTitle'),
37551
+ prompt: this.lastMessage,
37552
+ output: responseContentStart.concat(responseContentBody).join(''),
37553
+ };
37554
+ this.deleteLoadingOutput();
37555
+ this.aiToolDirective.promptOutputs.unshift(output);
37556
+ }
37557
+ handleError(error) {
37558
+ const responseErrorEvent = new GridToolbarAIResponseErrorEvent(error);
37559
+ this.aiToolDirective.responseError.emit(responseErrorEvent);
37560
+ if (responseErrorEvent.isDefaultPrevented()) {
37561
+ this.deleteLoadingOutput();
37562
+ return;
37563
+ }
37564
+ const output = {
37565
+ id: this.idCounter++,
37566
+ prompt: this.lastMessage,
37567
+ output: error.message
37568
+ };
37569
+ this.deleteLoadingOutput();
37570
+ this.aiToolDirective.promptOutputs.unshift(output);
37571
+ }
37572
+ deleteLoadingOutput() {
37573
+ if (this.aiToolDirective.promptOutputs[0]?.id === this.loadingOutput.id) {
37574
+ this.aiToolDirective.promptOutputs.splice(0, 1);
37575
+ }
37576
+ }
37577
+ unsubscribeCurrentRequest() {
37578
+ if (this.currentRequestSubscription) {
37579
+ this.currentRequestSubscription.unsubscribe();
37580
+ this.currentRequestSubscription = null;
37581
+ }
37582
+ }
37583
+ processArrayResponse(newItems, currentItems, getField, updateGrid) {
37584
+ if (newItems?.length === 0) {
37585
+ updateGrid([]);
37586
+ }
37587
+ else if (newItems?.length) {
37588
+ let mergedArray = [...newItems];
37589
+ const newFields = newItems.map(getField);
37590
+ const existingItemsToKeep = currentItems.filter(item => !newFields.includes(getField(item)));
37591
+ mergedArray = [...mergedArray, ...existingItemsToKeep];
37592
+ updateGrid(mergedArray);
37593
+ }
37594
+ }
37595
+ processHighlightResponse(highlight) {
37596
+ if (highlight.length === 0) {
37597
+ this.ctx.highlightDirective['setState']([]);
37598
+ return;
37599
+ }
37600
+ const highlightedItems = highlightBy(this.ctx.dataBindingDirective['originalData'], highlight, this.columns);
37601
+ this.ctx.highlightDirective['setState'](highlightedItems);
37602
+ }
37603
+ processFilterResponse(filter) {
37604
+ const processedFilter = convertDateStringsInFilter(filter);
37605
+ const clearFilter = Object.keys(processedFilter).length === 0;
37606
+ if (clearFilter) {
37607
+ this.ctx.grid.filterChange.next(undefined);
37608
+ }
37609
+ else if (processedFilter?.filters.length) {
37610
+ const currentFilter = this.ctx.grid.currentState.filter;
37611
+ let mergedFilter = processedFilter;
37612
+ if (currentFilter && currentFilter.filters?.length > 0) {
37613
+ mergedFilter = {
37614
+ logic: 'and',
37615
+ filters: [
37616
+ currentFilter,
37617
+ processedFilter
37618
+ ]
37619
+ };
37620
+ }
37621
+ this.ctx.grid.filterChange.next(mergedFilter);
37622
+ }
37623
+ }
37624
+ 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 });
37625
+ 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: `
37626
+ <kendo-aiprompt
37627
+ #aiPrompt
37628
+ [promptSuggestions]="aiPromptSettings?.promptSuggestions"
37629
+ [showOutputRating]="aiPromptSettings?.showOutputRating"
37630
+ [streaming]="streaming"
37631
+ [speechToTextButton]="aiPromptSettings?.speechToTextButton"
37632
+ [(activeView)]="activeView"
37633
+ [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon"
37634
+ [generateButtonIcon]="aiPromptSettings?.generateButtonIcon"
37635
+ [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0"
37636
+ [promptOutputs]="aiPromptSettings?.promptOutputs"
37637
+ [textAreaSettings]="aiPromptSettings?.textAreaSettings"
37638
+ (promptRequest)="onPromptRequest($event)"
37639
+ (promptRequestCancel)="cancelRequest()"
37640
+ >
37641
+ <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view>
37642
+ <kendo-aiprompt-output-view></kendo-aiprompt-output-view>
37643
+ <ng-template *ngIf="streaming && aiPrompt.streaming" kendoAIPromptOutputTemplate let-output>
37644
+ <div class="k-card">
37645
+ <div class="k-card-header">
37646
+ <div class="k-card-title">
37647
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span>
37648
+ </div>
37649
+ <div class="k-card-subtitle">
37650
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37651
+ </div>
37652
+ </div>
37653
+ <div class="k-card-body">
37654
+ <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span>
37655
+ </div>
37656
+ <div class="k-card-actions">
37657
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37658
+ </div>
37659
+ </div>
37660
+ </ng-template>
37661
+ <ng-template *ngIf="!(streaming && aiPrompt.streaming)" kendoAIPromptOutputBodyTemplate let-output>
37662
+ <p>{{output.output}}</p>
37663
+ </ng-template>
37664
+ <kendo-aiprompt-messages
37665
+ [generateOutput]="message('aiAssistantApplyButtonText')"
37666
+ ></kendo-aiprompt-messages>
37667
+ </kendo-aiprompt>
37668
+ `, 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]" }] });
37669
+ }
37670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiAssistantComponent, decorators: [{
37671
+ type: Component,
37195
37672
  args: [{
37196
- selector: '[kendoGridCancelTool]',
37197
- standalone: true
37673
+ standalone: true,
37674
+ imports: [NgIf, AIPromptComponent, AIPromptCustomMessagesComponent, PromptViewComponent, OutputViewComponent, AIPromptOutputTemplateDirective, AIPromptOutputBodyTemplateDirective],
37675
+ template: `
37676
+ <kendo-aiprompt
37677
+ #aiPrompt
37678
+ [promptSuggestions]="aiPromptSettings?.promptSuggestions"
37679
+ [showOutputRating]="aiPromptSettings?.showOutputRating"
37680
+ [streaming]="streaming"
37681
+ [speechToTextButton]="aiPromptSettings?.speechToTextButton"
37682
+ [(activeView)]="activeView"
37683
+ [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon"
37684
+ [generateButtonIcon]="aiPromptSettings?.generateButtonIcon"
37685
+ [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0"
37686
+ [promptOutputs]="aiPromptSettings?.promptOutputs"
37687
+ [textAreaSettings]="aiPromptSettings?.textAreaSettings"
37688
+ (promptRequest)="onPromptRequest($event)"
37689
+ (promptRequestCancel)="cancelRequest()"
37690
+ >
37691
+ <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view>
37692
+ <kendo-aiprompt-output-view></kendo-aiprompt-output-view>
37693
+ <ng-template *ngIf="streaming && aiPrompt.streaming" kendoAIPromptOutputTemplate let-output>
37694
+ <div class="k-card">
37695
+ <div class="k-card-header">
37696
+ <div class="k-card-title">
37697
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span>
37698
+ </div>
37699
+ <div class="k-card-subtitle">
37700
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37701
+ </div>
37702
+ </div>
37703
+ <div class="k-card-body">
37704
+ <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span>
37705
+ </div>
37706
+ <div class="k-card-actions">
37707
+ <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span>
37708
+ </div>
37709
+ </div>
37710
+ </ng-template>
37711
+ <ng-template *ngIf="!(streaming && aiPrompt.streaming)" kendoAIPromptOutputBodyTemplate let-output>
37712
+ <p>{{output.output}}</p>
37713
+ </ng-template>
37714
+ <kendo-aiprompt-messages
37715
+ [generateOutput]="message('aiAssistantApplyButtonText')"
37716
+ ></kendo-aiprompt-messages>
37717
+ </kendo-aiprompt>
37718
+ `
37198
37719
  }]
37199
- }], ctorParameters: function () { return [{ type: EditService }, { type: i54.ToolBarButtonComponent }, { type: SelectionService }, { type: ContextService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; } });
37720
+ }], ctorParameters: function () { return [{ type: i1$8.HttpClient }, { type: ContextService }, { type: ColumnInfoService }]; }, propDecorators: { aiPrompt: [{
37721
+ type: ViewChild,
37722
+ args: [AIPromptComponent]
37723
+ }] } });
37200
37724
 
37201
- let incrementingId = 0;
37202
37725
  /**
37203
- * Represents the toolbar tool for grouping columns of the Grid.
37726
+ * Represents an AI Assistant tool of the Grid.
37204
37727
  * 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
37728
  *
37207
37729
  * @example
37208
- * ```html
37730
+ * ```html-no-run
37209
37731
  * <kendo-grid>
37210
37732
  * <kendo-toolbar>
37211
- * <kendo-toolbar-button text="Group" kendoGridGroupTool></kendo-toolbar-button>
37733
+ * <kendo-toolbar-button kendoGridAIAssistantTool></kendo-toolbar-button>
37212
37734
  * </kendo-toolbar>
37213
37735
  * </kendo-grid>
37214
37736
  * ```
37215
37737
  * @remarks
37216
37738
  * Applied to: {@link ToolBarButtonComponent}.
37217
37739
  */
37218
- class GroupCommandToolbarDirective {
37740
+ class AIAssistantToolbarDirective extends ToolbarToolBase {
37741
+ windowService;
37219
37742
  host;
37220
- popupService;
37221
37743
  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) {
37744
+ zone;
37745
+ refresh;
37746
+ /**
37747
+ * The URL to which the AI Assistant tool sends the AI request.
37748
+ * - 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.
37749
+ * - 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.
37750
+ */
37751
+ requestUrl;
37752
+ /**
37753
+ * Configures the request options that the AI Assistant tool sends with the AI request.
37754
+ *
37755
+ * @default { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), role: 'user', method: 'POST', responseType: 'json', withCredentials: false }
37756
+ */
37757
+ requestOptions;
37758
+ /**
37759
+ * Configures the initial settings for the AI Assistant Window when opened.
37760
+ */
37761
+ aiWindowSettings;
37762
+ /**
37763
+ * Configures the initial settings for the AI Prompt component that the AI Assistant Window component uses when opened.
37764
+ */
37765
+ aiPromptSettings;
37766
+ /**
37767
+ * Determines whether to close the AI Assistant Window automatically after a successful request.
37768
+ * @default true
37769
+ */
37770
+ autoClose = true;
37771
+ /**
37772
+ * Determines whether to keep the AI Prompt's outputs after closing the AI Assistant Window.
37773
+ * @default false
37774
+ */
37775
+ keepOutputHistory = false;
37776
+ /**
37777
+ * Emits an event before the AI Assistant tool sends the AI request.
37778
+ * - When you provide a `requestUrl`, you can handle the event to modify the request options.
37779
+ * - When you do not provide a `requestUrl`, you can handle the event to perform an entirely custom request.
37780
+ */
37781
+ promptRequest = new EventEmitter();
37782
+ /**
37783
+ * Emits an event when the user clicks the cancel button.
37784
+ */
37785
+ cancelRequest = new EventEmitter();
37786
+ /**
37787
+ * Emits an event when the AI Assistant tool completes the AI request successfully.
37788
+ * The event contains the response from the AI service and is preventable to allow stopping the default response handling.
37789
+ */
37790
+ responseSuccess = new EventEmitter();
37791
+ /**
37792
+ * Emits an event when the AI Assistant tool completes the AI request with an error.
37793
+ * The event contains the error response from the AI service and is preventable to allow stopping the default error handling.
37794
+ */
37795
+ responseError = new EventEmitter();
37796
+ /**
37797
+ * Emits an event when the AI Assistant tool closes.
37798
+ */
37799
+ close = new EventEmitter();
37800
+ /**
37801
+ * Emits an event when the AI Assistant tool opens.
37802
+ */
37803
+ open = new EventEmitter();
37804
+ tableWizardIcon = tableWizardIcon;
37805
+ emitOpenClose = false;
37806
+ promptOutputs = [];
37807
+ windowRef;
37808
+ subs = new Subscription();
37809
+ defaultAiPromptSettings = {
37810
+ speechToTextButton: true,
37811
+ generateButtonSVGIcon: this.tableWizardIcon,
37812
+ generateButtonIcon: 'table-wizard'
37813
+ };
37814
+ constructor(windowService, host, ctx, zone, refresh, cdr) {
37815
+ super(host, ToolbarToolName.aiAssistant, ctx, zone, cdr);
37816
+ this.windowService = windowService;
37232
37817
  this.host = host;
37233
- this.popupService = popupService;
37234
37818
  this.ctx = ctx;
37235
- this.ngZone = ngZone;
37236
- this.renderer = renderer;
37237
- this.adaptiveGridService = adaptiveGridService;
37819
+ this.zone = zone;
37820
+ this.refresh = refresh;
37821
+ this.host.rounded = 'full';
37822
+ this.host.themeColor = 'primary';
37823
+ this.host.showText = 'never';
37238
37824
  }
37239
37825
  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);
37826
+ this.subs.add(this.host.click.subscribe(() => this.onClick()));
37246
37827
  const hasToolbarIcon = isPresent$1(this.host.toolbarOptions.icon) && this.host.toolbarOptions.icon !== '';
37247
37828
  const hasOverflowIcon = isPresent$1(this.host.overflowOptions.icon) && this.host.overflowOptions.icon !== '';
37248
37829
  const hasIcon = hasToolbarIcon && hasOverflowIcon;
37249
37830
  const hasSvgIcon = isPresent$1(this.host.toolbarOptions.svgIcon) && isPresent$1(this.host.overflowOptions.svgIcon);
37250
37831
  if (!hasIcon) {
37251
- this.host.icon = 'group';
37832
+ this.host.icon = 'sparkles';
37252
37833
  }
37253
37834
  if (!hasSvgIcon) {
37254
- this.host.svgIcon = groupIcon;
37835
+ this.host.svgIcon = sparklesIcon;
37255
37836
  }
37837
+ this.requestOptions = { ...DEFAULT_AI_REQUEST_OPTIONS, ...this.requestOptions };
37256
37838
  }
37257
37839
  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;
37840
+ super.ngAfterViewInit();
37841
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
37842
+ this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
37843
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37844
+ const needsTitle = this.host.showText !== 'always' && this.host.showText !== 'toolbar';
37845
+ if (needsTitle && !this.host.title) {
37846
+ this.buttonElement?.setAttribute('title', this.ctx.localization.get('aiAssistantToolbarToolText'));
37301
37847
  }
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
37848
  });
37315
- this.adaptiveGridService.popupRef = this.popupRef;
37316
- this.setPopupAttributes();
37317
- this.host.selected = true;
37318
- this.ngZone.runOutsideAngular(() => {
37319
- if (!isDocumentAvailable()) {
37320
- return;
37849
+ this.subs.add(this.refresh.onRefresh.pipe(filter((tool) => tool === this.host)).subscribe((tool) => {
37850
+ if (tool.overflows && this.windowRef) {
37851
+ this.windowRef.close();
37321
37852
  }
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
37853
  }));
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
37854
  }
37429
37855
  ngOnDestroy() {
37430
- this.reset();
37431
- this.ctx.highlightDirective = null;
37856
+ super.ngOnDestroy();
37857
+ this.subs.unsubscribe();
37858
+ this.promptOutputs = [];
37432
37859
  }
37433
37860
  /**
37434
37861
  * @hidden
37435
37862
  */
37436
- isRowHighlighted(row) {
37437
- return this.rowHighlightState.has(this.getItemKey(row));
37863
+ onClick() {
37864
+ this.emitOpenClose = true;
37865
+ this.toggleWindow();
37438
37866
  }
37439
37867
  /**
37440
- * @hidden
37868
+ * Toggles the AI Assistant window.
37441
37869
  */
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;
37870
+ toggleWindow() {
37871
+ if (!this.windowRef) {
37872
+ this.openWindow();
37462
37873
  }
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
- }
37874
+ else {
37875
+ this.closeWindow();
37470
37876
  }
37471
- return {
37472
- itemKey: itemIdentifiers.itemKey,
37473
- columnKey: itemIdentifiers.columnKey ? itemIdentifiers.columnKey : colIndex
37474
- };
37475
37877
  }
37476
- setState(highlightedKeys) {
37477
- this.reset();
37478
- if (!highlightedKeys || highlightedKeys.length === 0) {
37479
- return;
37878
+ openWindow() {
37879
+ if (!this.keepOutputHistory) {
37880
+ this.promptOutputs = [];
37480
37881
  }
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');
37882
+ const defaultWindowWidth = 437;
37883
+ const rtl = this.ctx.localization.rtl;
37884
+ const defaultWindowSettings = {
37885
+ left: rtl ? this.buttonElement.offsetLeft - (this.aiWindowSettings.width || defaultWindowWidth) : this.buttonElement.offsetLeft + this.buttonElement.offsetWidth,
37886
+ top: this.buttonElement.offsetTop + this.buttonElement.offsetHeight,
37887
+ width: defaultWindowWidth,
37888
+ title: this.ctx.localization.get('aiAssistantWindowTitle'),
37889
+ cssClass: 'k-grid-assistant-window',
37890
+ content: AiAssistantComponent,
37891
+ autoFocusedElement: '.k-input-inner',
37892
+ appendTo: this.ctx.grid.windowContainer
37893
+ };
37894
+ this.aiWindowSettings = {
37895
+ ...defaultWindowSettings,
37896
+ ...this.aiWindowSettings
37897
+ };
37898
+ this.windowRef = this.windowService.open(this.aiWindowSettings);
37899
+ this.windowRef.window.instance.messages = {
37900
+ closeTitle: this.ctx.localization.get('aiAssistantWindowCloseTitle'),
37901
+ maximizeTitle: this.ctx.localization.get('aiAssistantWindowMaximizeTitle'),
37902
+ minimizeTitle: this.ctx.localization.get('aiAssistantWindowMinimizeTitle'),
37903
+ restoreTitle: this.ctx.localization.get('aiAssistantWindowRestoreTitle')
37904
+ };
37905
+ const aiPrompt = this.windowRef.content.instance;
37906
+ aiPrompt.requestUrl = this.requestUrl;
37907
+ aiPrompt.requestOptions = this.requestOptions;
37908
+ aiPrompt.aiToolDirective = this;
37909
+ aiPrompt.disabledGenerateButton = this.aiPromptSettings?.disabledGenerateButton;
37910
+ aiPrompt.streaming = this.aiPromptSettings?.streaming || false;
37911
+ aiPrompt.activeView = this.aiPromptSettings?.activeView || 0;
37912
+ aiPrompt.aiPromptSettings = { ...this.defaultAiPromptSettings, ...this.aiPromptSettings };
37913
+ if (!aiPrompt.aiPromptSettings.promptOutputs) {
37914
+ aiPrompt.aiPromptSettings.promptOutputs = this.promptOutputs;
37485
37915
  }
37486
- if (rowHighlights.length > 0) {
37487
- rowHighlights.forEach(item => {
37488
- this.rowHighlightState.add(item.itemKey);
37916
+ if (this.emitOpenClose) {
37917
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
37918
+ const event = {
37919
+ aiWindow: this.windowRef.window.instance,
37920
+ aiPrompt: this.windowRef.content.instance.aiPrompt
37921
+ };
37922
+ this.open.emit(event);
37923
+ this.emitOpenClose = false;
37489
37924
  });
37490
37925
  }
37926
+ this.subs.add(this.windowRef.window.instance.close.subscribe(() => {
37927
+ this.emitOpenClose = true;
37928
+ this.closeWindow(true);
37929
+ }));
37930
+ this.host.selected = true;
37491
37931
  }
37492
- reset() {
37493
- this.rowHighlightState.clear();
37494
- this.cellHighlightState.clear();
37932
+ closeWindow(focusAnchor = false) {
37933
+ this.windowRef.close();
37934
+ if (this.emitOpenClose) {
37935
+ this.close.emit();
37936
+ this.emitOpenClose = false;
37937
+ }
37938
+ this.windowRef = null;
37939
+ this.buttonElement?.setAttribute('aria-expanded', 'false');
37940
+ this.buttonElement?.removeAttribute('aria-controls');
37941
+ this.host.selected = false;
37942
+ focusAnchor && this.buttonElement?.focus();
37495
37943
  }
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 });
37944
+ 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 });
37945
+ 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
37946
  }
37499
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HighlightDirective, decorators: [{
37947
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIAssistantToolbarDirective, decorators: [{
37500
37948
  type: Directive,
37501
37949
  args: [{
37502
- selector: '[kendoGridHighlight]',
37950
+ selector: '[kendoGridAIAssistantTool]',
37503
37951
  standalone: true
37504
37952
  }]
37505
- }], ctorParameters: function () { return [{ type: ContextService }]; }, propDecorators: { highlightedKeys: [{
37953
+ }], ctorParameters: function () { return [{ type: i1$7.WindowService }, { type: i54.ToolBarButtonComponent }, { type: ContextService }, { type: i0.NgZone }, { type: i54.RefreshService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { requestUrl: [{
37506
37954
  type: Input
37507
- }], highlightItemKey: [{
37508
- type: Input,
37509
- args: ["kendoGridHighlight"]
37510
- }], highlightColumnKey: [{
37955
+ }], requestOptions: [{
37956
+ type: Input
37957
+ }], aiWindowSettings: [{
37958
+ type: Input
37959
+ }], aiPromptSettings: [{
37511
37960
  type: Input
37961
+ }], autoClose: [{
37962
+ type: Input
37963
+ }], keepOutputHistory: [{
37964
+ type: Input
37965
+ }], promptRequest: [{
37966
+ type: Output
37967
+ }], cancelRequest: [{
37968
+ type: Output
37969
+ }], responseSuccess: [{
37970
+ type: Output
37971
+ }], responseError: [{
37972
+ type: Output
37973
+ }], close: [{
37974
+ type: Output
37975
+ }], open: [{
37976
+ type: Output
37512
37977
  }] } });
37513
37978
 
37514
37979
  /**
@@ -38089,5 +38554,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
38089
38554
  * Generated bundle index. Do not edit.
38090
38555
  */
38091
38556
 
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 };
38557
+ 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
38558