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

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