@progress/kendo-angular-popup 17.0.0-develop.9 → 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/{esm2020 → esm2022}/package-metadata.mjs +2 -2
  2. package/{esm2020 → esm2022}/popup.component.mjs +193 -151
  3. package/{esm2020 → esm2022}/popup.module.mjs +8 -7
  4. package/{esm2020 → esm2022}/popup.service.mjs +13 -9
  5. package/{esm2020 → esm2022}/services/align.service.mjs +5 -3
  6. package/{esm2020 → esm2022}/services/animation.service.mjs +8 -5
  7. package/{esm2020 → esm2022}/services/dom.service.mjs +4 -3
  8. package/{esm2020 → esm2022}/services/position.service.mjs +5 -3
  9. package/{esm2020 → esm2022}/services/resize.service.mjs +6 -3
  10. package/{esm2020 → esm2022}/services/scrollable.service.mjs +7 -3
  11. package/{fesm2020 → fesm2022}/progress-kendo-angular-popup.mjs +250 -188
  12. package/models/collision.type.d.ts +1 -1
  13. package/models/popup-animation.interface.d.ts +2 -2
  14. package/models/position-mode.d.ts +1 -1
  15. package/package.json +11 -17
  16. package/popup.component.d.ts +1 -1
  17. package/fesm2015/progress-kendo-angular-popup.mjs +0 -1404
  18. /package/{esm2020 → esm2022}/directives.mjs +0 -0
  19. /package/{esm2020 → esm2022}/index.mjs +0 -0
  20. /package/{esm2020 → esm2022}/models/align-element-settings.interface.mjs +0 -0
  21. /package/{esm2020 → esm2022}/models/align.interface.mjs +0 -0
  22. /package/{esm2020 → esm2022}/models/collision.interface.mjs +0 -0
  23. /package/{esm2020 → esm2022}/models/collision.type.mjs +0 -0
  24. /package/{esm2020 → esm2022}/models/margin.interface.mjs +0 -0
  25. /package/{esm2020 → esm2022}/models/offset.interface.mjs +0 -0
  26. /package/{esm2020 → esm2022}/models/popup-animation.interface.mjs +0 -0
  27. /package/{esm2020 → esm2022}/models/popup-ref.mjs +0 -0
  28. /package/{esm2020 → esm2022}/models/popup-settings.mjs +0 -0
  29. /package/{esm2020 → esm2022}/models/position-element-settings.interface.mjs +0 -0
  30. /package/{esm2020 → esm2022}/models/position-mode.mjs +0 -0
  31. /package/{esm2020 → esm2022}/models/position.interface.mjs +0 -0
  32. /package/{esm2020 → esm2022}/progress-kendo-angular-popup.mjs +0 -0
  33. /package/{esm2020 → esm2022}/scale.mjs +0 -0
  34. /package/{esm2020 → esm2022}/util.mjs +0 -0
