@shival99/z-ui 2.2.6 → 2.3.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.
- package/assets/css/base.css +4 -0
- package/assets/css/overlay.css +82 -0
- package/assets/css/tailwind.css +1 -0
- package/fesm2022/shival99-z-ui-components-z-button-group.mjs +15 -13
- package/fesm2022/shival99-z-ui-components-z-button-group.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-button.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs +23 -17
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-command.mjs +10 -24
- package/fesm2022/shival99-z-ui-components-z-command.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs +42 -60
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs +6 -8
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-icon.mjs +147 -3
- package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-marquee.mjs +19 -4
- package/fesm2022/shival99-z-ui-components-z-marquee.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-menu.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-modal.mjs +45 -62
- package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-overlay.mjs +363 -0
- package/fesm2022/shival99-z-ui-components-z-overlay.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-popover.mjs +94 -378
- package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +14 -3
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-table.mjs +42 -16
- package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs +85 -7
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-toast.mjs +32 -25
- package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +52 -222
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-services.mjs +42 -25
- package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
- package/package.json +9 -1
- package/types/shival99-z-ui-components-z-button-group.d.ts +12 -11
- package/types/shival99-z-ui-components-z-button.d.ts +2 -1
- package/types/shival99-z-ui-components-z-command.d.ts +2 -4
- package/types/shival99-z-ui-components-z-drawer.d.ts +11 -13
- package/types/shival99-z-ui-components-z-gallery.d.ts +7 -7
- package/types/shival99-z-ui-components-z-icon.d.ts +22 -2
- package/types/shival99-z-ui-components-z-marquee.d.ts +7 -1
- package/types/shival99-z-ui-components-z-modal.d.ts +52 -52
- package/types/shival99-z-ui-components-z-overlay.d.ts +145 -0
- package/types/shival99-z-ui-components-z-popover.d.ts +6 -14
- package/types/shival99-z-ui-components-z-qrcode.d.ts +1 -1
- package/types/shival99-z-ui-components-z-skeleton.d.ts +2 -0
- package/types/shival99-z-ui-components-z-table.d.ts +6 -2
- package/types/shival99-z-ui-components-z-tabs.d.ts +13 -3
- package/types/shival99-z-ui-components-z-toast.d.ts +7 -1
- package/types/shival99-z-ui-components-z-tooltip.d.ts +9 -7
- package/types/shival99-z-ui-services.d.ts +52 -31
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay';
|
|
2
|
-
import { ComponentPortal } from '@angular/cdk/portal';
|
|
3
1
|
import { NgTemplateOutlet, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
4
2
|
import * as i0 from '@angular/core';
|
|
5
3
|
import { signal, computed, ChangeDetectionStrategy, Component, inject, Renderer2, DestroyRef, PLATFORM_ID, viewChild, output, input, ElementRef, Directive } from '@angular/core';
|
|
6
4
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { Z_OVERLAY_FALLBACK_ORDER, ZOverlayService, startZOverlayAutoUpdate, computeZOverlayPlacement } from '@shival99/z-ui/components/z-overlay';
|
|
7
6
|
import { ZOverlayContainerService, ZOverlayZIndexService } from '@shival99/z-ui/services';
|
|
8
7
|
import { zMergeClasses, zIsMobileViewport, zTransform } from '@shival99/z-ui/utils';
|
|
9
8
|
import { Subject, switchMap, of, timer, map, filter } from 'rxjs';
|
|
@@ -196,85 +195,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
|
|
|
196
195
|
}]
|
|
197
196
|
}] });
|
|
198
197
|
|
|
199
|
-
const Z_POPOVER_MOBILE_VIEWPORT_MARGIN = 10;
|
|
200
198
|
function isMobilePopoverViewport() {
|
|
201
199
|
return zIsMobileViewport();
|
|
202
200
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
function getPopoverRenderPosition(position, _mobile = isMobilePopoverViewport()) {
|
|
207
|
-
return position;
|
|
208
|
-
}
|
|
209
|
-
function getMobilePopoverFallbackPositions(position, offset) {
|
|
210
|
-
return getPopoverFallbackPositions(position, offset).map(pos => ({
|
|
211
|
-
...pos,
|
|
212
|
-
offsetX: pos.offsetX ?? 0,
|
|
213
|
-
offsetY: pos.offsetY ?? 0,
|
|
214
|
-
}));
|
|
215
|
-
}
|
|
216
|
-
function clampPopoverPosition(value, min, max) {
|
|
217
|
-
return Math.min(Math.max(value, min), max);
|
|
218
|
-
}
|
|
219
|
-
function getAlignedX(position, triggerRect, overlayRect) {
|
|
220
|
-
if (position === 'left' || position.startsWith('left-')) {
|
|
221
|
-
return triggerRect.left - overlayRect.width;
|
|
222
|
-
}
|
|
223
|
-
if (position === 'right' || position.startsWith('right-')) {
|
|
224
|
-
return triggerRect.right;
|
|
225
|
-
}
|
|
226
|
-
if (position.endsWith('-right')) {
|
|
227
|
-
return triggerRect.right - overlayRect.width;
|
|
228
|
-
}
|
|
229
|
-
if (position === 'top' || position === 'bottom') {
|
|
230
|
-
return triggerRect.left + triggerRect.width / 2 - overlayRect.width / 2;
|
|
231
|
-
}
|
|
232
|
-
return triggerRect.left;
|
|
233
|
-
}
|
|
234
|
-
function getAlignedY(position, triggerRect, overlayRect) {
|
|
235
|
-
if (position === 'top' || position.startsWith('top-')) {
|
|
236
|
-
return triggerRect.top - overlayRect.height;
|
|
237
|
-
}
|
|
238
|
-
if (position === 'bottom' || position.startsWith('bottom-')) {
|
|
239
|
-
return triggerRect.bottom;
|
|
240
|
-
}
|
|
241
|
-
if (position.endsWith('-bottom')) {
|
|
242
|
-
return triggerRect.bottom - overlayRect.height;
|
|
243
|
-
}
|
|
244
|
-
if (position === 'left' || position === 'right') {
|
|
245
|
-
return triggerRect.top + triggerRect.height / 2 - overlayRect.height / 2;
|
|
246
|
-
}
|
|
247
|
-
return triggerRect.top;
|
|
248
|
-
}
|
|
249
|
-
function getMobilePopoverPaneStyles(config) {
|
|
250
|
-
const { position, triggerRect, overlayRect, offset, viewportWidth } = config;
|
|
251
|
-
const viewportMargin = config.viewportMargin ?? Z_POPOVER_MOBILE_VIEWPORT_MARGIN;
|
|
252
|
-
const maxLeft = Math.max(viewportMargin, viewportWidth - overlayRect.width - viewportMargin);
|
|
253
|
-
let left = getAlignedX(position, triggerRect, overlayRect);
|
|
254
|
-
let top = getAlignedY(position, triggerRect, overlayRect);
|
|
255
|
-
if (position === 'top' || position.startsWith('top-')) {
|
|
256
|
-
top -= offset;
|
|
257
|
-
}
|
|
258
|
-
if (position === 'bottom' || position.startsWith('bottom-')) {
|
|
259
|
-
top += offset;
|
|
260
|
-
}
|
|
261
|
-
if (position === 'left' || position.startsWith('left-')) {
|
|
262
|
-
left -= offset;
|
|
263
|
-
}
|
|
264
|
-
if (position === 'right' || position.startsWith('right-')) {
|
|
265
|
-
left += offset;
|
|
266
|
-
}
|
|
267
|
-
left = clampPopoverPosition(left, viewportMargin, maxLeft);
|
|
268
|
-
return {
|
|
269
|
-
top: `${top}px`,
|
|
270
|
-
left: `${left}px`,
|
|
271
|
-
right: '',
|
|
272
|
-
bottom: '',
|
|
273
|
-
transform: 'none',
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
function getPopoverPushEnabled(_mobile = isMobilePopoverViewport()) {
|
|
277
|
-
return false;
|
|
201
|
+
/** Danh sách fallback (không gồm vị trí chính — Floating UI tự thử vị trí chính trước). */
|
|
202
|
+
function getPopoverFallbackPlacements(position) {
|
|
203
|
+
return Z_OVERLAY_FALLBACK_ORDER[position];
|
|
278
204
|
}
|
|
279
205
|
function isPopoverTriggerVisibleInViewport(config) {
|
|
280
206
|
const { triggerRect, viewportWidth, viewportHeight } = config;
|
|
@@ -286,172 +212,12 @@ function isPopoverTriggerVisibleInViewport(config) {
|
|
|
286
212
|
triggerRect.right > 0 &&
|
|
287
213
|
triggerRect.left < viewportWidth);
|
|
288
214
|
}
|
|
289
|
-
function createPopoverPosition(position, offset) {
|
|
290
|
-
const positions = {
|
|
291
|
-
top: {
|
|
292
|
-
originX: 'center',
|
|
293
|
-
originY: 'top',
|
|
294
|
-
overlayX: 'center',
|
|
295
|
-
overlayY: 'bottom',
|
|
296
|
-
offsetY: -offset,
|
|
297
|
-
},
|
|
298
|
-
'top-left': {
|
|
299
|
-
originX: 'start',
|
|
300
|
-
originY: 'top',
|
|
301
|
-
overlayX: 'start',
|
|
302
|
-
overlayY: 'bottom',
|
|
303
|
-
offsetY: -offset,
|
|
304
|
-
},
|
|
305
|
-
'top-right': {
|
|
306
|
-
originX: 'end',
|
|
307
|
-
originY: 'top',
|
|
308
|
-
overlayX: 'end',
|
|
309
|
-
overlayY: 'bottom',
|
|
310
|
-
offsetY: -offset,
|
|
311
|
-
},
|
|
312
|
-
bottom: {
|
|
313
|
-
originX: 'center',
|
|
314
|
-
originY: 'bottom',
|
|
315
|
-
overlayX: 'center',
|
|
316
|
-
overlayY: 'top',
|
|
317
|
-
offsetY: offset,
|
|
318
|
-
},
|
|
319
|
-
'bottom-left': {
|
|
320
|
-
originX: 'start',
|
|
321
|
-
originY: 'bottom',
|
|
322
|
-
overlayX: 'start',
|
|
323
|
-
overlayY: 'top',
|
|
324
|
-
offsetY: offset,
|
|
325
|
-
},
|
|
326
|
-
'bottom-right': {
|
|
327
|
-
originX: 'end',
|
|
328
|
-
originY: 'bottom',
|
|
329
|
-
overlayX: 'end',
|
|
330
|
-
overlayY: 'top',
|
|
331
|
-
offsetY: offset,
|
|
332
|
-
},
|
|
333
|
-
left: {
|
|
334
|
-
originX: 'start',
|
|
335
|
-
originY: 'center',
|
|
336
|
-
overlayX: 'end',
|
|
337
|
-
overlayY: 'center',
|
|
338
|
-
offsetX: -offset,
|
|
339
|
-
},
|
|
340
|
-
'left-top': {
|
|
341
|
-
originX: 'start',
|
|
342
|
-
originY: 'top',
|
|
343
|
-
overlayX: 'end',
|
|
344
|
-
overlayY: 'top',
|
|
345
|
-
offsetX: -offset,
|
|
346
|
-
},
|
|
347
|
-
'left-bottom': {
|
|
348
|
-
originX: 'start',
|
|
349
|
-
originY: 'bottom',
|
|
350
|
-
overlayX: 'end',
|
|
351
|
-
overlayY: 'bottom',
|
|
352
|
-
offsetX: -offset,
|
|
353
|
-
},
|
|
354
|
-
right: {
|
|
355
|
-
originX: 'end',
|
|
356
|
-
originY: 'center',
|
|
357
|
-
overlayX: 'start',
|
|
358
|
-
overlayY: 'center',
|
|
359
|
-
offsetX: offset,
|
|
360
|
-
},
|
|
361
|
-
'right-top': {
|
|
362
|
-
originX: 'end',
|
|
363
|
-
originY: 'top',
|
|
364
|
-
overlayX: 'start',
|
|
365
|
-
overlayY: 'top',
|
|
366
|
-
offsetX: offset,
|
|
367
|
-
},
|
|
368
|
-
'right-bottom': {
|
|
369
|
-
originX: 'end',
|
|
370
|
-
originY: 'bottom',
|
|
371
|
-
overlayX: 'start',
|
|
372
|
-
overlayY: 'bottom',
|
|
373
|
-
offsetX: offset,
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
return positions[position];
|
|
377
|
-
}
|
|
378
|
-
function getPopoverFallbackPositions(position, offset) {
|
|
379
|
-
const fallbackOrder = {
|
|
380
|
-
top: ['top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],
|
|
381
|
-
'top-left': ['top-left', 'bottom-left', 'top', 'bottom', 'top-right', 'bottom-right'],
|
|
382
|
-
'top-right': ['top-right', 'bottom-right', 'top', 'bottom', 'top-left', 'bottom-left'],
|
|
383
|
-
bottom: ['bottom', 'top', 'bottom-left', 'bottom-right', 'top-left', 'top-right'],
|
|
384
|
-
'bottom-left': ['bottom-left', 'top-left', 'bottom', 'top', 'bottom-right', 'top-right'],
|
|
385
|
-
'bottom-right': ['bottom-right', 'top-right', 'bottom', 'top', 'bottom-left', 'top-left'],
|
|
386
|
-
left: ['left', 'right', 'left-top', 'left-bottom', 'right-top', 'right-bottom'],
|
|
387
|
-
'left-top': ['left-top', 'right-top', 'left', 'right', 'left-bottom', 'right-bottom'],
|
|
388
|
-
'left-bottom': ['left-bottom', 'right-bottom', 'left', 'right', 'left-top', 'right-top'],
|
|
389
|
-
right: ['right', 'left', 'right-top', 'right-bottom', 'left-top', 'left-bottom'],
|
|
390
|
-
'right-top': ['right-top', 'left-top', 'right', 'left', 'right-bottom', 'left-bottom'],
|
|
391
|
-
'right-bottom': ['right-bottom', 'left-bottom', 'right', 'left', 'right-top', 'left-top'],
|
|
392
|
-
};
|
|
393
|
-
const orderedPositions = fallbackOrder[position] ?? [position];
|
|
394
|
-
return orderedPositions.map(pos => createPopoverPosition(pos, offset));
|
|
395
|
-
}
|
|
396
|
-
function createPopoverPositionStrategy(overlayPositionBuilder, origin, position, offset) {
|
|
397
|
-
const mobile = isMobilePopoverViewport();
|
|
398
|
-
const positions = mobile
|
|
399
|
-
? getMobilePopoverFallbackPositions(position, offset)
|
|
400
|
-
: getPopoverFallbackPositions(position, offset);
|
|
401
|
-
return overlayPositionBuilder
|
|
402
|
-
.flexibleConnectedTo(origin)
|
|
403
|
-
.withPositions(positions)
|
|
404
|
-
.withFlexibleDimensions(false)
|
|
405
|
-
.withPush(getPopoverPushEnabled(mobile))
|
|
406
|
-
.withViewportMargin(10);
|
|
407
|
-
}
|
|
408
|
-
function getActualPopoverPosition(change) {
|
|
409
|
-
const { originX, originY, overlayX, overlayY } = change.connectionPair;
|
|
410
|
-
if (overlayY === 'bottom' && originY === 'top') {
|
|
411
|
-
if (originX === 'start' && overlayX === 'start') {
|
|
412
|
-
return 'top-left';
|
|
413
|
-
}
|
|
414
|
-
if (originX === 'end' && overlayX === 'end') {
|
|
415
|
-
return 'top-right';
|
|
416
|
-
}
|
|
417
|
-
return 'top';
|
|
418
|
-
}
|
|
419
|
-
if (overlayY === 'top' && originY === 'bottom') {
|
|
420
|
-
if (originX === 'start' && overlayX === 'start') {
|
|
421
|
-
return 'bottom-left';
|
|
422
|
-
}
|
|
423
|
-
if (originX === 'end' && overlayX === 'end') {
|
|
424
|
-
return 'bottom-right';
|
|
425
|
-
}
|
|
426
|
-
return 'bottom';
|
|
427
|
-
}
|
|
428
|
-
if (overlayX === 'end' && originX === 'start') {
|
|
429
|
-
if (originY === 'top' && overlayY === 'top') {
|
|
430
|
-
return 'left-top';
|
|
431
|
-
}
|
|
432
|
-
if (originY === 'bottom' && overlayY === 'bottom') {
|
|
433
|
-
return 'left-bottom';
|
|
434
|
-
}
|
|
435
|
-
return 'left';
|
|
436
|
-
}
|
|
437
|
-
if (overlayX === 'start' && originX === 'end') {
|
|
438
|
-
if (originY === 'top' && overlayY === 'top') {
|
|
439
|
-
return 'right-top';
|
|
440
|
-
}
|
|
441
|
-
if (originY === 'bottom' && overlayY === 'bottom') {
|
|
442
|
-
return 'right-bottom';
|
|
443
|
-
}
|
|
444
|
-
return 'right';
|
|
445
|
-
}
|
|
446
|
-
return 'top';
|
|
447
|
-
}
|
|
448
215
|
|
|
449
216
|
const Z_POPOVER_ANIMATION_DURATION = 200;
|
|
450
217
|
|
|
451
218
|
class ZPopoverComponent {
|
|
452
219
|
static _openPopovers = new Set();
|
|
453
|
-
|
|
454
|
-
_overlayPositionBuilder = inject(OverlayPositionBuilder);
|
|
220
|
+
_overlayService = inject(ZOverlayService);
|
|
455
221
|
_renderer = inject(Renderer2);
|
|
456
222
|
_destroyRef = inject(DestroyRef);
|
|
457
223
|
_platformId = inject(PLATFORM_ID);
|
|
@@ -489,7 +255,7 @@ class ZPopoverComponent {
|
|
|
489
255
|
_componentRef = null;
|
|
490
256
|
_delaySubject = new Subject();
|
|
491
257
|
_listenerCleanups = [];
|
|
492
|
-
|
|
258
|
+
_autoUpdateCleanup = null;
|
|
493
259
|
_scrollSubscription = null;
|
|
494
260
|
_viewportResizeSubscription = null;
|
|
495
261
|
_resizeObserver = null;
|
|
@@ -570,28 +336,13 @@ class ZPopoverComponent {
|
|
|
570
336
|
this._schedulePositionUpdate();
|
|
571
337
|
}
|
|
572
338
|
_createOverlay() {
|
|
573
|
-
const
|
|
574
|
-
const overlayRef = this._overlay.create({
|
|
575
|
-
positionStrategy,
|
|
576
|
-
scrollStrategy: this._createScrollStrategy(),
|
|
577
|
-
hasBackdrop: false,
|
|
578
|
-
...getPopoverOverlaySize(),
|
|
579
|
-
});
|
|
339
|
+
const overlayRef = this._overlayService.createAnchored();
|
|
580
340
|
this._zIndexService.applyToOverlay(overlayRef);
|
|
581
341
|
return overlayRef;
|
|
582
342
|
}
|
|
583
|
-
_createScrollStrategy() {
|
|
584
|
-
if (this.zScrollClose()) {
|
|
585
|
-
return this._overlay.scrollStrategies.close();
|
|
586
|
-
}
|
|
587
|
-
if (isMobilePopoverViewport() && (this.zSticky() || this.zKeyboardSafe())) {
|
|
588
|
-
return this._overlay.scrollStrategies.noop();
|
|
589
|
-
}
|
|
590
|
-
return this._overlay.scrollStrategies.reposition({ scrollThrottle: 10, autoClose: false });
|
|
591
|
-
}
|
|
592
343
|
_disposeOverlay() {
|
|
593
|
-
this.
|
|
594
|
-
this.
|
|
344
|
+
this._autoUpdateCleanup?.();
|
|
345
|
+
this._autoUpdateCleanup = null;
|
|
595
346
|
this._scrollSubscription?.unsubscribe();
|
|
596
347
|
this._scrollSubscription = null;
|
|
597
348
|
this._viewportResizeSubscription?.unsubscribe();
|
|
@@ -611,7 +362,7 @@ class ZPopoverComponent {
|
|
|
611
362
|
.pipe(switchMap(config => (config.delay <= 0 ? of(config) : timer(config.delay).pipe(map(() => config)))), takeUntilDestroyed(this._destroyRef))
|
|
612
363
|
.subscribe(config => {
|
|
613
364
|
if (config.show) {
|
|
614
|
-
this._showPopover();
|
|
365
|
+
void this._showPopover();
|
|
615
366
|
return;
|
|
616
367
|
}
|
|
617
368
|
this._hidePopover();
|
|
@@ -687,7 +438,7 @@ class ZPopoverComponent {
|
|
|
687
438
|
ticking = false;
|
|
688
439
|
return;
|
|
689
440
|
}
|
|
690
|
-
this._updatePositionNow();
|
|
441
|
+
void this._updatePositionNow();
|
|
691
442
|
ticking = false;
|
|
692
443
|
});
|
|
693
444
|
};
|
|
@@ -722,7 +473,7 @@ class ZPopoverComponent {
|
|
|
722
473
|
},
|
|
723
474
|
};
|
|
724
475
|
}
|
|
725
|
-
_showPopover() {
|
|
476
|
+
async _showPopover() {
|
|
726
477
|
const content = this.zContent();
|
|
727
478
|
if (!content || this._componentRef) {
|
|
728
479
|
return;
|
|
@@ -732,30 +483,24 @@ class ZPopoverComponent {
|
|
|
732
483
|
this._setupOutsideClick();
|
|
733
484
|
}
|
|
734
485
|
this._setupScrollClose();
|
|
735
|
-
|
|
736
|
-
this._overlayRef.updatePositionStrategy(positionStrategy);
|
|
737
|
-
this._overlayRef.updateSize(getPopoverOverlaySize());
|
|
738
|
-
const portal = new ComponentPortal(ZPopoverContentComponent);
|
|
739
|
-
this._componentRef = this._overlayRef.attach(portal);
|
|
740
|
-
const renderPosition = getPopoverRenderPosition(this.zPosition());
|
|
486
|
+
this._componentRef = this._overlayRef.attach(ZPopoverContentComponent);
|
|
741
487
|
this._componentRef.instance.setProps({
|
|
742
488
|
content,
|
|
743
|
-
position:
|
|
489
|
+
position: this.zPosition(),
|
|
744
490
|
customClass: this.zClass(),
|
|
745
491
|
onClose: () => this.hide(),
|
|
746
492
|
showArrow: this.zShowArrow(),
|
|
747
493
|
});
|
|
748
|
-
this.
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
});
|
|
494
|
+
await this._applyPosition();
|
|
495
|
+
if (!this._overlayRef || !this._componentRef) {
|
|
496
|
+
return; // đã bị dispose (hide/destroy) trong lúc chờ computePosition
|
|
497
|
+
}
|
|
498
|
+
this._autoUpdateCleanup = startZOverlayAutoUpdate(this._trigger().nativeElement, this._overlayRef.overlayElement, () => void this._applyPosition(), { ancestorScroll: false });
|
|
753
499
|
if (this.zTrigger() === 'hover') {
|
|
754
500
|
this._setupPopoverHover();
|
|
755
501
|
}
|
|
756
502
|
this._setupResizeObserver();
|
|
757
503
|
this._setupViewportResizeReposition();
|
|
758
|
-
this._updatePositionAfterContentSettles();
|
|
759
504
|
this._isVisible.set(true);
|
|
760
505
|
ZPopoverComponent._openPopovers.add(this);
|
|
761
506
|
this.zShow.emit();
|
|
@@ -792,16 +537,13 @@ class ZPopoverComponent {
|
|
|
792
537
|
this._resizeObserver.observe(wrapper);
|
|
793
538
|
}
|
|
794
539
|
}
|
|
795
|
-
_updatePositionAfterContentSettles() {
|
|
796
|
-
this._schedulePositionUpdate();
|
|
797
|
-
}
|
|
798
540
|
_schedulePositionUpdate(force = false) {
|
|
799
541
|
if (this._positionFrame !== null) {
|
|
800
542
|
return;
|
|
801
543
|
}
|
|
802
544
|
this._positionFrame = requestAnimationFrame(() => {
|
|
803
545
|
this._positionFrame = null;
|
|
804
|
-
this._updatePositionNow(force);
|
|
546
|
+
void this._updatePositionNow(force);
|
|
805
547
|
});
|
|
806
548
|
}
|
|
807
549
|
_scheduleSettledPositionUpdate() {
|
|
@@ -821,7 +563,7 @@ class ZPopoverComponent {
|
|
|
821
563
|
cancelAnimationFrame(this._positionFrame);
|
|
822
564
|
this._positionFrame = null;
|
|
823
565
|
}
|
|
824
|
-
_updatePositionNow(force = false) {
|
|
566
|
+
async _updatePositionNow(force = false) {
|
|
825
567
|
if (!this._overlayRef?.hasAttached()) {
|
|
826
568
|
return;
|
|
827
569
|
}
|
|
@@ -831,8 +573,30 @@ class ZPopoverComponent {
|
|
|
831
573
|
if (!force && this._shouldSkipMobileKeyboardUpdate()) {
|
|
832
574
|
return;
|
|
833
575
|
}
|
|
834
|
-
this.
|
|
835
|
-
|
|
576
|
+
await this._applyPosition();
|
|
577
|
+
}
|
|
578
|
+
async _applyPosition() {
|
|
579
|
+
if (!this._overlayRef || !this._componentRef) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
const anchorElement = this._trigger().nativeElement;
|
|
583
|
+
const floatingElement = this._overlayRef.overlayElement;
|
|
584
|
+
const position = this.zPosition();
|
|
585
|
+
const result = await computeZOverlayPlacement({
|
|
586
|
+
reference: anchorElement,
|
|
587
|
+
floating: floatingElement,
|
|
588
|
+
placement: position,
|
|
589
|
+
fallbackPlacements: getPopoverFallbackPlacements(position),
|
|
590
|
+
offset: this.zOffset(),
|
|
591
|
+
push: true,
|
|
592
|
+
viewportPadding: 10,
|
|
593
|
+
});
|
|
594
|
+
if (!this._componentRef) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
floatingElement.style.left = `${result.x}px`;
|
|
598
|
+
floatingElement.style.top = `${result.y}px`;
|
|
599
|
+
this._componentRef.instance.position.set(result.placement);
|
|
836
600
|
}
|
|
837
601
|
_markViewportSettling() {
|
|
838
602
|
this._viewportSettlingUntil = Date.now() + 260;
|
|
@@ -869,22 +633,6 @@ class ZPopoverComponent {
|
|
|
869
633
|
}
|
|
870
634
|
this._viewportResizeTimeouts = [];
|
|
871
635
|
}
|
|
872
|
-
_applyMobilePopoverPosition(position) {
|
|
873
|
-
if (!isMobilePopoverViewport() || !this._overlayRef?.hasAttached()) {
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
const { overlayElement } = this._overlayRef;
|
|
877
|
-
const { visualViewport } = window;
|
|
878
|
-
const styles = getMobilePopoverPaneStyles({
|
|
879
|
-
position,
|
|
880
|
-
triggerRect: this._trigger().nativeElement.getBoundingClientRect(),
|
|
881
|
-
overlayRect: overlayElement.getBoundingClientRect(),
|
|
882
|
-
offset: this.zOffset(),
|
|
883
|
-
viewportWidth: visualViewport?.width ?? window.innerWidth,
|
|
884
|
-
viewportHeight: visualViewport?.height ?? window.innerHeight,
|
|
885
|
-
});
|
|
886
|
-
this._setOverlayPaneStyles(styles);
|
|
887
|
-
}
|
|
888
636
|
_isTriggerVisibleInViewport() {
|
|
889
637
|
const { visualViewport } = window;
|
|
890
638
|
return isPopoverTriggerVisibleInViewport({
|
|
@@ -893,11 +641,6 @@ class ZPopoverComponent {
|
|
|
893
641
|
viewportHeight: visualViewport?.height ?? window.innerHeight,
|
|
894
642
|
});
|
|
895
643
|
}
|
|
896
|
-
_setOverlayPaneStyles(styles) {
|
|
897
|
-
for (const key of ['top', 'left', 'right', 'bottom', 'transform']) {
|
|
898
|
-
this._renderer.setStyle(this._overlayRef?.overlayElement, key, styles[key]);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
644
|
_setupPopoverHover() {
|
|
902
645
|
const overlayElement = this._overlayRef?.overlayElement;
|
|
903
646
|
if (!overlayElement) {
|
|
@@ -916,9 +659,6 @@ class ZPopoverComponent {
|
|
|
916
659
|
if (!this._componentRef) {
|
|
917
660
|
return;
|
|
918
661
|
}
|
|
919
|
-
if (this._hideTimeout) {
|
|
920
|
-
return;
|
|
921
|
-
}
|
|
922
662
|
this._componentRef.instance.state.set('closed');
|
|
923
663
|
this._hideTimeout = setTimeout(() => {
|
|
924
664
|
this._hideTimeout = null;
|
|
@@ -1001,8 +741,7 @@ class ZPopoverDirective {
|
|
|
1001
741
|
zOutsideClick = output();
|
|
1002
742
|
_trigger = computed(() => this.zPopoverTrigger() ?? this.zTrigger(), /* @ts-ignore */
|
|
1003
743
|
...(ngDevMode ? [{ debugName: "_trigger" }] : /* istanbul ignore next */ []));
|
|
1004
|
-
|
|
1005
|
-
_overlayPositionBuilder = inject(OverlayPositionBuilder);
|
|
744
|
+
_overlayService = inject(ZOverlayService);
|
|
1006
745
|
_elementRef = inject((ElementRef));
|
|
1007
746
|
_renderer = inject(Renderer2);
|
|
1008
747
|
_destroyRef = inject(DestroyRef);
|
|
@@ -1014,7 +753,7 @@ class ZPopoverDirective {
|
|
|
1014
753
|
_componentRef = null;
|
|
1015
754
|
_delaySubject = new Subject();
|
|
1016
755
|
_listenerCleanups = [];
|
|
1017
|
-
|
|
756
|
+
_autoUpdateCleanup = null;
|
|
1018
757
|
_scrollSubscription = null;
|
|
1019
758
|
_viewportResizeSubscription = null;
|
|
1020
759
|
_resizeObserver = null;
|
|
@@ -1105,36 +844,24 @@ class ZPopoverDirective {
|
|
|
1105
844
|
this._schedulePositionUpdate();
|
|
1106
845
|
}
|
|
1107
846
|
_createOverlay() {
|
|
1108
|
-
const
|
|
1109
|
-
const widthConfig = this._getWidthConfig();
|
|
1110
|
-
const overlayRef = this._overlay.create({
|
|
1111
|
-
positionStrategy,
|
|
1112
|
-
scrollStrategy: this._createScrollStrategy(),
|
|
1113
|
-
hasBackdrop: false,
|
|
1114
|
-
...widthConfig,
|
|
1115
|
-
});
|
|
847
|
+
const overlayRef = this._overlayService.createAnchored();
|
|
1116
848
|
this._zIndexService.applyToOverlay(overlayRef);
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
if (this.zScrollClose()) {
|
|
1121
|
-
return this._overlay.scrollStrategies.close();
|
|
1122
|
-
}
|
|
1123
|
-
if (isMobilePopoverViewport() && (this.zSticky() || this.zKeyboardSafe())) {
|
|
1124
|
-
return this._overlay.scrollStrategies.noop();
|
|
849
|
+
const widthConfig = this._getWidthConfig();
|
|
850
|
+
if (widthConfig.width) {
|
|
851
|
+
overlayRef.updateSize(widthConfig);
|
|
1125
852
|
}
|
|
1126
|
-
return
|
|
853
|
+
return overlayRef;
|
|
1127
854
|
}
|
|
1128
855
|
_getWidthConfig() {
|
|
1129
856
|
const width = this.zPopoverWidth();
|
|
1130
857
|
if (width === 'auto') {
|
|
1131
|
-
return
|
|
858
|
+
return {};
|
|
1132
859
|
}
|
|
1133
860
|
if (width === 'trigger') {
|
|
1134
861
|
const triggerWidth = this._getTriggerElement().getBoundingClientRect().width;
|
|
1135
|
-
return
|
|
862
|
+
return { width: `${triggerWidth}px`, minWidth: `${triggerWidth}px` };
|
|
1136
863
|
}
|
|
1137
|
-
return
|
|
864
|
+
return { width, minWidth: width };
|
|
1138
865
|
}
|
|
1139
866
|
_getTriggerElement() {
|
|
1140
867
|
const triggerRef = this.zTriggerRef();
|
|
@@ -1144,8 +871,8 @@ class ZPopoverDirective {
|
|
|
1144
871
|
return triggerRef ?? this._elementRef.nativeElement;
|
|
1145
872
|
}
|
|
1146
873
|
_disposeOverlay() {
|
|
1147
|
-
this.
|
|
1148
|
-
this.
|
|
874
|
+
this._autoUpdateCleanup?.();
|
|
875
|
+
this._autoUpdateCleanup = null;
|
|
1149
876
|
this._scrollSubscription?.unsubscribe();
|
|
1150
877
|
this._scrollSubscription = null;
|
|
1151
878
|
this._viewportResizeSubscription?.unsubscribe();
|
|
@@ -1165,7 +892,7 @@ class ZPopoverDirective {
|
|
|
1165
892
|
.pipe(switchMap(config => (config.delay <= 0 ? of(config) : timer(config.delay).pipe(map(() => config)))), takeUntilDestroyed(this._destroyRef))
|
|
1166
893
|
.subscribe(config => {
|
|
1167
894
|
if (config.show) {
|
|
1168
|
-
this._showPopover();
|
|
895
|
+
void this._showPopover();
|
|
1169
896
|
return;
|
|
1170
897
|
}
|
|
1171
898
|
this._hidePopover();
|
|
@@ -1256,7 +983,7 @@ class ZPopoverDirective {
|
|
|
1256
983
|
ticking = false;
|
|
1257
984
|
return;
|
|
1258
985
|
}
|
|
1259
|
-
this._updatePositionNow();
|
|
986
|
+
void this._updatePositionNow();
|
|
1260
987
|
ticking = false;
|
|
1261
988
|
});
|
|
1262
989
|
};
|
|
@@ -1294,7 +1021,7 @@ class ZPopoverDirective {
|
|
|
1294
1021
|
_delay(show, delay) {
|
|
1295
1022
|
this._delaySubject.next({ show, delay });
|
|
1296
1023
|
}
|
|
1297
|
-
_showPopover() {
|
|
1024
|
+
async _showPopover() {
|
|
1298
1025
|
const content = this.zContent();
|
|
1299
1026
|
if (!content) {
|
|
1300
1027
|
return;
|
|
@@ -1316,34 +1043,24 @@ class ZPopoverDirective {
|
|
|
1316
1043
|
this._setupOutsideClick();
|
|
1317
1044
|
}
|
|
1318
1045
|
this._setupScrollClose();
|
|
1319
|
-
|
|
1320
|
-
this._overlayRef.updatePositionStrategy(positionStrategy);
|
|
1321
|
-
const widthConfig = this._getWidthConfig();
|
|
1322
|
-
if (widthConfig.width) {
|
|
1323
|
-
this._overlayRef.updateSize(widthConfig);
|
|
1324
|
-
}
|
|
1325
|
-
const portal = new ComponentPortal(ZPopoverContentComponent);
|
|
1326
|
-
this._componentRef = this._overlayRef.attach(portal);
|
|
1327
|
-
const renderPosition = getPopoverRenderPosition(this.zPosition());
|
|
1046
|
+
this._componentRef = this._overlayRef.attach(ZPopoverContentComponent);
|
|
1328
1047
|
this._componentRef.instance.setProps({
|
|
1329
1048
|
content,
|
|
1330
|
-
position:
|
|
1049
|
+
position: this.zPosition(),
|
|
1331
1050
|
customClass: this.zClass(),
|
|
1332
1051
|
onClose: () => this.hide(),
|
|
1333
1052
|
showArrow: this.zShowArrow(),
|
|
1334
1053
|
});
|
|
1335
|
-
this.
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
});
|
|
1054
|
+
await this._applyPosition();
|
|
1055
|
+
if (!this._overlayRef || !this._componentRef) {
|
|
1056
|
+
return; // đã bị dispose (hide/destroy) trong lúc chờ computePosition
|
|
1057
|
+
}
|
|
1058
|
+
this._autoUpdateCleanup = startZOverlayAutoUpdate(this._getTriggerElement(), this._overlayRef.overlayElement, () => void this._applyPosition(), { ancestorScroll: false });
|
|
1341
1059
|
if (this._trigger() === 'hover') {
|
|
1342
1060
|
this._setupPopoverHover();
|
|
1343
1061
|
}
|
|
1344
1062
|
this._setupResizeObserver();
|
|
1345
1063
|
this._setupViewportResizeReposition();
|
|
1346
|
-
this._updatePositionAfterContentSettles();
|
|
1347
1064
|
this._isVisible.set(true);
|
|
1348
1065
|
ZPopoverDirective._openPopovers.add(this);
|
|
1349
1066
|
this._renderer.addClass(this._elementRef.nativeElement, 'z-popover-open');
|
|
@@ -1390,16 +1107,13 @@ class ZPopoverDirective {
|
|
|
1390
1107
|
this._resizeObserver.observe(wrapper);
|
|
1391
1108
|
}
|
|
1392
1109
|
}
|
|
1393
|
-
_updatePositionAfterContentSettles() {
|
|
1394
|
-
this._schedulePositionUpdate();
|
|
1395
|
-
}
|
|
1396
1110
|
_schedulePositionUpdate(force = false) {
|
|
1397
1111
|
if (this._positionFrame !== null) {
|
|
1398
1112
|
return;
|
|
1399
1113
|
}
|
|
1400
1114
|
this._positionFrame = requestAnimationFrame(() => {
|
|
1401
1115
|
this._positionFrame = null;
|
|
1402
|
-
this._updatePositionNow(force);
|
|
1116
|
+
void this._updatePositionNow(force);
|
|
1403
1117
|
});
|
|
1404
1118
|
}
|
|
1405
1119
|
_scheduleSettledPositionUpdate() {
|
|
@@ -1419,7 +1133,7 @@ class ZPopoverDirective {
|
|
|
1419
1133
|
cancelAnimationFrame(this._positionFrame);
|
|
1420
1134
|
this._positionFrame = null;
|
|
1421
1135
|
}
|
|
1422
|
-
_updatePositionNow(force = false) {
|
|
1136
|
+
async _updatePositionNow(force = false) {
|
|
1423
1137
|
if (!this._overlayRef?.hasAttached()) {
|
|
1424
1138
|
return;
|
|
1425
1139
|
}
|
|
@@ -1433,8 +1147,31 @@ class ZPopoverDirective {
|
|
|
1433
1147
|
if (widthConfig.width) {
|
|
1434
1148
|
this._overlayRef.updateSize(widthConfig);
|
|
1435
1149
|
}
|
|
1436
|
-
this.
|
|
1437
|
-
|
|
1150
|
+
await this._applyPosition();
|
|
1151
|
+
}
|
|
1152
|
+
async _applyPosition() {
|
|
1153
|
+
if (!this._overlayRef || !this._componentRef) {
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
const anchorElement = this._getTriggerElement();
|
|
1157
|
+
const floatingElement = this._overlayRef.overlayElement;
|
|
1158
|
+
const position = this.zPosition();
|
|
1159
|
+
const result = await computeZOverlayPlacement({
|
|
1160
|
+
reference: anchorElement,
|
|
1161
|
+
floating: floatingElement,
|
|
1162
|
+
placement: position,
|
|
1163
|
+
fallbackPlacements: getPopoverFallbackPlacements(position),
|
|
1164
|
+
offset: this.zOffset(),
|
|
1165
|
+
push: true,
|
|
1166
|
+
viewportPadding: 10,
|
|
1167
|
+
});
|
|
1168
|
+
if (!this._componentRef) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
floatingElement.style.left = `${result.x}px`;
|
|
1172
|
+
floatingElement.style.top = `${result.y}px`;
|
|
1173
|
+
this._componentRef.instance.position.set(result.placement);
|
|
1174
|
+
this.zPositionChange.emit(result.placement);
|
|
1438
1175
|
}
|
|
1439
1176
|
_markViewportSettling() {
|
|
1440
1177
|
this._viewportSettlingUntil = Date.now() + 260;
|
|
@@ -1471,22 +1208,6 @@ class ZPopoverDirective {
|
|
|
1471
1208
|
}
|
|
1472
1209
|
this._viewportResizeTimeouts = [];
|
|
1473
1210
|
}
|
|
1474
|
-
_applyMobilePopoverPosition(position) {
|
|
1475
|
-
if (!isMobilePopoverViewport() || !this._overlayRef?.hasAttached()) {
|
|
1476
|
-
return;
|
|
1477
|
-
}
|
|
1478
|
-
const { overlayElement } = this._overlayRef;
|
|
1479
|
-
const { visualViewport } = window;
|
|
1480
|
-
const styles = getMobilePopoverPaneStyles({
|
|
1481
|
-
position,
|
|
1482
|
-
triggerRect: this._getTriggerElement().getBoundingClientRect(),
|
|
1483
|
-
overlayRect: overlayElement.getBoundingClientRect(),
|
|
1484
|
-
offset: this.zOffset(),
|
|
1485
|
-
viewportWidth: visualViewport?.width ?? window.innerWidth,
|
|
1486
|
-
viewportHeight: visualViewport?.height ?? window.innerHeight,
|
|
1487
|
-
});
|
|
1488
|
-
this._setOverlayPaneStyles(styles);
|
|
1489
|
-
}
|
|
1490
1211
|
_isTriggerVisibleInViewport() {
|
|
1491
1212
|
const { visualViewport } = window;
|
|
1492
1213
|
return isPopoverTriggerVisibleInViewport({
|
|
@@ -1495,11 +1216,6 @@ class ZPopoverDirective {
|
|
|
1495
1216
|
viewportHeight: visualViewport?.height ?? window.innerHeight,
|
|
1496
1217
|
});
|
|
1497
1218
|
}
|
|
1498
|
-
_setOverlayPaneStyles(styles) {
|
|
1499
|
-
for (const key of ['top', 'left', 'right', 'bottom', 'transform']) {
|
|
1500
|
-
this._renderer.setStyle(this._overlayRef?.overlayElement, key, styles[key]);
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
1219
|
_setupPopoverHover() {
|
|
1504
1220
|
const overlayElement = this._overlayRef?.overlayElement;
|
|
1505
1221
|
if (!overlayElement) {
|