@progress/kendo-angular-pager 19.0.0-develop.8 → 19.0.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.
@@ -2,12 +2,12 @@
2
2
  * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { Component, Input, EventEmitter, Output, HostBinding, ElementRef, Renderer2, NgZone, HostListener, ContentChildren, QueryList, Optional, SkipSelf, inject } from '@angular/core';
5
+ import { Component, Input, EventEmitter, Output, HostBinding, ElementRef, Renderer2, NgZone, HostListener, ContentChildren, QueryList, Optional, SkipSelf, inject, ViewChild, ChangeDetectorRef } from '@angular/core';
6
6
  import { PagerTemplateDirective } from "./pager-template.directive";
7
- import { anyChanged, Keys, ResizeSensorComponent } from "@progress/kendo-angular-common";
7
+ import { anyChanged, isChanged, isDocumentAvailable, Keys, ResizeSensorComponent } from "@progress/kendo-angular-common";
8
8
  import { PagerContextService } from "./pager-context.service";
9
9
  import { Subscription } from "rxjs";
10
- import { DEFAULT_PAGE_SIZE_VALUES, getStylingClasses, DEFAULT_SIZE, replaceMessagePlaceholder } from '../util';
10
+ import { DEFAULT_PAGE_SIZE_VALUES, getStylingClasses, DEFAULT_SIZE, replaceMessagePlaceholder, calculatePadding, createMeasurementSpan, copyComputedStyles, positionOffScreen } from '../util';
11
11
  import { L10N_PREFIX, LocalizationService } from '@progress/kendo-angular-l10n';
12
12
  import { validatePackage } from '@progress/kendo-licensing';
13
13
  import { packageMetadata } from '../package-metadata';
@@ -15,12 +15,12 @@ import { PagerNavigationService } from './navigation.service';
15
15
  import { PagerNumericButtonsComponent } from './pager-numeric-buttons.component';
16
16
  import { PagerInfoComponent } from './pager-info.component';
17
17
  import { PagerPageSizesComponent } from './pager-page-sizes.component';
18
- import { RESPONSIVE_BREAKPOINT_MEDIUM, RESPONSIVE_BREAKPOINT_LARGE } from './common/constants';
19
18
  import { PagerNextButtonsComponent } from './pager-next-buttons.component';
20
19
  import { PagerInputComponent } from './pager-input.component';
21
20
  import { PagerPrevButtonsComponent } from './pager-prev-buttons.component';
22
- import { NgIf, NgTemplateOutlet } from '@angular/common';
21
+ import { NgIf, NgStyle, NgTemplateOutlet } from '@angular/common';
23
22
  import { LocalizedMessagesDirective } from './localization/localized-messages.directive';
23
+ import { take } from 'rxjs/operators';
24
24
  import * as i0 from "@angular/core";
25
25
  import * as i1 from "./pager-context.service";
26
26
  import * as i2 from "@progress/kendo-angular-l10n";
@@ -31,8 +31,29 @@ export class PagerComponent {
31
31
  localization;
32
32
  renderer;
33
33
  ngZone;
34
+ cdr;
34
35
  navigationService;
35
36
  template;
37
+ set numericButtons(buttons) {
38
+ const newWidth = buttons ? buttons.nativeElement?.offsetWidth : 0;
39
+ if (buttons && newWidth !== this.pagerDimensions.numericButtonsWidth) {
40
+ this.pagerDimensions.numericButtonsWidth = newWidth;
41
+ }
42
+ }
43
+ set pagerInput(input) {
44
+ const newWidth = input ? input.nativeElement?.offsetWidth : 0;
45
+ if (input && newWidth !== this.pagerDimensions.inputWidth) {
46
+ this.pagerDimensions.inputWidth = newWidth;
47
+ }
48
+ }
49
+ pagerInputComponent;
50
+ set pageSizes(sizes) {
51
+ const newWidth = sizes ? sizes.nativeElement?.offsetWidth : 0;
52
+ if (sizes && newWidth !== this.pagerDimensions.pageSizesWidth) {
53
+ this.pagerDimensions.pageSizesWidth = newWidth;
54
+ }
55
+ }
56
+ pageSizesComponent;
36
57
  /**
37
58
  * @hidden
38
59
  */
@@ -85,6 +106,9 @@ export class PagerComponent {
85
106
  this._pageSizeValues = value;
86
107
  }
87
108
  }
109
+ get pageSizeValues() {
110
+ return this._pageSizeValues;
111
+ }
88
112
  /**
89
113
  * Toggles the **Previous** and **Next** buttons.
90
114
  *
@@ -93,8 +117,8 @@ export class PagerComponent {
93
117
  previousNext = true;
94
118
  /**
95
119
  * If set to `true`, the user can use dedicated shortcuts to interact with the Pager ([see example]({% slug keyboard_navigation_pager %})).
96
- * By default, navigation is disabled and the Pager content is accessible in the normal tab sequence.
97
- * @default false
120
+ * By default, navigation is enabled. To disable it and make the Pager content accessible in the normal tab sequence, set the property to `false`.
121
+ * @default true
98
122
  */