@@ -1,1404 +0,0 @@
1
- /**-----------------------------------------------------------------------------------------
2
- * Copyright © 2024 Progress Software Corporation. All rights reserved.
3
- * Licensed under commercial license. See LICENSE.md in the project root for more information
4
- *-------------------------------------------------------------------------------------------*/
5
- import * as i0 from '@angular/core';
6
- import { InjectionToken, Injectable, Inject, Optional, EventEmitter, isDevMode, Component, Input, Output, ViewChild, TemplateRef, NgModule } from '@angular/core';
7
- import { siblingContainer, parents, addScroll, align, boundingOffset, offset, positionWithScroll, removeScroll, restrictToView, scrollPosition, getWindowViewPort } from '@progress/kendo-popup-common';
8
- import { isDocumentAvailable, hasObservers, ResizeSensorComponent, ResizeBatchService } from '@progress/kendo-angular-common';
9
- import { fromEvent, merge, from } from 'rxjs';
10
- import { auditTime } from 'rxjs/operators';
11
- import * as i1 from '@angular/animations';
12
- import { style, animate } from '@angular/animations';
13
- import { validatePackage } from '@progress/kendo-licensing';
14
- import { NgClass, NgTemplateOutlet, NgIf } from '@angular/common';
15
-
16
- /**
17
- * @hidden
18
- */
19
- const eitherRect = (rect, offset) => {
20
- if (!rect) {
21
- return { height: 0, left: offset.left, top: offset.top, width: 0 };
22
- }
23
- return rect;
24
- };
25
- /**
26
- * @hidden
27
- */
28
- const replaceOffset = (rect, offset) => {
29
- if (!offset) {
30
- return rect;
31
- }
32
- const result = {
33
- height: rect.height,
34
- left: offset.left,
35
- top: offset.top,
36
- width: rect.width
37
- };
38
- return result;
39
- };
40
- /**
41
- * @hidden
42
- */
43
- const removeStackingOffset = (rect, stackingOffset) => {
44
- if (!stackingOffset) {
45
- return rect;
46
- }
47
- const result = {
48
- height: rect.height,
49
- left: rect.left - stackingOffset.left,
50
- top: rect.top - stackingOffset.top,
51
- width: rect.width
52
- };
53
- return result;
54
- };
55
- /**
56
- * @hidden
57
- */
58
- const isDifferentOffset = (oldOffset, newOffset) => {
59
- const { left: oldLeft, top: oldTop } = oldOffset;
60
- const { left: newLeft, top: newTop } = newOffset;
61
- return Math.abs(oldLeft - newLeft) >= 1 || Math.abs(oldTop - newTop) >= 1;
62
- };
63
- /**
64
- * @hidden
65
- */
66
- const isWindowAvailable = () => {
67
- return typeof window !== 'undefined';
68
- };
69
- /**
70
- * @hidden
71
- */
72
- const hasBoundingRect = (elem) => !!elem.getBoundingClientRect;
73
- /**
74
- * @hidden
75
- */
76
- const OVERFLOW_REGEXP = /auto|scroll/;
77
- const overflowElementStyle = (element) => {
78
- return `${element.style.overflow}${element.style.overflowX}${element.style.overflowY}`;
79
- };
80
- const overflowComputedStyle = (element) => {
81
- const styles = window.getComputedStyle(element);
82
- return `${styles.overflow}${styles.overflowX}${styles.overflowY}`;
83
- };
84
- const overflowStyle = (element) => {
85
- return overflowElementStyle(element) || overflowComputedStyle(element);
86
- };
87
- /**
88
- * @hidden
89
- */
90
- const scrollableParents = (element) => {
91
- const parentElements = [];
92
- if (!isDocumentAvailable() || !isWindowAvailable()) {
93
- return parentElements;
94
- }
95
- let parent = element.parentElement;
96
- while (parent) {
97
- if (OVERFLOW_REGEXP.test(overflowStyle(parent)) || parent.hasAttribute('data-scrollable')) {
98
- parentElements.push(parent);
99
- }
100
- parent = parent.parentElement;
101
- }
102
- parentElements.push(window);
103
- return parentElements;
104
- };
105
- /**
106
- * @hidden
107
- */
108
- const FRAME_DURATION = 1000 / 60; //1000ms divided by 60fps
109
- // eslint-disable-next-line @typescript-eslint/ban-types
110
- function memoize(fun) {
111
- let result;
112
- let called = false;
113
- return (...args) => {
114
- if (called) {
115
- return result;
116
- }
117
- result = fun(...args);
118
- called = true;
119
- return result;
120
- };
121
- }
122
- /**
123
- * @hidden
124
- */
125
- const hasRelativeStackingContext = memoize(() => {
126
- if (!isDocumentAvailable() && document.body !== null) {
127
- return false;
128
- }
129
- const top = 10;
130
- const parent = document.createElement("div");
131
- parent.style.transform = "matrix(10, 0, 0, 10, 0, 0)";
132
- const childElement = document.createElement("div");
133
- childElement.style.position = 'fixed';
134
- childElement.style.top = `${top}px`;
135
- childElement.textContent = 'child';
136
- parent.appendChild(childElement);
137
- document.body.appendChild(parent);
138
- const isDifferent = parent.children[0].getBoundingClientRect().top !== top;
139
- document.body.removeChild(parent);
140
- return isDifferent;
141
- });
142
- /**
143
- * @hidden
144
- */
145
- const zIndex = (anchor, container) => {
146
- if (!anchor || !isDocumentAvailable() || !isWindowAvailable()) {
147
- return null;
148
- }
149
- const sibling = siblingContainer(anchor, container);
150
- if (!sibling) {
151
- return null;
152
- }
153
- const result = [anchor].concat(parents(anchor, sibling)).reduce((index, p) => {
154
- const zIndexStyle = p.style.zIndex || window.getComputedStyle(p).zIndex;
155
- const current = parseInt(zIndexStyle, 10);
156
- return current > index ? current : index;
157
- }, 0);
158
- return result ? (result + 1) : null;
159
- };
160
- /**
161
- * @hidden
162
- */
163
- const scaleRect = (rect, scale) => {
164
- if (!rect || scale === 1) {
165
- return rect;
166
- }
167
- return {
168
- height: rect.height / scale,
169
- left: rect.left / scale,
170
- top: rect.top / scale,
171
- width: rect.width / scale
172
- };
173
- };
174
-
175
- /**
176
- * Used to set the document scale when using a [scale transform](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale).
177
- *
178
- * The document or container scale is required to compute the popup position correctly. Detecting the scale is not reliable and must be set by providing a value for SCALE. See [Support for Document Scale]({% slug documentscale_popup %}).
179
- *
180
- * > Using this token is not necessary for user-applied browser zoom.
181
- *
182
- * {% meta height:300 %}
183
- * {% embed_file scale/app.component.ts preview %}
184
- * {% embed_file shared/app.module.ts %}
185
- * {% embed_file shared/main.ts %}
186
- * {% endmeta %}
187
- *
188
- *
189
- */
190
- const SCALE = new InjectionToken('Popup Document Scale');
191
-
192
- const STYLES = [
193
- 'font-size',
194
- 'font-family',
195
- 'font-stretch',
196
- 'font-style',
197
- 'font-weight',
198
- 'line-height'
199
- ];
200
- /**
201
- * @hidden
202
- */
203
- class DOMService {
204
- addOffset(current, addition) {
205
- return {
206
- left: current.left + addition.left,
207
- top: current.top + addition.top
208
- };
209
- }
210
- addScroll(rect, scroll) {
211
- return addScroll(rect, scroll);
212
- }
213
- align(settings) {
214
- return align(settings);
215
- }
216
- boundingOffset(el) {
217
- return boundingOffset(el);
218
- }
219
- getFontStyles(el) {
220
- const window = this.getWindow();
221
- if (!window || !el) {
222
- return [];
223
- }
224
- const computedStyles = window.getComputedStyle(el);
225
- return STYLES.map(key => ({ key: key, value: computedStyles[key] }));
226
- }
227
- getWindow() {
228
- return isWindowAvailable() ? window : null;
229
- }
230
- hasOffsetParent(el) {
231
- if (!el || !isDocumentAvailable()) {
232
- return false;
233
- }
234
- return !!this.nativeElement(el).offsetParent;
235
- }
236
- offset(el) {
237
- if (!el || !isDocumentAvailable()) {
238
- return null;
239
- }
240
- return offset(el);
241
- }
242
- offsetAtPoint(el, currentLocation) {
243
- if (!el || !isDocumentAvailable()) {
244
- return null;
245
- }
246
- const element = this.nativeElement(el);
247
- const { left, top, transition } = element.style;
248
- element.style.transition = 'none';
249
- element.style.left = `${currentLocation.left}px`;
250
- element.style.top = `${currentLocation.top}px`;
251
- const currentOffset = offset(element);
252
- element.style.left = left;
253
- element.style.top = top;
254
- // prevents elements with transition to be animated because of the change
255
- this._dummy = element.offsetHeight;
256
- element.style.transition = transition;
257
- return currentOffset;
258
- }
259
- nativeElement(el) {
260
- if (!el || !isDocumentAvailable()) {
261
- return null;
262
- }
263
- return el.nativeElement || el;
264
- }
265
- position(element, popup, scale = 1) {
266
- if (!element || !popup) {
267
- return null;
268
- }
269
- return positionWithScroll(element, this.nativeElement(popup), scale);
270
- }
271
- removeScroll(rect, scroll) {
272
- return removeScroll(rect, scroll);
273
- }
274
- restrictToView(settings) {
275
- return restrictToView(settings);
276
- }
277
- scrollPosition(el) {
278
- return scrollPosition(this.nativeElement(el));
279
- }
280
- scrollableParents(el) {
281
- return scrollableParents(el);
282
- }
283
- stackingElementOffset(el) {
284
- const relativeContextElement = this.getRelativeContextElement(el);
285
- if (!relativeContextElement) {
286
- return null;
287
- }
288
- return offset(relativeContextElement);
289
- }
290
- stackingElementScroll(el) {
291
- const relativeContextElement = this.getRelativeContextElement(el);
292
- if (!relativeContextElement) {
293
- return { x: 0, y: 0 };
294
- }
295
- return {
296
- x: relativeContextElement.scrollLeft,
297
- y: relativeContextElement.scrollTop
298
- };
299
- }
300
- getRelativeContextElement(el) {
301
- if (!el || !hasRelativeStackingContext()) {
302
- return null;
303
- }
304
- let parent = this.nativeElement(el).parentElement;
305
- while (parent) {
306
- if (window.getComputedStyle(parent).transform !== 'none') {
307
- return parent;
308
- }
309
- parent = parent.parentElement;
310
- }
311
- return null;
312
- }
313
- useRelativePosition(el) {
314
- return !!this.getRelativeContextElement(el);
315
- }
316
- windowViewPort(el) {
317
- return getWindowViewPort(this.nativeElement(el));
318
- }
319
- zIndex(anchor, container) {
320
- return zIndex(anchor, this.nativeElement(container));
321
- }
322
- zoomLevel() {
323
- if (!isDocumentAvailable() || !isWindowAvailable()) {
324
- return 1;
325
- }
326
- return parseFloat((document.documentElement.clientWidth / window.innerWidth).toFixed(2)) || 1;
327
- }
328
- isZoomed() {
329
- return this.zoomLevel() > 1;
330
- }
331
- }
332
- DOMService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DOMService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
333
- DOMService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DOMService });
334
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DOMService, decorators: [{
335
- type: Injectable
336
- }] });
337
-
338
- /**
339
- * @hidden
340
- */
341
- class AlignService {
342
- constructor(_dom, scale = 1) {
343
- this._dom = _dom;
344
- this.scale = scale;
345
- }
346
- alignElement(settings) {
347
- const { anchor, element, anchorAlign, elementAlign, margin, offset, positionMode } = settings;
348
- const scale = this.scale || 1;
349
- const fixedMode = positionMode === 'fixed' || !this._dom.hasOffsetParent(element);
350
- const anchorRect = fixedMode ? this.absoluteRect(anchor, element, offset, scale) : this.relativeRect(anchor, element, offset, scale);
351
- const elementRect = scaleRect(this._dom.offset(element.nativeElement), scale);
352
- const result = this._dom.align({
353
- anchorAlign: anchorAlign,
354
- anchorRect: anchorRect,
355
- elementAlign: elementAlign,
356
- elementRect: elementRect,
357
- margin
358
- });
359
- return result;
360
- }
361
- absoluteRect(anchor, element, offset, scale) {
362
- const scrollPos = this.elementScrollPosition(anchor, element);
363
- const rect = eitherRect(this._dom.offset(anchor), offset);
364
- const stackScale = 2 * scale;
365
- const stackScroll = this._dom.stackingElementScroll(element);
366
- if (scale !== 1 && stackScroll) {
367
- stackScroll.x /= stackScale;
368
- stackScroll.y /= stackScale;
369
- }
370
- const stackOffset = this._dom.stackingElementOffset(element);
371
- if (scale !== 1 && stackOffset) {
372
- stackOffset.left /= stackScale;
373
- stackOffset.top /= stackScale;
374
- }
375
- return this._dom.removeScroll(this._dom.addScroll(removeStackingOffset(scaleRect(rect, scale), stackOffset), stackScroll), scrollPos);
376
- }
377
- elementScrollPosition(anchor, element) {
378
- return anchor ? { x: 0, y: 0 } : this._dom.scrollPosition(element);
379
- }
380
- relativeRect(anchor, element, offset, scale) {
381
- const rect = eitherRect(this._dom.position(anchor, element, scale), offset);
382
- return scaleRect(rect, scale);
383
- }
384
- }
385
- AlignService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AlignService, deps: [{ token: DOMService }, { token: SCALE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
386
- AlignService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AlignService });
387
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AlignService, decorators: [{
388
- type: Injectable
389
- }], ctorParameters: function () {
390
- return [{ type: DOMService }, { type: undefined, decorators: [{
391
- type: Inject,
392
- args: [SCALE]
393
- }, {
394
- type: Optional
395
- }] }];
396
- } });
397
-
398
- /**
399
- * @hidden
400
- */
401
- class PositionService {
402
- constructor(_dom, scale = 1) {
403
- this._dom = _dom;
404
- this.scale = scale;
405
- }
406
- positionElement(settings) {
407
- const { anchor, currentLocation, element, anchorAlign, elementAlign, collisions, margin } = settings;
408
- const dom = this._dom;
409
- const scale = this.scale || 1;
410
- const elementOffset = dom.offsetAtPoint(element, currentLocation);
411
- const elementRect = scaleRect(elementOffset, scale);
412
- const anchorOffset = scaleRect(dom.offset(anchor), scale);
413
- const anchorRect = eitherRect(anchorOffset, currentLocation);
414
- const viewPort = settings.viewPort || dom.windowViewPort(element);
415
- viewPort.width = viewPort.width / scale;
416
- viewPort.height = viewPort.height / scale;
417
- const result = dom.restrictToView({
418
- anchorAlign,
419
- anchorRect,
420
- collisions,
421
- elementAlign,
422
- elementRect,
423
- margin,
424
- viewPort
425
- });
426
- const offset = dom.addOffset(currentLocation, result.offset);
427
- return {
428
- flip: result.flip,
429
- flipped: result.flipped,
430
- offset: offset
431
- };
432
- }
433
- }
434
- PositionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PositionService, deps: [{ token: DOMService }, { token: SCALE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
435
- PositionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PositionService });
436
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PositionService, decorators: [{
437
- type: Injectable
438
- }], ctorParameters: function () {
439
- return [{ type: DOMService }, { type: undefined, decorators: [{
440
- type: Inject,
441
- args: [SCALE]
442
- }, {
443
- type: Optional
444
- }] }];
445
- } });
446
-
447
- /**
448
- * @hidden
449
- */
450
- class ResizeService {
451
- constructor(_dom, _zone) {
452
- this._dom = _dom;
453
- this._zone = _zone;
454
- }
455
- subscribe(callback) {
456
- if (!isDocumentAvailable()) {
457
- return;
458
- }
459
- this._zone.runOutsideAngular(() => {
460
- this.subscription = fromEvent(this._dom.getWindow(), "resize")
461
- .pipe(auditTime(FRAME_DURATION))
462
- .subscribe(() => callback());
463
- });
464
- }
465
- unsubscribe() {
466
- if (!this.subscription) {
467
- return;
468
- }
469
- this.subscription.unsubscribe();
470
- }
471
- isUnsubscribed() {
472
- return this.subscription && this.subscription.closed;
473
- }
474
- }
475
- ResizeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ResizeService, deps: [{ token: DOMService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
476
- ResizeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ResizeService });
477
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ResizeService, decorators: [{
478
- type: Injectable
479
- }], ctorParameters: function () { return [{ type: DOMService }, { type: i0.NgZone }]; } });
480
-
481
- /**
482
- * @hidden
483
- */
484
- const THRESHOLD_DIFF = 1;
485
- /**
486
- * @hidden
487
- */
488
- class ScrollableService {
489
- constructor(_dom, _zone) {
490
- this._dom = _dom;
491
- this._zone = _zone;
492
- }
493
- forElement(element) {
494
- this.unsubscribe();
495
- this.element = element;
496
- return this;
497
- }
498
- subscribe(callback) {
499
- if (!callback || !isDocumentAvailable() || !this.element) {
500
- return;
501
- }
502
- const parents = this._dom.scrollableParents(this.element);
503
- this._zone.runOutsideAngular(() => {
504
- const observables = parents.map(p => fromEvent(p, "scroll").pipe(auditTime(FRAME_DURATION)));
505
- const subscriber = (e) => {
506
- const target = e.target;
507
- const isParent = parents.filter(p => p === target).length > 0;
508
- const isDocument = target === document;
509
- const isWindow = target === window;
510
- if (isParent || isDocument || isWindow) {
511
- callback(this.isVisible(this.element, target));
512
- }
513
- };
514
- this.subscription = merge(...observables).subscribe(subscriber);
515
- });
516
- }
517
- unsubscribe() {
518
- if (!this.subscription) {
519
- return;
520
- }
521
- this.subscription.unsubscribe();
522
- }
523
- isVisible(elem, container) {
524
- const elemRect = this._dom.boundingOffset(elem);
525
- const containerRect = this._dom.boundingOffset(this._dom.nativeElement(container));
526
- if (THRESHOLD_DIFF < (containerRect.top - elemRect.bottom)) {
527
- return false;
528
- }
529
- if (THRESHOLD_DIFF < (elemRect.top - containerRect.bottom)) {
530
- return false;
531
- }
532
- if (THRESHOLD_DIFF < (elemRect.left - containerRect.right)) {
533
- return false;
534
- }
535
- if (THRESHOLD_DIFF < (containerRect.left - elemRect.right)) {
536
- return false;
537
- }
538
- return true;
539
- }
540
- }
541
- ScrollableService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ScrollableService, deps: [{ token: DOMService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
542
- ScrollableService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ScrollableService });
543
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ScrollableService, decorators: [{
544
- type: Injectable
545
- }], ctorParameters: function () { return [{ type: DOMService }, { type: i0.NgZone }]; } });
546
-
547
- const LEFT = 'left';
548
- const RIGHT = 'right';
549
- const DOWN = 'down';
550
- const UP = 'up';
551
- const DEFAULT_TYPE = 'slide';
552
- const DEFAULT_DURATION = 100;
553
- const animationTypes = {};
554
- animationTypes.expand = (direction) => {
555
- const scale = direction === UP || direction === DOWN ? 'scaleY' : 'scaleX';
556
- const startScale = 0;
557
- const endScale = 1;
558
- let origin;
559
- if (direction === DOWN) {
560
- origin = 'top';
561
- }
562
- else if (direction === LEFT) {
563
- origin = RIGHT;
564
- }
565
- else if (direction === RIGHT) {
566
- origin = LEFT;
567
- }
568
- else {
569
- origin = 'bottom';
570
- }
571
- return {
572
- start: { transform: `${scale}(${startScale})`, transformOrigin: origin },
573
- end: { transform: `${scale}(${endScale})` }
574
- };
575
- };
576
- animationTypes.slide = (direction) => {
577
- const translate = direction === LEFT || direction === RIGHT ? 'translateX' : 'translateY';
578
- const start = direction === RIGHT || direction === DOWN ? -100 : 100;
579
- const end = 0;
580
- return {
581
- start: { transform: `${translate}(${start}%)` },
582
- end: { transform: `${translate}(${end}%)` }
583
- };
584
- };
585
- animationTypes.fade = () => {
586
- return {
587
- start: { opacity: 0 },
588
- end: { opacity: 1 }
589
- };
590
- };
591
- animationTypes.zoom = () => {
592
- const start = 0;
593
- const end = 1;
594
- return {
595
- start: { transform: `scale(${start})` },
596
- end: { transform: `scale(${end})` }
597
- };
598
- };
599
- /**
600
- * @hidden
601
- */
602
- class AnimationService {
603
- constructor(animationBuilder) {
604
- this.animationBuilder = animationBuilder;
605
- this.start = new EventEmitter();
606
- this.end = new EventEmitter();
607
- }
608
- play(element, options, flip) {
609
- if (!this.flip || this.flip.horizontal !== flip.horizontal ||
610
- this.flip.vertical !== flip.vertical) {
611
- this.flip = flip;
612
- const type = options.type || DEFAULT_TYPE;
613
- const statesFn = animationTypes[type];
614
- if (statesFn) {
615
- const direction = this.getDirection(flip, options);
616
- const states = statesFn(direction);
617
- this.playStates(element, states, options);
618
- }
619
- else if (isDevMode()) {
620
- throw new Error(`Unsupported animation type: "${type}". The supported types are slide, expand, fade and zoom.`);
621
- }
622
- }
623
- }
624
- ngOnDestroy() {
625
- this.stopPlayer();
626
- }
627
- playStates(element, states, options) {
628
- this.stopPlayer();
629
- const duration = options.duration || DEFAULT_DURATION;
630
- const factory = this.animationBuilder.build([
631
- style(states.start),
632
- animate(`${duration}ms ease-in`, style(states.end))
633
- ]);
634
- const player = this.player = factory.create(element);
635
- player.onDone(() => {
636
- this.end.emit();
637
- this.stopPlayer();
638
- });
639
- this.start.emit();
640
- player.play();
641
- }
642
- getDirection(flip, options) {
643
- let direction = options.direction || DOWN;
644
- if (flip.horizontal) {
645
- if (direction === LEFT) {
646
- direction = RIGHT;
647
- }
648
- else if (direction === RIGHT) {
649
- direction = LEFT;
650
- }
651
- }
652
- if (flip.vertical) {
653
- if (direction === DOWN) {
654
- direction = UP;
655
- }
656
- else if (direction === UP) {
657
- direction = DOWN;
658
- }
659
- }
660
- return direction;
661
- }
662
- stopPlayer() {
663
- if (this.player) {
664
- this.player.destroy();
665
- this.player = null;
666
- }
667
- }
668
- }
669
- AnimationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AnimationService, deps: [{ token: i1.AnimationBuilder }], target: i0.ɵɵFactoryTarget.Injectable });
670
- AnimationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AnimationService });
671
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AnimationService, decorators: [{
672
- type: Injectable
673
- }], ctorParameters: function () { return [{ type: i1.AnimationBuilder }]; } });
674
-
675
- /**
676
- * @hidden
677
- */
678
- const packageMetadata = {
679
- name: '@progress/kendo-angular-popup',
680
- productName: 'Kendo UI for Angular',
681
- productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
682
- publishDate: 1729174273,
683
- version: '17.0.0-develop.9',
684
- licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
685
- };
686
-
687
- const DEFAULT_OFFSET = { left: -10000, top: 0 };
688
- const ANIMATION_CONTAINER = 'k-animation-container';
689
- const ANIMATION_CONTAINER_FIXED = 'k-animation-container-fixed';
690
- /**
691
- * Represents the [Kendo UI Popup component for Angular]({% slug overview_popup %}).
692
- *
693
- * @example
694
- * ```ts
695
- * _@Component({
696
- * selector: 'my-app',
697
- * template: `
698
- * <button #anchor (click)="show=!show">Toggle</button>
699
- * <kendo-popup *ngIf="show" [anchor]="anchor">
700
- * <strong>Popup content!</strong>
701
- * </kendo-popup>
702
- * `
703
- * })
704
- * class AppComponent {
705
- * public show: boolean = false;
706
- * }
707
- * ```
708
- */
709
- class PopupComponent {
710
- constructor(container, _alignService, domService, _positionService, _resizeService, _scrollableService, animationService, _renderer, _zone) {
711
- this.container = container;
712
- this._alignService = _alignService;
713
- this.domService = domService;
714
- this._positionService = _positionService;
715
- this._resizeService = _resizeService;
716
- this._scrollableService = _scrollableService;
717
- this.animationService = animationService;
718
- this._renderer = _renderer;
719
- this._zone = _zone;
720
- /**
721
- * Controls the Popup animation. By default, the opening and closing animations
722
- * are enabled ([see example]({% slug animations_popup %})).
723
- */
724
- this.animate = true;
725
- /**
726
- * Specifies the anchor pivot point
727
- * ([see example]({% slug alignmentpositioning_popup %}#toc-positioning)).
728
- */
729
- this.anchorAlign = { horizontal: 'left', vertical: 'bottom' };
730
- /**
731
- * Configures the collision behavior of the Popup
732
- * ([see example]({% slug viewportboundarydetection_popup %})).
733
- */
734
- this.collision = { horizontal: 'fit', vertical: 'flip' };
735
- /**
736
- * Specifies the pivot point of the Popup
737
- * ([see example]({% slug alignmentpositioning_popup %}#toc-positioning)).
738
- */
739
- this.popupAlign = { horizontal: 'left', vertical: 'top' };
740
- /**
741
- * Controls whether the component will copy the `anchor` font styles.
742
- */
743
- this.copyAnchorStyles = false;
744
- /**
745
- * Specifies the position mode of the component. By default, the Popup uses fixed positioning.
746
- * To make the Popup acquire absolute positioning, set this option to `absolute`.
747
- *
748
- * > If you need to support mobile browsers with the zoom option,
749
- * use the `absolute` positioning of the Popup.
750
- *
751
- * @example
752
- * ```html
753
- * <style>
754
- * .parent-content {
755
- * position: relative;
756
- * width: 200px;
757
- * height: 200px;
758
- * overflow: auto;
759
- * margin: 200px auto;
760
- * border: 1px solid red;
761
- * }
762
- * .content {
763
- * position: relative;
764
- * width: 100px;
765
- * height: 100px;
766
- * overflow: auto;
767
- * margin: 300px;
768
- * border: 1px solid blue;
769
- * }
770
- * .anchor {
771
- * position: absolute;
772
- * top: 200px;
773
- * left: 200px;
774
- * }
775
- * </style>
776
- * ```
777
- * ```ts
778
- * _@Component({
779
- * selector: 'my-app',
780
- * template: `
781
- * <div class="example-config">
782
- * Position mode:
783
- * <label><input type="radio" value="fixed" [(ngModel)]="mode" /> Fixed</label>
784
- * <label><input type="radio" value="absolute" [(ngModel)]="mode" /> Absolute</label>
785
- * </div>
786
- * <div class="example-config">
787
- * Append to
788
- * <label>
789
- * <input type="radio" name="place" [value]="1" [(ngModel)]="checked" />
790
- * Root component
791
- * </label>
792
- * <label>
793
- * <input type="radio" name="place" [value]="2" [(ngModel)]="checked" />
794
- * <span [style.color]="'red'">Red Container</span>
795
- * </label>
796
- * <label>
797
- * <input type="radio" name="place" [value]="3" [(ngModel)]="checked" />
798
- * <span [style.color]="'blue'">Blue Container</span>
799
- * </label>
800
- * </div>
801
- * <div class="example">
802
- * <div class="parent-content" [scrollLeft]="250" [scrollTop]="230">
803
- * <div class="content" [scrollLeft]="170" [scrollTop]="165">
804
- * <button #anchor class="anchor" (click)="show = !show">Toggle</button>
805
- * <kendo-popup [positionMode]="mode" [anchor]="anchor" (anchorViewportLeave)="show=false" *ngIf="show && checked === 3">
806
- * <ul>
807
- * <li>Item1</li>
808
- * <li>Item2</li>
809
- * <li>Item3</li>
810
- * </ul>
811
- * </kendo-popup>
812
- * <span [style.position]="'absolute'" [style.top.px]="400" [style.left.px]="400">Bottom/Right</span>
813
- * </div>
814
- * <kendo-popup [positionMode]="mode" [anchor]="anchor" (anchorViewportLeave)="show=false" *ngIf="show && checked === 2">
815
- * <ul>
816
- * <li>Item1</li>
817
- * <li>Item2</li>
818
- * <li>Item3</li>
819
- * </ul>
820
- * </kendo-popup>
821
- * <span [style.position]="'absolute'" [style.top.px]="600" [style.left.px]="600">Bottom/Right</span>
822
- * </div>
823
- * <kendo-popup [positionMode]="mode" [anchor]="anchor" (anchorViewportLeave)="show=false" *ngIf="show && checked === 1">
824
- * <ul>
825
- * <li>Item1</li>
826
- * <li>Item2</li>
827
- * <li>Item3</li>
828
- * </ul>
829
- * </kendo-popup>
830
- * </div>
831
- * `
832
- * })
833
- * class AppComponent {
834
- * public checked: number = 3;
835
- * public mode: string = 'absolute';
836
- * public show: boolean = true;
837
- * }
838
- * ```
839
- */
840
- this.positionMode = 'fixed';
841
- /**
842
- * Specifies the absolute position of the element
843
- * ([see example]({% slug alignmentpositioning_popup %}#toc-aligning-to-absolute-points)).
844
- * The Popup opens next to that point. The Popup pivot point is defined by the `popupAlign` configuration option.
845
- * The boundary detection is applied by using the window viewport.
846
- */
847
- this.offset = DEFAULT_OFFSET;
848
- /**
849
- * Fires when the anchor is scrolled outside the screen boundaries.
850
- * ([see example]({% slug closing_popup %}#toc-after-leaving-the-viewport)).
851
- */
852
- this.anchorViewportLeave = new EventEmitter();
853
- /**
854
- * Fires after the component is closed.
855
- */
856
- this.close = new EventEmitter();
857
- /**
858
- * Fires after the component is opened and the opening animation ends.
859
- */
860
- this.open = new EventEmitter();
861
- /**
862
- * Fires after the component is opened and the Popup is positioned.
863
- */
864
- this.positionChange = new EventEmitter();
865
- this.resolvedPromise = Promise.resolve(null);
866
- this.initialCheck = true;
867
- validatePackage(packageMetadata);
868
- this._renderer.addClass(container.nativeElement, ANIMATION_CONTAINER);
869
- this.updateFixedClass();
870
- }
871
- ngOnInit() {
872
- this.reposition = this.reposition.bind(this);
873
- this._resizeService.subscribe(this.reposition);
874
- this.animationSubscriptions = this.animationService.start.subscribe(this.onAnimationStart.bind(this));
875
- this.animationSubscriptions.add(this.animationService.end.subscribe(this.onAnimationEnd.bind(this)));
876
- this._scrollableService.forElement(this.domService.nativeElement(this.anchor) || this.container.nativeElement).subscribe(this.onScroll.bind(this));
877
- this.currentOffset = DEFAULT_OFFSET;
878
- this.setZIndex();
879
- this.copyFontStyles();
880
- this.updateFixedClass();
881
- this.reposition();
882
- }
883
- ngOnChanges(changes) {
884
- if (changes.copyAnchorStyles) {
885
- this.copyFontStyles();
886
- }
887
- if (changes.positionMode) {
888
- this.updateFixedClass();
889
- }
890
- }
891
- ngAfterViewInit() {
892
- if (!this.animate) {
893
- this.resolvedPromise.then(() => {
894
- this.onAnimationEnd();
895
- });
896
- }
897
- this.reposition();
898
- }
899
- ngAfterViewChecked() {
900
- if (this.initialCheck) {
901
- this.initialCheck = false;
902
- return;
903
- }
904
- this._zone.runOutsideAngular(() => {
905
- // workarounds https://github.com/angular/angular/issues/19094
906
- // uses promise because it is executed synchronously after the content is updated
907
- // does not use onStable in case the current zone is not the angular one.
908
- this.unsubscribeReposition();
909
- this.repositionSubscription = from(this.resolvedPromise)
910
- .subscribe(this.reposition);
911
- });
912
- }
913
- ngOnDestroy() {
914
- this.anchorViewportLeave.complete();
915
- this.positionChange.complete();
916
- this.close.emit();
917
- this.close.complete();
918
- this._resizeService.unsubscribe();
919
- this._scrollableService.unsubscribe();
920
- this.animationSubscriptions.unsubscribe();
921
- this.unsubscribeReposition();
922
- }
923
- /**
924
- * @hidden
925
- */
926
- onResize() {
927
- this.reposition();
928
- }
929
- onAnimationStart() {
930
- this._renderer.removeClass(this.container.nativeElement, 'k-animation-container-shown');
931
- }
932
- onAnimationEnd() {
933
- this._renderer.addClass(this.container.nativeElement, 'k-animation-container-shown');
934
- this.open.emit();
935
- this.open.complete();
936
- }
937
- get currentOffset() {
938
- return this._currentOffset;
939
- }
940
- set currentOffset(offset) {
941
- this.setContainerStyle('left', `${offset.left}px`);
942
- this.setContainerStyle('top', `${offset.top}px`);
943
- this._currentOffset = offset;
944
- }
945
- setZIndex() {
946
- if (this.anchor) {
947
- this.setContainerStyle('z-index', String(this.domService.zIndex(this.domService.nativeElement(this.anchor), this.container)));
948
- }
949
- }
950
- reposition() {
951
- if (!isDocumentAvailable()) {
952
- return;
953
- }
954
- const { flip, offset } = this.position();
955
- if (!this.currentOffset || isDifferentOffset(this.currentOffset, offset)) {
956
- this.currentOffset = offset;
957
- if (hasObservers(this.positionChange)) {
958
- this._zone.run(() => this.positionChange.emit({ offset, flip }));
959
- }
960
- }
961
- if (this.animate) {
962
- this.animationService.play(this.contentContainer.nativeElement, this.animate, flip);
963
- }
964
- this.resizeSensor.acceptSize();
965
- }
966
- position() {
967
- const alignedOffset = this._alignService.alignElement({
968
- anchor: this.domService.nativeElement(this.anchor),
969
- anchorAlign: this.anchorAlign,
970
- element: this.container,
971
- elementAlign: this.popupAlign,
972
- margin: this.margin,
973
- offset: this.offset,
974
- positionMode: this.positionMode
975
- });
976
- return this._positionService.positionElement({
977
- anchor: this.domService.nativeElement(this.anchor),
978
- anchorAlign: this.anchorAlign,
979
- collisions: this.collision,
980
- currentLocation: alignedOffset,
981
- element: this.container,
982
- elementAlign: this.popupAlign,
983
- margin: this.margin
984
- });
985
- }
986
- onScroll(isInViewPort) {
987
- const hasLeaveObservers = hasObservers(this.anchorViewportLeave);
988
- if (isInViewPort || !hasLeaveObservers) {
989
- this.reposition();
990
- }
991
- else if (hasLeaveObservers) {
992
- this._zone.run(() => {
993
- this.anchorViewportLeave.emit();
994
- });
995
- }
996
- }
997
- copyFontStyles() {
998
- if (!this.anchor || !this.copyAnchorStyles) {
999
- return;
1000
- }
1001
- this.domService.getFontStyles(this.domService.nativeElement(this.anchor))
1002
- .forEach((s) => this.setContainerStyle(s.key, s.value));
1003
- }
1004
- updateFixedClass() {
1005
- const action = this.positionMode === 'fixed' ? 'addClass' : 'removeClass';
1006
- this._renderer[action](this.container.nativeElement, ANIMATION_CONTAINER_FIXED);
1007
- }
1008
- setContainerStyle(name, value) {
1009
- this._renderer.setStyle(this.container.nativeElement, name, value);
1010
- }
1011
- unsubscribeReposition() {
1012
- if (this.repositionSubscription) {
1013
- this.repositionSubscription.unsubscribe();
1014
- }
1015
- }
1016
- }
1017
- PopupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupComponent, deps: [{ token: i0.ElementRef }, { token: AlignService }, { token: DOMService }, { token: PositionService }, { token: ResizeService }, { token: ScrollableService }, { token: AnimationService }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1018
- PopupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PopupComponent, isStandalone: true, selector: "kendo-popup", inputs: { animate: "animate", anchor: "anchor", anchorAlign: "anchorAlign", collision: "collision", popupAlign: "popupAlign", copyAnchorStyles: "copyAnchorStyles", popupClass: "popupClass", positionMode: "positionMode", offset: "offset", margin: "margin" }, outputs: { anchorViewportLeave: "anchorViewportLeave", close: "close", open: "open", positionChange: "positionChange" }, providers: [AlignService, AnimationService, DOMService, PositionService, ResizeService, ScrollableService], viewQueries: [{ propertyName: "contentContainer", first: true, predicate: ["container"], descendants: true, static: true }, { propertyName: "resizeSensor", first: true, predicate: ResizeSensorComponent, descendants: true, static: true }], exportAs: ["kendo-popup"], usesOnChanges: true, ngImport: i0, template: `
1019
- <div class="k-child-animation-container">
1020
- <div class="k-popup" [ngClass]="popupClass" #container>
1021
- <ng-content></ng-content>
1022
- <ng-template [ngTemplateOutlet]="content" [ngIf]="content"></ng-template>
1023
- <kendo-resize-sensor [rateLimit]="100" (resize)="onResize()">
1024
- </kendo-resize-sensor>
1025
- </div>
1026
- </div>
1027
- `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
1028
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupComponent, decorators: [{
1029
- type: Component,
1030
- args: [{
1031
- exportAs: 'kendo-popup',
1032
- providers: [AlignService, AnimationService, DOMService, PositionService, ResizeService, ScrollableService],
1033
- selector: 'kendo-popup',
1034
- template: `
1035
- <div class="k-child-animation-container">
1036
- <div class="k-popup" [ngClass]="popupClass" #container>
1037
- <ng-content></ng-content>
1038
- <ng-template [ngTemplateOutlet]="content" [ngIf]="content"></ng-template>
1039
- <kendo-resize-sensor [rateLimit]="100" (resize)="onResize()">
1040
- </kendo-resize-sensor>
1041
- </div>
1042
- </div>
1043
- `,
1044
- standalone: true,
1045
- imports: [NgClass, NgTemplateOutlet, NgIf, ResizeSensorComponent]
1046
- }]
1047
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: AlignService }, { type: DOMService }, { type: PositionService }, { type: ResizeService }, { type: ScrollableService }, { type: AnimationService }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { animate: [{
1048
- type: Input
1049
- }], anchor: [{
1050
- type: Input
1051
- }], anchorAlign: [{
1052
- type: Input
1053
- }], collision: [{
1054
- type: Input
1055
- }], popupAlign: [{
1056
- type: Input
1057
- }], copyAnchorStyles: [{
1058
- type: Input
1059
- }], popupClass: [{
1060
- type: Input
1061
- }], positionMode: [{
1062
- type: Input
1063
- }], offset: [{
1064
- type: Input
1065
- }], margin: [{
1066
- type: Input
1067
- }], anchorViewportLeave: [{
1068
- type: Output
1069
- }], close: [{
1070
- type: Output
1071
- }], open: [{
1072
- type: Output
1073
- }], positionChange: [{
1074
- type: Output
1075
- }], contentContainer: [{
1076
- type: ViewChild,
1077
- args: ['container', { static: true }]
1078
- }], resizeSensor: [{
1079
- type: ViewChild,
1080
- args: [ResizeSensorComponent, { static: true }]
1081
- }] } });
1082
-
1083
- const removeElement = (element) => {
1084
- if (element && element.parentNode) {
1085
- element.parentNode.removeChild(element);
1086
- }
1087
- };
1088
- /**
1089
- * Used to inject the Popup container. If not provided, the first root component of
1090
- * the application is used.
1091
- *
1092
- * > The `POPUP_CONTAINER` can be used only with the [`PopupService`](slug:service_popup) class.
1093
- *
1094
- * In case you are using standalone components:
1095
- *
1096
- * @example
1097
- *
1098
- * ```ts
1099
- * import { Component } from '@angular/core';
1100
- * import { KENDO_POPUP, PopupService } from '@progress/kendo-angular-popup';
1101
- *
1102
- * @Component({
1103
- * standalone: true,
1104
- * imports: [KENDO_POPUP],
1105
- * providers: [PopupService, {
1106
- * provide: POPUP_CONTAINER,
1107
- * useFactory: () => {
1108
- * //return the container ElementRef, where the popup will be injected
1109
- * return { nativeElement: document.body } as ElementRef;
1110
- * }
1111
- * }],
1112
- * selector: 'app-root',
1113
- * templateUrl: './app.component.html',
1114
- * })
1115
- * export class AppComponent {}
1116
- * ```
1117
- *
1118
- * In case you are using an NgModule-based application:
1119
- *
1120
- * @example
1121
- *
1122
- * ```ts-no-run
1123
- * import { PopupModule, POPUP_CONTAINER } from '@progress/kendo-angular-popup';
1124
- * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
1125
- * import { ElementRef, NgModule } from '@angular/core';
1126
- * import { AppComponent } from './app.component';
1127
- *
1128
- * _@NgModule({
1129
- * declarations: [AppComponent], // declare app component
1130
- * imports: [BrowserModule, PopupModule], // import Popup module
1131
- * bootstrap: [AppComponent],
1132
- * providers: [{
1133
- * provide: POPUP_CONTAINER,
1134
- * useFactory: () => {
1135
- * //return the container ElementRef, where the popup will be injected
1136
- * return { nativeElement: document.body } as ElementRef;
1137
- * }
1138
- * }]
1139
- * })
1140
- * export class AppModule {}
1141
- *
1142
- * platformBrowserDynamic().bootstrapModule(AppModule);
1143
- * ```
1144
- */
1145
- const POPUP_CONTAINER = new InjectionToken('Popup Container');
1146
- /**
1147
- * A service for opening Popup components dynamically
1148
- * ([see example]({% slug service_popup %})).
1149
- *
1150
- * @export
1151
- * @class PopupService
1152
- */
1153
- class PopupService {
1154
- constructor(applicationRef, componentFactoryResolver, injector, container) {
1155
- this.applicationRef = applicationRef;
1156
- this.componentFactoryResolver = componentFactoryResolver;
1157
- this.injector = injector;
1158
- this.container = container;
1159
- }
1160
- /**
1161
- * Gets the root view container into which the component will be injected.
1162
- *
1163
- * @returns {ComponentRef<any>}
1164
- */
1165
- get rootViewContainer() {
1166
- // https://github.com/angular/angular/blob/4.0.x/packages/core/src/application_ref.ts#L571
1167
- const rootComponents = this.applicationRef.components || [];
1168
- if (rootComponents[0]) {
1169
- return rootComponents[0];
1170
- }
1171
- throw new Error(`
1172
- View Container not found! Inject the POPUP_CONTAINER or define a specific ViewContainerRef via the appendTo option.
1173
- See https://www.telerik.com/kendo-angular-ui/components/popup/api/POPUP_CONTAINER/ for more details.
1174
- `);
1175
- }
1176
- /**
1177
- * Sets or gets the HTML element of the root component container.
1178
- *
1179
- * @returns {HTMLElement}
1180
- */
1181
- get rootViewContainerNode() {
1182
- return this.container ? this.container.nativeElement : this.getComponentRootNode(this.rootViewContainer);
1183
- }
1184
- /**
1185
- * Opens a Popup component. Created Popups are mounted
1186
- * in the DOM directly in the root application component.
1187
- *
1188
- * @param {PopupSettings} options - The options which define the Popup.
1189
- * @returns {ComponentRef<PopupComponent>} - A reference to the Popup object.
1190
- *
1191
- * @example
1192
- *
1193
- * ```ts-no-run
1194
- * _@Component({
1195
- * selector: 'my-app',
1196
- * template: `
1197
- * <ng-template #template>
1198
- * Popup content
1199
- * </ng-template>
1200
- * <button #anchor kendoButton (click)="open(anchor, template)">Open</button>
1201
- * `
1202
- * })
1203
- * export class AppComponent {
1204
- * public popupRef: PopupRef;
1205
- *
1206
- * constructor( private popupService: PopupService ) {}
1207
- *
1208
- * public open(anchor: ElementRef, template: TemplateRef<any>): void {
1209
- * if (this.popupRef) {
1210
- * this.popupRef.close();
1211
- * this.popupRef = null;
1212
- * return;
1213
- * }
1214
- *
1215
- * this.popupRef = this.popupService.open({
1216
- * anchor: anchor,
1217
- * content: template
1218
- * });
1219
- * }
1220
- * }
1221
- * ```
1222
- */
1223
- open(options = {}) {
1224
- const { component, nodes } = this.contentFrom(options.content);
1225
- const popupComponentRef = this.appendPopup(nodes, options.appendTo);
1226
- const popupInstance = popupComponentRef.instance;
1227
- this.projectComponentInputs(popupComponentRef, options);
1228
- popupComponentRef.changeDetectorRef.detectChanges();
1229
- if (component) {
1230
- component.changeDetectorRef.detectChanges();
1231
- }
1232
- const popupElement = this.getComponentRootNode(popupComponentRef);
1233
- return {
1234
- close: () => {
1235
- if (component) {
1236
- component.destroy();
1237
- }
1238
- popupComponentRef.destroy();
1239
- // Angular will not remove the element unless the change detection is triggered
1240
- removeElement(popupElement);
1241
- },
1242
- content: component,
1243
- popup: popupComponentRef,
1244
- popupAnchorViewportLeave: popupInstance.anchorViewportLeave,
1245
- popupClose: popupInstance.close,
1246
- popupElement: popupElement,
1247
- popupOpen: popupInstance.open,
1248
- popupPositionChange: popupInstance.positionChange
1249
- };
1250
- }
1251
- appendPopup(nodes, container) {
1252
- const popupComponentRef = this.createComponent(PopupComponent, nodes, container);
1253
- if (!container) {
1254
- this.rootViewContainerNode.appendChild(this.getComponentRootNode(popupComponentRef));
1255
- }
1256
- return popupComponentRef;
1257
- }
1258
- /**
1259
- * Gets the HTML element for a component reference.
1260
- *
1261
- * @param {ComponentRef<any>} componentRef
1262
- * @returns {HTMLElement}
1263
- */
1264
- getComponentRootNode(componentRef) {
1265
- return componentRef.location.nativeElement;
1266
- }
1267
- /**
1268
- * Gets the `ComponentFactory` instance by its type.
1269
- *
1270
- * @param {*} componentClass
1271
- * @param {*} nodes
1272
- * @returns {ComponentRef<any>}
1273
- */
1274
- getComponentFactory(componentClass) {
1275
- return this.componentFactoryResolver.resolveComponentFactory(componentClass);
1276
- }
1277
- /**
1278
- * Creates a component reference from a `Component` type class.
1279
- *
1280
- * @param {*} componentClass
1281
- * @param {*} nodes
1282
- * @returns {ComponentRef<any>}
1283
- */
1284
- createComponent(componentClass, nodes, container) {
1285
- const factory = this.getComponentFactory(componentClass);
1286
- if (container) {
1287
- return container.createComponent(factory, undefined, this.injector, nodes);
1288
- }
1289
- else {
1290
- const component = factory.create(this.injector, nodes);
1291
- this.applicationRef.attachView(component.hostView);
1292
- return component;
1293
- }
1294
- }
1295
- /**
1296
- * Projects the inputs on the component.
1297
- *
1298
- * @param {ComponentRef<any>} component
1299
- * @param {*} options
1300
- * @returns {ComponentRef<any>}
1301
- */
1302
- projectComponentInputs(component, options) {
1303
- Object.getOwnPropertyNames(options)
1304
- .filter(prop => prop !== 'content' || options.content instanceof TemplateRef)
1305
- .map((prop) => {
1306
- component.instance[prop] = options[prop];
1307
- });
1308
- return component;
1309
- }
1310
- /**
1311
- * Gets the component and the nodes to append from the `content` option.
1312
- *
1313
- * @param {*} content
1314
- * @returns {any}
1315
- */
1316
- contentFrom(content) {
1317
- if (!content || content instanceof TemplateRef) {
1318
- return { component: null, nodes: [[]] };
1319
- }
1320
- const component = this.createComponent(content);
1321
- const nodes = component ? [component.location.nativeElement] : [];
1322
- return {
1323
- component: component,
1324
- nodes: [
1325
- nodes // <ng-content>
1326
- ]
1327
- };
1328
- }
1329
- }
1330
- PopupService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupService, deps: [{ token: i0.ApplicationRef }, { token: i0.ComponentFactoryResolver }, { token: i0.Injector }, { token: POPUP_CONTAINER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1331
- PopupService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupService, providedIn: 'root' });
1332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupService, decorators: [{
1333
- type: Injectable,
1334
- args: [{
1335
- providedIn: 'root'
1336
- }]
1337
- }], ctorParameters: function () {
1338
- return [{ type: i0.ApplicationRef }, { type: i0.ComponentFactoryResolver }, { type: i0.Injector }, { type: i0.ElementRef, decorators: [{
1339
- type: Inject,
1340
- args: [POPUP_CONTAINER]
1341
- }, {
1342
- type: Optional
1343
- }] }];
1344
- } });
1345
-
1346
- /**
1347
- * Utility array that contains all `@progress/kendo-angular-popup` related components and directives
1348
- */
1349
- const KENDO_POPUP = [
1350
- PopupComponent
1351
- ];
1352
-
1353
- //IMPORTANT: NgModule export kept for backwards compatibility
1354
- /**
1355
- * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
1356
- * definition for the Popup component.
1357
- *
1358
- * @example
1359
- *
1360
- * ```ts-no-run
1361
- * // Import the Popup module
1362
- * import { PopupModule } from '@progress/kendo-angular-popup';
1363
- *
1364
- * // The browser platform with a compiler
1365
- * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
1366
- *
1367
- * import { NgModule } from '@angular/core';
1368
- *
1369
- * // Import the app component
1370
- * import { AppComponent } from './app.component';
1371
- *
1372
- * // Define the app module
1373
- * _@NgModule({
1374
- * declarations: [AppComponent], // declare app component
1375
- * imports: [BrowserModule, PopupModule], // import Popup module
1376
- * bootstrap: [AppComponent]
1377
- * })
1378
- * export class AppModule {}
1379
- *
1380
- * // Compile and launch the module
1381
- * platformBrowserDynamic().bootstrapModule(AppModule);
1382
- *
1383
- * ```
1384
- */
1385
- class PopupModule {
1386
- }
1387
- PopupModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1388
- PopupModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: PopupModule, imports: [ResizeSensorComponent, PopupComponent], exports: [PopupComponent] });
1389
- PopupModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupModule, providers: [PopupService, ResizeBatchService], imports: [ResizeSensorComponent, KENDO_POPUP] });
1390
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PopupModule, decorators: [{
1391
- type: NgModule,
1392
- args: [{
1393
- exports: [...KENDO_POPUP],
1394
- imports: [ResizeSensorComponent, ...KENDO_POPUP],
1395
- providers: [PopupService, ResizeBatchService]
1396
- }]
1397
- }] });
1398
-
1399
- /**
1400
- * Generated bundle index. Do not edit.
1401
- */
1402
-
1403
- export { KENDO_POPUP, POPUP_CONTAINER, PopupComponent, PopupModule, PopupService, SCALE };
1404
-