@progress/kendo-angular-tooltip 16.5.0 → 16.6.0-develop.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/directives.d.ts +25 -0
  2. package/esm2020/directives.mjs +39 -0
  3. package/esm2020/index.mjs +2 -0
  4. package/esm2020/localization/localized-messages.directive.mjs +3 -2
  5. package/esm2020/package-metadata.mjs +2 -2
  6. package/esm2020/popover/anchor.directive.mjs +4 -3
  7. package/esm2020/popover/container.directive.mjs +4 -3
  8. package/esm2020/popover/directives-base.mjs +1 -1
  9. package/esm2020/popover/popover.component.mjs +7 -5
  10. package/esm2020/popover/template-directives/actions-template.directive.mjs +3 -2
  11. package/esm2020/popover/template-directives/body-template.directive.mjs +3 -2
  12. package/esm2020/popover/template-directives/title-template.directive.mjs +3 -2
  13. package/esm2020/popover.module.mjs +15 -35
  14. package/esm2020/tooltip/tooltip.content.component.mjs +8 -6
  15. package/esm2020/tooltip/tooltip.directive.mjs +3 -2
  16. package/esm2020/tooltip.module.mjs +13 -12
  17. package/esm2020/tooltips.module.mjs +19 -5
  18. package/fesm2015/progress-kendo-angular-tooltip.mjs +1745 -1729
  19. package/fesm2020/progress-kendo-angular-tooltip.mjs +1729 -1713
  20. package/index.d.ts +1 -0
  21. package/localization/localized-messages.directive.d.ts +1 -1
  22. package/package.json +6 -6
  23. package/popover/anchor.directive.d.ts +2 -2
  24. package/popover/container.directive.d.ts +3 -3
  25. package/popover/directives-base.d.ts +1 -1
  26. package/popover/popover.component.d.ts +2 -2
  27. package/popover/template-directives/actions-template.directive.d.ts +1 -1
  28. package/popover/template-directives/body-template.directive.d.ts +1 -1
  29. package/popover/template-directives/title-template.directive.d.ts +1 -1
  30. package/popover.module.d.ts +7 -9
  31. package/tooltip/tooltip.content.component.d.ts +1 -1
  32. package/tooltip/tooltip.directive.d.ts +1 -1
  33. package/tooltip.module.d.ts +1 -4
  34. package/tooltips.module.d.ts +10 -3
@@ -3,76 +3,120 @@
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
5
  import * as i0 from '@angular/core';
6
- import { InjectionToken, Injectable, forwardRef, Directive, Input, EventEmitter, Component, HostBinding, Output, isDevMode, Optional, Inject, ViewChild, ContentChild, ElementRef, NgModule } from '@angular/core';
7
- import { filter, take, auditTime } from 'rxjs/operators';
8
- import { Subscription, fromEvent, BehaviorSubject, Subject, combineLatest } from 'rxjs';
9
- import { validatePackage } from '@progress/kendo-licensing';
6
+ import { forwardRef, Directive, Input, Optional, EventEmitter, isDevMode, Component, HostBinding, Output, ViewChild, ContentChild, ElementRef, Injectable, InjectionToken, Inject, NgModule } from '@angular/core';
10
7
  import * as i1 from '@progress/kendo-angular-l10n';
11
8
  import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
12
- import { focusableSelector, isDocumentAvailable, Keys, PreventableEvent, closest, hasObservers } from '@progress/kendo-angular-common';
13
- import { xIcon } from '@progress/kendo-svg-icons';
14
- import * as i2 from '@angular/common';
15
- import { CommonModule } from '@angular/common';
16
- import * as i3 from '@progress/kendo-angular-icons';
17
- import { IconsModule } from '@progress/kendo-angular-icons';
9
+ import { PreventableEvent, focusableSelector, Keys, isDocumentAvailable, closest, hasObservers, ResizeBatchService } from '@progress/kendo-angular-common';
10
+ import { take, auditTime, filter } from 'rxjs/operators';
11
+ import { Subscription, BehaviorSubject, Subject, combineLatest, fromEvent } from 'rxjs';
12
+ import { validatePackage } from '@progress/kendo-licensing';
13
+ import { NgIf, NgStyle, NgClass, NgTemplateOutlet } from '@angular/common';
18
14
  import * as i1$1 from '@progress/kendo-angular-popup';
19
- import { PopupModule } from '@progress/kendo-angular-popup';
15
+ import { PopupService } from '@progress/kendo-angular-popup';
16
+ import { xIcon } from '@progress/kendo-svg-icons';
17
+ import { IconWrapperComponent, IconsService } from '@progress/kendo-angular-icons';
20
18
 
21
19
  /**
22
20
  * @hidden
23
21
  */
24
- const packageMetadata = {
25
- name: '@progress/kendo-angular-tooltip',
26
- productName: 'Kendo UI for Angular',
27
- productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
28
- publishDate: 1721814140,
29
- version: '16.5.0',
30
- licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
31
- };
22
+ class LocalizedMessagesDirective extends ComponentMessages {
23
+ constructor(service) {
24
+ super();
25
+ this.service = service;
26
+ }
27
+ }
28
+ LocalizedMessagesDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocalizedMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
29
+ LocalizedMessagesDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: LocalizedMessagesDirective, isStandalone: true, selector: "[kendoTooltipLocalizedMessages]", inputs: { closeTitle: "closeTitle" }, providers: [
30
+ {
31
+ provide: ComponentMessages,
32
+ useExisting: forwardRef(() => LocalizedMessagesDirective)
33
+ }
34
+ ], usesInheritance: true, ngImport: i0 });
35
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocalizedMessagesDirective, decorators: [{
36
+ type: Directive,
37
+ args: [{
38
+ providers: [
39
+ {
40
+ provide: ComponentMessages,
41
+ useExisting: forwardRef(() => LocalizedMessagesDirective)
42
+ }
43
+ ],
44
+ selector: `[kendoTooltipLocalizedMessages]`,
45
+ standalone: true
46
+ }]
47
+ }], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { closeTitle: [{
48
+ type: Input
49
+ }] } });
32
50
 
33
51
  /**
34
- * Obsolete. Provide the TooltipSettings class instead.
35
- *
36
52
  * @hidden
37
53
  */
38
- const TOOLTIP_SETTINGS = new InjectionToken('kendo-ui-tooltip-settings');
54
+ const ERRORS = {
55
+ popover: `Invalid value provided for the 'popover' property. The accepted data types are 'PopoverComponent' or 'PopoverFn'.`,
56
+ templateData: `templateData must be a function, but received`,
57
+ showOn: `Invalid value provided for the 'showOn' property. The available options are 'click', 'hover', 'focus' or 'none'.`
58
+ };
59
+
39
60
  /**
40
- * Provides a global configuration for the Kendo UI Tooltip. Once injected through
41
- * the `AppComponent` constructor, the configuration properties can be overridden.
42
- *
43
- * @example
44
- * ```ts-no-run
45
- * import { TooltipSettings } from '@progress/kendo-angular-tooltip';
46
- *
47
- * _@Component({
48
- * selector: 'my-app',
49
- * template: `
50
- * <div kendoTooltip>
51
- * <button title="Saves the current document">Save</button>
52
- * </div>`,
53
- * providers: [{
54
- * provide: TooltipSettings,
55
- * useFactory: (): TooltipSettings => ({
56
- * // Override default values of tooltips if wanted
57
- * position: 'right'
58
- * })
59
- * }]
60
- * })
61
- * export class AppComponent { }
62
- * ```
61
+ * Arguments for the `show` event. The `show` event fires when a popover is about
62
+ * to be opened. If you cancel the event, the opening is prevented.
63
63
  */
64
- class TooltipSettings {
64
+ class PopoverShowEvent extends PreventableEvent {
65
65
  /**
66
66
  * @hidden
67
+ * Constructs the event arguments for the `show` event.
68
+ * @param anchor - The host element related to the popover.
67
69
  */
68
- // eslint-disable-next-line @typescript-eslint/no-empty-function
69
- constructor() { }
70
+ constructor(anchor) {
71
+ super();
72
+ this.anchor = anchor;
73
+ }
74
+ }
75
+ /**
76
+ * Arguments for the `hide` event. The `hide` event fires when a popover is about
77
+ * to be closed. If you cancel the event, the popover stays open.
78
+ */
79
+ class PopoverHideEvent extends PreventableEvent {
80
+ /**
81
+ * @hidden
82
+ * Constructs the event arguments for the `hide` event.
83
+ * @param anchor - The host element related to the popover.
84
+ * @param popover - The popover element.
85
+ */
86
+ constructor(anchor, popover) {
87
+ super();
88
+ this.anchor = anchor;
89
+ this.popover = popover;
90
+ }
91
+ }
92
+ /**
93
+ * Arguments for the `shown` event. The `shown` event fires after the popover has opened and its opening animation has finished.
94
+ */
95
+ class PopoverShownEvent {
96
+ /**
97
+ * @hidden
98
+ * Constructs the event arguments for the `shown` event.
99
+ * @param anchor - The host element related to the popover.
100
+ * @param popover - The popover element.
101
+ */
102
+ constructor(anchor, popover) {
103
+ this.anchor = anchor;
104
+ this.popover = popover;
105
+ }
106
+ }
107
+ /**
108
+ * Arguments for the `hidden` event. The `hidden` event fires after the popover has closed and its closing animation has finished.
109
+ */
110
+ class PopoverHiddenEvent {
111
+ /**
112
+ * @hidden
113
+ * Constructs the event arguments for the `hidden` event.
114
+ * @param anchor - The host element related to the popover.
115
+ */
116
+ constructor(anchor) {
117
+ this.anchor = anchor;
118
+ }
70
119
  }
71
- TooltipSettings.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipSettings, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
- TooltipSettings.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipSettings });
73
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipSettings, decorators: [{
74
- type: Injectable
75
- }], ctorParameters: function () { return []; } });
76
120
 
77
121
  /**
78
122
  * @hidden
@@ -226,1906 +270,1897 @@ function getFirstAndLastFocusable(parent) {
226
270
  /**
227
271
  * @hidden
228
272
  */
229
- class LocalizedMessagesDirective extends ComponentMessages {
230
- constructor(service) {
231
- super();
232
- this.service = service;
273
+ const packageMetadata = {
274
+ name: '@progress/kendo-angular-tooltip',
275
+ productName: 'Kendo UI for Angular',
276
+ productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
277
+ publishDate: 1721827743,
278
+ version: '16.6.0-develop.1',
279
+ licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
280
+ };
281
+
282
+ /**
283
+ * Represents a template that defines the content of the Popover title.
284
+ *
285
+ * To define the template, nest an `<ng-template>` tag
286
+ * with the `kendoPopoverTitleTemplate` directive inside the `<kendo-popover>` tag.
287
+ */
288
+ class PopoverTitleTemplateDirective {
289
+ constructor(templateRef) {
290
+ this.templateRef = templateRef;
233
291
  }
234
292
  }
235
- LocalizedMessagesDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocalizedMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
236
- LocalizedMessagesDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: LocalizedMessagesDirective, selector: "[kendoTooltipLocalizedMessages]", inputs: { closeTitle: "closeTitle" }, providers: [
237
- {
238
- provide: ComponentMessages,
239
- useExisting: forwardRef(() => LocalizedMessagesDirective)
240
- }
241
- ], usesInheritance: true, ngImport: i0 });
242
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocalizedMessagesDirective, decorators: [{
293
+ PopoverTitleTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverTitleTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
294
+ PopoverTitleTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverTitleTemplateDirective, isStandalone: true, selector: "[kendoPopoverTitleTemplate]", ngImport: i0 });
295
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverTitleTemplateDirective, decorators: [{
243
296
  type: Directive,
244
297
  args: [{
245
- providers: [
246
- {
247
- provide: ComponentMessages,
248
- useExisting: forwardRef(() => LocalizedMessagesDirective)
249
- }
250
- ],
251
- selector: `[kendoTooltipLocalizedMessages]`
298
+ selector: '[kendoPopoverTitleTemplate]',
299
+ standalone: true
252
300
  }]
253
- }], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { closeTitle: [{
254
- type: Input
255
- }] } });
301
+ }], ctorParameters: function () {
302
+ return [{ type: i0.TemplateRef, decorators: [{
303
+ type: Optional
304
+ }] }];
305
+ } });
256
306
 
257
307
  /**
258
- * @hidden
308
+ * Represents a template that defines the content of the Popover body.
309
+ *
310
+ * To define the template, nest an `<ng-template>` tag
311
+ * with the `kendoPopoverBodyTemplate` directive inside the `<kendo-popover>` tag.
259
312
  */
260
- class TooltipContentComponent {
261
- constructor(content, localizationService) {
262
- this.content = content;
263
- this.localizationService = localizationService;
264
- /**
265
- * @hidden
266
- */
267
- this.xIcon = xIcon;
268
- this.close = new EventEmitter();
269
- this.hostRole = 'tooltip';
270
- this.tooltipWidth = null;
271
- this.tooltipHeight = null;
272
- this.callout = true;
273
- this.calloutStyles = (position, calloutSize, isFlip) => {
274
- const styles = {};
275
- const isVertical = position === 'top' || position === 'bottom';
276
- const flipDeg = '180deg';
277
- const zeroDeg = '0deg';
278
- if (!isFlip) {
279
- styles.transform = isVertical ? `rotateX(${zeroDeg})` : `rotateY(${zeroDeg})`;
280
- return styles;
281
- }
282
- if (position === 'top') {
283
- styles.bottom = 'unset';
284
- }
285
- else if (position === 'bottom') {
286
- styles.top = 'unset';
287
- }
288
- else if (position === 'left') {
289
- styles.right = 'unset';
290
- }
291
- else if (position === 'right') {
292
- styles.left = 'unset';
293
- }
294
- styles[position] = `${-calloutSize}px`;
295
- styles.transform = isVertical ? `rotateX(${flipDeg})` : `rotateY(${flipDeg})`;
296
- return styles;
297
- };
298
- this.direction = localizationService.rtl ? 'rtl' : 'ltr';
299
- }
300
- get cssClasses() {
301
- return 'k-tooltip';
302
- }
303
- get hostId() {
304
- return this.tooltipId;
305
- }
306
- get className() {
307
- return this.closable;
308
- }
309
- get cssPosition() {
310
- return 'relative';
313
+ class PopoverBodyTemplateDirective {
314
+ constructor(templateRef) {
315
+ this.templateRef = templateRef;
311
316
  }
312
- ngOnInit() {
313
- this.tooltipId = getId('tooltip');
314
- this.dynamicRTLSubscription = this.localizationService.changes
315
- .subscribe(({ rtl }) => this.direction = rtl ? 'rtl' : 'ltr');
316
- }
317
- ngOnDestroy() {
318
- if (this.dynamicRTLSubscription) {
319
- this.dynamicRTLSubscription.unsubscribe();
320
- }
321
- }
322
- get closeButtonTitle() {
323
- return this.closeTitle || this.localizationService.get('closeTitle');
324
- }
325
- calloutPositionClass() {
326
- return {
327
- 'top': 'k-callout-s',
328
- 'left': 'k-callout-e',
329
- 'bottom': 'k-callout-n',
330
- 'right': 'k-callout-w'
331
- }[this.position];
332
- }
333
- onCloseClick(event) {
334
- event.preventDefault();
335
- this.close.emit();
336
- }
337
- updateCalloutPosition(position, isFlip) {
338
- if (!this.callout) {
339
- return;
340
- }
341
- const callout = this.content.nativeElement.querySelector('.k-callout');
342
- const isVertical = position === 'top' || position === 'bottom';
343
- const size = isVertical ? 'width' : 'height';
344
- const dir = isVertical ? 'left' : 'top';
345
- const offsetProperty = isVertical ? 'marginLeft' : 'marginTop';
346
- const calloutSize = callout.getBoundingClientRect()[size];
347
- const anchorCenter = getCenterOffset(this.anchor.nativeElement, dir, size);
348
- const contentCenter = getCenterOffset(this.content.nativeElement, dir, size);
349
- const diff = Math.abs(contentCenter - anchorCenter);
350
- if (diff > 1 || diff === 0 || Math.round(diff) === 0) {
351
- const newMargin = contentCenter - anchorCenter + (calloutSize / 2);
352
- callout.style[offsetProperty] = `${-newMargin}px`;
353
- }
354
- const calloutStyles = this.calloutStyles(position, calloutSize, isFlip);
355
- Object.keys(calloutStyles).forEach((style) => {
356
- callout.style[style] = calloutStyles[style];
357
- });
317
+ }
318
+ PopoverBodyTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverBodyTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
319
+ PopoverBodyTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverBodyTemplateDirective, isStandalone: true, selector: "[kendoPopoverBodyTemplate]", ngImport: i0 });
320
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverBodyTemplateDirective, decorators: [{
321
+ type: Directive,
322
+ args: [{
323
+ selector: '[kendoPopoverBodyTemplate]',
324
+ standalone: true
325
+ }]
326
+ }], ctorParameters: function () {
327
+ return [{ type: i0.TemplateRef, decorators: [{
328
+ type: Optional
329
+ }] }];
330
+ } });
331
+
332
+ /**
333
+ * Represents a template that defines the content of the Popover actions.
334
+ *
335
+ * To define the template, nest an `<ng-template>` tag
336
+ * with the `kendoPopoverActionsTemplate` directive inside the `<kendo-popover>` tag.
337
+ */
338
+ class PopoverActionsTemplateDirective {
339
+ constructor(templateRef) {
340
+ this.templateRef = templateRef;
358
341
  }
359
342
  }
360
- TooltipContentComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipContentComponent, deps: [{ token: i0.ElementRef }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
361
- TooltipContentComponentcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TooltipContentComponent, selector: "kendo-tooltip", inputs: { tooltipWidth: "tooltipWidth", tooltipHeight: "tooltipHeight", titleTemplate: "titleTemplate", anchor: "anchor", closable: "closable", templateRef: "templateRef", templateString: "templateString" }, outputs: { close: "close" }, host: { properties: { "attr.dir": "this.direction", "class": "this.cssClasses", "attr.role": "this.hostRole", "attr.id": "this.hostId", "class.k-tooltip-closable": "this.className", "style.position": "this.cssPosition", "style.width.px": "this.tooltipWidth", "style.height.px": "this.tooltipHeight" } }, providers: [
362
- LocalizationService,
363
- {
364
- provide: L10N_PREFIX,
365
- useValue: 'kendo.tooltip'
366
- }
367
- ], ngImport: i0, template: `
368
- <ng-container kendoTooltipLocalizedMessages
369
- i18n-closeTitle="kendo.tooltip.closeTitle|The title of the close button"
370
- closeTitle="Close"
371
- >
372
- </ng-container>
373
-
374
- <div class="k-tooltip-content">
375
- <div class="k-tooltip-title" *ngIf="titleTemplate">
376
- <ng-template
377
- [ngIf]="titleTemplate"
378
- [ngTemplateOutlet]="titleTemplate"
379
- [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
380
- </ng-template>
381
- </div>
382
-
383
- <ng-template
384
- [ngIf]="templateRef"
385
- [ngTemplateOutlet]="templateRef"
386
- [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
387
- </ng-template>
388
- <ng-template
389
- [ngIf]="templateString">
390
- {{ templateString }}
391
- </ng-template>
392
- </div>
393
-
394
- <div *ngIf="closable" [attr.aria-hidden]="true" class="k-tooltip-button" (click)="onCloseClick($event)">
395
- <a href="#" [attr.title]="closeButtonTitle" class="k-icon">
396
- <kendo-icon-wrapper
397
- name="x"
398
- [svgIcon]="xIcon">
399
- </kendo-icon-wrapper>
400
- </a>
401
- </div>
402
-
403
- <div class="k-callout" *ngIf="callout" [ngClass]="calloutPositionClass()"></div>
404
- `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoTooltipLocalizedMessages]", inputs: ["closeTitle"] }] });
405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipContentComponent, decorators: [{
406
- type: Component,
343
+ PopoverActionsTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverActionsTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
344
+ PopoverActionsTemplateDirectivedir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverActionsTemplateDirective, isStandalone: true, selector: "[kendoPopoverActionsTemplate]", ngImport: i0 });
345
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverActionsTemplateDirective, decorators: [{
346
+ type: Directive,
407
347
  args: [{
408
- selector: 'kendo-tooltip',
409
- template: `
410
- <ng-container kendoTooltipLocalizedMessages
411
- i18n-closeTitle="kendo.tooltip.closeTitle|The title of the close button"
412
- closeTitle="Close"
413
- >
414
- </ng-container>
415
-
416
- <div class="k-tooltip-content">
417
- <div class="k-tooltip-title" *ngIf="titleTemplate">
418
- <ng-template
419
- [ngIf]="titleTemplate"
420
- [ngTemplateOutlet]="titleTemplate"
421
- [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
422
- </ng-template>
423
- </div>
424
-
425
- <ng-template
426
- [ngIf]="templateRef"
427
- [ngTemplateOutlet]="templateRef"
428
- [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
429
- </ng-template>
430
- <ng-template
431
- [ngIf]="templateString">
432
- {{ templateString }}
433
- </ng-template>
434
- </div>
435
-
436
- <div *ngIf="closable" [attr.aria-hidden]="true" class="k-tooltip-button" (click)="onCloseClick($event)">
437
- <a href="#" [attr.title]="closeButtonTitle" class="k-icon">
438
- <kendo-icon-wrapper
439
- name="x"
440
- [svgIcon]="xIcon">
441
- </kendo-icon-wrapper>
442
- </a>
443
- </div>
444
-
445
- <div class="k-callout" *ngIf="callout" [ngClass]="calloutPositionClass()"></div>
446
- `,
447
- providers: [
448
- LocalizationService,
449
- {
450
- provide: L10N_PREFIX,
451
- useValue: 'kendo.tooltip'
452
- }
453
- ]
348
+ selector: '[kendoPopoverActionsTemplate]',
349
+ standalone: true
454
350
  }]
455
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.LocalizationService }]; }, propDecorators: { direction: [{
456
- type: HostBinding,
457
- args: ['attr.dir']
458
- }], close: [{
459
- type: Output
460
- }], cssClasses: [{
461
- type: HostBinding,
462
- args: ['class']
463
- }], hostRole: [{
464
- type: HostBinding,
465
- args: ['attr.role']
466
- }], hostId: [{
467
- type: HostBinding,
468
- args: ['attr.id']
469
- }], className: [{
470
- type: HostBinding,
471
- args: ['class.k-tooltip-closable']
472
- }], cssPosition: [{
473
- type: HostBinding,
474
- args: ['style.position']
475
- }], tooltipWidth: [{
476
- type: HostBinding,
477
- args: ['style.width.px']
478
- }, {
479
- type: Input
480
- }], tooltipHeight: [{
481
- type: HostBinding,
482
- args: ['style.height.px']
483
- }, {
484
- type: Input
485
- }], titleTemplate: [{
486
- type: Input
487
- }], anchor: [{
488
- type: Input
489
- }], closable: [{
490
- type: Input
491
- }], templateRef: [{
492
- type: Input
493
- }], templateString: [{
494
- type: Input
495
- }] } });
351
+ }], ctorParameters: function () {
352
+ return [{ type: i0.TemplateRef, decorators: [{
353
+ type: Optional
354
+ }] }];
355
+ } });
496
356
 