99
123
  set navigable(value) {
100
124
  this._navigable = value;
@@ -121,12 +145,17 @@ export class PagerComponent {
121
145
  return this._size;
122
146
  }
123
147
  /**
124
- * @hidden
125
- * Toggles the Pager responsive functionality.
148
+ * Toggles the Pager responsive functionality ([see example](slug:responsive_pager)).
126
149
  *
127
150
  * @default true
128
151
  */
129
152
  responsive = true;
153
+ /**
154
+ * Toggles the Pager adaptiveness functionality ([see example](slug:adaptive_mode_pager)).
155
+ *
156
+ * @default 'auto'
157
+ */
158
+ adaptiveMode = 'auto';
130
159
  /**
131
160
  * Fires when the current page of the Pager is changed ([see example](slug:overview_pager)).
132
161
  * You have to handle the event yourself and page the data.
@@ -138,7 +167,22 @@ export class PagerComponent {
138
167
  * If the event is prevented, the page size will remain unchanged ([see example]({% slug pager_events %})).
139
168
  */
140
169
  pageSizeChange = new EventEmitter();
170
+ /**
171
+ * @hidden
172
+ */
173
+ pagerInputVisibilityChange = new EventEmitter();
174
+ /**
175
+ * @hidden
176
+ */
177
+ pageTextVisibilityChange = new EventEmitter();
178
+ /**
179
+ * @hidden
180
+ */
181
+ itemsTextVisibilityChange = new EventEmitter();
141
182
  pagerClass = true;
183
+ get responsiveClass() {
184
+ return this.responsive;
185
+ }
142
186
  widgetRole = 'application';
143
187
  roleDescription = 'pager';
144
188
  keyShortcuts = 'Enter ArrowRight ArrowLeft';
@@ -170,19 +214,76 @@ export class PagerComponent {
170
214
  context.currentPage = this.currentPage;
171
215
  return context;
172
216
  }
217
+ /**
218
+ * @hidden
219
+ */
220
+ get showPageText() {
221
+ return this._showPageText;
222
+ }
223
+ set showPageText(value) {
224
+ this._showPageText = value;
225
+ this.pagerInputComponent && (this.pagerInputComponent.showPageText = value);
226
+ this.pageTextVisibilityChange.emit(value);
227
+ }
228
+ /**
229
+ * @hidden
230
+ */
231
+ get showItemsText() {
232
+ return this._showItemsText;
233
+ }
234
+ set showItemsText(value) {
235
+ this._showItemsText = value;
236
+ this.pageSizesComponent && (this.pageSizesComponent.showItemsText = value);
237
+ this.itemsTextVisibilityChange.emit(value);
238
+ }
239
+ /**
240
+ * @hidden
241
+ */
242
+ get showInput() {
243
+ return this._showInput;
244
+ }
245
+ set showInput(value) {
246
+ this._showInput = value;
247
+ this.pagerInputVisibilityChange.emit(value);
248
+ }
249
+ /**
250
+ * @hidden
251
+ */
252
+ initialized = false;
173
253
  subscriptions = new Subscription();
174
254
  _templateContext = {};
175
255
  _pageSizeValues = DEFAULT_PAGE_SIZE_VALUES;
176
256
  direction;
177
257
  isInnerNavigationEnabled = false;
178
- _navigable = false;
258
+ _navigable = true;
179
259
  _size = DEFAULT_SIZE;
180
- constructor(pagerContext, element, localization, renderer, ngZone, navigationService) {
260
+ _showInput = true;
261
+ _showPageText = true;
262
+ _showItemsText = true;
263
+ /**
264
+ * Stores the measurements of various Pager elements.
265
+ * These dimensions are used for responsive layout calculations.
266
+ * @hidden
267
+ */
268
+ pagerDimensions = {
269
+ padding: 0,
270
+ numericButtonsWidth: 0,
271
+ inputWidth: 0,
272
+ pageSizesWidth: 0,
273
+ sizesTextWidth: 0,
274
+ pageTextWidth: 0,
275
+ infoTextWidth: 0,
276
+ gapNumbersSizes: 0,
277
+ gapSizesInfo: 0,
278
+ width: 0
279
+ };
280
+ constructor(pagerContext, element, localization, renderer, ngZone, cdr, navigationService) {
181
281
  this.pagerContext = pagerContext;
182
282
  this.element = element;
183
283
  this.localization = localization;
184
284
  this.renderer = renderer;
185
285
  this.ngZone = ngZone;
286
+ this.cdr = cdr;
186
287
  this.navigationService = navigationService;
187
288
  validatePackage(packageMetadata);
188
289
  this.direction = localization.rtl ? 'rtl' : 'ltr';
@@ -199,6 +300,8 @@ export class PagerComponent {
199
300
  this.subscriptions.add(this.pagerContext.pageSizeChange.subscribe(this.changePageSize.bind(this)));
200
301
  this.subscriptions.add(this.localization.changes.subscribe(({ rtl }) => {
201
302
  this.direction = rtl ? 'rtl' : 'ltr';
303
+ this.measureAllTextWidths();
304
+ this.responsive && this.resizeHandler();
202
305
  }));
203
306
  this.subscriptions.add(this.navigationService.innerNavigationChange.subscribe(this.innerNavigationChange.bind(this)));
204
307
  if (this.navigable) {
@@ -208,25 +311,67 @@ export class PagerComponent {
208
311
  });
209
312
  }
210
313
  }
314
+ get maxItems() {
315
+ return Math.min(this.currentPage * this.pageSize, this.total);
316
+ }
211
317
  ngAfterViewInit() {
212
- this.responsive && this.resizeHandler();
213
318
  this.renderer.setAttribute(this.element.nativeElement, 'aria-label', this.ariaLabel);
214
319
  this.subscriptions.add(this.template.changes.subscribe(() => {
215
- this.responsive && this.resizeHandler();
320
+ this.measureAllTextWidths();
321
+ this.responsive && this.resizeHandler(false);
216
322
  }));
217
323
  this.handleClasses(this.size, 'size');
324
+ this.measureAllTextWidths();
325
+ !this.numericButtons && (this.pagerDimensions.numericButtonsWidth = this.element.nativeElement.querySelector('.k-pager-numbers')?.offsetWidth ?? 0);
326
+ !this.pagerInput && (this.pagerDimensions.inputWidth = this.element.nativeElement.querySelector('.k-pager-input')?.offsetWidth ?? 0);
327
+ !this.pageSizes && (this.pagerDimensions.pageSizesWidth = this.element.nativeElement.querySelector('.k-pager-sizes')?.offsetWidth ?? 0);
328
+ const padding = calculatePadding(this.element.nativeElement);
329
+ this.pagerDimensions.padding = padding.padding;
330
+ this.pagerDimensions.gapNumbersSizes = padding.gapNumbersSizes;
331
+ this.pagerDimensions.gapSizesInfo = padding.gapSizesInfo;
332
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => {
333
+ if (this.type !== 'input') {
334
+ this.showInput = false;
335
+ }
336
+ });
337
+ if (!isDocumentAvailable()) {
338
+ this.initialized = true;
339
+ return;
340
+ }
341
+ this.responsive && this.resizeHandler();
342
+ setTimeout(() => {
343
+ this.initialized = true;
344
+ this.cdr.markForCheck();
345
+ }, 0);
218
346
  }
219
347
  ngOnChanges(changes) {
220
348
  if (anyChanged(["pageSize", "skip", "total"], changes, false)) {
349
+ const previousButtonCount = Math.min(this.buttonCount, (changes['total']?.previousValue || this.total) / (changes['pageSize']?.previousValue || this.pageSize));
221
350
  this.pagerContext.notifyChanges({
222
351
  pageSize: this.pageSize,
223
352
  skip: this.skip,
224
353
  total: this.total
225
354
  });
355
+ this.pagerDimensions.numericButtonsWidth = (this.pagerDimensions.numericButtonsWidth * Math.min(this.buttonCount, this.total / this.pageSize)) / previousButtonCount;
226
356
  this.renderer.setAttribute(this.element.nativeElement, 'aria-label', this.ariaLabel);
357
+ this.responsive && this.resizeHandler(false);
227
358
  }
228
- if (changes['responsive']) {
229
- this.responsive && this.resizeHandler();
359
+ if (anyChanged(["pageSizeValues", "previousNext", "buttonCount"], changes, true)) {
360
+ this.responsive && this.resizeHandler(false);
361
+ }
362
+ if (isChanged('responsive', changes, true)) {
363
+ if (changes['responsive'].currentValue && !changes['responsive'].previousValue) {
364
+ this.measureAllTextWidths();
365
+ this.resizeHandler(false);
366
+ }
367
+ if (!this.responsive) {
368
+ this.showInput = this.type === 'input';
369
+ this.showElementsInOrder(this.element.nativeElement.offsetWidth, this.pagerDimensions.width);
370
+ }
371
+ }
372
+ if (isChanged('type', changes, true)) {
373
+ this.showNumericButtonsResponsive();
374
+ this.responsive && this.resizeHandler(false);
230
375
  }
231
376
  }
232
377
  ngOnDestroy() {
@@ -264,44 +409,47 @@ export class PagerComponent {
264
409
  /**
265
410
  * @hidden
266
411
  */
267
- resizeHandler = () => {
412
+ resizeHandler = (compareWidth = true) => {
268
413
  if (this.template?.first && !this.responsive) {
269
414
  return;
270
415
  }
271
- const width = this.element.nativeElement.offsetWidth;
416
+ if (!isDocumentAvailable() || !this.element?.nativeElement) {
417
+ this.initialized = true;
418
+ return;
419
+ }
420
+ let pagerWidth = this.element.nativeElement.offsetWidth;
421
+ if (pagerWidth <= 0) {
422
+ return;
423
+ }
424
+ if (compareWidth && pagerWidth === this.pagerDimensions.width) {
425
+ return;
426
+ }
427
+ else {
428
+ this.pagerDimensions.width = pagerWidth;
429
+ }
272
430
  this.ngZone.runOutsideAngular(() => {
273
431
  setTimeout(() => {
274
- const numericButtonsElement = this.element.nativeElement.querySelector('kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons');
432
+ if (this.template?.first && !this.responsive) {
433
+ return;
434
+ }
435
+ const numericButtonsWrapperElement = this.element.nativeElement.querySelector('.k-pager-numbers-wrap');
275
436
  const pagerInfoElement = this.element.nativeElement.querySelector('.k-pager-info');
276
437
  const pagerPageSizes = this.element.nativeElement.querySelector('.k-pager-sizes');
277
- if (numericButtonsElement) {
278
- const selectElement = numericButtonsElement.querySelector('select');
279
- const numbersElement = numericButtonsElement.querySelector('.k-pager-numbers');
280
- if (width < RESPONSIVE_BREAKPOINT_MEDIUM) {
281
- this.renderer.removeClass(selectElement, 'k-hidden');
282
- this.renderer.addClass(numbersElement, 'k-hidden');
283
- }
284
- else {
285
- this.renderer.addClass(selectElement, 'k-hidden');
286
- this.renderer.removeClass(numbersElement, 'k-hidden');
287
- }
438
+ let elementsWidths = numericButtonsWrapperElement?.offsetWidth + (pagerPageSizes?.offsetWidth || 0) + (pagerInfoElement?.offsetWidth > 0 ? Math.min(this.pagerDimensions.infoTextWidth) : 0);
439
+ if (this.isElementVisible(pagerInfoElement)) {
440
+ elementsWidths += this.pagerDimensions.gapSizesInfo;
441
+ }
442
+ pagerWidth -= this.pagerDimensions.padding;
443
+ if (this.isElementVisible(pagerPageSizes)) {
444
+ pagerWidth -= this.pagerDimensions.gapNumbersSizes;
288
445
  }
289
- if (pagerInfoElement) {
290
- if (width < RESPONSIVE_BREAKPOINT_LARGE) {
291
- this.renderer.addClass(pagerInfoElement, 'k-hidden');
292
- }
293
- else {
294
- this.renderer.removeClass(pagerInfoElement, 'k-hidden');
295
- }
446
+ if (Math.ceil(elementsWidths) <= pagerWidth) {
447
+ this.showElementsInOrder(pagerWidth, elementsWidths);
296
448
  }
297
- if (pagerPageSizes) {
298
- if (width < RESPONSIVE_BREAKPOINT_MEDIUM) {
299
- this.renderer.addClass(pagerPageSizes, 'k-hidden');
300
- }
301
- else {
302
- this.renderer.removeClass(pagerPageSizes, 'k-hidden');
303
- }
449
+ else {
450
+ this.hideElementsInOrder(pagerWidth, elementsWidths);
304
451
  }
452
+ !this.initialized && this.ngZone.onStable.pipe(take(1)).subscribe(() => this.initialized = true);
305
453
  });
306
454
  });
307
455
  };
@@ -379,8 +527,183 @@ export class PagerComponent {
379
527
  this.renderer.addClass(elem, classes.toAdd);
380
528
  }
381
529
  }
382
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PagerComponent, deps: [{ token: i1.PagerContextService, optional: true, skipSelf: true }, { token: i0.ElementRef }, { token: i2.LocalizationService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i3.PagerNavigationService, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Component });
383
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PagerComponent, isStandalone: true, selector: "kendo-datapager, kendo-pager", inputs: { externalTemplate: "externalTemplate", total: "total", skip: "skip", pageSize: "pageSize", buttonCount: "buttonCount", info: "info", type: "type", pageSizeValues: "pageSizeValues", previousNext: "previousNext", navigable: "navigable", size: "size", responsive: "responsive" }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange" }, host: { listeners: { "focusin": "focusHandler($event)" }, properties: { "class.k-pager": "this.pagerClass", "attr.role": "this.widgetRole", "attr.aria-roledescription": "this.roleDescription", "attr.aria-keyshortcuts": "this.keyShortcuts", "attr.tabindex": "this.hostTabindex", "attr.dir": "this.dir" } }, providers: [
530
+ showElementsInOrder(availableWidth, currentWidth) {
531
+ const el = this.element.nativeElement;
532
+ const numericButtonsElement = el.querySelector('kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons');
533
+ const pagerInfoElement = el.querySelector('.k-pager-info');
534
+ const pagerPageSizes = el.querySelector('.k-pager-sizes');
535
+ const pagerSizesDropDown = el.querySelector('.k-pager-sizes .k-dropdownlist');
536
+ const checkOverflow = this.responsive;
537
+ if (this.type === 'input' && this.isElementVisible(pagerInfoElement) || this.isElementVisible(numericButtonsElement)) {
538
+ return;
539
+ }
540
+ if (this.showPageSizes && !this.isElementVisible(pagerPageSizes)) {
541
+ const addDropDownWidth = currentWidth + this.pagerDimensions.pageSizesWidth + this.pagerDimensions.gapNumbersSizes - this.pagerDimensions.sizesTextWidth;
542
+ if (checkOverflow && addDropDownWidth > availableWidth)
543
+ return;
544
+ this.ngZone.run(() => this.showItemsText = false);
545
+ this.showElement(pagerPageSizes);
546
+ currentWidth = addDropDownWidth;
547
+ if (checkOverflow && currentWidth >= availableWidth)
548
+ return;
549
+ }
550
+ if (this.showPageSizes && this.isElementVisible(pagerPageSizes) && !this.showItemsText) {
551
+ const addPageSizesText = currentWidth - pagerSizesDropDown?.offsetWidth + this.pagerDimensions.pageSizesWidth;
552
+ if (checkOverflow && addPageSizesText > availableWidth)
553
+ return;
554
+ this.ngZone.run(() => this.showItemsText = true);
555
+ currentWidth = addPageSizesText;
556
+ if (checkOverflow && currentWidth >= availableWidth)
557
+ return;
558
+ }
559
+ if (!this.showPageText && (!this.showPageSizes || (this.isElementVisible(pagerPageSizes) && this.showItemsText))) {
560
+ const addPageText = currentWidth + this.pagerDimensions.pageTextWidth;
561
+ if (checkOverflow && addPageText > availableWidth)
562
+ return;
563
+ this.ngZone.run(() => this.showPageText = true);
564
+ currentWidth = addPageText;
565
+ if (checkOverflow && currentWidth >= availableWidth)
566
+ return;
567
+ }
568
+ if (this.info && !this.isElementVisible(pagerInfoElement) && (!this.showPageSizes || (this.isElementVisible(pagerPageSizes) && this.showPageText))) {
569
+ const addInfoText = currentWidth + this.pagerDimensions.infoTextWidth + this.pagerDimensions.gapSizesInfo;
570
+ if (checkOverflow && addInfoText > availableWidth)
571
+ return;
572
+ this.ngZone.run(() => {
573
+ this.showElement(pagerInfoElement);
574
+ });
575
+ currentWidth = addInfoText;
576
+ }
577
+ if (this.type === 'numeric' && (!this.info || this.isElementVisible(pagerInfoElement))) {
578
+ const addNumericButtons = currentWidth - this.pagerDimensions.inputWidth + this.pagerDimensions.numericButtonsWidth;
579
+ if (checkOverflow && addNumericButtons > availableWidth)
580
+ return;
581
+ this.showElement(numericButtonsElement);
582
+ this.ngZone.run(() => {
583
+ this.showInput = false;
584
+ this.cdr.markForCheck();
585
+ });
586
+ }
587
+ }
588
+ hideElementsInOrder(availableWidth, currentWidth) {
589
+ const el = this.element.nativeElement;
590
+ const numericButtonsElement = el.querySelector('kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons');
591
+ const pagerInfoElement = el.querySelector('.k-pager-info');
592
+ const pagerPageSizes = el.querySelector('.k-pager-sizes');
593
+ const pagerSizesDropDown = el.querySelector('.k-pager-sizes .k-dropdownlist');
594
+ if (this.isElementVisible(numericButtonsElement)) {
595
+ this.hideElement(numericButtonsElement);
596
+ this.ngZone.run(() => this.showInput = true);
597
+ currentWidth += this.pagerDimensions.inputWidth - this.pagerDimensions.numericButtonsWidth;
598
+ if (currentWidth <= availableWidth)
599
+ return;
600
+ }
601
+ if (this.isElementVisible(pagerInfoElement)) {
602
+ this.hideElement(pagerInfoElement);
603
+ currentWidth -= (this.pagerDimensions.infoTextWidth + this.pagerDimensions.gapSizesInfo);
604
+ if (currentWidth <= availableWidth)
605
+ return;
606
+ }
607
+ if (this.showPageText) {
608
+ this.ngZone.run(() => this.showPageText = false);
609
+ currentWidth = currentWidth - this.pagerDimensions.pageTextWidth;
610
+ if (currentWidth <= availableWidth)
611
+ return;
612
+ }
613
+ if (this.showPageSizes && this.isElementVisible(pagerPageSizes) && this.showItemsText) {
614
+ this.ngZone.run(() => this.showItemsText = false);
615
+ currentWidth = currentWidth - this.pagerDimensions.pageSizesWidth + pagerSizesDropDown?.offsetWidth;
616
+ if (currentWidth <= availableWidth)
617
+ return;
618
+ }
619
+ this.hideElement(pagerPageSizes);
620
+ }
621
+ isElementVisible(element) {
622
+ return element && !element?.classList.contains('k-hidden');
623
+ }
624
+ hideElement(element) {
625
+ if (element) {
626
+ this.renderer.addClass(element, 'k-hidden');
627
+ }
628
+ }
629
+ showElement(element) {
630
+ if (element) {
631
+ this.renderer.removeClass(element, 'k-hidden');
632
+ }
633
+ }
634
+ measureAllTextWidths() {
635
+ if (!isDocumentAvailable()) {
636
+ return;
637
+ }
638
+ const el = this.element.nativeElement;
639
+ const existingInfo = el.querySelector('.k-pager-info');
640
+ const existingInput = el.querySelector('.k-pager-input');
641
+ const existingSizes = el.querySelector('.k-pager-sizes');
642
+ // create a single measurement container
643
+ const measureContainer = this.renderer.createElement('div');
644
+ positionOffScreen(this.renderer, measureContainer);
645
+ this.renderer.appendChild(this.element.nativeElement, measureContainer);
646
+ const infoSpan = createMeasurementSpan(this.renderer, measureContainer, 'k-pager-info');
647
+ const pageSpan = createMeasurementSpan(this.renderer, measureContainer, 'k-pager-input');
648
+ const sizesSpan = createMeasurementSpan(this.renderer, measureContainer, 'k-pager-sizes');
649
+ const infoText = `${this.currentPage} - ${this.maxItems} ${this.localization.get('of')} ${this.total} ${this.localization.get('items')}`;
650
+ this.renderer.setProperty(infoSpan, 'textContent', infoText);
651
+ this.renderer.setProperty(pageSpan, 'textContent', this.localization.get('page'));
652
+ this.renderer.setProperty(sizesSpan, 'textContent', this.localization.get('itemsPerPage'));
653
+ // copy computed styles if available
654
+ if (existingInfo)
655
+ copyComputedStyles(this.renderer, existingInfo, infoSpan);
656
+ if (existingInput)
657
+ copyComputedStyles(this.renderer, existingInput, pageSpan);
658
+ if (existingSizes)
659
+ copyComputedStyles(this.renderer, existingSizes, sizesSpan);
660
+ // force a reflow to ensure measurements are accurate
661
+ measureContainer.getBoundingClientRect();
662
+ this.pagerDimensions.infoTextWidth = infoSpan?.offsetWidth;
663
+ if (this.pagerDimensions.inputWidth && this.pagerDimensions.pageTextWidth) {
664
+ this.pagerDimensions.inputWidth = this.pagerDimensions.inputWidth - this.pagerDimensions.pageTextWidth + pageSpan.offsetWidth;
665
+ }
666
+ this.pagerDimensions.pageTextWidth = pageSpan?.offsetWidth;
667
+ if (this.pagerDimensions.pageSizesWidth && this.pagerDimensions.sizesTextWidth) {
668
+ this.pagerDimensions.pageSizesWidth = this.pagerDimensions.pageSizesWidth - this.pagerDimensions.sizesTextWidth + sizesSpan.offsetWidth;
669
+ }
670
+ this.pagerDimensions.sizesTextWidth = sizesSpan?.offsetWidth;
671
+ this.renderer.removeChild(this.element.nativeElement, measureContainer);
672
+ }
673
+ showNumericButtonsResponsive() {
674
+ if (!isDocumentAvailable() || !this.element?.nativeElement) {
675
+ return;
676
+ }
677
+ const numericButtonsElement = this.element.nativeElement.querySelector('kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons');
678
+ const hasNumericButtons = this.numericButtons || numericButtonsElement;
679
+ const hasInput = this.pagerInput || this.element.nativeElement.querySelector('.k-pager-input');
680
+ if (!this.responsive || (!hasNumericButtons && !hasInput)) {
681
+ this.showInput = this.type === 'input';
682
+ return;
683
+ }
684
+ const pagerInfoElement = this.element.nativeElement.querySelector('.k-pager-info');
685
+ if (this.type === 'input' || !this.isElementVisible(pagerInfoElement)) {
686
+ this.showInput = true;
687
+ return;
688
+ }
689
+ if (this.isElementVisible(numericButtonsElement)) {
690
+ this.showInput = false;
691
+ return;
692
+ }
693
+ const pagerWidth = this.element.nativeElement?.offsetWidth;
694
+ const numericButtonsWrapperElement = this.element.nativeElement.querySelector('.k-pager-numbers-wrap');
695
+ const elementsWidths = numericButtonsWrapperElement?.offsetWidth + this.pagerDimensions.pageSizesWidth + this.pagerDimensions.infoTextWidth + this.pagerDimensions.gapSizesInfo;
696
+ const hasAvailableWidth = pagerWidth > elementsWidths - this.pagerDimensions.inputWidth + this.pagerDimensions.numericButtonsWidth;
697
+ this.showInput = !hasAvailableWidth;
698
+ }
699
+ get showPageSizes() {
700
+ if (typeof this.pageSizeValues === 'boolean') {
701
+ return this.pageSizeValues;
702
+ }
703
+ return this.pageSizeValues?.length > 0;
704
+ }
705
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PagerComponent, deps: [{ token: i1.PagerContextService, optional: true, skipSelf: true }, { token: i0.ElementRef }, { token: i2.LocalizationService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i3.PagerNavigationService, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Component });
706
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PagerComponent, isStandalone: true, selector: "kendo-datapager, kendo-pager", inputs: { externalTemplate: "externalTemplate", total: "total", skip: "skip", pageSize: "pageSize", buttonCount: "buttonCount", info: "info", type: "type", pageSizeValues: "pageSizeValues", previousNext: "previousNext", navigable: "navigable", size: "size", responsive: "responsive", adaptiveMode: "adaptiveMode" }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange", pagerInputVisibilityChange: "pagerInputVisibilityChange", pageTextVisibilityChange: "pageTextVisibilityChange", itemsTextVisibilityChange: "itemsTextVisibilityChange" }, host: { listeners: { "focusin": "focusHandler($event)" }, properties: { "class.k-pager": "this.pagerClass", "class.k-pager-responsive": "this.responsiveClass", "attr.role": "this.widgetRole", "attr.aria-roledescription": "this.roleDescription", "attr.aria-keyshortcuts": "this.keyShortcuts", "attr.tabindex": "this.hostTabindex", "attr.dir": "this.dir" } }, providers: [
384
707
  LocalizationService,
385
708
  PagerContextService,
386
709
  PagerNavigationService,
@@ -388,7 +711,7 @@ export class PagerComponent {
388
711
  provide: L10N_PREFIX,
389
712
  useValue: 'kendo.pager'
390
713
  }
391
- ], queries: [{ propertyName: "template", predicate: PagerTemplateDirective }], exportAs: ["kendoDataPager", "kendoPager"], usesOnChanges: true, ngImport: i0, template: `
714
+ ], queries: [{ propertyName: "template", predicate: PagerTemplateDirective }], viewQueries: [{ propertyName: "numericButtons", first: true, predicate: PagerNumericButtonsComponent, descendants: true, read: ElementRef }, { propertyName: "pagerInput", first: true, predicate: PagerInputComponent, descendants: true, read: ElementRef }, { propertyName: "pagerInputComponent", first: true, predicate: PagerInputComponent, descendants: true }, { propertyName: "pageSizes", first: true, predicate: PagerPageSizesComponent, descendants: true, read: ElementRef }, { propertyName: "pageSizesComponent", first: true, predicate: PagerPageSizesComponent, descendants: true }], exportAs: ["kendoDataPager", "kendoPager"], usesOnChanges: true, ngImport: i0, template: `
392
715
  <ng-container kendoPagerLocalizedMessages
393
716
  i18n-ariaLabel="kendo.pager.ariaLabel|The value of the aria-label attribute of the Pager"
394
717
  ariaLabel="{{ 'Page navigation, page {currentPage} of {totalPages}' }}"
@@ -433,25 +756,27 @@ export class PagerComponent {
433
756
  [ngTemplateOutletContext]="templateContext">
434
757
  </ng-container>
435
758
  <ng-template #default>
436
- <div class="k-pager-numbers-wrap">
759
+ <div class="k-pager-numbers-wrap" [ngStyle]="{opacity: initialized ? null : '0'}">
437
760
  <kendo-pager-prev-buttons [size]="size" *ngIf="previousNext"></kendo-pager-prev-buttons>
438
761
  <kendo-pager-numeric-buttons
439
762
  [size]="size"
440
763
  *ngIf="type === 'numeric' && buttonCount > 0"
441
764
  [buttonCount]="buttonCount">
442
765
  </kendo-pager-numeric-buttons>
443
- <kendo-pager-input [size]="size" *ngIf="type === 'input'"></kendo-pager-input>
766
+ <kendo-pager-input [size]="size" *ngIf="showInput"></kendo-pager-input>
444
767
  <kendo-pager-next-buttons [size]="size" *ngIf="previousNext"></kendo-pager-next-buttons>
445
768
  </div>
446
769
  <kendo-pager-page-sizes *ngIf="_pageSizeValues.length"
770
+ [ngStyle]="{opacity: initialized ? null : '0'}"
447
771
  [size]="size"
448
- [pageSizes]="_pageSizeValues">
772
+ [pageSizes]="_pageSizeValues"
773
+ [adaptiveMode]="adaptiveMode">
449
774
  </kendo-pager-page-sizes>
450
- <kendo-pager-info *ngIf="info">
775
+ <kendo-pager-info *ngIf="info" [ngStyle]="{opacity: initialized ? null : '0'}">
451
776
  </kendo-pager-info>
452
777
  </ng-template>
453
778
  <kendo-resize-sensor *ngIf="responsive" (resize)="resizeHandler()"></kendo-resize-sensor>
454
- `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoPagerLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PagerPrevButtonsComponent, selector: "kendo-datapager-prev-buttons, kendo-pager-prev-buttons", inputs: ["size"] }, { kind: "component", type: PagerNumericButtonsComponent, selector: "kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons", inputs: ["buttonCount", "size"] }, { kind: "component", type: PagerInputComponent, selector: "kendo-datapager-input, kendo-pager-input", inputs: ["size"] }, { kind: "component", type: PagerNextButtonsComponent, selector: "kendo-datapager-next-buttons, kendo-pager-next-buttons", inputs: ["size"] }, { kind: "component", type: PagerPageSizesComponent, selector: "kendo-datapager-page-sizes, kendo-pager-page-sizes", inputs: ["pageSizes", "size"] }, { kind: "component", type: PagerInfoComponent, selector: "kendo-datapager-info, kendo-pager-info" }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
779
+ `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoPagerLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PagerPrevButtonsComponent, selector: "kendo-datapager-prev-buttons, kendo-pager-prev-buttons", inputs: ["size"] }, { kind: "component", type: PagerNumericButtonsComponent, selector: "kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons", inputs: ["buttonCount", "size"] }, { kind: "component", type: PagerInputComponent, selector: "kendo-datapager-input, kendo-pager-input", inputs: ["showPageText", "size"] }, { kind: "component", type: PagerNextButtonsComponent, selector: "kendo-datapager-next-buttons, kendo-pager-next-buttons", inputs: ["size"] }, { kind: "component", type: PagerPageSizesComponent, selector: "kendo-datapager-page-sizes, kendo-pager-page-sizes", inputs: ["showItemsText", "pageSizes", "size", "adaptiveMode"] }, { kind: "component", type: PagerInfoComponent, selector: "kendo-datapager-info, kendo-pager-info" }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
455
780
  }
456
781
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PagerComponent, decorators: [{
457
782
  type: Component,
@@ -512,39 +837,56 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
512
837
  [ngTemplateOutletContext]="templateContext">
513
838
  </ng-container>
514
839
  <ng-template #default>
515
- <div class="k-pager-numbers-wrap">
840
+ <div class="k-pager-numbers-wrap" [ngStyle]="{opacity: initialized ? null : '0'}">
516
841
  <kendo-pager-prev-buttons [size]="size" *ngIf="previousNext"></kendo-pager-prev-buttons>
517
842
  <kendo-pager-numeric-buttons
518
843
  [size]="size"
519
844
  *ngIf="type === 'numeric' && buttonCount > 0"
520
845
  [buttonCount]="buttonCount">
521
846
  </kendo-pager-numeric-buttons>
522
- <kendo-pager-input [size]="size" *ngIf="type === 'input'"></kendo-pager-input>
847
+ <kendo-pager-input [size]="size" *ngIf="showInput"></kendo-pager-input>
523
848
  <kendo-pager-next-buttons [size]="size" *ngIf="previousNext"></kendo-pager-next-buttons>
524
849
  </div>
525
850
  <kendo-pager-page-sizes *ngIf="_pageSizeValues.length"
851
+ [ngStyle]="{opacity: initialized ? null : '0'}"
526
852
  [size]="size"
527
- [pageSizes]="_pageSizeValues">
853
+ [pageSizes]="_pageSizeValues"
854
+ [adaptiveMode]="adaptiveMode">
528
855
  </kendo-pager-page-sizes>
529
- <kendo-pager-info *ngIf="info">
856
+ <kendo-pager-info *ngIf="info" [ngStyle]="{opacity: initialized ? null : '0'}">
530
857
  </kendo-pager-info>
531
858
  </ng-template>
532
859
  <kendo-resize-sensor *ngIf="responsive" (resize)="resizeHandler()"></kendo-resize-sensor>
533
860
  `,
534
861
  standalone: true,
535
- imports: [LocalizedMessagesDirective, NgIf, NgTemplateOutlet, PagerPrevButtonsComponent, PagerNumericButtonsComponent, PagerInputComponent, PagerNextButtonsComponent, PagerPageSizesComponent, PagerInfoComponent, ResizeSensorComponent]
862
+ imports: [LocalizedMessagesDirective, NgIf, NgTemplateOutlet, PagerPrevButtonsComponent, PagerNumericButtonsComponent, PagerInputComponent, PagerNextButtonsComponent, PagerPageSizesComponent, PagerInfoComponent, ResizeSensorComponent, NgStyle]
536
863
  }]
537
864
  }], ctorParameters: function () { return [{ type: i1.PagerContextService, decorators: [{
538
865
  type: Optional
539
866
  }, {
540
867
  type: SkipSelf
541
- }] }, { type: i0.ElementRef }, { type: i2.LocalizationService }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i3.PagerNavigationService, decorators: [{
868
+ }] }, { type: i0.ElementRef }, { type: i2.LocalizationService }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i3.PagerNavigationService, decorators: [{
542
869
  type: Optional
543
870
  }, {
544
871
  type: SkipSelf
545
872
  }] }]; }, propDecorators: { template: [{
546
873
  type: ContentChildren,
547
874
  args: [PagerTemplateDirective]
875
+ }], numericButtons: [{
876
+ type: ViewChild,
877
+ args: [PagerNumericButtonsComponent, { read: ElementRef }]
878
+ }], pagerInput: [{
879
+ type: ViewChild,
880
+ args: [PagerInputComponent, { read: ElementRef }]
881
+ }], pagerInputComponent: [{
882
+ type: ViewChild,
883
+ args: [PagerInputComponent]
884
+ }], pageSizes: [{
885
+ type: ViewChild,
886
+ args: [PagerPageSizesComponent, { read: ElementRef }]
887
+ }], pageSizesComponent: [{
888
+ type: ViewChild,
889
+ args: [PagerPageSizesComponent]
548
890
  }], externalTemplate: [{
549
891
  type: Input
550
892
  }], total: [{
@@ -569,13 +911,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
569
911
  type: Input
570
912
  }], responsive: [{
571
913
  type: Input
914
+ }], adaptiveMode: [{
915
+ type: Input
572
916
  }], pageChange: [{
573
917
  type: Output
574
918
  }], pageSizeChange: [{
575
919
  type: Output
920
+ }], pagerInputVisibilityChange: [{
921
+ type: Output
922
+ }], pageTextVisibilityChange: [{
923
+ type: Output
924
+ }], itemsTextVisibilityChange: [{
925
+ type: Output
576
926
  }], pagerClass: [{
577
927
  type: HostBinding,
578
928
  args: ['class.k-pager']
929
+ }], responsiveClass: [{
930
+ type: HostBinding,
931
+ args: ['class.k-pager-responsive']
579
932
  }], widgetRole: [{
580
933
  type: HostBinding,
581
934
  args: ['attr.role']