357
+ /* eslint-disable @typescript-eslint/no-explicit-any */
497
358
  /**
498
- * Represents the [Kendo UI Tooltip directive for Angular]({% slug overview_tooltip %}).
499
- * Used to display additional information that is related to an element.
359
+ * Represents the [Kendo UI Popover component for Angular]({% slug overview_popover %}).
360
+ * Used to display additional information that is related to a target element.
500
361
  *
501
362
  * @example
502
363
  * ```ts-no-run
503
- * <div kendoTooltip>
504
- * <a title="Tooltip title" href="foo">foo</a>
505
- * </div>
364
+ * <kendo-popover>
365
+ * <ng-template kendoPopoverTitleTemplate>Foo Title</ng-template>
366
+ * <ng-template kendoPopoverBodyTemplate>Foo Body</ng-template>
367
+ * <ng-template kendoPopoverActionsTemplate>Foo Actions</ng-template>
368
+ * </kendo-popover>
506
369
  * ```
507
370
  */
508
- class TooltipDirective {
509
- constructor(tooltipWrapper, ngZone, renderer, popupService, settings, legacySettings) {
510
- this.tooltipWrapper = tooltipWrapper;
511
- this.ngZone = ngZone;
371
+ class PopoverComponent {
372
+ constructor(localization, renderer, element, zone) {
373
+ this.localization = localization;
512
374
  this.renderer = renderer;
513
- this.popupService = popupService;
514
- /**
515
- * Specifies a selector for elements within a container which will display a tooltip
516
- * ([see example]({% slug anchorelements_tooltip %})). The possible values include any
517
- * DOM `selector`. The default value is `[title]`.
518
- */
519
- this.filter = '[title]';
375
+ this.element = element;
376
+ this.zone = zone;
520
377
  /**
521
- * Specifies the position of the Tooltip that is relative to the
522
- * anchor element ([see example]({% slug positioning_tooltip %})).
378
+ * Specifies the position of the Popover in relation to its anchor element. [See example]({% slug positioning_popover %})
523
379
  *
524
- * The possible values are:
525
- * * `top` (default)
526
- * * `bottom`
527
- * * `left`
528
- * * `right`
529
- */
530
- this.position = 'top';
531
- /**
532
- * Specifies the delay in milliseconds before the Tooltip is shown.
533
- * * `100` (default) milliseconds.
380
+ * The possible options are:
381
+ * `top`
382
+ * `bottom`
383
+ * `right` (Default)
384
+ * `left`
534
385
  */
535
- this.showAfter = 100;
386
+ this.position = 'right';
536
387
  /**
537
- * Specifies if the Тooltip will display a callout arrow.
388
+ * Determines whether a callout will be rendered along the Popover. [See example]({% slug callout_popover %})
538
389
  *
539
- * The possible values are:
540
- * * `true` (default)
541
- * * `false`
390
+ * @default true
542
391
  */
543
392
  this.callout = true;
544
393
  /**
545
- * Specifies if the Тooltip will display a **Close** button
546
- * ([see example]({% slug closable_tooltip %})).
394
+ * Enables and configures the Popover animation. [See example]({% slug animations_popover %})
547
395
  *
548
- * The possible values are:
549
- * * `true`
550
- * * `false`
396
+ * The possible options are:
397
+ *
398
+ * * `boolean`&mdash;Enables the default animation
399
+ * * `PopoverAnimation`&mdash;A configuration object which allows setting the `direction`, `duration` and `type` of the animation.
400
+ *
401
+ * @default false
551
402
  */
552
- this.closable = false;
403
+ this.animation = false;
553
404
  /**
554
- * Specifies the offset in pixels between the Tooltip and the anchor. Defaults to `6` pixels.
555
- * If the `callout` property is set to `true`, the offset is rendered from the callout arrow.
556
- * If the `callout` property is set to `false`, the offset is rendered from the content of the Tooltip.
405
+ * @hidden
406
+ * Determines the visibility of the Popover.
557
407
  */
558
- this.offset = 6;
559
- this.anchor = null;
560
- this.keyboardNavigationSubscription = new Subscription();
561
- this.validPositions = ['top', 'bottom', 'right', 'left'];
562
- this.validShowOptions = ['hover', 'click', 'none'];
408
+ this.visible = false;
409
+ /**
410
+ * Fires before the Popover is about to be shown ([see example]({% slug events_popover %})).
411
+ * The event is preventable. If canceled, the Popover will not be displayed. [See example]({% slug events_popover %})
412
+ */
413
+ this.show = new EventEmitter();
414
+ /**
415
+ * Fires after the Popover has been shown and the animation has ended. [See example]({% slug events_popover %})
416
+ */
417
+ this.shown = new EventEmitter();
418
+ /**
419
+ * Fires when the Popover is about to be hidden ([see example]({% slug events_popover %})).
420
+ * The event is preventable. If canceled, the Popover will remain visible.
421
+ */
422
+ this.hide = new EventEmitter();
423
+ /**
424
+ * Fires after the Popover has been hidden and the animation has ended. [See example]({% slug events_popover %})
425
+ */
426
+ this.hidden = new EventEmitter();
427
+ /**
428
+ * @hidden
429
+ */
430
+ this.closeOnKeyDown = new EventEmitter();
431
+ /**
432
+ * @hidden
433
+ */
434
+ this._width = 'auto';
435
+ /**
436
+ * @hidden
437
+ */
438
+ this._height = 'auto';
439
+ /**
440
+ * @hidden
441
+ */
442
+ this.popoverId = '';
443
+ this._offset = 6;
444
+ this.subs = new Subscription();
445
+ this._templateData = () => null;
563
446
  validatePackage(packageMetadata);
564
- Object.assign(this, settings, legacySettings);
565
- this.ngZone.runOutsideAngular(() => {
566
- const wrapper = this.tooltipWrapper.nativeElement;
567
- this.anchorTitleSubscription = fromEvent(wrapper, 'mouseover')
568
- .pipe(filter(() => this.filter !== ''))
569
- .subscribe((e) => {
570
- const filterElement = closestBySelector(e.target, this.filter);
571
- if (filterElement) {
572
- this.hideElementTitle({ nativeElement: filterElement });
573
- }
574
- });
575
- this.mouseOverSubscription = fromEvent(wrapper, 'mouseover')
576
- .pipe(filter(() => this.filter !== ''))
577
- .subscribe(e => this.onMouseOver(e));
578
- this.mouseOutSubscription = fromEvent(wrapper, 'mouseout')
579
- .subscribe(e => this.onMouseOut(e));
580
- });
581
447
  }
582
448
  /**
583
- * Sets the content of the Tooltip as a template reference
584
- * ([see example]({% slug templates_tooltip %})).
449
+ * Specifies the distance from the Popover to its anchor element in pixels.
450
+ *
451
+ * @default `6`
585
452
  */
586
- set tooltipTemplate(value) {
587
- this.template = value;
453
+ set offset(value) {
454
+ this._offset = value;
588
455
  }
589
- get tooltipTemplate() {
590
- return this.template;
456
+ get offset() {
457
+ const calloutBuffer = 14;
458
+ return this.callout
459
+ ? calloutBuffer + this._offset
460
+ : this._offset;
591
461
  }
592
462
  /**
593
- * Shows the Tooltip.
594
- * @param anchor&mdash; ElementRef|Element.
595
- * Specifies the element that will be used as an anchor. The Tooltip opens relative to that element.
463
+ * Determines the width of the popover. Numeric values are treated as pixels.
464
+ * @default 'auto'
596
465
  */
597
- show(anchor) {
598
- if (this.popupRef) {
599
- return;
600
- }
601
- if (anchor instanceof Element) {
602
- anchor = { nativeElement: anchor };
603
- }
604
- this.anchor = anchor;
605
- if (this.showOn === 'hover') {
606
- if (this.popupRef) {
607
- return;
608
- }
609
- clearTimeout(this.showTimeout);
610
- this.showTimeout = setTimeout(() => this.showContent(this.anchor), this.showAfter);
611
- }
612
- else {
613
- this.hideElementTitle(this.anchor);
614
- this.showContent(this.anchor);
615
- }
466
+ set width(value) {
467
+ this._width = typeof value === 'number' ? `${value}px` : value;
468
+ }
469
+ get width() {
470
+ return this._width;
616
471
  }
617
472
  /**
618
- * Hides the Tooltip.
473
+ * Determines the height of the popover. Numeric values are treated as pixels.
474
+ * @default 'auto'
619
475
  */
620
- hide() {
621
- clearTimeout(this.showTimeout);
622
- const anchor = this.anchor && this.anchor.nativeElement;
623
- if (anchor && anchor.getAttribute('data-title')) {
624
- if (!anchor.getAttribute('title') && anchor.hasAttribute('title')) {
625
- anchor.setAttribute('title', anchor.getAttribute('data-title'));
626
- }
627
- anchor.setAttribute('data-title', '');
628
- }
629
- if (this.popupMouseOutSubscription) {
630
- this.popupMouseOutSubscription.unsubscribe();
631
- }
632
- if (this.closeClickSubscription) {
633
- this.closeClickSubscription.unsubscribe();
634
- }
635
- this.closePopup();
476
+ set height(value) {
477
+ this._height = typeof value === 'number' ? `${value}px` : value;
478
+ }
479
+ get height() {
480
+ return this._height;
636
481
  }
637
482
  /**
638
- * Toggle visibility of the Tooltip.
639
- *
640
- * @param anchor&mdash; ElementRef|Element. Specifies the element that will be used as an anchor.
641
- * @param show&mdash; Optional. Boolean. Specifies if the Tooltip will be rendered.
483
+ * Defines a callback function which returns custom data passed to the Popover templates.
484
+ * It exposes the current anchor element as an argument. [See example](slug:templates_popover#toc-passing-data-to-templates)
642
485
  */
643
- toggle(anchor, show) {
644
- const previousAnchor = this.anchor && this.anchor.nativeElement;
645
- if (anchor instanceof Element) {
646
- anchor = { nativeElement: anchor };
647
- }
648
- if (previousAnchor !== anchor.nativeElement) {
649
- this.hide();
650
- }
651
- if (previousAnchor === anchor.nativeElement && this.showOn === 'click') {
652
- this.hide();
653
- }
654
- if (typeof show === 'undefined') {
655
- show = !this.popupRef;
656
- }
657
- if (show) {
658
- this.show(anchor);
659
- }
660
- else {
661
- this.hide();
486
+ set templateData(fn) {
487
+ if (isDevMode && typeof fn !== 'function') {
488
+ throw new Error(`${ERRORS.templateData} ${JSON.stringify(fn)}.`);
662
489
  }
490
+ this._templateData = fn;
491
+ }
492
+ get templateData() {
493
+ return this._templateData;
494
+ }
495
+ /**
496
+ * @hidden
497
+ */
498
+ get isHidden() {
499
+ return !this.visible;
500
+ }
501
+ /**
502
+ * @hidden
503
+ */
504
+ get hasAttributeHidden() {
505
+ return !this.visible;
663
506
  }
664
507
  ngOnInit() {
665
- if (this.showOn === undefined) {
666
- this.showOn = 'hover';
667
- }
668
- this.keyboardNavigationSubscription.add(this.renderer.listen(this.tooltipWrapper.nativeElement, 'keydown', event => this.onKeyDown(event)));
669
- this.verifyProperties();
508
+ this.popoverId = getId('k-popover');
509
+ this.subs.add(this.localization.changes.subscribe(({ rtl }) => { this.direction = rtl ? 'rtl' : 'ltr'; }));
510
+ this.subs.add(this.renderer.listen(this.element.nativeElement, 'keydown', event => this.onKeyDown(event)));
670
511
  }
671
- ngOnChanges(changes) {
672
- if (changes.showOn && isDocumentAvailable()) {
673
- this.subscribeClick();
512
+ ngAfterViewInit() {
513
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
514
+ if (this.visible) {
515
+ const wrapper = this.popoverWrapper.nativeElement;
516
+ const focusablePopoverChildren = getAllFocusableChildren(wrapper);
517
+ if (focusablePopoverChildren.length > 0) {
518
+ focusablePopoverChildren[0].focus();
519
+ }
520
+ this.setAriaAttributes(wrapper, focusablePopoverChildren);
521
+ }
522
+ });
523
+ }
524
+ ngOnDestroy() {
525
+ this.subs.unsubscribe();
526
+ }
527
+ /**
528
+ * @hidden
529
+ */
530
+ getCalloutPosition() {
531
+ switch (this.position) {
532
+ case 'top': return { 'k-callout-s': true };
533
+ case 'bottom': return { 'k-callout-n': true };
534
+ case 'left': return { 'k-callout-e': true };
535
+ case 'right': return { 'k-callout-w': true };
536
+ default: return { 'k-callout-s': true };
674
537
  }
675
538
  }
676
- ngAfterViewChecked() {
677
- if (!this.popupRef) {
678
- return;
539
+ /**
540
+ * @hidden
541
+ */
542
+ onKeyDown(event) {
543
+ const keyCode = event.keyCode;
544
+ const target = event.target;
545
+ if (keyCode === Keys.Tab) {
546
+ this.keepFocusWithinComponent(target, event);
679
547
  }
680
- if (this.anchor &&
681
- !hasParent(this.anchor.nativeElement || this.anchor, this.tooltipWrapper.nativeElement)) {
682
- this.anchor = null;
683
- this.hide();
548
+ if (keyCode === Keys.Escape) {
549
+ this.closeOnKeyDown.emit();
684
550
  }
685
551
  }
686
- ngOnDestroy() {
687
- this.hide();
688
- this.template = null;
689
- this.anchorTitleSubscription.unsubscribe();
690
- this.mouseOverSubscription.unsubscribe();
691
- this.mouseOutSubscription.unsubscribe();
692
- this.keyboardNavigationSubscription.unsubscribe();
693
- if (this.mouseClickSubscription) {
694
- this.mouseClickSubscription.unsubscribe();
695
- }
696
- if (this.popupPositionChangeSubscription) {
697
- this.popupPositionChangeSubscription.unsubscribe();
552
+ keepFocusWithinComponent(target, event) {
553
+ const wrapper = this.popoverWrapper.nativeElement;
554
+ const [firstFocusable, lastFocusable] = getFirstAndLastFocusable(wrapper);
555
+ const tabAfterLastFocusable = !event.shiftKey && target === lastFocusable;
556
+ const shiftTabAfterFirstFocusable = event.shiftKey && target === firstFocusable;
557
+ if (tabAfterLastFocusable) {
558
+ event.preventDefault();
559
+ firstFocusable.focus();
698
560
  }
699
- if (this.popupMouseOutSubscription) {
700
- this.popupMouseOutSubscription.unsubscribe();
561
+ if (shiftTabAfterFirstFocusable) {
562
+ event.preventDefault();
563
+ lastFocusable.focus();
701
564
  }
702
565
  }
703
- showContent(anchorRef) {
704
- if (!anchorRef.nativeElement.getAttribute('data-title') && !this.template) {
705
- return;
706
- }
707
- this.ngZone.run(() => {
708
- this.openPopup(anchorRef);
709
- this.bindContent(this.popupRef.content, anchorRef);
710
- });
711
- this.popupRef.popupAnchorViewportLeave
712
- .pipe(take(1))
713
- .subscribe(() => this.hide());
714
- }
715
- bindContent(contentComponent, anchorRef) {
716
- const content = contentComponent.instance;
717
- this.closeClickSubscription = content.close
718
- .subscribe(() => {
719
- this.hide();
720
- });
721
- if (!this.template) {
722
- content.templateString = this.anchor.nativeElement.getAttribute('data-title');
723
- }
724
- else {
725
- content.templateRef = this.template;
726
- }
566
+ setAriaAttributes(wrapper, focusablePopoverChildren) {
727
567
  if (this.titleTemplate) {
728
- content.titleTemplate = this.titleTemplate;
729
- }
730
- content.closeTitle = this.closeTitle;
731
- content.anchor = anchorRef;
732
- content.callout = this.callout;
733
- content.closable = this.closable;
734
- content.position = this.position;
735
- content.tooltipWidth = this.tooltipWidth;
736
- content.tooltipHeight = this.tooltipHeight;
737
- this.popupRef.content.changeDetectorRef.detectChanges();
738
- }
739
- hideElementTitle(elementRef) {
740
- const element = elementRef.nativeElement;
741
- if (element.getAttribute('title')) {
742
- element.setAttribute('data-title', element.getAttribute('title'));
743
- element.setAttribute('title', '');
744
- }
745
- }
746
- openPopup(anchorRef) {
747
- const alignSettings = align(this.position, this.offset);
748
- const anchorAlign = alignSettings.anchorAlign;
749
- const popupAlign = alignSettings.popupAlign;
750
- const popupMargin = alignSettings.popupMargin;
751
- this.popupRef = this.popupService.open({
752
- anchor: anchorRef,
753
- anchorAlign,
754
- animate: false,
755
- content: TooltipContentComponent,
756
- collision: collision(this.collision, this.position),
757
- margin: popupMargin,
758
- popupAlign,
759
- popupClass: 'k-popup-transparent'
760
- });
761
- if (this.tooltipClass) {
762
- this.renderer.addClass(this.popupRef.popupElement, this.tooltipClass);
763
- }
764
- if (this.tooltipContentClass) {
765
- this.renderer.addClass(this.popupRef.content.instance['content'].nativeElement, this.tooltipContentClass);
766
- }
767
- const popupInstance = this.popupRef.content.instance;
768
- if (anchorRef) {
769
- this.renderer.setAttribute(anchorRef.nativeElement, 'aria-labelledby', popupInstance.tooltipId);
770
- }
771
- if (popupInstance.callout) {
772
- this.popupPositionChangeSubscription = this.popupRef.popupPositionChange
773
- .subscribe(({ flip }) => {
774
- const isFlip = flip.horizontal === true || flip.vertical === true;
775
- popupInstance.updateCalloutPosition(this.position, isFlip);
776
- });
777
- }
778
- if (this.showOn === 'hover') {
779
- this.ngZone.runOutsideAngular(() => {
780
- const popup = this.popupRef.popupElement;
781
- this.popupMouseOutSubscription = fromEvent(popup, 'mouseout')
782
- .subscribe((e) => this.onMouseOut(e));
783
- });
784
- }
785
- }
786
- closePopup() {
787
- if (this.popupRef) {
788
- if (this.anchor) {
789
- this.renderer.removeAttribute(this.anchor.nativeElement, 'aria-labelledby');
790
- }
791
- this.popupRef.close();
792
- this.popupRef = null;
793
- }
794
- if (this.popupPositionChangeSubscription) {
795
- this.popupPositionChangeSubscription.unsubscribe();
796
- }
797
- }
798
- subscribeClick() {
799
- if (this.mouseClickSubscription) {
800
- this.mouseClickSubscription.unsubscribe();
801
- }
802
- if (this.showOn === 'click') {
803
- this.mouseClickSubscription = fromEvent(document, 'click')
804
- .pipe(filter(() => this.filter !== ''))
805
- .subscribe(e => this.onMouseClick(e, this.tooltipWrapper.nativeElement));
806
- }
807
- }
808
- onMouseClick(e, wrapper) {
809
- const target = e.target;
810
- const filterElement = closestBySelector(target, this.filter);
811
- const popup = this.popupRef && this.popupRef.popupElement;
812
- if (popup) {
813
- if (popup.contains(target)) {
814
- return;
815
- }
816
- if (this.closable) {
817
- return;
568
+ const titleRef = this.titleTemplateWrapper.nativeElement;
569
+ const focusableHeaderChildren = getAllFocusableChildren(titleRef).length > 0;
570
+ if (focusableHeaderChildren) {
571
+ const headerId = getId('k-popover-header', 'popoverTitle');
572
+ this.renderer.setAttribute(titleRef, 'id', headerId);
573
+ this.renderer.setAttribute(wrapper, 'aria-labelledby', headerId);
818
574
  }
819
575
  }
820
- if (wrapper.contains(target) && filterElement) {
821
- this.toggle(filterElement, true);
822
- }
823
- else if (popup) {
824
- this.hide();
825
- }
826
- }
827
- onKeyDown(event) {
828
- const keyCode = event.keyCode;
829
- const target = event.target;
830
- if (this.popupRef) {
831
- const tooltipId = this.popupRef.content.location.nativeElement.getAttribute('id');
832
- const anchorLabelledBy = target.getAttribute('aria-labelledby');
833
- if (keyCode === Keys.Escape && this.canCloseTooltip(target, tooltipId, anchorLabelledBy)) {
834
- this.closePopup();
576
+ if (this.bodyTemplate) {
577
+ const bodyRef = this.bodyTemplateWrapper.nativeElement;
578
+ const focusableBodyChildren = getAllFocusableChildren(bodyRef).length > 0;
579
+ if (focusableBodyChildren) {
580
+ const bodyId = getId('k-popover-body', 'popoverBody');
581
+ this.renderer.setAttribute(bodyRef, 'id', bodyId);
582
+ this.renderer.setAttribute(wrapper, 'aria-describedby', bodyId);
835
583
  }
836
584
  }
837
- }
838
- canCloseTooltip(target, tooltipId, anchorLabelledBy) {
839
- const isIdEqualsLabel = tooltipId === anchorLabelledBy;
840
- const filterElement = closestBySelector(target, this.filter);
841
- const isTargetFocused = target === document.activeElement;
842
- const isTargetInsideWrapper = this.tooltipWrapper.nativeElement.contains(target);
843
- return isTargetInsideWrapper && filterElement && isTargetFocused && isIdEqualsLabel;
844
- }
845
- onMouseOver(e) {
846
- const filterElement = closestBySelector(e.target, this.filter);
847
- if (this.showOn !== 'hover') {
848
- return;
849
- }
850
- if (filterElement) {
851
- this.toggle(filterElement, true);
852
- }
853
- }
854
- onMouseOut(e) {
855
- if (this.showOn !== 'hover') {
856
- return;
857
- }
858
- if (this.closable) {
859
- return;
860
- }
861
- const popup = this.popupRef && this.popupRef.popupElement;
862
- const relatedTarget = e.relatedTarget;
863
- if (relatedTarget && this.anchor && contains(this.anchor.nativeElement, relatedTarget)) {
864
- return;
865
- }
866
- if (relatedTarget && contains(popup, relatedTarget)) {
867
- return;
868
- }
869
- this.hide();
870
- }
871
- verifyProperties() {
872
- if (!isDevMode()) {
873
- return;
874
- }
875
- if (!containsItem(this.validPositions, this.position)) {
876
- throw new Error(`Invalid value provided for position property.The available options are 'top', 'bottom', 'left', or 'right'.`);
877
- }
878
- if (!containsItem(this.validShowOptions, this.showOn)) {
879
- throw new Error(`Invalid value provided for showOn property.The available options are 'hover' or 'none'.`);
880
- }
585
+ this.renderer.setAttribute(wrapper, 'id', this.popoverId);
586
+ this.renderer.setAttribute(wrapper, 'role', focusablePopoverChildren.length > 0 ? 'dialog' : 'tooltip');
881
587
  }
882
588
  }
883
- TooltipDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i1$1.PopupService }, { token: TooltipSettings, optional: true }, { token: TOOLTIP_SETTINGS, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
884
- TooltipDirectivedir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: TooltipDirective, selector: "[kendoTooltip]", inputs: { filter: "filter", position: "position", titleTemplate: "titleTemplate", showOn: "showOn", showAfter: "showAfter", callout: "callout", closable: "closable", offset: "offset", tooltipWidth: "tooltipWidth", tooltipHeight: "tooltipHeight", tooltipClass: "tooltipClass", tooltipContentClass: "tooltipContentClass", collision: "collision", closeTitle: "closeTitle", tooltipTemplate: "tooltipTemplate" }, exportAs: ["kendoTooltip"], usesOnChanges: true, ngImport: i0 });
885
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipDirective, decorators: [{
886
- type: Directive,
589
+ PopoverComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
590
+ PopoverComponentcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PopoverComponent, isStandalone: true, selector: "kendo-popover", inputs: { position: "position", offset: "offset", width: "width", height: "height", title: "title", subtitle: "subtitle", body: "body", callout: "callout", animation: "animation", templateData: "templateData" }, outputs: { show: "show", shown: "shown", hide: "hide", hidden: "hidden", closeOnKeyDown: "closeOnKeyDown" }, host: { properties: { "attr.dir": "this.direction", "class.k-hidden": "this.isHidden", "attr.aria-hidden": "this.hasAttributeHidden", "style.width": "this._width", "style.height": "this._height" } }, providers: [
591
+ LocalizationService,
592
+ {
593
+ provide: L10N_PREFIX,
594
+ useValue: 'kendo.popover'
595
+ }
596
+ ], queries: [{ propertyName: "titleTemplate", first: true, predicate: PopoverTitleTemplateDirective, descendants: true }, { propertyName: "bodyTemplate", first: true, predicate: PopoverBodyTemplateDirective, descendants: true }, { propertyName: "actionsTemplate", first: true, predicate: PopoverActionsTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "popoverWrapper", first: true, predicate: ["popoverWrapper"], descendants: true }, { propertyName: "titleTemplateWrapper", first: true, predicate: ["titleTemplateWrapper"], descendants: true }, { propertyName: "bodyTemplateWrapper", first: true, predicate: ["bodyTemplateWrapper"], descendants: true }], ngImport: i0, template: `
597
+ <div #popoverWrapper *ngIf="visible" class="k-popover k-popup" [ngStyle]="{'width': width, 'height': height}">
598
+ <div class="k-popover-callout" [ngClass]="getCalloutPosition()" *ngIf="callout"></div>
599
+
600
+ <div class="k-popover-inner" *ngIf="callout; else noCallout">
601
+ <ng-container *ngTemplateOutlet="noCallout"></ng-container>
602
+ </div>
603
+
604
+ <ng-template #noCallout>
605
+ <div #titleTemplateWrapper *ngIf="titleTemplate || title" class="k-popover-header">
606
+ <ng-template *ngIf="titleTemplate"
607
+ [ngTemplateOutlet]="titleTemplate?.templateRef"
608
+ [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
609
+ </ng-template>
610
+ <ng-container *ngIf="title && !titleTemplate">
611
+ {{ title }}
612
+ </ng-container>
613
+ </div>
614
+
615
+ <div #bodyTemplateWrapper *ngIf="bodyTemplate || body" class="k-popover-body">
616
+ <ng-template *ngIf="bodyTemplate"
617
+ [ngTemplateOutlet]="bodyTemplate?.templateRef"
618
+ [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
619
+ </ng-template>
620
+ <ng-container *ngIf="body && !bodyTemplate">
621
+ {{ body }}
622
+ </ng-container>
623
+ </div>
624
+
625
+ <div *ngIf="actionsTemplate" class="k-popover-actions k-actions k-actions-stretched k-actions-horizontal">
626
+ <ng-template *ngIf="actionsTemplate"
627
+ [ngTemplateOutlet]="actionsTemplate?.templateRef"
628
+ [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
629
+ </ng-template>
630
+ </div>
631
+ </ng-template>
632
+ </div>
633
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
634
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverComponent, decorators: [{
635
+ type: Component,
887
636
  args: [{
888
- selector: '[kendoTooltip]',
889
- exportAs: 'kendoTooltip'
637
+ selector: 'kendo-popover',
638
+ providers: [
639
+ LocalizationService,
640
+ {
641
+ provide: L10N_PREFIX,
642
+ useValue: 'kendo.popover'
643
+ }
644
+ ],
645
+ template: `
646
+ <div #popoverWrapper *ngIf="visible" class="k-popover k-popup" [ngStyle]="{'width': width, 'height': height}">
647
+ <div class="k-popover-callout" [ngClass]="getCalloutPosition()" *ngIf="callout"></div>
648
+
649
+ <div class="k-popover-inner" *ngIf="callout; else noCallout">
650
+ <ng-container *ngTemplateOutlet="noCallout"></ng-container>
651
+ </div>
652
+
653
+ <ng-template #noCallout>
654
+ <div #titleTemplateWrapper *ngIf="titleTemplate || title" class="k-popover-header">
655
+ <ng-template *ngIf="titleTemplate"
656
+ [ngTemplateOutlet]="titleTemplate?.templateRef"
657
+ [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
658
+ </ng-template>
659
+ <ng-container *ngIf="title && !titleTemplate">
660
+ {{ title }}
661
+ </ng-container>
662
+ </div>
663
+
664
+ <div #bodyTemplateWrapper *ngIf="bodyTemplate || body" class="k-popover-body">
665
+ <ng-template *ngIf="bodyTemplate"
666
+ [ngTemplateOutlet]="bodyTemplate?.templateRef"
667
+ [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
668
+ </ng-template>
669
+ <ng-container *ngIf="body && !bodyTemplate">
670
+ {{ body }}
671
+ </ng-container>
672
+ </div>
673
+
674
+ <div *ngIf="actionsTemplate" class="k-popover-actions k-actions k-actions-stretched k-actions-horizontal">
675
+ <ng-template *ngIf="actionsTemplate"
676
+ [ngTemplateOutlet]="actionsTemplate?.templateRef"
677
+ [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
678
+ </ng-template>
679
+ </div>
680
+ </ng-template>
681
+ </div>
682
+ `,
683
+ standalone: true,
684
+ imports: [NgIf, NgStyle, NgClass, NgTemplateOutlet]
890
685
  }]
891
- }], ctorParameters: function () {
892
- return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i1$1.PopupService }, { type: TooltipSettings, decorators: [{
893
- type: Optional
894
- }] }, { type: TooltipSettings, decorators: [{
895
- type: Optional
896
- }, {
897
- type: Inject,
898
- args: [TOOLTIP_SETTINGS]
899
- }] }];
900
- }, propDecorators: { filter: [{
901
- type: Input
902
- }], position: [{
903
- type: Input
904
- }], titleTemplate: [{
905
- type: Input
906
- }], showOn: [{
907
- type: Input
908
- }], showAfter: [{
909
- type: Input
910
- }], callout: [{
911
- type: Input
912
- }], closable: [{
686
+ }], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { position: [{
913
687
  type: Input
914
688
  }], offset: [{
915
689
  type: Input
916
- }], tooltipWidth: [{
690
+ }], width: [{
917
691
  type: Input
918
- }], tooltipHeight: [{
692
+ }], height: [{
919
693
  type: Input
920
- }], tooltipClass: [{
694
+ }], direction: [{
695
+ type: HostBinding,
696
+ args: ['attr.dir']
697
+ }], title: [{
921
698
  type: Input
922
- }], tooltipContentClass: [{
699
+ }], subtitle: [{
923
700
  type: Input
924
- }], collision: [{
701
+ }], body: [{
925
702
  type: Input
926
- }], closeTitle: [{
703
+ }], callout: [{
927
704
  type: Input
928
- }], tooltipTemplate: [{
705
+ }], animation: [{
706
+ type: Input
707
+ }], templateData: [{
929
708
  type: Input
709
+ }], isHidden: [{
710
+ type: HostBinding,
711
+ args: ['class.k-hidden']
712
+ }], hasAttributeHidden: [{
713
+ type: HostBinding,
714
+ args: ['attr.aria-hidden']
715
+ }], show: [{
716
+ type: Output
717
+ }], shown: [{
718
+ type: Output
719
+ }], hide: [{
720
+ type: Output
721
+ }], hidden: [{
722
+ type: Output
723
+ }], closeOnKeyDown: [{
724
+ type: Output
725
+ }], popoverWrapper: [{
726
+ type: ViewChild,
727
+ args: ['popoverWrapper']
728
+ }], titleTemplateWrapper: [{
729
+ type: ViewChild,
730
+ args: ['titleTemplateWrapper']
731
+ }], bodyTemplateWrapper: [{
732
+ type: ViewChild,
733
+ args: ['bodyTemplateWrapper']
734
+ }], titleTemplate: [{
735
+ type: ContentChild,
736
+ args: [PopoverTitleTemplateDirective, { static: false }]
737
+ }], bodyTemplate: [{
738
+ type: ContentChild,
739
+ args: [PopoverBodyTemplateDirective, { static: false }]
740
+ }], actionsTemplate: [{
741
+ type: ContentChild,
742
+ args: [PopoverActionsTemplateDirective, { static: false }]
743
+ }], _width: [{
744
+ type: HostBinding,
745
+ args: ['style.width']
746
+ }], _height: [{
747
+ type: HostBinding,
748
+ args: ['style.height']
930
749
  }] } });
931
750
 
932
- /**
933
- * @hidden
934
- */
935
- const ERRORS = {
936
- popover: `Invalid value provided for the 'popover' property. The accepted data types are 'PopoverComponent' or 'PopoverFn'.`,
937
- templateData: `templateData must be a function, but received`,
938
- showOn: `Invalid value provided for the 'showOn' property. The available options are 'click', 'hover', 'focus' or 'none'.`
939
- };
940
-
941
- /**
942
- * Represents a template that defines the content of the Popover title.
943
- *
944
- * To define the template, nest an `<ng-template>` tag
945
- * with the `kendoPopoverTitleTemplate` directive inside the `<kendo-popover>` tag.
946
- */
947
- class PopoverTitleTemplateDirective {
948
- constructor(templateRef) {
949
- this.templateRef = templateRef;
950
- }
951
- }
952
- PopoverTitleTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverTitleTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
953
- PopoverTitleTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverTitleTemplateDirective, selector: "[kendoPopoverTitleTemplate]", ngImport: i0 });
954
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverTitleTemplateDirective, decorators: [{
955
- type: Directive,
956
- args: [{
957
- selector: '[kendoPopoverTitleTemplate]'
958
- }]
959
- }], ctorParameters: function () {
960
- return [{ type: i0.TemplateRef, decorators: [{
961
- type: Optional
962
- }] }];
963
- } });
964
-
965
- /**
966
- * Represents a template that defines the content of the Popover body.
967
- *
968
- * To define the template, nest an `<ng-template>` tag
969
- * with the `kendoPopoverBodyTemplate` directive inside the `<kendo-popover>` tag.
970
- */
971
- class PopoverBodyTemplateDirective {
972
- constructor(templateRef) {
973
- this.templateRef = templateRef;
974
- }
975
- }
976
- PopoverBodyTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverBodyTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
977
- PopoverBodyTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverBodyTemplateDirective, selector: "[kendoPopoverBodyTemplate]", ngImport: i0 });
978
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverBodyTemplateDirective, decorators: [{
979
- type: Directive,
980
- args: [{
981
- selector: '[kendoPopoverBodyTemplate]'
982
- }]
983
- }], ctorParameters: function () {
984
- return [{ type: i0.TemplateRef, decorators: [{
985
- type: Optional
986
- }] }];
987
- } });
988
-
989
- /**
990
- * Represents a template that defines the content of the Popover actions.
991
- *
992
- * To define the template, nest an `<ng-template>` tag
993
- * with the `kendoPopoverActionsTemplate` directive inside the `<kendo-popover>` tag.
994
- */
995
- class PopoverActionsTemplateDirective {
996
- constructor(templateRef) {
997
- this.templateRef = templateRef;
998
- }
999
- }
1000
- PopoverActionsTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverActionsTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1001
- PopoverActionsTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverActionsTemplateDirective, selector: "[kendoPopoverActionsTemplate]", ngImport: i0 });
1002
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverActionsTemplateDirective, decorators: [{
1003
- type: Directive,
1004
- args: [{
1005
- selector: '[kendoPopoverActionsTemplate]'
1006
- }]
1007
- }], ctorParameters: function () {
1008
- return [{ type: i0.TemplateRef, decorators: [{
1009
- type: Optional
1010
- }] }];
1011
- } });
1012
-
1013
- /* eslint-disable @typescript-eslint/no-explicit-any */
1014
- /**
1015
- * Represents the [Kendo UI Popover component for Angular]({% slug overview_popover %}).
1016
- * Used to display additional information that is related to a target element.
1017
- *
1018
- * @example
1019
- * ```ts-no-run
1020
- * <kendo-popover>
1021
- * <ng-template kendoPopoverTitleTemplate>Foo Title</ng-template>
1022
- * <ng-template kendoPopoverBodyTemplate>Foo Body</ng-template>
1023
- * <ng-template kendoPopoverActionsTemplate>Foo Actions</ng-template>
1024
- * </kendo-popover>
1025
- * ```
1026
- */
1027
- class PopoverComponent {
1028
- constructor(localization, renderer, element, zone) {
1029
- this.localization = localization;
1030
- this.renderer = renderer;
1031
- this.element = element;
1032
- this.zone = zone;
1033
- /**
1034
- * Specifies the position of the Popover in relation to its anchor element. [See example]({% slug positioning_popover %})
1035
- *
1036
- * The possible options are:
1037
- * `top`
1038
- * `bottom`
1039
- * `right` (Default)
1040
- * `left`
1041
- */
1042
- this.position = 'right';
1043
- /**
1044
- * Determines whether a callout will be rendered along the Popover. [See example]({% slug callout_popover %})
1045
- *
1046
- * @default true
1047
- */
1048
- this.callout = true;
1049
- /**
1050
- * Enables and configures the Popover animation. [See example]({% slug animations_popover %})
1051
- *
1052
- * The possible options are:
1053
- *
1054
- * * `boolean`&mdash;Enables the default animation
1055
- * * `PopoverAnimation`&mdash;A configuration object which allows setting the `direction`, `duration` and `type` of the animation.
1056
- *
1057
- * @default false
1058
- */
1059
- this.animation = false;
1060
- /**
1061
- * @hidden
1062
- * Determines the visibility of the Popover.
1063
- */
1064
- this.visible = false;
1065
- /**
1066
- * Fires before the Popover is about to be shown ([see example]({% slug events_popover %})).
1067
- * The event is preventable. If canceled, the Popover will not be displayed. [See example]({% slug events_popover %})
1068
- */
1069
- this.show = new EventEmitter();
1070
- /**
1071
- * Fires after the Popover has been shown and the animation has ended. [See example]({% slug events_popover %})
1072
- */
1073
- this.shown = new EventEmitter();
1074
- /**
1075
- * Fires when the Popover is about to be hidden ([see example]({% slug events_popover %})).
1076
- * The event is preventable. If canceled, the Popover will remain visible.
1077
- */
1078
- this.hide = new EventEmitter();
1079
- /**
1080
- * Fires after the Popover has been hidden and the animation has ended. [See example]({% slug events_popover %})
1081
- */
1082
- this.hidden = new EventEmitter();
1083
- /**
1084
- * @hidden
1085
- */
1086
- this.closeOnKeyDown = new EventEmitter();
1087
- /**
1088
- * @hidden
1089
- */
1090
- this._width = 'auto';
1091
- /**
1092
- * @hidden
1093
- */
1094
- this._height = 'auto';
751
+ /* eslint-disable @typescript-eslint/no-unused-vars */
752
+ /* eslint-disable @typescript-eslint/no-explicit-any */
753
+ const validShowOptions = ['hover', 'click', 'none', 'focus'];
754
+ /**
755
+ * @hidden
756
+ */
757
+ class PopoverDirectivesBase {
758
+ constructor(ngZone, popupService, renderer) {
759
+ this.ngZone = ngZone;
760
+ this.popupService = popupService;
761
+ this.renderer = renderer;
1095
762
  /**
1096
763
  * @hidden
1097
764
  */
1098
- this.popoverId = '';
1099
- this._offset = 6;
765
+ this.anchor = null;
1100
766
  this.subs = new Subscription();
1101
- this._templateData = () => null;
1102
- validatePackage(packageMetadata);
767
+ this._showOn = 'click';
1103
768
  }
1104
769
  /**
1105
- * Specifies the distance from the Popover to its anchor element in pixels.
770
+ * Specifies the popover instance that will be rendered.
771
+ * Accepts a [`PopoverComponent`]({% slug api_tooltip_popovercomponent %}) instance or
772
+ * a [`PopoverFn`]({% slug api_tooltip_popoverfn %}) callback which returns a [`PopoverComponent`]({% slug api_tooltip_popovercomponent %}) instance
773
+ * depending on the current anchor element.
1106
774
  *
1107
- * @default `6`
775
+ * [See example](slug:templates_popover#toc-passing-data-to-templates)
1108
776
  */
1109
- set offset(value) {
1110
- this._offset = value;
777
+ set popover(value) {
778
+ if (value instanceof PopoverComponent || typeof value === `function`) {
779
+ this._popover = value;
780
+ }
781
+ else {
782
+ if (isDevMode) {
783
+ throw new Error(ERRORS.popover);
784
+ }
785
+ }
1111
786
  }
1112
- get offset() {
1113
- const calloutBuffer = 14;
1114
- return this.callout
1115
- ? calloutBuffer + this._offset
1116
- : this._offset;
787
+ get popover() {
788
+ return this._popover;
1117
789
  }
1118
790
  /**
1119
- * Determines the width of the popover. Numeric values are treated as pixels.
1120
- * @default 'auto'
791
+ * The event on which the Popover will be shown
792
+ *
793
+ * The supported values are:
794
+ * - `click` (default) &mdash;The Popover will be shown when its `anchor` element is clicked.
795
+ * - `hover`&mdash;The Popover will be shown when its `anchor` element is hovered.
796
+ * - `focus`&mdash;The Popover will be shown when its `anchor` element is focused.
797
+ * - `none`&mdash;The Popover will not be shown on user interaction. It could be rendered via the Popover API methods.
1121
798
  */
1122
- set width(value) {
1123
- this._width = typeof value === 'number' ? `${value}px` : value;
799
+ set showOn(value) {
800
+ if (isDevMode && !containsItem(validShowOptions, value)) {
801
+ throw new Error(ERRORS.showOn);
802
+ }
803
+ this._showOn = value;
1124
804
  }
1125
- get width() {
1126
- return this._width;
805
+ get showOn() {
806
+ return this._showOn;
1127
807
  }
1128
- /**
1129
- * Determines the height of the popover. Numeric values are treated as pixels.
1130
- * @default 'auto'
1131
- */
1132
- set height(value) {
1133
- this._height = typeof value === 'number' ? `${value}px` : value;
808
+ ngAfterViewInit() {
809
+ if (!isDocumentAvailable()) {
810
+ return;
811
+ }
812
+ this.ngZone.runOutsideAngular(() => {
813
+ switch (this.showOn) {
814
+ case 'hover':
815
+ this.subscribeToShowEvents([{
816
+ name: 'mouseenter', handler: this.mouseenterHandler
817
+ }, {
818
+ name: 'mouseleave', handler: this.mouseleaveHandler
819
+ }]);
820
+ break;
821
+ case 'focus':
822
+ this.subscribeToShowEvents([{
823
+ name: 'focus', handler: this.focusHandler
824
+ }, {
825
+ name: 'blur', handler: this.blurHandler
826
+ }]);
827
+ break;
828
+ case 'click':
829
+ this.subscribeClick();
830
+ break;
831
+ default:
832
+ break;
833
+ }
834
+ });
1134
835
  }
1135
- get height() {
1136
- return this._height;
836
+ ngOnDestroy() {
837
+ this.closePopup();
838
+ this.subs.unsubscribe();
839
+ if (this.disposeHoverOverListener) {
840
+ this.disposeHoverOverListener();
841
+ }
842
+ if (this.disposeHoverOutListener) {
843
+ this.disposeHoverOutListener();
844
+ }
845
+ if (this.disposeClickListener) {
846
+ this.disposeClickListener();
847
+ }
848
+ if (this._focusInsideSub) {
849
+ this._focusInsideSub.unsubscribe();
850
+ }
851
+ if (this._hideSub) {
852
+ this._hideSub.unsubscribe();
853
+ }
854
+ if (this._popupOpenSub) {
855
+ this._popupOpenSub.unsubscribe();
856
+ }
857
+ if (this._popupCloseSub) {
858
+ this._popupCloseSub.unsubscribe();
859
+ }
1137
860
  }
1138
861
  /**
1139
- * Defines a callback function which returns custom data passed to the Popover templates.
1140
- * It exposes the current anchor element as an argument. [See example]({% slug templates_popover %}#toc-popoverdatacallback)
862
+ * Hides the Popover ([See example]({% slug programmaticcontrol_popover %})).
1141
863
  */
1142
- set templateData(fn) {
1143
- if (isDevMode && typeof fn !== 'function') {
1144
- throw new Error(`${ERRORS.templateData} ${JSON.stringify(fn)}.`);
1145
- }
1146
- this._templateData = fn;
1147
- }
1148
- get templateData() {
1149
- return this._templateData;
864
+ hide() {
865
+ this.closePopup();
1150
866
  }
1151
867
  /**
1152
868
  * @hidden
1153
869
  */
1154
- get isHidden() {
1155
- return !this.visible;
870
+ closePopup() {
871
+ if (this.popupRef) {
872
+ if (this.anchor) {
873
+ this.renderer.removeAttribute(this.anchor, 'aria-describedby');
874
+ }
875
+ this.popupRef.close();
876
+ this.popupRef = null;
877
+ if (this.disposePopupHoverOutListener) {
878
+ this.disposePopupHoverOutListener();
879
+ }
880
+ if (this.disposePopupHoverInListener) {
881
+ this.disposePopupHoverInListener();
882
+ }
883
+ if (this.disposePopupFocusOutListener) {
884
+ this.disposePopupFocusOutListener();
885
+ }
886
+ }
1156
887
  }
1157
888
  /**
1158
889
  * @hidden
1159
890
  */
1160
- get hasAttributeHidden() {
1161
- return !this.visible;
1162
- }
1163
- ngOnInit() {
1164
- this.popoverId = getId('k-popover');
1165
- this.subs.add(this.localization.changes.subscribe(({ rtl }) => { this.direction = rtl ? 'rtl' : 'ltr'; }));
1166
- this.subs.add(this.renderer.listen(this.element.nativeElement, 'keydown', event => this.onKeyDown(event)));
1167
- }
1168
- ngAfterViewInit() {
1169
- this.zone.onStable.pipe(take(1)).subscribe(() => {
1170
- if (this.visible) {
1171
- const wrapper = this.popoverWrapper.nativeElement;
1172
- const focusablePopoverChildren = getAllFocusableChildren(wrapper);
1173
- if (focusablePopoverChildren.length > 0) {
1174
- focusablePopoverChildren[0].focus();
1175
- }
1176
- this.setAriaAttributes(wrapper, focusablePopoverChildren);
1177
- }
891
+ openPopup(anchor) {
892
+ this.anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor;
893
+ const popoverComp = this.popover instanceof PopoverComponent ? this.popover : this.popover(this.anchor);
894
+ const alignSettings = align(popoverComp.position, popoverComp.offset);
895
+ const anchorAlign = alignSettings.anchorAlign;
896
+ const popupAlign = alignSettings.popupAlign;
897
+ const popupMargin = alignSettings.popupMargin;
898
+ const _animation = popoverComp.animation;
899
+ this.popupRef = this.popupService.open({
900
+ anchor: { nativeElement: this.anchor },
901
+ animate: _animation,
902
+ content: PopoverComponent,
903
+ popupAlign,
904
+ anchorAlign,
905
+ margin: popupMargin,
906
+ popupClass: 'k-popup-transparent',
907
+ collision: { horizontal: 'fit', vertical: 'fit' }
1178
908
  });
909
+ const popupInstance = this.popupRef.content.instance;
910
+ if (anchor) {
911
+ this.subs.add(this.renderer.listen(this.anchor, 'keydown', event => this.onKeyDown(event)));
912
+ this.renderer.setAttribute(this.anchor, 'aria-describedby', popupInstance.popoverId);
913
+ }
914
+ this.subs.add(popupInstance.closeOnKeyDown.subscribe(() => {
915
+ this.anchor.focus();
916
+ this.hide();
917
+ }));
918
+ this.applySettings(this.popupRef.content, popoverComp);
919
+ this.monitorPopup();
920
+ this.initializeCompletionEvents(popoverComp, this.anchor);
1179
921
  }
1180
- ngOnDestroy() {
1181
- this.subs.unsubscribe();
922
+ /**
923
+ * @hidden
924
+ */
925
+ isPrevented(anchorElement, show) {
926
+ const popoverComp = this.popover instanceof PopoverComponent ? this.popover : this.popover(anchorElement);
927
+ let eventArgs;
928
+ // eslint-disable-next-line prefer-const
929
+ eventArgs = this.initializeEvents(popoverComp, eventArgs, show, anchorElement);
930
+ return eventArgs.isDefaultPrevented();
1182
931
  }
1183
932
  /**
1184
933
  * @hidden
1185
934
  */
1186
- getCalloutPosition() {
1187
- switch (this.position) {
1188
- case 'top': return { 'k-callout-s': true };
1189
- case 'bottom': return { 'k-callout-n': true };
1190
- case 'left': return { 'k-callout-e': true };
1191
- case 'right': return { 'k-callout-w': true };
1192
- default: return { 'k-callout-s': true };
935
+ monitorPopup() {
936
+ if (this.showOn === 'hover') {
937
+ this.ngZone.runOutsideAngular(() => {
938
+ const popup = this.popupRef.popupElement;
939
+ this.disposePopupHoverInListener = this.renderer.listen(popup, 'mouseenter', _ => {
940
+ this.ngZone.run(_ => this._popoverService.emitPopoverState(true));
941
+ });
942
+ this.disposePopupHoverOutListener = this.renderer.listen(popup, 'mouseleave', _ => {
943
+ this.ngZone.run(_ => this._popoverService.emitPopoverState(false));
944
+ });
945
+ });
946
+ }
947
+ if (this.showOn === 'focus') {
948
+ this.ngZone.runOutsideAngular(() => {
949
+ const popup = this.popupRef.popupElement;
950
+ this.disposePopupFocusOutListener = this.renderer.listen(popup, 'focusout', (e) => {
951
+ const isInsidePopover = closest(e.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
952
+ if (!isInsidePopover) {
953
+ this.ngZone.run(_ => this._popoverService.emitFocusInsidePopover(false));
954
+ }
955
+ });
956
+ });
1193
957
  }
1194
958
  }
959
+ applySettings(contentComponent, popover) {
960
+ const content = contentComponent.instance;
961
+ content.visible = true;
962
+ content.anchor = this.anchor;
963
+ content.position = popover.position;
964
+ content.offset = popover.offset;
965
+ content.width = popover.width;
966
+ content.height = popover.height;
967
+ content.title = popover.title;
968
+ content.body = popover.body;
969
+ content.callout = popover.callout;
970
+ content.animation = popover.animation;
971
+ content.contextData = popover.templateData(this.anchor);
972
+ content.titleTemplate = popover.titleTemplate;
973
+ content.bodyTemplate = popover.bodyTemplate;
974
+ content.actionsTemplate = popover.actionsTemplate;
975
+ this.popupRef.content.changeDetectorRef.detectChanges();
976
+ }
1195
977
  /**
1196
978
  * @hidden
1197
979
  */
1198
- onKeyDown(event) {
1199
- const keyCode = event.keyCode;
1200
- const target = event.target;
1201
- if (keyCode === Keys.Tab) {
1202
- this.keepFocusWithinComponent(target, event);
980
+ initializeEvents(popoverComp, eventArgs, show, anchorElement) {
981
+ if (show) {
982
+ eventArgs = new PopoverShowEvent(anchorElement);
983
+ if (this.shouldEmitEvent(!!this.popupRef, 'show', popoverComp)) {
984
+ this.ngZone.run(() => popoverComp.show.emit(eventArgs));
985
+ }
1203
986
  }
1204
- if (keyCode === Keys.Escape) {
1205
- this.closeOnKeyDown.emit();
987
+ else {
988
+ eventArgs = new PopoverHideEvent(anchorElement, this.popupRef);
989
+ if (this.shouldEmitEvent(!!this.popupRef, 'hide', popoverComp)) {
990
+ this.ngZone.run(() => popoverComp.hide.emit(eventArgs));
991
+ }
1206
992
  }
993
+ return eventArgs;
1207
994
  }
1208
- keepFocusWithinComponent(target, event) {
1209
- const wrapper = this.popoverWrapper.nativeElement;
1210
- const [firstFocusable, lastFocusable] = getFirstAndLastFocusable(wrapper);
1211
- const tabAfterLastFocusable = !event.shiftKey && target === lastFocusable;
1212
- const shiftTabAfterFirstFocusable = event.shiftKey && target === firstFocusable;
1213
- if (tabAfterLastFocusable) {
1214
- event.preventDefault();
1215
- firstFocusable.focus();
1216
- }
1217
- if (shiftTabAfterFirstFocusable) {
1218
- event.preventDefault();
1219
- lastFocusable.focus();
995
+ onKeyDown(event) {
996
+ const keyCode = event.keyCode;
997
+ if (keyCode === Keys.Escape) {
998
+ this.hide();
1220
999
  }
1221
1000
  }
1222
- setAriaAttributes(wrapper, focusablePopoverChildren) {
1223
- if (this.titleTemplate) {
1224
- const titleRef = this.titleTemplateWrapper.nativeElement;
1225
- const focusableHeaderChildren = getAllFocusableChildren(titleRef).length > 0;
1226
- if (focusableHeaderChildren) {
1227
- const headerId = getId('k-popover-header', 'popoverTitle');
1228
- this.renderer.setAttribute(titleRef, 'id', headerId);
1229
- this.renderer.setAttribute(wrapper, 'aria-labelledby', headerId);
1230
- }
1231
- }
1232
- if (this.bodyTemplate) {
1233
- const bodyRef = this.bodyTemplateWrapper.nativeElement;
1234
- const focusableBodyChildren = getAllFocusableChildren(bodyRef).length > 0;
1235
- if (focusableBodyChildren) {
1236
- const bodyId = getId('k-popover-body', 'popoverBody');
1237
- this.renderer.setAttribute(bodyRef, 'id', bodyId);
1238
- this.renderer.setAttribute(wrapper, 'aria-describedby', bodyId);
1239
- }
1001
+ initializeCompletionEvents(popoverComp, _anchor) {
1002
+ if (this.shouldEmitCompletionEvents('shown', popoverComp)) {
1003
+ this.popupRef.popupOpen.subscribe(() => {
1004
+ const eventArgs = new PopoverShownEvent(_anchor, this.popupRef);
1005
+ popoverComp.shown.emit(eventArgs);
1006
+ });
1240
1007
  }
1241
- this.renderer.setAttribute(wrapper, 'id', this.popoverId);
1242
- this.renderer.setAttribute(wrapper, 'role', focusablePopoverChildren.length > 0 ? 'dialog' : 'tooltip');
1243
- }
1244
- }
1245
- PopoverComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1246
- PopoverComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PopoverComponent, selector: "kendo-popover", inputs: { position: "position", offset: "offset", width: "width", height: "height", title: "title", subtitle: "subtitle", body: "body", callout: "callout", animation: "animation", templateData: "templateData" }, outputs: { show: "show", shown: "shown", hide: "hide", hidden: "hidden", closeOnKeyDown: "closeOnKeyDown" }, host: { properties: { "attr.dir": "this.direction", "class.k-hidden": "this.isHidden", "attr.aria-hidden": "this.hasAttributeHidden", "style.width": "this._width", "style.height": "this._height" } }, providers: [
1247
- LocalizationService,
1248
- {
1249
- provide: L10N_PREFIX,
1250
- useValue: 'kendo.popover'
1008
+ if (this.shouldEmitCompletionEvents('hidden', popoverComp)) {
1009
+ this.popupRef.popupClose.subscribe(() => {
1010
+ this.ngZone.run(_ => {
1011
+ const eventArgs = new PopoverHiddenEvent(_anchor);
1012
+ popoverComp.hidden.emit(eventArgs);
1013
+ });
1014
+ });
1251
1015
  }
1252
- ], queries: [{ propertyName: "titleTemplate", first: true, predicate: PopoverTitleTemplateDirective, descendants: true }, { propertyName: "bodyTemplate", first: true, predicate: PopoverBodyTemplateDirective, descendants: true }, { propertyName: "actionsTemplate", first: true, predicate: PopoverActionsTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "popoverWrapper", first: true, predicate: ["popoverWrapper"], descendants: true }, { propertyName: "titleTemplateWrapper", first: true, predicate: ["titleTemplateWrapper"], descendants: true }, { propertyName: "bodyTemplateWrapper", first: true, predicate: ["bodyTemplateWrapper"], descendants: true }], ngImport: i0, template: `
1253
- <div #popoverWrapper *ngIf="visible" class="k-popover k-popup" [ngStyle]="{'width': width, 'height': height}">
1254
- <div class="k-popover-callout" [ngClass]="getCalloutPosition()" *ngIf="callout"></div>
1255
-
1256
- <div class="k-popover-inner" *ngIf="callout; else noCallout">
1257
- <ng-container *ngTemplateOutlet="noCallout"></ng-container>
1258
- </div>
1259
-
1260
- <ng-template #noCallout>
1261
- <div #titleTemplateWrapper *ngIf="titleTemplate || title" class="k-popover-header">
1262
- <ng-template *ngIf="titleTemplate"
1263
- [ngTemplateOutlet]="titleTemplate?.templateRef"
1264
- [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
1265
- </ng-template>
1266
- <ng-container *ngIf="title && !titleTemplate">
1267
- {{ title }}
1268
- </ng-container>
1269
- </div>
1270
-
1271
- <div #bodyTemplateWrapper *ngIf="bodyTemplate || body" class="k-popover-body">
1272
- <ng-template *ngIf="bodyTemplate"
1273
- [ngTemplateOutlet]="bodyTemplate?.templateRef"
1274
- [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
1275
- </ng-template>
1276
- <ng-container *ngIf="body && !bodyTemplate">
1277
- {{ body }}
1278
- </ng-container>
1279
- </div>
1280
-
1281
- <div *ngIf="actionsTemplate" class="k-popover-actions k-actions k-actions-stretched k-actions-horizontal">
1282
- <ng-template *ngIf="actionsTemplate"
1283
- [ngTemplateOutlet]="actionsTemplate?.templateRef"
1284
- [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
1285
- </ng-template>
1286
- </div>
1287
- </ng-template>
1288
- </div>
1289
- `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
1290
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverComponent, decorators: [{
1291
- type: Component,
1292
- args: [{
1293
- selector: 'kendo-popover',
1294
- providers: [
1295
- LocalizationService,
1296
- {
1297
- provide: L10N_PREFIX,
1298
- useValue: 'kendo.popover'
1299
- }
1300
- ],
1301
- template: `
1302
- <div #popoverWrapper *ngIf="visible" class="k-popover k-popup" [ngStyle]="{'width': width, 'height': height}">
1303
- <div class="k-popover-callout" [ngClass]="getCalloutPosition()" *ngIf="callout"></div>
1304
-
1305
- <div class="k-popover-inner" *ngIf="callout; else noCallout">
1306
- <ng-container *ngTemplateOutlet="noCallout"></ng-container>
1307
- </div>
1308
-
1309
- <ng-template #noCallout>
1310
- <div #titleTemplateWrapper *ngIf="titleTemplate || title" class="k-popover-header">
1311
- <ng-template *ngIf="titleTemplate"
1312
- [ngTemplateOutlet]="titleTemplate?.templateRef"
1313
- [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
1314
- </ng-template>
1315
- <ng-container *ngIf="title && !titleTemplate">
1316
- {{ title }}
1317
- </ng-container>
1318
- </div>
1319
-
1320
- <div #bodyTemplateWrapper *ngIf="bodyTemplate || body" class="k-popover-body">
1321
- <ng-template *ngIf="bodyTemplate"
1322
- [ngTemplateOutlet]="bodyTemplate?.templateRef"
1323
- [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
1324
- </ng-template>
1325
- <ng-container *ngIf="body && !bodyTemplate">
1326
- {{ body }}
1327
- </ng-container>
1328
- </div>
1329
-
1330
- <div *ngIf="actionsTemplate" class="k-popover-actions k-actions k-actions-stretched k-actions-horizontal">
1331
- <ng-template *ngIf="actionsTemplate"
1332
- [ngTemplateOutlet]="actionsTemplate?.templateRef"
1333
- [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
1334
- </ng-template>
1335
- </div>
1336
- </ng-template>
1337
- </div>
1338
- `
1339
- }]
1340
- }], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { position: [{
1341
- type: Input
1342
- }], offset: [{
1343
- type: Input
1344
- }], width: [{
1345
- type: Input
1346
- }], height: [{
1347
- type: Input
1348
- }], direction: [{
1349
- type: HostBinding,
1350
- args: ['attr.dir']
1351
- }], title: [{
1352
- type: Input
1353
- }], subtitle: [{
1354
- type: Input
1355
- }], body: [{
1356
- type: Input
1357
- }], callout: [{
1358
- type: Input
1359
- }], animation: [{
1360
- type: Input
1361
- }], templateData: [{
1362
- type: Input
1363
- }], isHidden: [{
1364
- type: HostBinding,
1365
- args: ['class.k-hidden']
1366
- }], hasAttributeHidden: [{
1367
- type: HostBinding,
1368
- args: ['attr.aria-hidden']
1369
- }], show: [{
1370
- type: Output
1371
- }], shown: [{
1372
- type: Output
1373
- }], hide: [{
1374
- type: Output
1375
- }], hidden: [{
1376
- type: Output
1377
- }], closeOnKeyDown: [{
1378
- type: Output
1379
- }], popoverWrapper: [{
1380
- type: ViewChild,
1381
- args: ['popoverWrapper']
1382
- }], titleTemplateWrapper: [{
1383
- type: ViewChild,
1384
- args: ['titleTemplateWrapper']
1385
- }], bodyTemplateWrapper: [{
1386
- type: ViewChild,
1387
- args: ['bodyTemplateWrapper']
1388
- }], titleTemplate: [{
1389
- type: ContentChild,
1390
- args: [PopoverTitleTemplateDirective, { static: false }]
1391
- }], bodyTemplate: [{
1392
- type: ContentChild,
1393
- args: [PopoverBodyTemplateDirective, { static: false }]
1394
- }], actionsTemplate: [{
1395
- type: ContentChild,
1396
- args: [PopoverActionsTemplateDirective, { static: false }]
1397
- }], _width: [{
1398
- type: HostBinding,
1399
- args: ['style.width']
1400
- }], _height: [{
1401
- type: HostBinding,
1402
- args: ['style.height']
1403
- }] } });
1404
-
1405
- /**
1406
- * Arguments for the `show` event. The `show` event fires when a popover is about
1407
- * to be opened. If you cancel the event, the opening is prevented.
1408
- */
1409
- class PopoverShowEvent extends PreventableEvent {
1410
- /**
1411
- * @hidden
1412
- * Constructs the event arguments for the `show` event.
1413
- * @param anchor - The host element related to the popover.
1414
- */
1415
- constructor(anchor) {
1416
- super();
1417
- this.anchor = anchor;
1418
1016
  }
1419
- }
1420
- /**
1421
- * Arguments for the `hide` event. The `hide` event fires when a popover is about
1422
- * to be closed. If you cancel the event, the popover stays open.
1423
- */
1424
- class PopoverHideEvent extends PreventableEvent {
1425
- /**
1426
- * @hidden
1427
- * Constructs the event arguments for the `hide` event.
1428
- * @param anchor - The host element related to the popover.
1429
- * @param popover - The popover element.
1430
- */
1431
- constructor(anchor, popover) {
1432
- super();
1433
- this.anchor = anchor;
1434
- this.popover = popover;
1017
+ shouldEmitEvent(hasPopup, event, popoverComp) {
1018
+ if ((event === 'show' && !hasPopup && hasObservers(popoverComp[event]))
1019
+ || (event === 'hide' && hasPopup && hasObservers(popoverComp[event]))) {
1020
+ return true;
1021
+ }
1022
+ return false;
1435
1023
  }
1436
- }
1437
- /**
1438
- * Arguments for the `shown` event. The `shown` event fires after the popover has opened and its opening animation has finished.
1439
- */
1440
- class PopoverShownEvent {
1441
- /**
1442
- * @hidden
1443
- * Constructs the event arguments for the `shown` event.
1444
- * @param anchor - The host element related to the popover.
1445
- * @param popover - The popover element.
1446
- */
1447
- constructor(anchor, popover) {
1448
- this.anchor = anchor;
1449
- this.popover = popover;
1024
+ shouldEmitCompletionEvents(event, popoverComp) {
1025
+ if ((hasObservers(popoverComp[event]) && !this._popupOpenSub)
1026
+ || (hasObservers(popoverComp[event]) && !this._popupCloseSub)) {
1027
+ return true;
1028
+ }
1029
+ return false;
1450
1030
  }
1451
1031
  }
1032
+ PopoverDirectivesBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverDirectivesBase, deps: [{ token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
1033
+ PopoverDirectivesBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverDirectivesBase, inputs: { popover: "popover", showOn: "showOn" }, ngImport: i0 });
1034
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverDirectivesBase, decorators: [{
1035
+ type: Directive,
1036
+ args: [{}]
1037
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }]; }, propDecorators: { popover: [{
1038
+ type: Input
1039
+ }], showOn: [{
1040
+ type: Input
1041
+ }] } });
1042
+
1452
1043
  /**
1453
- * Arguments for the `hidden` event. The `hidden` event fires after the popover has closed and its closing animation has finished.
1044
+ * @hidden
1454
1045
  */
1455
- class PopoverHiddenEvent {
1456
- /**
1457
- * @hidden
1458
- * Constructs the event arguments for the `hidden` event.
1459
- * @param anchor - The host element related to the popover.
1460
- */
1461
- constructor(anchor) {
1462
- this.anchor = anchor;
1046
+ class PopoverService {
1047
+ constructor(ngZone) {
1048
+ this.ngZone = ngZone;
1049
+ this._pointerOverPopup = new BehaviorSubject(null);
1050
+ this._pointerOverAnchor = new BehaviorSubject(null);
1051
+ this._focusInsidePopover = new BehaviorSubject(null);
1052
+ this._hidePopover = new Subject();
1053
+ this.subs = new Subscription();
1054
+ this.monitor();
1055
+ }
1056
+ ngOnDestroy() {
1057
+ this.subs.unsubscribe();
1058
+ }
1059
+ get isPopoverHovered() {
1060
+ return this._pointerOverPopup.asObservable();
1061
+ }
1062
+ emitPopoverState(isHovered) {
1063
+ this.ngZone.run(_ => this._pointerOverPopup.next(isHovered));
1064
+ }
1065
+ get isAnchorHovered() {
1066
+ return this._pointerOverAnchor.asObservable();
1067
+ }
1068
+ emitAnchorState(isHovered, anchor) {
1069
+ this._isOrigin = this.originAnchor === anchor;
1070
+ this.currentAnchor = anchor;
1071
+ if (isHovered) {
1072
+ this.originAnchor = anchor;
1073
+ }
1074
+ this.ngZone.run(_ => this._pointerOverAnchor.next(isHovered));
1075
+ }
1076
+ get isFocusInsidePopover() {
1077
+ return this._focusInsidePopover.asObservable();
1078
+ }
1079
+ emitFocusInsidePopover(isFocused) {
1080
+ this.ngZone.run(_ => this._focusInsidePopover.next(isFocused));
1081
+ this._focusInsidePopover.next(null);
1082
+ }
1083
+ get hidePopover() {
1084
+ return this._hidePopover.asObservable();
1085
+ }
1086
+ monitor() {
1087
+ this.subs.add(combineLatest(this.isPopoverHovered, this.isAnchorHovered).pipe(
1088
+ // `auditTime` is used because the `mouseleave` event is emitted before `mouseenter`
1089
+ // i.e. there is a millisecond in which the pointer leaves the first target (e.g. anchor) and hasn't reached the second one (e.g. popup)
1090
+ // resulting in both observables emitting `false`
1091
+ auditTime(20)).subscribe(val => {
1092
+ const [isPopoverHovered, isAnchorHovered] = val;
1093
+ this._hidePopover.next([isPopoverHovered, isAnchorHovered, this._isOrigin, this.currentAnchor]);
1094
+ }));
1463
1095
  }
1464
1096
  }
1097
+ PopoverService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
1098
+ PopoverService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverService });
1099
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverService, decorators: [{
1100
+ type: Injectable
1101
+ }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
1465
1102
 
1466
- /* eslint-disable @typescript-eslint/no-unused-vars */
1467
1103
  /* eslint-disable @typescript-eslint/no-explicit-any */
1468
- const validShowOptions = ['hover', 'click', 'none', 'focus'];
1469
1104
  /**
1470
- * @hidden
1105
+ * Represents the [`kendoPopoverAnchor`](slug:configuration_popover#toc-popover-anchor) directive.
1106
+ * It is used to target an element, which should display a popover on interaction.
1107
+ *
1108
+ * @example
1109
+ * ```ts-no-run
1110
+ * <button kendoPopoverAnchor [popover]="myPopover">Show Popover</button>
1111
+ * ```
1471
1112
  */
1472
- class PopoverDirectivesBase {
1473
- constructor(ngZone, popupService, renderer) {
1113
+ class PopoverAnchorDirective extends PopoverDirectivesBase {
1114
+ constructor(hostEl, ngZone, popupService, renderer, popoverService) {
1115
+ super(ngZone, popupService, renderer);
1116
+ this.hostEl = hostEl;
1474
1117
  this.ngZone = ngZone;
1475
1118
  this.popupService = popupService;
1476
1119
  this.renderer = renderer;
1477
- /**
1478
- * @hidden
1479
- */
1480
- this.anchor = null;
1481
- this.subs = new Subscription();
1482
- this._showOn = 'click';
1120
+ this.popoverService = popoverService;
1121
+ this.mouseenterHandler = () => {
1122
+ this.controlVisibility(this.hostEl.nativeElement, true);
1123
+ };
1124
+ this.mouseleaveHandler = () => {
1125
+ if (this.isPrevented(this.hostEl.nativeElement, false)) {
1126
+ return;
1127
+ }
1128
+ if (!this._hideSub) {
1129
+ this._hideSub = this.popoverService.hidePopover.subscribe((val) => {
1130
+ const [isPopoverHovered, isAnchorHovered] = val;
1131
+ if (!isPopoverHovered && !isAnchorHovered) {
1132
+ this.hide();
1133
+ }
1134
+ });
1135
+ }
1136
+ };
1137
+ this.focusHandler = () => {
1138
+ this.controlVisibility(this.hostEl.nativeElement, true);
1139
+ };
1140
+ this.blurHandler = (args) => {
1141
+ const event = args.domEvent;
1142
+ if (this.isPrevented(this.hostEl.nativeElement, false)) {
1143
+ return;
1144
+ }
1145
+ // from anchor to popup focus check
1146
+ const isFocusInside = !!closest(event.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
1147
+ if (!isFocusInside) {
1148
+ this.hide();
1149
+ }
1150
+ if (!this._focusInsideSub) {
1151
+ // inside popup focus check
1152
+ this._focusInsideSub = this.popoverService.isFocusInsidePopover.pipe(filter(v => v !== null)).subscribe((val) => {
1153
+ if (!val) {
1154
+ this.hide();
1155
+ }
1156
+ });
1157
+ }
1158
+ };
1159
+ this._popoverService = this.popoverService;
1483
1160
  }
1484
1161
  /**
1485
- * Specifies the popover instance that will be rendered.
1486
- * Accepts a [`PopoverComponent`]({% slug api_tooltip_popovercomponent %}) instance or
1487
- * a [`PopoverFn`]({% slug api_tooltip_popoverfn %}) callback which returns a [`PopoverComponent`]({% slug api_tooltip_popovercomponent %}) instance
1488
- * depending on the current anchor element.
1489
- *
1490
- * [See example]({% slug templates_popover %}#toc-popovercallback)
1162
+ * Shows the Popover. [See example]({% slug programmaticcontrol_popover %})
1491
1163
  */
1492
- set popover(value) {
1493
- if (value instanceof PopoverComponent || typeof value === `function`) {
1494
- this._popover = value;
1495
- }
1496
- else {
1497
- if (isDevMode) {
1498
- throw new Error(ERRORS.popover);
1499
- }
1164
+ show() {
1165
+ if (this.popupRef) {
1166
+ return;
1500
1167
  }
1501
- }
1502
- get popover() {
1503
- return this._popover;
1168
+ this.ngZone.run(() => {
1169
+ this.openPopup(this.hostEl);
1170
+ });
1171
+ this.popupRef.popupAnchorViewportLeave
1172
+ .pipe(take(1))
1173
+ .subscribe(() => this.hide());
1504
1174
  }
1505
1175
  /**
1506
- * The event on which the Popover will be shown
1507
- *
1508
- * The supported values are:
1509
- * - `click` (default) &mdash;The Popover will be shown when its `anchor` element is clicked.
1510
- * - `hover`&mdash;The Popover will be shown when its `anchor` element is hovered.
1511
- * - `focus`&mdash;The Popover will be shown when its `anchor` element is focused.
1512
- * - `none`&mdash;The Popover will not be shown on user interaction. It could be rendered via the Popover API methods.
1176
+ * Toggles the visibility of the Popover. [See example]({% slug programmaticcontrol_popover %})
1513
1177
  */
1514
- set showOn(value) {
1515
- if (isDevMode && !containsItem(validShowOptions, value)) {
1516
- throw new Error(ERRORS.showOn);
1178
+ toggle() {
1179
+ if (this.popupRef) {
1180
+ this.hide();
1517
1181
  }
1518
- this._showOn = value;
1519
- }
1520
- get showOn() {
1521
- return this._showOn;
1522
- }
1523
- ngAfterViewInit() {
1524
- if (!isDocumentAvailable()) {
1525
- return;
1182
+ else {
1183
+ this.show();
1526
1184
  }
1527
- this.ngZone.runOutsideAngular(() => {
1528
- switch (this.showOn) {
1529
- case 'hover':
1530
- this.subscribeToShowEvents([{
1531
- name: 'mouseenter', handler: this.mouseenterHandler
1532
- }, {
1533
- name: 'mouseleave', handler: this.mouseleaveHandler
1534
- }]);
1535
- break;
1536
- case 'focus':
1537
- this.subscribeToShowEvents([{
1538
- name: 'focus', handler: this.focusHandler
1539
- }, {
1540
- name: 'blur', handler: this.blurHandler
1541
- }]);
1542
- break;
1543
- case 'click':
1544
- this.subscribeClick();
1545
- break;
1546
- default:
1547
- break;
1548
- }
1549
- });
1550
1185
  }
1551
- ngOnDestroy() {
1552
- this.closePopup();
1553
- this.subs.unsubscribe();
1554
- if (this.disposeHoverOverListener) {
1555
- this.disposeHoverOverListener();
1186
+ subscribeToShowEvents(arr) {
1187
+ const hostEl = this.hostEl.nativeElement;
1188
+ this.subs.add(this.renderer.listen(hostEl, arr[0].name, () => {
1189
+ this.popoverService.emitAnchorState(true, hostEl);
1190
+ arr[0].handler();
1191
+ }));
1192
+ this.subs.add(this.renderer.listen(hostEl, arr[1].name, (e) => {
1193
+ this.popoverService.emitAnchorState(false, null);
1194
+ arr[1].handler({ domEvent: e });
1195
+ }));
1196
+ }
1197
+ subscribeClick() {
1198
+ if (this.disposeClickListener) {
1199
+ this.disposeClickListener();
1556
1200
  }
1557
- if (this.disposeHoverOutListener) {
1558
- this.disposeHoverOutListener();
1201
+ this.disposeClickListener = this.renderer.listen(document, 'click', (e) => {
1202
+ this.onClick(e);
1203
+ });
1204
+ }
1205
+ /**
1206
+ * @hidden
1207
+ */
1208
+ onClick(event) {
1209
+ const isInsidePopup = !!closest(event.target, (node) => node.classList && node.classList.contains('k-popup'));
1210
+ const isAnchor = !!closest(event.target, (node) => node === this.hostEl.nativeElement);
1211
+ if (isInsidePopup || (this.popupRef && isAnchor)) {
1212
+ return;
1559
1213
  }
1560
- if (this.disposeClickListener) {
1561
- this.disposeClickListener();
1214
+ if (isAnchor) {
1215
+ // on opening
1216
+ this.controlVisibility(this.hostEl.nativeElement, true);
1562
1217
  }
1563
- if (this._focusInsideSub) {
1564
- this._focusInsideSub.unsubscribe();
1218
+ else {
1219
+ // on closing
1220
+ this.controlVisibility(this.hostEl.nativeElement, false);
1565
1221
  }
1566
- if (this._hideSub) {
1567
- this._hideSub.unsubscribe();
1222
+ }
1223
+ controlVisibility(anchor, show) {
1224
+ if (this.isPrevented(anchor, show)) {
1225
+ return;
1568
1226
  }
1569
- if (this._popupOpenSub) {
1570
- this._popupOpenSub.unsubscribe();
1227
+ if (show) {
1228
+ this.show();
1571
1229
  }
1572
- if (this._popupCloseSub) {
1573
- this._popupCloseSub.unsubscribe();
1230
+ else {
1231
+ this.hide();
1574
1232
  }
1575
1233
  }
1576
- /**
1577
- * Hides the Popover ([See example]({% slug programmaticcontrol_popover %})).
1578
- */
1579
- hide() {
1580
- this.closePopup();
1581
- }
1582
- /**
1583
- * @hidden
1584
- */
1585
- closePopup() {
1586
- if (this.popupRef) {
1587
- if (this.anchor) {
1588
- this.renderer.removeAttribute(this.anchor, 'aria-describedby');
1234
+ }
1235
+ PopoverAnchorDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverAnchorDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }, { token: PopoverService }], target: i0.ɵɵFactoryTarget.Directive });
1236
+ PopoverAnchorDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverAnchorDirective, isStandalone: true, selector: "[kendoPopoverAnchor]", providers: [PopoverService], exportAs: ["kendoPopoverAnchor"], usesInheritance: true, ngImport: i0 });
1237
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverAnchorDirective, decorators: [{
1238
+ type: Directive,
1239
+ args: [{
1240
+ selector: '[kendoPopoverAnchor]',
1241
+ exportAs: 'kendoPopoverAnchor',
1242
+ providers: [PopoverService],
1243
+ standalone: true
1244
+ }]
1245
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }, { type: PopoverService }]; } });
1246
+
1247
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1248
+ /**
1249
+ * Represents the [`kendoPopoverContainer`](slug:configuration_popover#toc-popover-container) directive.
1250
+ * It is used to filter and target multiple elements, which should display a popover on interaction.
1251
+ *
1252
+ * @example
1253
+ * ```ts-no-run
1254
+ * <div kendoPopoverContainer [popover]="myPopover" filter=".has-popover">
1255
+ * <button class="has-popover">Show Popover</button>
1256
+ * <button>Button Without Popover</button>
1257
+ * <button class="has-popover">Show Popover</button>
1258
+ * </div>
1259
+ * ```
1260
+ */
1261
+ class PopoverContainerDirective extends PopoverDirectivesBase {
1262
+ constructor(wrapperEl, ngZone, popupService, renderer, popoverService) {
1263
+ super(ngZone, popupService, renderer);
1264
+ this.wrapperEl = wrapperEl;
1265
+ this.ngZone = ngZone;
1266
+ this.popupService = popupService;
1267
+ this.renderer = renderer;
1268
+ this.popoverService = popoverService;
1269
+ this.mouseenterHandler = (anchor) => {
1270
+ this.controlVisibility(anchor, true);
1271
+ };
1272
+ this.mouseleaveHandler = (args) => {
1273
+ const anchor = args.anchor;
1274
+ if (this.isPrevented(anchor, false)) {
1275
+ return;
1589
1276
  }
1590
- this.popupRef.close();
1591
- this.popupRef = null;
1592
- if (this.disposePopupHoverOutListener) {
1593
- this.disposePopupHoverOutListener();
1277
+ if (!this._hideSub) {
1278
+ this._hideSub = this.popoverService.hidePopover.subscribe((val) => {
1279
+ const [isPopoverHovered, , isOriginAnchor, currentAnchor] = val;
1280
+ if (!isPopoverHovered && !isOriginAnchor) {
1281
+ this.hide();
1282
+ if (!isOriginAnchor && currentAnchor) {
1283
+ this.show(currentAnchor);
1284
+ }
1285
+ }
1286
+ });
1594
1287
  }
1595
- if (this.disposePopupHoverInListener) {
1596
- this.disposePopupHoverInListener();
1288
+ };
1289
+ this.focusHandler = (anchor) => {
1290
+ this.controlVisibility(anchor, true);
1291
+ };
1292
+ this.blurHandler = (args) => {
1293
+ const anchor = args.anchor;
1294
+ const event = args.domEvent;
1295
+ if (this.isPrevented(anchor, false)) {
1296
+ return;
1597
1297
  }
1598
- if (this.disposePopupFocusOutListener) {
1599
- this.disposePopupFocusOutListener();
1298
+ // from anchor to popup focus check
1299
+ const isFocusInside = !!closest(event.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
1300
+ if (!isFocusInside) {
1301
+ this.hide();
1600
1302
  }
1601
- }
1303
+ if (!this._focusInsideSub) {
1304
+ // inside popup focus check
1305
+ this._focusInsideSub = this.popoverService.isFocusInsidePopover.pipe(filter(v => v !== null)).subscribe((val) => {
1306
+ if (!val && !isFocusInside) {
1307
+ this.hide();
1308
+ }
1309
+ });
1310
+ }
1311
+ };
1312
+ this._popoverService = this.popoverService;
1602
1313
  }
1603
1314
  /**
1604
- * @hidden
1315
+ * Shows the Popover.
1316
+ *
1317
+ * @param anchor&mdash;Specifies the element that will be used as an anchor. The Popover opens relative to that element. [See example]({% slug programmaticcontrol_popover %})
1605
1318
  */
1606
- openPopup(anchor) {
1607
- this.anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor;
1608
- const popoverComp = this.popover instanceof PopoverComponent ? this.popover : this.popover(this.anchor);
1609
- const alignSettings = align(popoverComp.position, popoverComp.offset);
1610
- const anchorAlign = alignSettings.anchorAlign;
1611
- const popupAlign = alignSettings.popupAlign;
1612
- const popupMargin = alignSettings.popupMargin;
1613
- const _animation = popoverComp.animation;
1614
- this.popupRef = this.popupService.open({
1615
- anchor: { nativeElement: this.anchor },
1616
- animate: _animation,
1617
- content: PopoverComponent,
1618
- popupAlign,
1619
- anchorAlign,
1620
- margin: popupMargin,
1621
- popupClass: 'k-popup-transparent',
1622
- collision: { horizontal: 'fit', vertical: 'fit' }
1623
- });
1624
- const popupInstance = this.popupRef.content.instance;
1625
- if (anchor) {
1626
- this.subs.add(this.renderer.listen(this.anchor, 'keydown', event => this.onKeyDown(event)));
1627
- this.renderer.setAttribute(this.anchor, 'aria-describedby', popupInstance.popoverId);
1319
+ show(anchor) {
1320
+ if (this.popupRef) {
1321
+ return;
1628
1322
  }
1629
- this.subs.add(popupInstance.closeOnKeyDown.subscribe(() => {
1630
- this.anchor.focus();
1631
- this.hide();
1632
- }));
1633
- this.applySettings(this.popupRef.content, popoverComp);
1634
- this.monitorPopup();
1635
- this.initializeCompletionEvents(popoverComp, this.anchor);
1636
- }
1637
- /**
1638
- * @hidden
1639
- */
1640
- isPrevented(anchorElement, show) {
1641
- const popoverComp = this.popover instanceof PopoverComponent ? this.popover : this.popover(anchorElement);
1642
- let eventArgs;
1643
- // eslint-disable-next-line prefer-const
1644
- eventArgs = this.initializeEvents(popoverComp, eventArgs, show, anchorElement);
1645
- return eventArgs.isDefaultPrevented();
1323
+ this.ngZone.run(() => {
1324
+ this.openPopup(anchor);
1325
+ });
1326
+ this.popupRef.popupAnchorViewportLeave
1327
+ .pipe(take(1))
1328
+ .subscribe(() => this.hide());
1646
1329
  }
1647
1330
  /**
1648
- * @hidden
1331
+ * Toggles the visibility of the Popover. [See example]({% slug programmaticcontrol_popover %})
1332
+ *
1333
+ * @param anchor&mdash;Specifies the element that will be used as an anchor. The Popover opens relative to that element.
1649
1334
  */
1650
- monitorPopup() {
1651
- if (this.showOn === 'hover') {
1652
- this.ngZone.runOutsideAngular(() => {
1653
- const popup = this.popupRef.popupElement;
1654
- this.disposePopupHoverInListener = this.renderer.listen(popup, 'mouseenter', _ => {
1655
- this.ngZone.run(_ => this._popoverService.emitPopoverState(true));
1656
- });
1657
- this.disposePopupHoverOutListener = this.renderer.listen(popup, 'mouseleave', _ => {
1658
- this.ngZone.run(_ => this._popoverService.emitPopoverState(false));
1659
- });
1660
- });
1335
+ toggle(anchor) {
1336
+ const previousAnchor = this.popupRef && this.popupRef.content.instance.anchor;
1337
+ if (this.popupRef) {
1338
+ this.hide();
1339
+ if (previousAnchor !== anchor) {
1340
+ this.show(anchor);
1341
+ }
1661
1342
  }
1662
- if (this.showOn === 'focus') {
1663
- this.ngZone.runOutsideAngular(() => {
1664
- const popup = this.popupRef.popupElement;
1665
- this.disposePopupFocusOutListener = this.renderer.listen(popup, 'focusout', (e) => {
1666
- const isInsidePopover = closest(e.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
1667
- if (!isInsidePopover) {
1668
- this.ngZone.run(_ => this._popoverService.emitFocusInsidePopover(false));
1669
- }
1670
- });
1671
- });
1343
+ else {
1344
+ this.show(anchor);
1672
1345
  }
1673
1346
  }
1674
- applySettings(contentComponent, popover) {
1675
- const content = contentComponent.instance;
1676
- content.visible = true;
1677
- content.anchor = this.anchor;
1678
- content.position = popover.position;
1679
- content.offset = popover.offset;
1680
- content.width = popover.width;
1681
- content.height = popover.height;
1682
- content.title = popover.title;
1683
- content.body = popover.body;
1684
- content.callout = popover.callout;
1685
- content.animation = popover.animation;
1686
- content.contextData = popover.templateData(this.anchor);
1687
- content.titleTemplate = popover.titleTemplate;
1688
- content.bodyTemplate = popover.bodyTemplate;
1689
- content.actionsTemplate = popover.actionsTemplate;
1690
- this.popupRef.content.changeDetectorRef.detectChanges();
1347
+ subscribeClick() {
1348
+ if (this.disposeClickListener) {
1349
+ this.disposeClickListener();
1350
+ }
1351
+ this.disposeClickListener = this.renderer.listen(document, 'click', (e) => {
1352
+ const filterElement = closestBySelector(e.target, this.filter);
1353
+ this.clickHandler(filterElement, e);
1354
+ });
1355
+ }
1356
+ subscribeToShowEvents(arr) {
1357
+ const filteredElements = Array.from(document.querySelectorAll(this.filter));
1358
+ filteredElements.forEach((el) => {
1359
+ this.subs.add(this.renderer.listen(el, arr[0].name, () => {
1360
+ this.popoverService.emitAnchorState(true, el);
1361
+ arr[0].handler(el);
1362
+ }));
1363
+ this.subs.add(this.renderer.listen(el, arr[1].name, (e) => {
1364
+ this.popoverService.emitAnchorState(false, null);
1365
+ arr[1].handler({ anchor: el, domEvent: e });
1366
+ }));
1367
+ });
1368
+ }
1369
+ clickHandler(anchor, event) {
1370
+ const isInsidePopup = !!closest(event.target, (node) => node.classList && node.classList.contains('k-popup'));
1371
+ const popupRefAnchor = this.popupRef && this.popupRef.content.instance.anchor;
1372
+ const isOriginAnchor = !!closest(event.target, (node) => node === (popupRefAnchor ? popupRefAnchor : anchor));
1373
+ if (this.showOn !== 'click' || isInsidePopup || (this.popupRef && isOriginAnchor)) {
1374
+ return;
1375
+ }
1376
+ if (!anchor && this.popupRef) {
1377
+ this.controlVisibility(anchor, false);
1378
+ return;
1379
+ }
1380
+ if (isOriginAnchor) {
1381
+ this.controlVisibility(anchor, true);
1382
+ }
1383
+ else if (this.popupRef) {
1384
+ this.controlVisibility(anchor, false);
1385
+ this.controlVisibility(anchor, true);
1386
+ }
1691
1387
  }
1692
- /**
1693
- * @hidden
1694
- */
1695
- initializeEvents(popoverComp, eventArgs, show, anchorElement) {
1388
+ controlVisibility(anchor, show) {
1389
+ if (this.isPrevented(anchor, show)) {
1390
+ return;
1391
+ }
1696
1392
  if (show) {
1697
- eventArgs = new PopoverShowEvent(anchorElement);
1698
- if (this.shouldEmitEvent(!!this.popupRef, 'show', popoverComp)) {
1699
- this.ngZone.run(() => popoverComp.show.emit(eventArgs));
1700
- }
1393
+ this.show(anchor);
1701
1394
  }
1702
1395
  else {
1703
- eventArgs = new PopoverHideEvent(anchorElement, this.popupRef);
1704
- if (this.shouldEmitEvent(!!this.popupRef, 'hide', popoverComp)) {
1705
- this.ngZone.run(() => popoverComp.hide.emit(eventArgs));
1706
- }
1707
- }
1708
- return eventArgs;
1709
- }
1710
- onKeyDown(event) {
1711
- const keyCode = event.keyCode;
1712
- if (keyCode === Keys.Escape) {
1713
1396
  this.hide();
1714
1397
  }
1715
1398
  }
1716
- initializeCompletionEvents(popoverComp, _anchor) {
1717
- if (this.shouldEmitCompletionEvents('shown', popoverComp)) {
1718
- this.popupRef.popupOpen.subscribe(() => {
1719
- const eventArgs = new PopoverShownEvent(_anchor, this.popupRef);
1720
- popoverComp.shown.emit(eventArgs);
1721
- });
1722
- }
1723
- if (this.shouldEmitCompletionEvents('hidden', popoverComp)) {
1724
- this.popupRef.popupClose.subscribe(() => {
1725
- this.ngZone.run(_ => {
1726
- const eventArgs = new PopoverHiddenEvent(_anchor);
1727
- popoverComp.hidden.emit(eventArgs);
1728
- });
1729
- });
1730
- }
1399
+ }
1400
+ PopoverContainerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverContainerDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }, { token: PopoverService }], target: i0.ɵɵFactoryTarget.Directive });
1401
+ PopoverContainerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverContainerDirective, isStandalone: true, selector: "[kendoPopoverContainer]", inputs: { filter: "filter" }, providers: [PopoverService], exportAs: ["kendoPopoverContainer"], usesInheritance: true, ngImport: i0 });
1402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverContainerDirective, decorators: [{
1403
+ type: Directive,
1404
+ args: [{
1405
+ selector: '[kendoPopoverContainer]',
1406
+ exportAs: 'kendoPopoverContainer',
1407
+ providers: [PopoverService],
1408
+ standalone: true
1409
+ }]
1410
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }, { type: PopoverService }]; }, propDecorators: { filter: [{
1411
+ type: Input
1412
+ }] } });
1413
+
1414
+ /**
1415
+ * @hidden
1416
+ */
1417
+ class TooltipContentComponent {
1418
+ constructor(content, localizationService) {
1419
+ this.content = content;
1420
+ this.localizationService = localizationService;
1421
+ /**
1422
+ * @hidden
1423
+ */
1424
+ this.xIcon = xIcon;
1425
+ this.close = new EventEmitter();
1426
+ this.hostRole = 'tooltip';
1427
+ this.tooltipWidth = null;
1428
+ this.tooltipHeight = null;
1429
+ this.callout = true;
1430
+ this.calloutStyles = (position, calloutSize, isFlip) => {
1431
+ const styles = {};
1432
+ const isVertical = position === 'top' || position === 'bottom';
1433
+ const flipDeg = '180deg';
1434
+ const zeroDeg = '0deg';
1435
+ if (!isFlip) {
1436
+ styles.transform = isVertical ? `rotateX(${zeroDeg})` : `rotateY(${zeroDeg})`;
1437
+ return styles;
1438
+ }
1439
+ if (position === 'top') {
1440
+ styles.bottom = 'unset';
1441
+ }
1442
+ else if (position === 'bottom') {
1443
+ styles.top = 'unset';
1444
+ }
1445
+ else if (position === 'left') {
1446
+ styles.right = 'unset';
1447
+ }
1448
+ else if (position === 'right') {
1449
+ styles.left = 'unset';
1450
+ }
1451
+ styles[position] = `${-calloutSize}px`;
1452
+ styles.transform = isVertical ? `rotateX(${flipDeg})` : `rotateY(${flipDeg})`;
1453
+ return styles;
1454
+ };
1455
+ this.direction = localizationService.rtl ? 'rtl' : 'ltr';
1731
1456
  }
1732
- shouldEmitEvent(hasPopup, event, popoverComp) {
1733
- if ((event === 'show' && !hasPopup && hasObservers(popoverComp[event]))
1734
- || (event === 'hide' && hasPopup && hasObservers(popoverComp[event]))) {
1735
- return true;
1457
+ get cssClasses() {
1458
+ return 'k-tooltip';
1459
+ }
1460
+ get hostId() {
1461
+ return this.tooltipId;
1462
+ }
1463
+ get className() {
1464
+ return this.closable;
1465
+ }
1466
+ get cssPosition() {
1467
+ return 'relative';
1468
+ }
1469
+ ngOnInit() {
1470
+ this.tooltipId = getId('tooltip');
1471
+ this.dynamicRTLSubscription = this.localizationService.changes
1472
+ .subscribe(({ rtl }) => this.direction = rtl ? 'rtl' : 'ltr');
1473
+ }
1474
+ ngOnDestroy() {
1475
+ if (this.dynamicRTLSubscription) {
1476
+ this.dynamicRTLSubscription.unsubscribe();
1736
1477
  }
1737
- return false;
1738
1478
  }
1739
- shouldEmitCompletionEvents(event, popoverComp) {
1740
- if ((hasObservers(popoverComp[event]) && !this._popupOpenSub)
1741
- || (hasObservers(popoverComp[event]) && !this._popupCloseSub)) {
1742
- return true;
1479
+ get closeButtonTitle() {
1480
+ return this.closeTitle || this.localizationService.get('closeTitle');
1481
+ }
1482
+ calloutPositionClass() {
1483
+ return {
1484
+ 'top': 'k-callout-s',
1485
+ 'left': 'k-callout-e',
1486
+ 'bottom': 'k-callout-n',
1487
+ 'right': 'k-callout-w'
1488
+ }[this.position];
1489
+ }
1490
+ onCloseClick(event) {
1491
+ event.preventDefault();
1492
+ this.close.emit();
1493
+ }
1494
+ updateCalloutPosition(position, isFlip) {
1495
+ if (!this.callout) {
1496
+ return;
1743
1497
  }
1744
- return false;
1498
+ const callout = this.content.nativeElement.querySelector('.k-callout');
1499
+ const isVertical = position === 'top' || position === 'bottom';
1500
+ const size = isVertical ? 'width' : 'height';
1501
+ const dir = isVertical ? 'left' : 'top';
1502
+ const offsetProperty = isVertical ? 'marginLeft' : 'marginTop';
1503
+ const calloutSize = callout.getBoundingClientRect()[size];
1504
+ const anchorCenter = getCenterOffset(this.anchor.nativeElement, dir, size);
1505
+ const contentCenter = getCenterOffset(this.content.nativeElement, dir, size);
1506
+ const diff = Math.abs(contentCenter - anchorCenter);
1507
+ if (diff > 1 || diff === 0 || Math.round(diff) === 0) {
1508
+ const newMargin = contentCenter - anchorCenter + (calloutSize / 2);
1509
+ callout.style[offsetProperty] = `${-newMargin}px`;
1510
+ }
1511
+ const calloutStyles = this.calloutStyles(position, calloutSize, isFlip);
1512
+ Object.keys(calloutStyles).forEach((style) => {
1513
+ callout.style[style] = calloutStyles[style];
1514
+ });
1745
1515
  }
1746
1516
  }
1747
- PopoverDirectivesBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverDirectivesBase, deps: [{ token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
1748
- PopoverDirectivesBasedir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverDirectivesBase, inputs: { popover: "popover", showOn: "showOn" }, ngImport: i0 });
1749
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverDirectivesBase, decorators: [{
1750
- type: Directive,
1751
- args: [{}]
1752
- }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }]; }, propDecorators: { popover: [{
1517
+ TooltipContentComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipContentComponent, deps: [{ token: i0.ElementRef }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1518
+ TooltipContentComponentcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TooltipContentComponent, isStandalone: true, selector: "kendo-tooltip", inputs: { tooltipWidth: "tooltipWidth", tooltipHeight: "tooltipHeight", titleTemplate: "titleTemplate", anchor: "anchor", closable: "closable", templateRef: "templateRef", templateString: "templateString" }, outputs: { close: "close" }, host: { properties: { "attr.dir": "this.direction", "class": "this.cssClasses", "attr.role": "this.hostRole", "attr.id": "this.hostId", "class.k-tooltip-closable": "this.className", "style.position": "this.cssPosition", "style.width.px": "this.tooltipWidth", "style.height.px": "this.tooltipHeight" } }, providers: [
1519
+ LocalizationService,
1520
+ {
1521
+ provide: L10N_PREFIX,
1522
+ useValue: 'kendo.tooltip'
1523
+ }
1524
+ ], ngImport: i0, template: `
1525
+ <ng-container kendoTooltipLocalizedMessages
1526
+ i18n-closeTitle="kendo.tooltip.closeTitle|The title of the close button"
1527
+ closeTitle="Close"
1528
+ >
1529
+ </ng-container>
1530
+
1531
+ <div class="k-tooltip-content">
1532
+ <div class="k-tooltip-title" *ngIf="titleTemplate">
1533
+ <ng-template
1534
+ [ngIf]="titleTemplate"
1535
+ [ngTemplateOutlet]="titleTemplate"
1536
+ [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
1537
+ </ng-template>
1538
+ </div>
1539
+
1540
+ <ng-template
1541
+ [ngIf]="templateRef"
1542
+ [ngTemplateOutlet]="templateRef"
1543
+ [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
1544
+ </ng-template>
1545
+ <ng-template
1546
+ [ngIf]="templateString">
1547
+ {{ templateString }}
1548
+ </ng-template>
1549
+ </div>
1550
+
1551
+ <div *ngIf="closable" [attr.aria-hidden]="true" class="k-tooltip-button" (click)="onCloseClick($event)">
1552
+ <a href="#" [attr.title]="closeButtonTitle" class="k-icon">
1553
+ <kendo-icon-wrapper
1554
+ name="x"
1555
+ [svgIcon]="xIcon">
1556
+ </kendo-icon-wrapper>
1557
+ </a>
1558
+ </div>
1559
+
1560
+ <div class="k-callout" *ngIf="callout" [ngClass]="calloutPositionClass()"></div>
1561
+ `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoTooltipLocalizedMessages]", inputs: ["closeTitle"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipContentComponent, decorators: [{
1563
+ type: Component,
1564
+ args: [{
1565
+ selector: 'kendo-tooltip',
1566
+ template: `
1567
+ <ng-container kendoTooltipLocalizedMessages
1568
+ i18n-closeTitle="kendo.tooltip.closeTitle|The title of the close button"
1569
+ closeTitle="Close"
1570
+ >
1571
+ </ng-container>
1572
+
1573
+ <div class="k-tooltip-content">
1574
+ <div class="k-tooltip-title" *ngIf="titleTemplate">
1575
+ <ng-template
1576
+ [ngIf]="titleTemplate"
1577
+ [ngTemplateOutlet]="titleTemplate"
1578
+ [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
1579
+ </ng-template>
1580
+ </div>
1581
+
1582
+ <ng-template
1583
+ [ngIf]="templateRef"
1584
+ [ngTemplateOutlet]="templateRef"
1585
+ [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
1586
+ </ng-template>
1587
+ <ng-template
1588
+ [ngIf]="templateString">
1589
+ {{ templateString }}
1590
+ </ng-template>
1591
+ </div>
1592
+
1593
+ <div *ngIf="closable" [attr.aria-hidden]="true" class="k-tooltip-button" (click)="onCloseClick($event)">
1594
+ <a href="#" [attr.title]="closeButtonTitle" class="k-icon">
1595
+ <kendo-icon-wrapper
1596
+ name="x"
1597
+ [svgIcon]="xIcon">
1598
+ </kendo-icon-wrapper>
1599
+ </a>
1600
+ </div>
1601
+
1602
+ <div class="k-callout" *ngIf="callout" [ngClass]="calloutPositionClass()"></div>
1603
+ `,
1604
+ providers: [
1605
+ LocalizationService,
1606
+ {
1607
+ provide: L10N_PREFIX,
1608
+ useValue: 'kendo.tooltip'
1609
+ }
1610
+ ],
1611
+ standalone: true,
1612
+ imports: [LocalizedMessagesDirective, NgIf, NgTemplateOutlet, IconWrapperComponent, NgClass]
1613
+ }]
1614
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.LocalizationService }]; }, propDecorators: { direction: [{
1615
+ type: HostBinding,
1616
+ args: ['attr.dir']
1617
+ }], close: [{
1618
+ type: Output
1619
+ }], cssClasses: [{
1620
+ type: HostBinding,
1621
+ args: ['class']
1622
+ }], hostRole: [{
1623
+ type: HostBinding,
1624
+ args: ['attr.role']
1625
+ }], hostId: [{
1626
+ type: HostBinding,
1627
+ args: ['attr.id']
1628
+ }], className: [{
1629
+ type: HostBinding,
1630
+ args: ['class.k-tooltip-closable']
1631
+ }], cssPosition: [{
1632
+ type: HostBinding,
1633
+ args: ['style.position']
1634
+ }], tooltipWidth: [{
1635
+ type: HostBinding,
1636
+ args: ['style.width.px']
1637
+ }, {
1753
1638
  type: Input
1754
- }], showOn: [{
1639
+ }], tooltipHeight: [{
1640
+ type: HostBinding,
1641
+ args: ['style.height.px']
1642
+ }, {
1643
+ type: Input
1644
+ }], titleTemplate: [{
1645
+ type: Input
1646
+ }], anchor: [{
1647
+ type: Input
1648
+ }], closable: [{
1649
+ type: Input
1650
+ }], templateRef: [{
1651
+ type: Input
1652
+ }], templateString: [{
1755
1653
  type: Input
1756
1654
  }] } });
1757
1655
 
1758
1656
  /**
1657
+ * Obsolete. Provide the TooltipSettings class instead.
1658
+ *
1759
1659
  * @hidden
1760
1660
  */
1761
- class PopoverService {
1762
- constructor(ngZone) {
1763
- this.ngZone = ngZone;
1764
- this._pointerOverPopup = new BehaviorSubject(null);
1765
- this._pointerOverAnchor = new BehaviorSubject(null);
1766
- this._focusInsidePopover = new BehaviorSubject(null);
1767
- this._hidePopover = new Subject();
1768
- this.subs = new Subscription();
1769
- this.monitor();
1770
- }
1771
- ngOnDestroy() {
1772
- this.subs.unsubscribe();
1773
- }
1774
- get isPopoverHovered() {
1775
- return this._pointerOverPopup.asObservable();
1776
- }
1777
- emitPopoverState(isHovered) {
1778
- this.ngZone.run(_ => this._pointerOverPopup.next(isHovered));
1779
- }
1780
- get isAnchorHovered() {
1781
- return this._pointerOverAnchor.asObservable();
1782
- }
1783
- emitAnchorState(isHovered, anchor) {
1784
- this._isOrigin = this.originAnchor === anchor;
1785
- this.currentAnchor = anchor;
1786
- if (isHovered) {
1787
- this.originAnchor = anchor;
1788
- }
1789
- this.ngZone.run(_ => this._pointerOverAnchor.next(isHovered));
1790
- }
1791
- get isFocusInsidePopover() {
1792
- return this._focusInsidePopover.asObservable();
1793
- }
1794
- emitFocusInsidePopover(isFocused) {
1795
- this.ngZone.run(_ => this._focusInsidePopover.next(isFocused));
1796
- this._focusInsidePopover.next(null);
1797
- }
1798
- get hidePopover() {
1799
- return this._hidePopover.asObservable();
1800
- }
1801
- monitor() {
1802
- this.subs.add(combineLatest(this.isPopoverHovered, this.isAnchorHovered).pipe(
1803
- // `auditTime` is used because the `mouseleave` event is emitted before `mouseenter`
1804
- // i.e. there is a millisecond in which the pointer leaves the first target (e.g. anchor) and hasn't reached the second one (e.g. popup)
1805
- // resulting in both observables emitting `false`
1806
- auditTime(20)).subscribe(val => {
1807
- const [isPopoverHovered, isAnchorHovered] = val;
1808
- this._hidePopover.next([isPopoverHovered, isAnchorHovered, this._isOrigin, this.currentAnchor]);
1809
- }));
1810
- }
1661
+ const TOOLTIP_SETTINGS = new InjectionToken('kendo-ui-tooltip-settings');
1662
+ /**
1663
+ * Provides a global configuration for the Kendo UI Tooltip. Once injected through
1664
+ * the `AppComponent` constructor, the configuration properties can be overridden.
1665
+ *
1666
+ * @example
1667
+ * ```ts-no-run
1668
+ * import { TooltipSettings } from '@progress/kendo-angular-tooltip';
1669
+ *
1670
+ * _@Component({
1671
+ * selector: 'my-app',
1672
+ * template: `
1673
+ * <div kendoTooltip>
1674
+ * <button title="Saves the current document">Save</button>
1675
+ * </div>`,
1676
+ * providers: [{
1677
+ * provide: TooltipSettings,
1678
+ * useFactory: (): TooltipSettings => ({
1679
+ * // Override default values of tooltips if wanted
1680
+ * position: 'right'
1681
+ * })
1682
+ * }]
1683
+ * })
1684
+ * export class AppComponent { }
1685
+ * ```
1686
+ */
1687
+ class TooltipSettings {
1688
+ /**
1689
+ * @hidden
1690
+ */
1691
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1692
+ constructor() { }
1811
1693
  }
1812
- PopoverService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
1813
- PopoverService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverService });
1814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverService, decorators: [{
1694
+ TooltipSettings.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipSettings, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1695
+ TooltipSettings.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipSettings });
1696
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipSettings, decorators: [{
1815
1697
  type: Injectable
1816
- }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
1698
+ }], ctorParameters: function () { return []; } });
1817
1699
 
1818
- /* eslint-disable @typescript-eslint/no-explicit-any */
1819
1700
  /**
1820
- * Represents the [`kendoPopoverContainer`]({% slug configuration_popover %}#toc-containerdirective) directive.
1821
- * It is used to filter and target multiple elements, which should display a popover on interaction.
1701
+ * Represents the [Kendo UI Tooltip directive for Angular]({% slug overview_tooltip %}).
1702
+ * Used to display additional information that is related to an element.
1822
1703
  *
1823
1704
  * @example
1824
1705
  * ```ts-no-run
1825
- * <div kendoPopoverContainer [popover]="myPopover" filter=".has-popover">
1826
- * <button class="has-popover">Show Popover</button>
1827
- * <button>Button Without Popover</button>
1828
- * <button class="has-popover">Show Popover</button>
1706
+ * <div kendoTooltip>
1707
+ * <a title="Tooltip title" href="foo">foo</a>
1829
1708
  * </div>
1830
1709
  * ```
1831
1710
  */
1832
- class PopoverContainerDirective extends PopoverDirectivesBase {
1833
- constructor(wrapperEl, ngZone, popupService, renderer, popoverService) {
1834
- super(ngZone, popupService, renderer);
1835
- this.wrapperEl = wrapperEl;
1711
+ class TooltipDirective {
1712
+ constructor(tooltipWrapper, ngZone, renderer, popupService, settings, legacySettings) {
1713
+ this.tooltipWrapper = tooltipWrapper;
1836
1714
  this.ngZone = ngZone;
1837
- this.popupService = popupService;
1838
1715
  this.renderer = renderer;
1839
- this.popoverService = popoverService;
1840
- this.mouseenterHandler = (anchor) => {
1841
- this.controlVisibility(anchor, true);
1842
- };
1843
- this.mouseleaveHandler = (args) => {
1844
- const anchor = args.anchor;
1845
- if (this.isPrevented(anchor, false)) {
1846
- return;
1847
- }
1848
- if (!this._hideSub) {
1849
- this._hideSub = this.popoverService.hidePopover.subscribe((val) => {
1850
- const [isPopoverHovered, , isOriginAnchor, currentAnchor] = val;
1851
- if (!isPopoverHovered && !isOriginAnchor) {
1852
- this.hide();
1853
- if (!isOriginAnchor && currentAnchor) {
1854
- this.show(currentAnchor);
1855
- }
1856
- }
1857
- });
1858
- }
1859
- };
1860
- this.focusHandler = (anchor) => {
1861
- this.controlVisibility(anchor, true);
1862
- };
1863
- this.blurHandler = (args) => {
1864
- const anchor = args.anchor;
1865
- const event = args.domEvent;
1866
- if (this.isPrevented(anchor, false)) {
1716
+ this.popupService = popupService;
1717
+ /**
1718
+ * Specifies a selector for elements within a container which will display a tooltip
1719
+ * ([see example]({% slug anchorelements_tooltip %})). The possible values include any
1720
+ * DOM `selector`. The default value is `[title]`.
1721
+ */
1722
+ this.filter = '[title]';
1723
+ /**
1724
+ * Specifies the position of the Tooltip that is relative to the
1725
+ * anchor element ([see example]({% slug positioning_tooltip %})).
1726
+ *
1727
+ * The possible values are:
1728
+ * * `top` (default)
1729
+ * * `bottom`
1730
+ * * `left`
1731
+ * * `right`
1732
+ */
1733
+ this.position = 'top';
1734
+ /**
1735
+ * Specifies the delay in milliseconds before the Tooltip is shown.
1736
+ * * `100` (default) milliseconds.
1737
+ */
1738
+ this.showAfter = 100;
1739
+ /**
1740
+ * Specifies if the Тooltip will display a callout arrow.
1741
+ *
1742
+ * The possible values are:
1743
+ * * `true` (default)
1744
+ * * `false`
1745
+ */
1746
+ this.callout = true;
1747
+ /**
1748
+ * Specifies if the Тooltip will display a **Close** button
1749
+ * ([see example]({% slug closable_tooltip %})).
1750
+ *
1751
+ * The possible values are:
1752
+ * * `true`
1753
+ * * `false`
1754
+ */
1755
+ this.closable = false;
1756
+ /**
1757
+ * Specifies the offset in pixels between the Tooltip and the anchor. Defaults to `6` pixels.
1758
+ * If the `callout` property is set to `true`, the offset is rendered from the callout arrow.
1759
+ * If the `callout` property is set to `false`, the offset is rendered from the content of the Tooltip.
1760
+ */
1761
+ this.offset = 6;
1762
+ this.anchor = null;
1763
+ this.keyboardNavigationSubscription = new Subscription();
1764
+ this.validPositions = ['top', 'bottom', 'right', 'left'];
1765
+ this.validShowOptions = ['hover', 'click', 'none'];
1766
+ validatePackage(packageMetadata);
1767
+ Object.assign(this, settings, legacySettings);
1768
+ this.ngZone.runOutsideAngular(() => {
1769
+ const wrapper = this.tooltipWrapper.nativeElement;
1770
+ this.anchorTitleSubscription = fromEvent(wrapper, 'mouseover')
1771
+ .pipe(filter(() => this.filter !== ''))
1772
+ .subscribe((e) => {
1773
+ const filterElement = closestBySelector(e.target, this.filter);
1774
+ if (filterElement) {
1775
+ this.hideElementTitle({ nativeElement: filterElement });
1776
+ }
1777
+ });
1778
+ this.mouseOverSubscription = fromEvent(wrapper, 'mouseover')
1779
+ .pipe(filter(() => this.filter !== ''))
1780
+ .subscribe(e => this.onMouseOver(e));
1781
+ this.mouseOutSubscription = fromEvent(wrapper, 'mouseout')
1782
+ .subscribe(e => this.onMouseOut(e));
1783
+ });
1784
+ }
1785
+ /**
1786
+ * Sets the content of the Tooltip as a template reference
1787
+ * ([see example]({% slug templates_tooltip %})).
1788
+ */
1789
+ set tooltipTemplate(value) {
1790
+ this.template = value;
1791
+ }
1792
+ get tooltipTemplate() {
1793
+ return this.template;
1794
+ }
1795
+ /**
1796
+ * Shows the Tooltip.
1797
+ * @param anchor&mdash; ElementRef|Element.
1798
+ * Specifies the element that will be used as an anchor. The Tooltip opens relative to that element.
1799
+ */
1800
+ show(anchor) {
1801
+ if (this.popupRef) {
1802
+ return;
1803
+ }
1804
+ if (anchor instanceof Element) {
1805
+ anchor = { nativeElement: anchor };
1806
+ }
1807
+ this.anchor = anchor;
1808
+ if (this.showOn === 'hover') {
1809
+ if (this.popupRef) {
1867
1810
  return;
1868
1811
  }
1869
- // from anchor to popup focus check
1870
- const isFocusInside = !!closest(event.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
1871
- if (!isFocusInside) {
1872
- this.hide();
1873
- }
1874
- if (!this._focusInsideSub) {
1875
- // inside popup focus check
1876
- this._focusInsideSub = this.popoverService.isFocusInsidePopover.pipe(filter(v => v !== null)).subscribe((val) => {
1877
- if (!val && !isFocusInside) {
1878
- this.hide();
1879
- }
1880
- });
1812
+ clearTimeout(this.showTimeout);
1813
+ this.showTimeout = setTimeout(() => this.showContent(this.anchor), this.showAfter);
1814
+ }
1815
+ else {
1816
+ this.hideElementTitle(this.anchor);
1817
+ this.showContent(this.anchor);
1818
+ }
1819
+ }
1820
+ /**
1821
+ * Hides the Tooltip.
1822
+ */
1823
+ hide() {
1824
+ clearTimeout(this.showTimeout);
1825
+ const anchor = this.anchor && this.anchor.nativeElement;
1826
+ if (anchor && anchor.getAttribute('data-title')) {
1827
+ if (!anchor.getAttribute('title') && anchor.hasAttribute('title')) {
1828
+ anchor.setAttribute('title', anchor.getAttribute('data-title'));
1881
1829
  }
1882
- };
1883
- this._popoverService = this.popoverService;
1830
+ anchor.setAttribute('data-title', '');
1831
+ }
1832
+ if (this.popupMouseOutSubscription) {
1833
+ this.popupMouseOutSubscription.unsubscribe();
1834
+ }
1835
+ if (this.closeClickSubscription) {
1836
+ this.closeClickSubscription.unsubscribe();
1837
+ }
1838
+ this.closePopup();
1884
1839
  }
1885
1840
  /**
1886
- * Shows the Popover.
1841
+ * Toggle visibility of the Tooltip.
1887
1842
  *
1888
- * @param anchor&mdash;Specifies the element that will be used as an anchor. The Popover opens relative to that element. [See example]({% slug programmaticcontrol_popover %})
1843
+ * @param anchor&mdash; ElementRef|Element. Specifies the element that will be used as an anchor.
1844
+ * @param show&mdash; Optional. Boolean. Specifies if the Tooltip will be rendered.
1889
1845
  */
1890
- show(anchor) {
1891
- if (this.popupRef) {
1846
+ toggle(anchor, show) {
1847
+ const previousAnchor = this.anchor && this.anchor.nativeElement;
1848
+ if (anchor instanceof Element) {
1849
+ anchor = { nativeElement: anchor };
1850
+ }
1851
+ if (previousAnchor !== anchor.nativeElement) {
1852
+ this.hide();
1853
+ }
1854
+ if (previousAnchor === anchor.nativeElement && this.showOn === 'click') {
1855
+ this.hide();
1856
+ }
1857
+ if (typeof show === 'undefined') {
1858
+ show = !this.popupRef;
1859
+ }
1860
+ if (show) {
1861
+ this.show(anchor);
1862
+ }
1863
+ else {
1864
+ this.hide();
1865
+ }
1866
+ }
1867
+ ngOnInit() {
1868
+ if (this.showOn === undefined) {
1869
+ this.showOn = 'hover';
1870
+ }
1871
+ this.keyboardNavigationSubscription.add(this.renderer.listen(this.tooltipWrapper.nativeElement, 'keydown', event => this.onKeyDown(event)));
1872
+ this.verifyProperties();
1873
+ }
1874
+ ngOnChanges(changes) {
1875
+ if (changes.showOn && isDocumentAvailable()) {
1876
+ this.subscribeClick();
1877
+ }
1878
+ }
1879
+ ngAfterViewChecked() {
1880
+ if (!this.popupRef) {
1881
+ return;
1882
+ }
1883
+ if (this.anchor &&
1884
+ !hasParent(this.anchor.nativeElement || this.anchor, this.tooltipWrapper.nativeElement)) {
1885
+ this.anchor = null;
1886
+ this.hide();
1887
+ }
1888
+ }
1889
+ ngOnDestroy() {
1890
+ this.hide();
1891
+ this.template = null;
1892
+ this.anchorTitleSubscription.unsubscribe();
1893
+ this.mouseOverSubscription.unsubscribe();
1894
+ this.mouseOutSubscription.unsubscribe();
1895
+ this.keyboardNavigationSubscription.unsubscribe();
1896
+ if (this.mouseClickSubscription) {
1897
+ this.mouseClickSubscription.unsubscribe();
1898
+ }
1899
+ if (this.popupPositionChangeSubscription) {
1900
+ this.popupPositionChangeSubscription.unsubscribe();
1901
+ }
1902
+ if (this.popupMouseOutSubscription) {
1903
+ this.popupMouseOutSubscription.unsubscribe();
1904
+ }
1905
+ }
1906
+ showContent(anchorRef) {
1907
+ if (!anchorRef.nativeElement.getAttribute('data-title') && !this.template) {
1892
1908
  return;
1893
1909
  }
1894
1910
  this.ngZone.run(() => {
1895
- this.openPopup(anchor);
1911
+ this.openPopup(anchorRef);
1912
+ this.bindContent(this.popupRef.content, anchorRef);
1896
1913
  });
1897
1914
  this.popupRef.popupAnchorViewportLeave
1898
1915
  .pipe(take(1))
1899
1916
  .subscribe(() => this.hide());
1900
1917
  }
1901
- /**
1902
- * Toggles the visibility of the Popover. [See example]({% slug programmaticcontrol_popover %})
1903
- *
1904
- * @param anchor&mdash;Specifies the element that will be used as an anchor. The Popover opens relative to that element.
1905
- */
1906
- toggle(anchor) {
1907
- const previousAnchor = this.popupRef && this.popupRef.content.instance.anchor;
1908
- if (this.popupRef) {
1918
+ bindContent(contentComponent, anchorRef) {
1919
+ const content = contentComponent.instance;
1920
+ this.closeClickSubscription = content.close
1921
+ .subscribe(() => {
1909
1922
  this.hide();
1910
- if (previousAnchor !== anchor) {
1911
- this.show(anchor);
1912
- }
1923
+ });
1924
+ if (!this.template) {
1925
+ content.templateString = this.anchor.nativeElement.getAttribute('data-title');
1913
1926
  }
1914
1927
  else {
1915
- this.show(anchor);
1928
+ content.templateRef = this.template;
1929
+ }
1930
+ if (this.titleTemplate) {
1931
+ content.titleTemplate = this.titleTemplate;
1916
1932
  }
1933
+ content.closeTitle = this.closeTitle;
1934
+ content.anchor = anchorRef;
1935
+ content.callout = this.callout;
1936
+ content.closable = this.closable;
1937
+ content.position = this.position;
1938
+ content.tooltipWidth = this.tooltipWidth;
1939
+ content.tooltipHeight = this.tooltipHeight;
1940
+ this.popupRef.content.changeDetectorRef.detectChanges();
1917
1941
  }
1918
- subscribeClick() {
1919
- if (this.disposeClickListener) {
1920
- this.disposeClickListener();
1942
+ hideElementTitle(elementRef) {
1943
+ const element = elementRef.nativeElement;
1944
+ if (element.getAttribute('title')) {
1945
+ element.setAttribute('data-title', element.getAttribute('title'));
1946
+ element.setAttribute('title', '');
1921
1947
  }
1922
- this.disposeClickListener = this.renderer.listen(document, 'click', (e) => {
1923
- const filterElement = closestBySelector(e.target, this.filter);
1924
- this.clickHandler(filterElement, e);
1925
- });
1926
1948
  }
1927
- subscribeToShowEvents(arr) {
1928
- const filteredElements = Array.from(document.querySelectorAll(this.filter));
1929
- filteredElements.forEach((el) => {
1930
- this.subs.add(this.renderer.listen(el, arr[0].name, () => {
1931
- this.popoverService.emitAnchorState(true, el);
1932
- arr[0].handler(el);
1933
- }));
1934
- this.subs.add(this.renderer.listen(el, arr[1].name, (e) => {
1935
- this.popoverService.emitAnchorState(false, null);
1936
- arr[1].handler({ anchor: el, domEvent: e });
1937
- }));
1949
+ openPopup(anchorRef) {
1950
+ const alignSettings = align(this.position, this.offset);
1951
+ const anchorAlign = alignSettings.anchorAlign;
1952
+ const popupAlign = alignSettings.popupAlign;
1953
+ const popupMargin = alignSettings.popupMargin;
1954
+ this.popupRef = this.popupService.open({
1955
+ anchor: anchorRef,
1956
+ anchorAlign,
1957
+ animate: false,
1958
+ content: TooltipContentComponent,
1959
+ collision: collision(this.collision, this.position),
1960
+ margin: popupMargin,
1961
+ popupAlign,
1962
+ popupClass: 'k-popup-transparent'
1938
1963
  });
1939
- }
1940
- clickHandler(anchor, event) {
1941
- const isInsidePopup = !!closest(event.target, (node) => node.classList && node.classList.contains('k-popup'));
1942
- const popupRefAnchor = this.popupRef && this.popupRef.content.instance.anchor;
1943
- const isOriginAnchor = !!closest(event.target, (node) => node === (popupRefAnchor ? popupRefAnchor : anchor));
1944
- if (this.showOn !== 'click' || isInsidePopup || (this.popupRef && isOriginAnchor)) {
1945
- return;
1964
+ if (this.tooltipClass) {
1965
+ this.renderer.addClass(this.popupRef.popupElement, this.tooltipClass);
1946
1966
  }
1947
- if (!anchor && this.popupRef) {
1948
- this.controlVisibility(anchor, false);
1949
- return;
1967
+ if (this.tooltipContentClass) {
1968
+ this.renderer.addClass(this.popupRef.content.instance['content'].nativeElement, this.tooltipContentClass);
1950
1969
  }
1951
- if (isOriginAnchor) {
1952
- this.controlVisibility(anchor, true);
1970
+ const popupInstance = this.popupRef.content.instance;
1971
+ if (anchorRef) {
1972
+ this.renderer.setAttribute(anchorRef.nativeElement, 'aria-labelledby', popupInstance.tooltipId);
1953
1973
  }
1954
- else if (this.popupRef) {
1955
- this.controlVisibility(anchor, false);
1956
- this.controlVisibility(anchor, true);
1974
+ if (popupInstance.callout) {
1975
+ this.popupPositionChangeSubscription = this.popupRef.popupPositionChange
1976
+ .subscribe(({ flip }) => {
1977
+ const isFlip = flip.horizontal === true || flip.vertical === true;
1978
+ popupInstance.updateCalloutPosition(this.position, isFlip);
1979
+ });
1980
+ }
1981
+ if (this.showOn === 'hover') {
1982
+ this.ngZone.runOutsideAngular(() => {
1983
+ const popup = this.popupRef.popupElement;
1984
+ this.popupMouseOutSubscription = fromEvent(popup, 'mouseout')
1985
+ .subscribe((e) => this.onMouseOut(e));
1986
+ });
1957
1987
  }
1958
1988
  }
1959
- controlVisibility(anchor, show) {
1960
- if (this.isPrevented(anchor, show)) {
1961
- return;
1989
+ closePopup() {
1990
+ if (this.popupRef) {
1991
+ if (this.anchor) {
1992
+ this.renderer.removeAttribute(this.anchor.nativeElement, 'aria-labelledby');
1993
+ }
1994
+ this.popupRef.close();
1995
+ this.popupRef = null;
1996
+ }
1997
+ if (this.popupPositionChangeSubscription) {
1998
+ this.popupPositionChangeSubscription.unsubscribe();
1962
1999
  }
1963
- if (show) {
1964
- this.show(anchor);
2000
+ }
2001
+ subscribeClick() {
2002
+ if (this.mouseClickSubscription) {
2003
+ this.mouseClickSubscription.unsubscribe();
1965
2004
  }
1966
- else {
1967
- this.hide();
2005
+ if (this.showOn === 'click') {
2006
+ this.mouseClickSubscription = fromEvent(document, 'click')
2007
+ .pipe(filter(() => this.filter !== ''))
2008
+ .subscribe(e => this.onMouseClick(e, this.tooltipWrapper.nativeElement));
1968
2009
  }
1969
2010
  }
1970
- }
1971
- PopoverContainerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverContainerDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }, { token: PopoverService }], target: i0.ɵɵFactoryTarget.Directive });
1972
- PopoverContainerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverContainerDirective, selector: "[kendoPopoverContainer]", inputs: { filter: "filter" }, providers: [PopoverService], exportAs: ["kendoPopoverContainer"], usesInheritance: true, ngImport: i0 });
1973
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverContainerDirective, decorators: [{
1974
- type: Directive,
1975
- args: [{
1976
- selector: '[kendoPopoverContainer]',
1977
- exportAs: 'kendoPopoverContainer',
1978
- providers: [PopoverService]
1979
- }]
1980
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }, { type: PopoverService }]; }, propDecorators: { filter: [{
1981
- type: Input
1982
- }] } });
1983
-
1984
- /* eslint-disable @typescript-eslint/no-explicit-any */
1985
- /**
1986
- * Represents the [`kendoPopoverAnchor`]({% slug configuration_popover %}#toc-anchordirective) directive.
1987
- * It is used to target an element, which should display a popover on interaction.
1988
- *
1989
- * @example
1990
- * ```ts-no-run
1991
- * <button kendoPopoverAnchor [popover]="myPopover">Show Popover</button>
1992
- * ```
1993
- */
1994
- class PopoverAnchorDirective extends PopoverDirectivesBase {
1995
- constructor(hostEl, ngZone, popupService, renderer, popoverService) {
1996
- super(ngZone, popupService, renderer);
1997
- this.hostEl = hostEl;
1998
- this.ngZone = ngZone;
1999
- this.popupService = popupService;
2000
- this.renderer = renderer;
2001
- this.popoverService = popoverService;
2002
- this.mouseenterHandler = () => {
2003
- this.controlVisibility(this.hostEl.nativeElement, true);
2004
- };
2005
- this.mouseleaveHandler = () => {
2006
- if (this.isPrevented(this.hostEl.nativeElement, false)) {
2011
+ onMouseClick(e, wrapper) {
2012
+ const target = e.target;
2013
+ const filterElement = closestBySelector(target, this.filter);
2014
+ const popup = this.popupRef && this.popupRef.popupElement;
2015
+ if (popup) {
2016
+ if (popup.contains(target)) {
2007
2017
  return;
2008
2018
  }
2009
- if (!this._hideSub) {
2010
- this._hideSub = this.popoverService.hidePopover.subscribe((val) => {
2011
- const [isPopoverHovered, isAnchorHovered] = val;
2012
- if (!isPopoverHovered && !isAnchorHovered) {
2013
- this.hide();
2014
- }
2015
- });
2016
- }
2017
- };
2018
- this.focusHandler = () => {
2019
- this.controlVisibility(this.hostEl.nativeElement, true);
2020
- };
2021
- this.blurHandler = (args) => {
2022
- const event = args.domEvent;
2023
- if (this.isPrevented(this.hostEl.nativeElement, false)) {
2019
+ if (this.closable) {
2024
2020
  return;
2025
2021
  }
2026
- // from anchor to popup focus check
2027
- const isFocusInside = !!closest(event.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
2028
- if (!isFocusInside) {
2029
- this.hide();
2030
- }
2031
- if (!this._focusInsideSub) {
2032
- // inside popup focus check
2033
- this._focusInsideSub = this.popoverService.isFocusInsidePopover.pipe(filter(v => v !== null)).subscribe((val) => {
2034
- if (!val) {
2035
- this.hide();
2036
- }
2037
- });
2038
- }
2039
- };
2040
- this._popoverService = this.popoverService;
2041
- }
2042
- /**
2043
- * Shows the Popover. [See example]({% slug programmaticcontrol_popover %})
2044
- */
2045
- show() {
2046
- if (this.popupRef) {
2047
- return;
2048
2022
  }
2049
- this.ngZone.run(() => {
2050
- this.openPopup(this.hostEl);
2051
- });
2052
- this.popupRef.popupAnchorViewportLeave
2053
- .pipe(take(1))
2054
- .subscribe(() => this.hide());
2055
- }
2056
- /**
2057
- * Toggles the visibility of the Popover. [See example]({% slug programmaticcontrol_popover %})
2058
- */
2059
- toggle() {
2060
- if (this.popupRef) {
2023
+ if (wrapper.contains(target) && filterElement) {
2024
+ this.toggle(filterElement, true);
2025
+ }
2026
+ else if (popup) {
2061
2027
  this.hide();
2062
2028
  }
2063
- else {
2064
- this.show();
2029
+ }
2030
+ onKeyDown(event) {
2031
+ const keyCode = event.keyCode;
2032
+ const target = event.target;
2033
+ if (this.popupRef) {
2034
+ const tooltipId = this.popupRef.content.location.nativeElement.getAttribute('id');
2035
+ const anchorLabelledBy = target.getAttribute('aria-labelledby');
2036
+ if (keyCode === Keys.Escape && this.canCloseTooltip(target, tooltipId, anchorLabelledBy)) {
2037
+ this.closePopup();
2038
+ }
2065
2039
  }
2066
2040
  }
2067
- subscribeToShowEvents(arr) {
2068
- const hostEl = this.hostEl.nativeElement;
2069
- this.subs.add(this.renderer.listen(hostEl, arr[0].name, () => {
2070
- this.popoverService.emitAnchorState(true, hostEl);
2071
- arr[0].handler();
2072
- }));
2073
- this.subs.add(this.renderer.listen(hostEl, arr[1].name, (e) => {
2074
- this.popoverService.emitAnchorState(false, null);
2075
- arr[1].handler({ domEvent: e });
2076
- }));
2041
+ canCloseTooltip(target, tooltipId, anchorLabelledBy) {
2042
+ const isIdEqualsLabel = tooltipId === anchorLabelledBy;
2043
+ const filterElement = closestBySelector(target, this.filter);
2044
+ const isTargetFocused = target === document.activeElement;
2045
+ const isTargetInsideWrapper = this.tooltipWrapper.nativeElement.contains(target);
2046
+ return isTargetInsideWrapper && filterElement && isTargetFocused && isIdEqualsLabel;
2077
2047
  }
2078
- subscribeClick() {
2079
- if (this.disposeClickListener) {
2080
- this.disposeClickListener();
2048
+ onMouseOver(e) {
2049
+ const filterElement = closestBySelector(e.target, this.filter);
2050
+ if (this.showOn !== 'hover') {
2051
+ return;
2052
+ }
2053
+ if (filterElement) {
2054
+ this.toggle(filterElement, true);
2081
2055
  }
2082
- this.disposeClickListener = this.renderer.listen(document, 'click', (e) => {
2083
- this.onClick(e);
2084
- });
2085
2056
  }
2086
- /**
2087
- * @hidden
2088
- */
2089
- onClick(event) {
2090
- const isInsidePopup = !!closest(event.target, (node) => node.classList && node.classList.contains('k-popup'));
2091
- const isAnchor = !!closest(event.target, (node) => node === this.hostEl.nativeElement);
2092
- if (isInsidePopup || (this.popupRef && isAnchor)) {
2057
+ onMouseOut(e) {
2058
+ if (this.showOn !== 'hover') {
2093
2059
  return;
2094
2060
  }
2095
- if (isAnchor) {
2096
- // on opening
2097
- this.controlVisibility(this.hostEl.nativeElement, true);
2061
+ if (this.closable) {
2062
+ return;
2098
2063
  }
2099
- else {
2100
- // on closing
2101
- this.controlVisibility(this.hostEl.nativeElement, false);
2064
+ const popup = this.popupRef && this.popupRef.popupElement;
2065
+ const relatedTarget = e.relatedTarget;
2066
+ if (relatedTarget && this.anchor && contains(this.anchor.nativeElement, relatedTarget)) {
2067
+ return;
2068
+ }
2069
+ if (relatedTarget && contains(popup, relatedTarget)) {
2070
+ return;
2102
2071
  }
2072
+ this.hide();
2103
2073
  }
2104
- controlVisibility(anchor, show) {
2105
- if (this.isPrevented(anchor, show)) {
2074
+ verifyProperties() {
2075
+ if (!isDevMode()) {
2106
2076
  return;
2107
2077
  }
2108
- if (show) {
2109
- this.show();
2078
+ if (!containsItem(this.validPositions, this.position)) {
2079
+ throw new Error(`Invalid value provided for position property.The available options are 'top', 'bottom', 'left', or 'right'.`);
2110
2080
  }
2111
- else {
2112
- this.hide();
2081
+ if (!containsItem(this.validShowOptions, this.showOn)) {
2082
+ throw new Error(`Invalid value provided for showOn property.The available options are 'hover' or 'none'.`);
2113
2083
  }
2114
2084
  }
2115
2085
  }
2116
- PopoverAnchorDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverAnchorDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }, { token: PopoverService }], target: i0.ɵɵFactoryTarget.Directive });
2117
- PopoverAnchorDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: PopoverAnchorDirective, selector: "[kendoPopoverAnchor]", providers: [PopoverService], exportAs: ["kendoPopoverAnchor"], usesInheritance: true, ngImport: i0 });
2118
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverAnchorDirective, decorators: [{
2086
+ TooltipDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i1$1.PopupService }, { token: TooltipSettings, optional: true }, { token: TOOLTIP_SETTINGS, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2087
+ TooltipDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: TooltipDirective, isStandalone: true, selector: "[kendoTooltip]", inputs: { filter: "filter", position: "position", titleTemplate: "titleTemplate", showOn: "showOn", showAfter: "showAfter", callout: "callout", closable: "closable", offset: "offset", tooltipWidth: "tooltipWidth", tooltipHeight: "tooltipHeight", tooltipClass: "tooltipClass", tooltipContentClass: "tooltipContentClass", collision: "collision", closeTitle: "closeTitle", tooltipTemplate: "tooltipTemplate" }, exportAs: ["kendoTooltip"], usesOnChanges: true, ngImport: i0 });
2088
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipDirective, decorators: [{
2119
2089
  type: Directive,
2120
2090
  args: [{
2121
- selector: '[kendoPopoverAnchor]',
2122
- exportAs: 'kendoPopoverAnchor',
2123
- providers: [PopoverService]
2091
+ selector: '[kendoTooltip]',
2092
+ exportAs: 'kendoTooltip',
2093
+ standalone: true
2124
2094
  }]
2125
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }, { type: PopoverService }]; } });
2095
+ }], ctorParameters: function () {
2096
+ return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i1$1.PopupService }, { type: TooltipSettings, decorators: [{
2097
+ type: Optional
2098
+ }] }, { type: TooltipSettings, decorators: [{
2099
+ type: Optional
2100
+ }, {
2101
+ type: Inject,
2102
+ args: [TOOLTIP_SETTINGS]
2103
+ }] }];
2104
+ }, propDecorators: { filter: [{
2105
+ type: Input
2106
+ }], position: [{
2107
+ type: Input
2108
+ }], titleTemplate: [{
2109
+ type: Input
2110
+ }], showOn: [{
2111
+ type: Input
2112
+ }], showAfter: [{
2113
+ type: Input
2114
+ }], callout: [{
2115
+ type: Input
2116
+ }], closable: [{
2117
+ type: Input
2118
+ }], offset: [{
2119
+ type: Input
2120
+ }], tooltipWidth: [{
2121
+ type: Input
2122
+ }], tooltipHeight: [{
2123
+ type: Input
2124
+ }], tooltipClass: [{
2125
+ type: Input
2126
+ }], tooltipContentClass: [{
2127
+ type: Input
2128
+ }], collision: [{
2129
+ type: Input
2130
+ }], closeTitle: [{
2131
+ type: Input
2132
+ }], tooltipTemplate: [{
2133
+ type: Input
2134
+ }] } });
2135
+
2136
+ /**
2137
+ * Utility array that contains all `Tooltip` related components and directives
2138
+ */
2139
+ const KENDO_TOOLTIP = [
2140
+ TooltipDirective,
2141
+ TooltipContentComponent,
2142
+ LocalizedMessagesDirective
2143
+ ];
2144
+ /**
2145
+ * Utility array that contains all `Popover` related components and directives
2146
+ */
2147
+ const KENDO_POPOVER = [
2148
+ PopoverComponent,
2149
+ PopoverActionsTemplateDirective,
2150
+ PopoverBodyTemplateDirective,
2151
+ PopoverTitleTemplateDirective,
2152
+ PopoverAnchorDirective,
2153
+ PopoverContainerDirective
2154
+ ];
2155
+ /**
2156
+ * Utility array that contains all `@progress/kendo-angular-tooltip` related components and directives
2157
+ */
2158
+ const KENDO_TOOLTIPS = [
2159
+ ...KENDO_TOOLTIP,
2160
+ ...KENDO_POPOVER
2161
+ ];
2126
2162
 
2127
- const COMPONENT_DIRECTIVES = [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective];
2128
- const COMPONENT_MODULES = [PopupModule, IconsModule];
2163
+ // IMPORTANT: NgModule export kept for backwards compatibility
2129
2164
  /**
2130
2165
  * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
2131
2166
  * definition for the Tooltip component.
@@ -2159,25 +2194,19 @@ const COMPONENT_MODULES = [PopupModule, IconsModule];
2159
2194
  class TooltipModule {
2160
2195
  }
2161
2196
  TooltipModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2162
- TooltipModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: TooltipModule, declarations: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective], imports: [CommonModule, PopupModule, IconsModule], exports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective] });
2163
- TooltipModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipModule, imports: [CommonModule, COMPONENT_MODULES] });
2197
+ TooltipModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: TooltipModule, imports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective], exports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective] });
2198
+ TooltipModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipModule, providers: [PopupService, ResizeBatchService, IconsService], imports: [TooltipContentComponent] });
2164
2199
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipModule, decorators: [{
2165
2200
  type: NgModule,
2166
2201
  args: [{
2167
- declarations: [COMPONENT_DIRECTIVES],
2168
2202
  entryComponents: [TooltipContentComponent],
2169
- imports: [CommonModule, ...COMPONENT_MODULES],
2170
- exports: [COMPONENT_DIRECTIVES]
2203
+ imports: [...KENDO_TOOLTIP],
2204
+ exports: [...KENDO_TOOLTIP],
2205
+ providers: [PopupService, ResizeBatchService, IconsService]
2171
2206
  }]
2172
2207
  }] });
2173
2208
 
2174
- const DIRECTIVES = [
2175
- PopoverActionsTemplateDirective,
2176
- PopoverBodyTemplateDirective,
2177
- PopoverTitleTemplateDirective,
2178
- PopoverAnchorDirective,
2179
- PopoverContainerDirective
2180
- ];
2209
+ // IMPORTANT: NgModule export kept for backwards compatibility
2181
2210
  /**
2182
2211
  * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
2183
2212
  * definition for the Popover component.
@@ -2206,34 +2235,19 @@ const DIRECTIVES = [
2206
2235
  class PopoverModule {
2207
2236
  }
2208
2237
  PopoverModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2209
- PopoverModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: PopoverModule, declarations: [PopoverActionsTemplateDirective,
2210
- PopoverBodyTemplateDirective,
2211
- PopoverTitleTemplateDirective,
2212
- PopoverAnchorDirective,
2213
- PopoverContainerDirective, PopoverComponent], imports: [CommonModule,
2214
- PopupModule], exports: [PopoverActionsTemplateDirective,
2215
- PopoverBodyTemplateDirective,
2216
- PopoverTitleTemplateDirective,
2217
- PopoverAnchorDirective,
2218
- PopoverContainerDirective, PopoverComponent] });
2219
- PopoverModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverModule, imports: [CommonModule,
2220
- PopupModule] });
2238
+ PopoverModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: PopoverModule, imports: [PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective], exports: [PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective] });
2239
+ PopoverModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverModule, providers: [PopupService, ResizeBatchService], imports: [PopoverComponent] });
2221
2240
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopoverModule, decorators: [{
2222
2241
  type: NgModule,
2223
2242
  args: [{
2224
- declarations: [
2225
- ...DIRECTIVES,
2226
- PopoverComponent
2227
- ],
2228
2243
  entryComponents: [PopoverComponent],
2229
- exports: [...DIRECTIVES, PopoverComponent],
2230
- imports: [
2231
- CommonModule,
2232
- PopupModule
2233
- ]
2244
+ exports: [...KENDO_POPOVER],
2245
+ imports: [...KENDO_POPOVER],
2246
+ providers: [PopupService, ResizeBatchService]
2234
2247
  }]
2235
2248
  }] });
2236
2249
 
2250
+ // IMPORTANT: NgModule export kept for backwards compatibility
2237
2251
  /**
2238
2252
  * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
2239
2253
  * definition for the Tooltips components.
@@ -2263,20 +2277,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
2263
2277
  class TooltipsModule {
2264
2278
  }
2265
2279
  TooltipsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2266
- TooltipsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: TooltipsModule, exports: [TooltipModule, PopoverModule] });
2267
- TooltipsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipsModule, imports: [TooltipModule, PopoverModule] });
2280
+ TooltipsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: TooltipsModule, imports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective, PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective], exports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective, PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective] });
2281
+ TooltipsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipsModule, providers: [PopupService, ResizeBatchService, IconsService], imports: [TooltipContentComponent, PopoverComponent] });
2268
2282
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TooltipsModule, decorators: [{
2269
2283
  type: NgModule,
2270
2284
  args: [{
2271
- exports: [TooltipModule, PopoverModule]
2285
+ imports: [...KENDO_TOOLTIPS],
2286
+ exports: [...KENDO_TOOLTIPS],
2287
+ providers: [PopupService, ResizeBatchService, IconsService]
2272
2288
  }]
2273
2289
  }] });
2274
2290
 
2275
- // Tooltip
2291
+ // Standalone Directives Arrays
2276
2292
 
2277
2293
  /**
2278
2294
  * Generated bundle index. Do not edit.
2279
2295
  */
2280
2296
 
2281
- export { LocalizedMessagesDirective, PopoverActionsTemplateDirective, PopoverAnchorDirective, PopoverBodyTemplateDirective, PopoverComponent, PopoverContainerDirective, PopoverHiddenEvent, PopoverHideEvent, PopoverModule, PopoverShowEvent, PopoverShownEvent, PopoverTitleTemplateDirective, TOOLTIP_SETTINGS, TooltipContentComponent, TooltipDirective, TooltipModule, TooltipSettings, TooltipsModule };
2297
+ export { KENDO_POPOVER, KENDO_TOOLTIP, KENDO_TOOLTIPS, LocalizedMessagesDirective, PopoverActionsTemplateDirective, PopoverAnchorDirective, PopoverBodyTemplateDirective, PopoverComponent, PopoverContainerDirective, PopoverHiddenEvent, PopoverHideEvent, PopoverModule, PopoverShowEvent, PopoverShownEvent, PopoverTitleTemplateDirective, TOOLTIP_SETTINGS, TooltipContentComponent, TooltipDirective, TooltipModule, TooltipSettings, TooltipsModule };
2282
2298