@mesgflow/ui-kit 0.6.0 → 0.7.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/README.md +56 -5
- package/fesm2022/mesgflow-ui-kit-accordion.mjs +3 -2
- package/fesm2022/mesgflow-ui-kit-accordion.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-agenda.mjs +208 -0
- package/fesm2022/mesgflow-ui-kit-agenda.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-aspect-ratio.mjs +37 -0
- package/fesm2022/mesgflow-ui-kit-aspect-ratio.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-blocks.mjs +207 -0
- package/fesm2022/mesgflow-ui-kit-blocks.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-box-input.mjs +2 -2
- package/fesm2022/mesgflow-ui-kit-box-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-button.mjs +188 -242
- package/fesm2022/mesgflow-ui-kit-button.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-card.mjs +37 -16
- package/fesm2022/mesgflow-ui-kit-card.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-carousel.mjs +308 -0
- package/fesm2022/mesgflow-ui-kit-carousel.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs +16 -21
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-chip.mjs +2 -2
- package/fesm2022/mesgflow-ui-kit-chip.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-code-block.mjs +9 -5
- package/fesm2022/mesgflow-ui-kit-code-block.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs +6 -4
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-combobox.mjs +145 -65
- package/fesm2022/mesgflow-ui-kit-combobox.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs +4 -6
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-core.mjs +441 -128
- package/fesm2022/mesgflow-ui-kit-core.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-countdown.mjs +149 -0
- package/fesm2022/mesgflow-ui-kit-countdown.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs +131 -10
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-dialog.mjs +117 -34
- package/fesm2022/mesgflow-ui-kit-dialog.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-drawer.mjs +109 -0
- package/fesm2022/mesgflow-ui-kit-drawer.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-field.mjs +53 -12
- package/fesm2022/mesgflow-ui-kit-field.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-file-upload.mjs +356 -0
- package/fesm2022/mesgflow-ui-kit-file-upload.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs +131 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-icon.mjs +6 -1
- package/fesm2022/mesgflow-ui-kit-icon.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-icons-lucide.mjs +371 -0
- package/fesm2022/mesgflow-ui-kit-icons-lucide.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-inline-edit.mjs +279 -0
- package/fesm2022/mesgflow-ui-kit-inline-edit.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-input.mjs +147 -4
- package/fesm2022/mesgflow-ui-kit-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-lightbox.mjs +299 -0
- package/fesm2022/mesgflow-ui-kit-lightbox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-link.mjs +2 -2
- package/fesm2022/mesgflow-ui-kit-link.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-listbox.mjs +151 -0
- package/fesm2022/mesgflow-ui-kit-listbox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-mention.mjs +283 -0
- package/fesm2022/mesgflow-ui-kit-mention.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-menu.mjs +169 -5
- package/fesm2022/mesgflow-ui-kit-menu.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-nav-menu.mjs +276 -0
- package/fesm2022/mesgflow-ui-kit-nav-menu.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-notification-center.mjs +281 -0
- package/fesm2022/mesgflow-ui-kit-notification-center.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-number-input.mjs +7 -4
- package/fesm2022/mesgflow-ui-kit-number-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-pagination.mjs +4 -3
- package/fesm2022/mesgflow-ui-kit-pagination.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-password-input.mjs +7 -2
- package/fesm2022/mesgflow-ui-kit-password-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-popover.mjs +9 -49
- package/fesm2022/mesgflow-ui-kit-popover.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-progress.mjs +162 -21
- package/fesm2022/mesgflow-ui-kit-progress.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-radio.mjs +4 -6
- package/fesm2022/mesgflow-ui-kit-radio.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-rating.mjs +2 -2
- package/fesm2022/mesgflow-ui-kit-rating.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-search-input.mjs +9 -5
- package/fesm2022/mesgflow-ui-kit-search-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs +12 -8
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-select.mjs +3 -2
- package/fesm2022/mesgflow-ui-kit-select.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs +16 -13
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs +4 -3
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-slider.mjs +250 -3
- package/fesm2022/mesgflow-ui-kit-slider.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-sortable.mjs +526 -0
- package/fesm2022/mesgflow-ui-kit-sortable.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-spinner.mjs +42 -13
- package/fesm2022/mesgflow-ui-kit-spinner.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-split-button.mjs +205 -0
- package/fesm2022/mesgflow-ui-kit-split-button.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-splitter.mjs +210 -3
- package/fesm2022/mesgflow-ui-kit-splitter.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs +11 -4
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-stepper.mjs +167 -60
- package/fesm2022/mesgflow-ui-kit-stepper.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-switch.mjs +2 -2
- package/fesm2022/mesgflow-ui-kit-switch.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-table.mjs +16 -10
- package/fesm2022/mesgflow-ui-kit-table.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tabs.mjs +410 -169
- package/fesm2022/mesgflow-ui-kit-tabs.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs +7 -2
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-theming.mjs +4 -4
- package/fesm2022/mesgflow-ui-kit-theming.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-toast.mjs +113 -30
- package/fesm2022/mesgflow-ui-kit-toast.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-toggle.mjs +3 -2
- package/fesm2022/mesgflow-ui-kit-toggle.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs +4 -2
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs +73 -50
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tour.mjs +8 -20
- package/fesm2022/mesgflow-ui-kit-tour.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-transfer-list.mjs +288 -0
- package/fesm2022/mesgflow-ui-kit-transfer-list.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tree.mjs +1 -1
- package/fesm2022/mesgflow-ui-kit-tree.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-virtual-list.mjs +109 -0
- package/fesm2022/mesgflow-ui-kit-virtual-list.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit.mjs +92 -12836
- package/fesm2022/mesgflow-ui-kit.mjs.map +1 -1
- package/package.json +87 -3
- package/schematics/collection.json +10 -0
- package/schematics/migration.json +10 -0
- package/schematics/migrations/v0-7.cjs +70 -0
- package/schematics/ng-add/index.cjs +234 -0
- package/schematics/ng-add/schema.json +43 -0
- package/tokens/color.css +96 -0
- package/tokens/controls.css +145 -0
- package/tokens/elevation.css +62 -6
- package/tokens/motion.css +304 -66
- package/tokens/radius.css +14 -0
- package/tokens.css +1 -0
- package/tokens.json +1583 -0
- package/types/mesgflow-ui-kit-agenda.d.ts +49 -0
- package/types/mesgflow-ui-kit-aspect-ratio.d.ts +18 -0
- package/types/mesgflow-ui-kit-blocks.d.ts +128 -0
- package/types/mesgflow-ui-kit-button.d.ts +23 -38
- package/types/mesgflow-ui-kit-card.d.ts +26 -16
- package/types/mesgflow-ui-kit-carousel.d.ts +51 -0
- package/types/mesgflow-ui-kit-checkbox.d.ts +8 -5
- package/types/mesgflow-ui-kit-code-block.d.ts +4 -1
- package/types/mesgflow-ui-kit-combobox.d.ts +47 -22
- package/types/mesgflow-ui-kit-core.d.ts +271 -21
- package/types/mesgflow-ui-kit-countdown.d.ts +47 -0
- package/types/mesgflow-ui-kit-date-picker.d.ts +31 -1
- package/types/mesgflow-ui-kit-dialog.d.ts +29 -6
- package/types/mesgflow-ui-kit-drawer.d.ts +45 -0
- package/types/mesgflow-ui-kit-field.d.ts +17 -8
- package/types/mesgflow-ui-kit-file-upload.d.ts +64 -0
- package/types/mesgflow-ui-kit-hover-card.d.ts +2 -2
- package/types/mesgflow-ui-kit-icons-lucide.d.ts +27 -0
- package/types/mesgflow-ui-kit-inline-edit.d.ts +42 -0
- package/types/mesgflow-ui-kit-input.d.ts +64 -2
- package/types/mesgflow-ui-kit-lightbox.d.ts +54 -0
- package/types/mesgflow-ui-kit-listbox.d.ts +30 -0
- package/types/mesgflow-ui-kit-mention.d.ts +59 -0
- package/types/mesgflow-ui-kit-menu.d.ts +41 -2
- package/types/mesgflow-ui-kit-nav-menu.d.ts +58 -0
- package/types/mesgflow-ui-kit-notification-center.d.ts +41 -0
- package/types/mesgflow-ui-kit-number-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-password-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-popover.d.ts +13 -5
- package/types/mesgflow-ui-kit-progress.d.ts +33 -12
- package/types/mesgflow-ui-kit-radio.d.ts +2 -2
- package/types/mesgflow-ui-kit-search-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-segmented-control.d.ts +4 -0
- package/types/mesgflow-ui-kit-sidebar.d.ts +1 -1
- package/types/mesgflow-ui-kit-slider.d.ts +60 -1
- package/types/mesgflow-ui-kit-sortable.d.ts +103 -0
- package/types/mesgflow-ui-kit-spinner.d.ts +5 -8
- package/types/mesgflow-ui-kit-split-button.d.ts +47 -0
- package/types/mesgflow-ui-kit-splitter.d.ts +64 -1
- package/types/mesgflow-ui-kit-stat-tile.d.ts +3 -0
- package/types/mesgflow-ui-kit-stepper.d.ts +54 -32
- package/types/mesgflow-ui-kit-table.d.ts +2 -0
- package/types/mesgflow-ui-kit-tabs.d.ts +193 -93
- package/types/mesgflow-ui-kit-tag-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-toast.d.ts +48 -22
- package/types/mesgflow-ui-kit-tooltip.d.ts +15 -12
- package/types/mesgflow-ui-kit-transfer-list.d.ts +34 -0
- package/types/mesgflow-ui-kit-virtual-list.d.ts +35 -0
- package/types/mesgflow-ui-kit.d.ts +87 -5444
|
@@ -2,33 +2,19 @@ import { Overlay } from '@angular/cdk/overlay';
|
|
|
2
2
|
import { TemplatePortal, DomPortal } from '@angular/cdk/portal';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { input, inject, ElementRef, ViewContainerRef, Directive } from '@angular/core';
|
|
5
|
+
import { nextId, overlayPositions, exitDurationMs } from '@mesgflow/ui-kit/core';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },
|
|
9
|
-
{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },
|
|
10
|
-
],
|
|
11
|
-
bottom: [
|
|
12
|
-
{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },
|
|
13
|
-
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },
|
|
14
|
-
],
|
|
15
|
-
left: [
|
|
16
|
-
{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },
|
|
17
|
-
{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },
|
|
18
|
-
],
|
|
19
|
-
right: [
|
|
20
|
-
{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },
|
|
21
|
-
{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },
|
|
22
|
-
],
|
|
23
|
-
};
|
|
7
|
+
/** Tetikleyici ile balon arası boşluk — overlay panellerinden (4px) biraz fazla, imleç balonun üstüne binmesin. */
|
|
8
|
+
const TOOLTIP_OFFSET = 8;
|
|
24
9
|
/** `role`/`pointer-events-none` DIŞINDAKİ görsel kabuk — CDK'nın `panelClass`'ı ile OVERLAY PANELİNİN kendisine uygulanır (bkz. `show()`), hem düz metin hem şablon içeriği AYNI balon çerçevesini paylaşır. */
|
|
25
10
|
const BUBBLE_CLASSES = [
|
|
26
|
-
'rounded-
|
|
11
|
+
'rounded-md',
|
|
27
12
|
'bg-surface-inverse',
|
|
28
|
-
'px-2',
|
|
29
|
-
'py-1',
|
|
13
|
+
'px-2.5',
|
|
14
|
+
'py-1.5',
|
|
30
15
|
'text-xs',
|
|
31
16
|
'font-medium',
|
|
17
|
+
'leading-tight',
|
|
32
18
|
'whitespace-nowrap',
|
|
33
19
|
'text-fg-inverse',
|
|
34
20
|
'shadow-2',
|
|
@@ -46,11 +32,11 @@ const BUBBLE_CLASSES = [
|
|
|
46
32
|
* </ng-template>
|
|
47
33
|
* ```
|
|
48
34
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
35
|
+
* Erişilebilirlik: balon açıkken tetikleyiciye `aria-describedby` eklenir
|
|
36
|
+
* (tetikleyicinin `aria-label`'ı balon metniyle AYNIYSA eklenmez — ekran
|
|
37
|
+
* okuyucu aynı cümleyi iki kez okumasın). Konum ortak `overlayPositions()`
|
|
38
|
+
* üreticisinden gelir: balon tetikleyiciden dışarı doğru büyür, taşmada
|
|
39
|
+
* karşı tarafa çevrilir.
|
|
54
40
|
*/
|
|
55
41
|
class Tooltip {
|
|
56
42
|
/** Boş string verilirse (ve `mfTooltipContent` de yoksa) tooltip tamamen devre dışı kalır (ör. koşullu etiketler için). */
|
|
@@ -62,8 +48,9 @@ class Tooltip {
|
|
|
62
48
|
tooltipPosition = input('top', /* @ts-ignore */
|
|
63
49
|
...(ngDevMode ? [{ debugName: "tooltipPosition" }] : /* istanbul ignore next */ []));
|
|
64
50
|
overlay = inject(Overlay);
|
|
65
|
-
elementRef = inject(
|
|
51
|
+
elementRef = inject(ElementRef);
|
|
66
52
|
viewContainerRef = inject(ViewContainerRef);
|
|
53
|
+
bubbleId = nextId('mf-tooltip');
|
|
67
54
|
overlayRef;
|
|
68
55
|
bubbleEl;
|
|
69
56
|
showHandle;
|
|
@@ -81,27 +68,27 @@ class Tooltip {
|
|
|
81
68
|
const positionStrategy = this.overlay
|
|
82
69
|
.position()
|
|
83
70
|
.flexibleConnectedTo(this.elementRef)
|
|
84
|
-
.withPositions(
|
|
71
|
+
.withPositions(overlayPositions(this.tooltipPosition(), TOOLTIP_OFFSET))
|
|
85
72
|
.withPush(true);
|
|
86
73
|
this.overlayRef = this.overlay.create({
|
|
87
74
|
positionStrategy,
|
|
88
75
|
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
89
76
|
panelClass: [...BUBBLE_CLASSES, 'animate-overlay-in'],
|
|
90
77
|
});
|
|
91
|
-
this.overlayRef.overlayElement
|
|
92
|
-
|
|
78
|
+
const panel = this.overlayRef.overlayElement;
|
|
79
|
+
panel.setAttribute('role', 'tooltip');
|
|
80
|
+
panel.id = this.bubbleId;
|
|
81
|
+
panel.classList.add('pointer-events-none');
|
|
82
|
+
this.describe(text);
|
|
93
83
|
if (template) {
|
|
94
84
|
this.overlayRef.attach(new TemplatePortal(template, this.viewContainerRef));
|
|
95
85
|
return;
|
|
96
86
|
}
|
|
97
87
|
// Düz `appendChild` YETMİYOR: CDK'nın konumlandırma stratejisi (flexibleConnectedTo)
|
|
98
88
|
// sadece `OverlayRef.attach()` çağrıldığında çalışıyor — atlanırsa panel {0,0,0,0}
|
|
99
|
-
// boyutunda kalıp hiçbir yerde görünmüyor
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
// node'un ZATEN bir parent'a bağlı olmasını şart koşuyor (detach sonrası eski
|
|
103
|
-
// yerine geri koyabilmek için konumunu hatırlıyor), o yüzden önce `body`'ye
|
|
104
|
-
// ekleyip Portal'ı ondan SONRA kuruyoruz.
|
|
89
|
+
// boyutunda kalıp hiçbir yerde görünmüyor. `DomPortal` ham bir DOM node'unu attach
|
|
90
|
+
// akışına sokuyor, ama node'un ZATEN bir parent'a bağlı olmasını şart koşuyor —
|
|
91
|
+
// o yüzden önce `body`'ye ekleyip Portal'ı ondan SONRA kuruyoruz.
|
|
105
92
|
const bubble = document.createElement('span');
|
|
106
93
|
bubble.textContent = text;
|
|
107
94
|
document.body.appendChild(bubble);
|
|
@@ -110,29 +97,65 @@ class Tooltip {
|
|
|
110
97
|
}
|
|
111
98
|
/**
|
|
112
99
|
* Public: `SearchInput` gibi, kendi state değişimiyle tooltip'i ANINDA
|
|
113
|
-
* kapatmak isteyen tüketiciler için (bkz. search-input.ts `expand()`)
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* `
|
|
119
|
-
*
|
|
100
|
+
* kapatmak isteyen tüketiciler için (bkz. search-input.ts `expand()`).
|
|
101
|
+
*
|
|
102
|
+
* Erişilebilirlik ağacından ANINDA çıkar (`role`/`aria-describedby`
|
|
103
|
+
* kaldırılır — ekran okuyucu ve testler için "blur → kaldırıldı"
|
|
104
|
+
* sözleşmesi korunur), görsel balon ise `animate-overlay-out` oynatıp
|
|
105
|
+
* `exitDurationMs()` sonra dispose edilir. Yeni bir hover bu sırada yeni
|
|
106
|
+
* bir balon açabilir — eski ref bağımsız olarak kapanır.
|
|
120
107
|
*/
|
|
121
108
|
hide() {
|
|
122
109
|
clearTimeout(this.showHandle);
|
|
123
|
-
this.overlayRef
|
|
110
|
+
const ref = this.overlayRef;
|
|
111
|
+
const bubble = this.bubbleEl;
|
|
124
112
|
this.overlayRef = undefined;
|
|
125
|
-
// `dispose()` DomPortal'ı "attach öncesi" body konumuna geri koyuyor,
|
|
126
|
-
// DOM'dan silmiyor — silinmezse hover'dan çıkınca balon body'nin sonunda
|
|
127
|
-
// öksüz kalıp görünür kalıyordu (gerçek bulgu, birden fazla satırda
|
|
128
|
-
// sırayla hover edince ui-kit'te yakalandı). Şablon yolunda `bubbleEl`
|
|
129
|
-
// hiç atanmadığı için bu satır NO-OP.
|
|
130
|
-
this.bubbleEl?.remove();
|
|
131
113
|
this.bubbleEl = undefined;
|
|
114
|
+
this.undescribe();
|
|
115
|
+
if (!ref)
|
|
116
|
+
return;
|
|
117
|
+
const panel = ref.overlayElement;
|
|
118
|
+
panel.removeAttribute('role');
|
|
119
|
+
panel.removeAttribute('id');
|
|
120
|
+
panel.setAttribute('aria-hidden', 'true');
|
|
121
|
+
const dispose = () => {
|
|
122
|
+
ref.dispose();
|
|
123
|
+
// `dispose()` DomPortal'ı "attach öncesi" body konumuna geri koyuyor,
|
|
124
|
+
// DOM'dan silmiyor — silinmezse balon body'nin sonunda öksüz kalırdı.
|
|
125
|
+
bubble?.remove();
|
|
126
|
+
};
|
|
127
|
+
const exitMs = exitDurationMs();
|
|
128
|
+
if (exitMs === 0) {
|
|
129
|
+
dispose();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
panel.classList.remove('animate-overlay-in');
|
|
133
|
+
panel.classList.add('animate-overlay-out');
|
|
134
|
+
setTimeout(dispose, exitMs);
|
|
132
135
|
}
|
|
133
136
|
ngOnDestroy() {
|
|
134
137
|
this.hide();
|
|
135
138
|
}
|
|
139
|
+
describe(text) {
|
|
140
|
+
const host = this.elementRef.nativeElement;
|
|
141
|
+
if (text && host.getAttribute('aria-label')?.trim() === text.trim())
|
|
142
|
+
return;
|
|
143
|
+
const ids = (host.getAttribute('aria-describedby') ?? '').split(/\s+/).filter(Boolean);
|
|
144
|
+
if (!ids.includes(this.bubbleId))
|
|
145
|
+
ids.push(this.bubbleId);
|
|
146
|
+
host.setAttribute('aria-describedby', ids.join(' '));
|
|
147
|
+
}
|
|
148
|
+
undescribe() {
|
|
149
|
+
const host = this.elementRef.nativeElement;
|
|
150
|
+
const current = host.getAttribute('aria-describedby');
|
|
151
|
+
if (!current)
|
|
152
|
+
return;
|
|
153
|
+
const ids = current.split(/\s+/).filter((id) => id && id !== this.bubbleId);
|
|
154
|
+
if (ids.length)
|
|
155
|
+
host.setAttribute('aria-describedby', ids.join(' '));
|
|
156
|
+
else
|
|
157
|
+
host.removeAttribute('aria-describedby');
|
|
158
|
+
}
|
|
136
159
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
137
160
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: Tooltip, isStandalone: true, selector: "[mfTooltip], [mfTooltipContent]", inputs: { mfTooltip: { classPropertyName: "mfTooltip", publicName: "mfTooltip", isSignal: true, isRequired: false, transformFunction: null }, mfTooltipContent: { classPropertyName: "mfTooltipContent", publicName: "mfTooltipContent", isSignal: true, isRequired: false, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "scheduleShow()", "mouseleave": "hide()", "focus": "show()", "blur": "hide()", "keydown.escape": "hide()", "click": "hide()" } }, exportAs: ["mfTooltip"], ngImport: i0 });
|
|
138
161
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mesgflow-ui-kit-tooltip.mjs","sources":["../../../projects/ui-kit/tooltip/tooltip.ts","../../../projects/ui-kit/tooltip/mesgflow-ui-kit-tooltip.ts"],"sourcesContent":["import { Overlay, type ConnectedPosition, type OverlayRef } from '@angular/cdk/overlay';\r\nimport { DomPortal, TemplatePortal } from '@angular/cdk/portal';\r\nimport {\r\n Directive,\r\n ElementRef,\r\n OnDestroy,\r\n TemplateRef,\r\n ViewContainerRef,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\n\r\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\r\n\r\nconst POSITIONS: Record<TooltipPosition, ConnectedPosition[]> = {\r\n top: [\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },\r\n ],\r\n bottom: [\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },\r\n ],\r\n left: [\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },\r\n ],\r\n right: [\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },\r\n ],\r\n};\r\n\r\n/** `role`/`pointer-events-none` DIŞINDAKİ görsel kabuk — CDK'nın `panelClass`'ı ile OVERLAY PANELİNİN kendisine uygulanır (bkz. `show()`), hem düz metin hem şablon içeriği AYNI balon çerçevesini paylaşır. */\r\nconst BUBBLE_CLASSES = [\r\n 'rounded-sm',\r\n 'bg-surface-inverse',\r\n 'px-2',\r\n 'py-1',\r\n 'text-xs',\r\n 'font-medium',\r\n 'whitespace-nowrap',\r\n 'text-fg-inverse',\r\n 'shadow-2',\r\n];\r\n\r\n/**\r\n * `<button mfButton [mfTooltip]=\"'Filtreler'\">` (düz metin) veya\r\n * `<button mfButton [mfTooltipContent]=\"richTpl\">` (bkz. aşağıdaki örnek —\r\n * zengin/reaktif içerik) — hover/focus'ta CDK Overlay ile konumlanan bir\r\n * balon gösterir. `mfTooltipContent` VERİLMİŞSE `mfTooltip` YOK SAYILIR.\r\n *\r\n * ```html\r\n * <button mfButton [mfTooltipContent]=\"kbdHint\">Kaydet</button>\r\n * <ng-template #kbdHint>\r\n * Kaydet <kbd mfKbd>Ctrl</kbd>+<kbd mfKbd>S</kbd>\r\n * </ng-template>\r\n * ```\r\n *\r\n * Düz metin YOLU (ayrı bir Angular component/`ComponentPortal` kurmadan) ham\r\n * bir DOM node'u ile çiziliyor — statik metin için fazla makine olurdu.\r\n * Şablon YOLU `TemplatePortal` kullanır (gerçek Angular içeriği — binding/\r\n * directive/başka bir bileşen barındırabilir), bunun için `ViewContainerRef`\r\n * gerekiyor.\r\n */\r\n@Directive({\r\n selector: '[mfTooltip], [mfTooltipContent]',\r\n exportAs: 'mfTooltip',\r\n host: {\r\n '(mouseenter)': 'scheduleShow()',\r\n '(mouseleave)': 'hide()',\r\n '(focus)': 'show()',\r\n '(blur)': 'hide()',\r\n '(keydown.escape)': 'hide()',\r\n '(click)': 'hide()',\r\n },\r\n})\r\nexport class Tooltip implements OnDestroy {\r\n /** Boş string verilirse (ve `mfTooltipContent` de yoksa) tooltip tamamen devre dışı kalır (ör. koşullu etiketler için). */\r\n readonly mfTooltip = input('');\r\n /** Verilmişse `mfTooltip`'in YERİNE geçer — bkz. sınıf üstündeki JSDoc örneği. */\r\n readonly mfTooltipContent = input<TemplateRef<unknown> | null>(null);\r\n readonly tooltipPosition = input<TooltipPosition>('top');\r\n\r\n private readonly overlay = inject(Overlay);\r\n private readonly elementRef = inject(ElementRef<HTMLElement>);\r\n private readonly viewContainerRef = inject(ViewContainerRef);\r\n private overlayRef?: OverlayRef;\r\n private bubbleEl?: HTMLElement;\r\n private showHandle?: ReturnType<typeof setTimeout>;\r\n\r\n protected scheduleShow(): void {\r\n if (!this.mfTooltip() && !this.mfTooltipContent()) return;\r\n clearTimeout(this.showHandle);\r\n this.showHandle = setTimeout(() => this.show(), 350);\r\n }\r\n\r\n protected show(): void {\r\n const template = this.mfTooltipContent();\r\n const text = this.mfTooltip();\r\n if ((!template && !text) || this.overlayRef) return;\r\n\r\n const positionStrategy = this.overlay\r\n .position()\r\n .flexibleConnectedTo(this.elementRef)\r\n .withPositions(POSITIONS[this.tooltipPosition()])\r\n .withPush(true);\r\n\r\n this.overlayRef = this.overlay.create({\r\n positionStrategy,\r\n scrollStrategy: this.overlay.scrollStrategies.reposition(),\r\n panelClass: [...BUBBLE_CLASSES, 'animate-overlay-in'],\r\n });\r\n this.overlayRef.overlayElement.setAttribute('role', 'tooltip');\r\n this.overlayRef.overlayElement.classList.add('pointer-events-none');\r\n\r\n if (template) {\r\n this.overlayRef.attach(new TemplatePortal(template, this.viewContainerRef));\r\n return;\r\n }\r\n\r\n // Düz `appendChild` YETMİYOR: CDK'nın konumlandırma stratejisi (flexibleConnectedTo)\r\n // sadece `OverlayRef.attach()` çağrıldığında çalışıyor — atlanırsa panel {0,0,0,0}\r\n // boyutunda kalıp hiçbir yerde görünmüyor (gerçek bulgu, ui-kit'te yakalandı).\r\n // `DomPortal` gerçek bir Angular component'i olmadan (ComponentPortal'a gerek\r\n // kalmadan) ham bir DOM node'unu attach akışına sokuyor — ama `DomPortal`\r\n // node'un ZATEN bir parent'a bağlı olmasını şart koşuyor (detach sonrası eski\r\n // yerine geri koyabilmek için konumunu hatırlıyor), o yüzden önce `body`'ye\r\n // ekleyip Portal'ı ondan SONRA kuruyoruz.\r\n const bubble = document.createElement('span');\r\n bubble.textContent = text;\r\n document.body.appendChild(bubble);\r\n this.overlayRef.attach(new DomPortal(bubble));\r\n this.bubbleEl = bubble;\r\n }\r\n\r\n /**\r\n * Public: `SearchInput` gibi, kendi state değişimiyle tooltip'i ANINDA\r\n * kapatmak isteyen tüketiciler için (bkz. search-input.ts `expand()`) —\r\n * BİLEREK senkron: tooltip hover/focus/Escape gibi yüksek frekanslı,\r\n * anlık etkileşimlerle kapanıyor, `Popover`'ın gecikmeli-dispose deseni\r\n * (bkz. `popover.ts` `EXIT_MS`) burada gereksiz karmaşıklık + testlerin\r\n * beklediği \"blur → anında kaldırılır\" sözleşmesini bozardı (bkz.\r\n * `tooltip.spec.ts`). Giriş animasyonu (`show()`teki `animate-overlay-in`)\r\n * yeterli — önceden tooltip'in HİÇ animasyonu yoktu (gerçek bulgu).\r\n */\r\n hide(): void {\r\n clearTimeout(this.showHandle);\r\n this.overlayRef?.dispose();\r\n this.overlayRef = undefined;\r\n // `dispose()` DomPortal'ı \"attach öncesi\" body konumuna geri koyuyor,\r\n // DOM'dan silmiyor — silinmezse hover'dan çıkınca balon body'nin sonunda\r\n // öksüz kalıp görünür kalıyordu (gerçek bulgu, birden fazla satırda\r\n // sırayla hover edince ui-kit'te yakalandı). Şablon yolunda `bubbleEl`\r\n // hiç atanmadığı için bu satır NO-OP.\r\n this.bubbleEl?.remove();\r\n this.bubbleEl = undefined;\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.hide();\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-tooltip.mjs","sources":["../../../projects/ui-kit/tooltip/tooltip.ts","../../../projects/ui-kit/tooltip/mesgflow-ui-kit-tooltip.ts"],"sourcesContent":["import { Overlay, type OverlayRef } from '@angular/cdk/overlay';\r\nimport { DomPortal, TemplatePortal } from '@angular/cdk/portal';\r\nimport {\r\n Directive,\r\n ElementRef,\r\n OnDestroy,\r\n TemplateRef,\r\n ViewContainerRef,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\nimport { exitDurationMs, nextId, overlayPositions } from '@mesgflow/ui-kit/core';\r\n\r\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\r\n\r\n/** Tetikleyici ile balon arası boşluk — overlay panellerinden (4px) biraz fazla, imleç balonun üstüne binmesin. */\r\nconst TOOLTIP_OFFSET = 8;\r\n\r\n/** `role`/`pointer-events-none` DIŞINDAKİ görsel kabuk — CDK'nın `panelClass`'ı ile OVERLAY PANELİNİN kendisine uygulanır (bkz. `show()`), hem düz metin hem şablon içeriği AYNI balon çerçevesini paylaşır. */\r\nconst BUBBLE_CLASSES = [\r\n 'rounded-md',\r\n 'bg-surface-inverse',\r\n 'px-2.5',\r\n 'py-1.5',\r\n 'text-xs',\r\n 'font-medium',\r\n 'leading-tight',\r\n 'whitespace-nowrap',\r\n 'text-fg-inverse',\r\n 'shadow-2',\r\n];\r\n\r\n/**\r\n * `<button mfButton [mfTooltip]=\"'Filtreler'\">` (düz metin) veya\r\n * `<button mfButton [mfTooltipContent]=\"richTpl\">` (bkz. aşağıdaki örnek —\r\n * zengin/reaktif içerik) — hover/focus'ta CDK Overlay ile konumlanan bir\r\n * balon gösterir. `mfTooltipContent` VERİLMİŞSE `mfTooltip` YOK SAYILIR.\r\n *\r\n * ```html\r\n * <button mfButton [mfTooltipContent]=\"kbdHint\">Kaydet</button>\r\n * <ng-template #kbdHint>\r\n * Kaydet <kbd mfKbd>Ctrl</kbd>+<kbd mfKbd>S</kbd>\r\n * </ng-template>\r\n * ```\r\n *\r\n * Erişilebilirlik: balon açıkken tetikleyiciye `aria-describedby` eklenir\r\n * (tetikleyicinin `aria-label`'ı balon metniyle AYNIYSA eklenmez — ekran\r\n * okuyucu aynı cümleyi iki kez okumasın). Konum ortak `overlayPositions()`\r\n * üreticisinden gelir: balon tetikleyiciden dışarı doğru büyür, taşmada\r\n * karşı tarafa çevrilir.\r\n */\r\n@Directive({\r\n selector: '[mfTooltip], [mfTooltipContent]',\r\n exportAs: 'mfTooltip',\r\n host: {\r\n '(mouseenter)': 'scheduleShow()',\r\n '(mouseleave)': 'hide()',\r\n '(focus)': 'show()',\r\n '(blur)': 'hide()',\r\n '(keydown.escape)': 'hide()',\r\n '(click)': 'hide()',\r\n },\r\n})\r\nexport class Tooltip implements OnDestroy {\r\n /** Boş string verilirse (ve `mfTooltipContent` de yoksa) tooltip tamamen devre dışı kalır (ör. koşullu etiketler için). */\r\n readonly mfTooltip = input('');\r\n /** Verilmişse `mfTooltip`'in YERİNE geçer — bkz. sınıf üstündeki JSDoc örneği. */\r\n readonly mfTooltipContent = input<TemplateRef<unknown> | null>(null);\r\n readonly tooltipPosition = input<TooltipPosition>('top');\r\n\r\n private readonly overlay = inject(Overlay);\r\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly viewContainerRef = inject(ViewContainerRef);\r\n private readonly bubbleId = nextId('mf-tooltip');\r\n private overlayRef?: OverlayRef;\r\n private bubbleEl?: HTMLElement;\r\n private showHandle?: ReturnType<typeof setTimeout>;\r\n\r\n protected scheduleShow(): void {\r\n if (!this.mfTooltip() && !this.mfTooltipContent()) return;\r\n clearTimeout(this.showHandle);\r\n this.showHandle = setTimeout(() => this.show(), 350);\r\n }\r\n\r\n protected show(): void {\r\n const template = this.mfTooltipContent();\r\n const text = this.mfTooltip();\r\n if ((!template && !text) || this.overlayRef) return;\r\n\r\n const positionStrategy = this.overlay\r\n .position()\r\n .flexibleConnectedTo(this.elementRef)\r\n .withPositions(overlayPositions(this.tooltipPosition(), TOOLTIP_OFFSET))\r\n .withPush(true);\r\n\r\n this.overlayRef = this.overlay.create({\r\n positionStrategy,\r\n scrollStrategy: this.overlay.scrollStrategies.reposition(),\r\n panelClass: [...BUBBLE_CLASSES, 'animate-overlay-in'],\r\n });\r\n const panel = this.overlayRef.overlayElement;\r\n panel.setAttribute('role', 'tooltip');\r\n panel.id = this.bubbleId;\r\n panel.classList.add('pointer-events-none');\r\n this.describe(text);\r\n\r\n if (template) {\r\n this.overlayRef.attach(new TemplatePortal(template, this.viewContainerRef));\r\n return;\r\n }\r\n\r\n // Düz `appendChild` YETMİYOR: CDK'nın konumlandırma stratejisi (flexibleConnectedTo)\r\n // sadece `OverlayRef.attach()` çağrıldığında çalışıyor — atlanırsa panel {0,0,0,0}\r\n // boyutunda kalıp hiçbir yerde görünmüyor. `DomPortal` ham bir DOM node'unu attach\r\n // akışına sokuyor, ama node'un ZATEN bir parent'a bağlı olmasını şart koşuyor —\r\n // o yüzden önce `body`'ye ekleyip Portal'ı ondan SONRA kuruyoruz.\r\n const bubble = document.createElement('span');\r\n bubble.textContent = text;\r\n document.body.appendChild(bubble);\r\n this.overlayRef.attach(new DomPortal(bubble));\r\n this.bubbleEl = bubble;\r\n }\r\n\r\n /**\r\n * Public: `SearchInput` gibi, kendi state değişimiyle tooltip'i ANINDA\r\n * kapatmak isteyen tüketiciler için (bkz. search-input.ts `expand()`).\r\n *\r\n * Erişilebilirlik ağacından ANINDA çıkar (`role`/`aria-describedby`\r\n * kaldırılır — ekran okuyucu ve testler için \"blur → kaldırıldı\"\r\n * sözleşmesi korunur), görsel balon ise `animate-overlay-out` oynatıp\r\n * `exitDurationMs()` sonra dispose edilir. Yeni bir hover bu sırada yeni\r\n * bir balon açabilir — eski ref bağımsız olarak kapanır.\r\n */\r\n hide(): void {\r\n clearTimeout(this.showHandle);\r\n const ref = this.overlayRef;\r\n const bubble = this.bubbleEl;\r\n this.overlayRef = undefined;\r\n this.bubbleEl = undefined;\r\n this.undescribe();\r\n if (!ref) return;\r\n\r\n const panel = ref.overlayElement;\r\n panel.removeAttribute('role');\r\n panel.removeAttribute('id');\r\n panel.setAttribute('aria-hidden', 'true');\r\n\r\n const dispose = () => {\r\n ref.dispose();\r\n // `dispose()` DomPortal'ı \"attach öncesi\" body konumuna geri koyuyor,\r\n // DOM'dan silmiyor — silinmezse balon body'nin sonunda öksüz kalırdı.\r\n bubble?.remove();\r\n };\r\n\r\n const exitMs = exitDurationMs();\r\n if (exitMs === 0) {\r\n dispose();\r\n return;\r\n }\r\n panel.classList.remove('animate-overlay-in');\r\n panel.classList.add('animate-overlay-out');\r\n setTimeout(dispose, exitMs);\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.hide();\r\n }\r\n\r\n private describe(text: string): void {\r\n const host = this.elementRef.nativeElement;\r\n if (text && host.getAttribute('aria-label')?.trim() === text.trim()) return;\r\n const ids = (host.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean);\r\n if (!ids.includes(this.bubbleId)) ids.push(this.bubbleId);\r\n host.setAttribute('aria-describedby', ids.join(' '));\r\n }\r\n\r\n private undescribe(): void {\r\n const host = this.elementRef.nativeElement;\r\n const current = host.getAttribute('aria-describedby');\r\n if (!current) return;\r\n const ids = current.split(/\\s+/).filter((id) => id && id !== this.bubbleId);\r\n if (ids.length) host.setAttribute('aria-describedby', ids.join(' '));\r\n else host.removeAttribute('aria-describedby');\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { signal, computed, inject, ElementRef, afterRenderEffect, Component, Injector, DOCUMENT, Service } from '@angular/core';
|
|
3
3
|
import { createOverlayRef, createGlobalPositionStrategy, createFlexibleConnectedPositionStrategy, createRepositionScrollStrategy } from '@angular/cdk/overlay';
|
|
4
4
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
5
|
-
import { MF_TOUR_LABELS, isRtl } from '@mesgflow/ui-kit/core';
|
|
5
|
+
import { MF_TOUR_LABELS, isRtl, overlayPositions } from '@mesgflow/ui-kit/core';
|
|
6
6
|
import * as i1 from '@angular/cdk/a11y';
|
|
7
7
|
import { A11yModule } from '@angular/cdk/a11y';
|
|
8
8
|
import { Button } from '@mesgflow/ui-kit/button';
|
|
@@ -125,24 +125,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
125
125
|
|
|
126
126
|
const GAP = 12;
|
|
127
127
|
const DEFAULT_PADDING = 6;
|
|
128
|
-
/** Tercih edilen taraf önce, sığmazsa
|
|
129
|
-
const
|
|
130
|
-
bottom:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
top: [
|
|
135
|
-
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -GAP },
|
|
136
|
-
{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: GAP },
|
|
137
|
-
],
|
|
138
|
-
end: [
|
|
139
|
-
{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: GAP },
|
|
140
|
-
{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -GAP },
|
|
141
|
-
],
|
|
142
|
-
start: [
|
|
143
|
-
{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -GAP },
|
|
144
|
-
{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: GAP },
|
|
145
|
-
],
|
|
128
|
+
/** Tercih edilen taraf önce, sığmazsa karşısı — ortak üretici (anchor-origin panelClass dahil). */
|
|
129
|
+
const PLACEMENT = {
|
|
130
|
+
bottom: 'bottom',
|
|
131
|
+
top: 'top',
|
|
132
|
+
end: 'right',
|
|
133
|
+
start: 'left',
|
|
146
134
|
};
|
|
147
135
|
/**
|
|
148
136
|
* `const result = await tour.start([{ target: '#new-campaign', title: '…', content: '…' }, …]);`
|
|
@@ -208,7 +196,7 @@ class TourService {
|
|
|
208
196
|
const place = (step) => {
|
|
209
197
|
const strategy = target
|
|
210
198
|
? createFlexibleConnectedPositionStrategy(this.injector, target)
|
|
211
|
-
.withPositions(
|
|
199
|
+
.withPositions(overlayPositions(PLACEMENT[step.placement ?? 'bottom'], GAP))
|
|
212
200
|
.withViewportMargin(12)
|
|
213
201
|
.withPush(true)
|
|
214
202
|
: createGlobalPositionStrategy(this.injector).centerHorizontally().centerVertically();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mesgflow-ui-kit-tour.mjs","sources":["../../../projects/ui-kit/tour/tour.model.ts","../../../projects/ui-kit/tour/tour-card.ts","../../../projects/ui-kit/tour/tour-card.html","../../../projects/ui-kit/tour/tour-spotlight.ts","../../../projects/ui-kit/tour/tour.service.ts","../../../projects/ui-kit/tour/mesgflow-ui-kit-tour.ts"],"sourcesContent":["import { ElementRef, computed, signal } from '@angular/core';\r\n\r\nexport type TourPlacement = 'bottom' | 'top' | 'start' | 'end';\r\n\r\nexport interface TourStep {\r\n /**\r\n * Vurgulanacak öğe: CSS seçicisi, öğe ya da `ElementRef`. Verilmezse adım ekran ortasında\r\n * bir karşılama/kapanış kartı olarak gösterilir (spot ışığı deliksiz karartır).\r\n */\r\n target?: string | Element | ElementRef<Element>;\r\n title: string;\r\n content: string;\r\n /** Kartın hedefe göre yeri — mantıksal (`start`/`end` RTL'de yer değiştirir). Sığmazsa karşı taraf. */\r\n placement?: TourPlacement;\r\n}\r\n\r\nexport type TourResult = 'completed' | 'skipped';\r\n\r\nexport interface TourOptions {\r\n /** Hedefin çevresindeki boşluk (px). */\r\n padding?: number;\r\n /** Her adım değişiminde (0 tabanlı indeks) — analitik ya da hedefin görünür olması için. */\r\n stepChange?: (index: number, step: TourStep) => void;\r\n}\r\n\r\nexport interface SpotlightRect {\r\n top: number;\r\n left: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\n/** Bir tur çalışmasının durumu — servis ile spot ışığı ve kart bileşenleri bunu paylaşır. */\r\nexport class TourRun {\r\n readonly index = signal(0);\r\n /** Hedefin viewport'taki kutusu (padding dahil); hedefsiz adımda `null`. */\r\n readonly rect = signal<SpotlightRect | null>(null);\r\n\r\n readonly step = computed(() => this.steps[this.index()]!);\r\n readonly isFirst = computed(() => this.index() === 0);\r\n readonly isLast = computed(() => this.index() === this.steps.length - 1);\r\n\r\n constructor(\r\n readonly steps: readonly TourStep[],\r\n private readonly onNavigate: (index: number) => void,\r\n private readonly onFinish: (result: TourResult) => void,\r\n ) {}\r\n\r\n next(): void {\r\n if (this.isLast()) this.onFinish('completed');\r\n else this.onNavigate(this.index() + 1);\r\n }\r\n\r\n back(): void {\r\n if (!this.isFirst()) this.onNavigate(this.index() - 1);\r\n }\r\n\r\n skip(): void {\r\n this.onFinish('skipped');\r\n }\r\n}\r\n","import { A11yModule } from '@angular/cdk/a11y';\r\nimport { Component, ElementRef, afterRenderEffect, inject } from '@angular/core';\r\nimport { Button } from '@mesgflow/ui-kit/button';\r\nimport { MF_TOUR_LABELS } from '@mesgflow/ui-kit/core';\r\nimport { Icon } from '@mesgflow/ui-kit/icon';\r\nimport { TourRun } from './tour.model';\r\n\r\nlet tourCardIdSeq = 0;\r\n\r\n/**\r\n * Adım kartı — modal `role=\"dialog\"`, odak kartın içinde tutulur (`cdkTrapFocus`). Her adım\r\n * değişiminde odak kartın KENDİSİNE taşınır: ekran okuyucu `aria-labelledby` (başlık) +\r\n * `aria-describedby` (içerik) üzerinden yeni adımı baştan okur. Esc turu atlar.\r\n */\r\n@Component({\r\n selector: 'mf-tour-card',\r\n imports: [A11yModule, Button, Icon],\r\n templateUrl: './tour-card.html',\r\n})\r\nexport class TourCard {\r\n protected readonly run = inject(TourRun);\r\n protected readonly labels = inject(MF_TOUR_LABELS);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n\r\n private readonly id = `mf-tour-${++tourCardIdSeq}`;\r\n protected readonly titleId = `${this.id}-title`;\r\n protected readonly contentId = `${this.id}-content`;\r\n\r\n constructor() {\r\n afterRenderEffect(() => {\r\n this.run.index();\r\n this.host.nativeElement.querySelector<HTMLElement>('[role=\"dialog\"]')?.focus();\r\n });\r\n }\r\n}\r\n","<div\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n cdkTrapFocus\r\n [attr.aria-labelledby]=\"titleId\"\r\n [attr.aria-describedby]=\"contentId\"\r\n class=\"w-[min(20rem,calc(100vw-2rem))] animate-overlay-in rounded-xl border border-hairline bg-overlay p-4 shadow-3 outline-none\"\r\n (keydown.escape)=\"run.skip()\"\r\n>\r\n <div class=\"flex items-center justify-between gap-2\">\r\n <span class=\"font-mono text-eyebrow text-help uppercase tabular-nums\">\r\n {{ run.index() + 1 }} {{ labels().stepOf }} {{ run.steps.length }}\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"-me-1.5 inline-flex size-7 cursor-pointer appearance-none items-center justify-center rounded-md border-0 bg-transparent text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-state-hover hover:text-fg focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring\"\r\n [attr.aria-label]=\"labels().skip\"\r\n (click)=\"run.skip()\"\r\n >\r\n <span mfIcon [size]=\"16\">close</span>\r\n </button>\r\n </div>\r\n\r\n <h2 [id]=\"titleId\" class=\"mt-1.5 font-display text-base font-semibold text-fg\">\r\n {{ run.step().title }}\r\n </h2>\r\n <p [id]=\"contentId\" class=\"mt-1 text-sm text-fg-muted\">{{ run.step().content }}</p>\r\n\r\n <div class=\"mt-4 flex items-center gap-2\">\r\n <!-- İlerleme: adım başına bir çizgi; salt görsel, sayı zaten yukarıda. -->\r\n <div class=\"flex flex-1 items-center gap-1\" aria-hidden=\"true\">\r\n @for (step of run.steps; track $index) {\r\n <span\r\n class=\"h-1 flex-1 rounded-full transition-colors duration-base ease-emphasis\"\r\n [class]=\"$index <= run.index() ? 'bg-help' : 'bg-surface-alt'\"\r\n ></span>\r\n }\r\n </div>\r\n @if (!run.isFirst()) {\r\n <button\r\n mfButton\r\n appearance=\"text\"\r\n tone=\"neutral\"\r\n size=\"sm\"\r\n type=\"button\"\r\n (click)=\"run.back()\"\r\n >\r\n {{ labels().back }}\r\n </button>\r\n }\r\n <button mfButton tone=\"help\" size=\"sm\" type=\"button\" (click)=\"run.next()\">\r\n {{ run.isLast() ? labels().done : labels().next }}\r\n </button>\r\n </div>\r\n</div>\r\n","import { Component, inject } from '@angular/core';\r\nimport { TourRun } from './tour.model';\r\n\r\n/** Dialog arka planıyla aynı karartma (bkz. motion.css `.mf-dialog-backdrop`), biraz daha koyu. */\r\nconst SCRIM = 'color-mix(in srgb, var(--color-neutral-975) 55%, transparent)';\r\n\r\n/**\r\n * Tam ekran katman: tıklamaları yutar (tur modal) ve hedefin çevresi dışını karartır. Delik,\r\n * hedef kutusuna oturan bir öğenin çok büyük `box-shadow`'u — maske/SVG yolu gerekmez, konumu\r\n * `transition` ile adımlar arasında kayar. Hedefsiz adımda düz karartma.\r\n */\r\n@Component({\r\n selector: 'mf-tour-spotlight',\r\n host: { class: 'fixed inset-0 block' },\r\n template: `\r\n @if (run.rect(); as rect) {\r\n <div class=\"absolute inset-0\" aria-hidden=\"true\"></div>\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"pointer-events-none fixed rounded-lg outline outline-2 outline-offset-0 outline-help transition-[top,left,width,height] duration-base ease-emphasis\"\r\n [style.top.px]=\"rect.top\"\r\n [style.left.px]=\"rect.left\"\r\n [style.width.px]=\"rect.width\"\r\n [style.height.px]=\"rect.height\"\r\n [style.box-shadow]=\"'0 0 0 200vmax ' + scrim\"\r\n ></div>\r\n } @else {\r\n <div class=\"absolute inset-0\" aria-hidden=\"true\" [style.background-color]=\"scrim\"></div>\r\n }\r\n `,\r\n})\r\nexport class TourSpotlight {\r\n protected readonly run = inject(TourRun);\r\n protected readonly scrim = SCRIM;\r\n}\r\n","import {\r\n createFlexibleConnectedPositionStrategy,\r\n createGlobalPositionStrategy,\r\n createOverlayRef,\r\n createRepositionScrollStrategy,\r\n type ConnectedPosition,\r\n type OverlayRef,\r\n} from '@angular/cdk/overlay';\r\nimport { ComponentPortal } from '@angular/cdk/portal';\r\nimport { DOCUMENT, ElementRef, Injector, Service, inject } from '@angular/core';\r\nimport { isRtl } from '@mesgflow/ui-kit/core';\r\nimport { TourCard } from './tour-card';\r\nimport {\r\n TourRun,\r\n type SpotlightRect,\r\n type TourOptions,\r\n type TourPlacement,\r\n type TourResult,\r\n type TourStep,\r\n} from './tour.model';\r\nimport { TourSpotlight } from './tour-spotlight';\r\n\r\nconst GAP = 12;\r\nconst DEFAULT_PADDING = 6;\r\n\r\n/** Tercih edilen taraf önce, sığmazsa karşısı, sonra diğer eksen. */\r\nconst POSITIONS: Record<TourPlacement, ConnectedPosition[]> = {\r\n bottom: [\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: GAP },\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -GAP },\r\n ],\r\n top: [\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -GAP },\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: GAP },\r\n ],\r\n end: [\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: GAP },\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -GAP },\r\n ],\r\n start: [\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -GAP },\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: GAP },\r\n ],\r\n};\r\n\r\n/**\r\n * `const result = await tour.start([{ target: '#new-campaign', title: '…', content: '…' }, …]);`\r\n *\r\n * Ürün turu / coachmark — `help` tonu tam bunun için. İki overlay: tam ekran spot ışığı (karartır,\r\n * tıklamaları yutar) ve hedefe bağlı adım kartı. Her adımda hedef görünür alana kaydırılır\r\n * (azaltılmış harekette anında), kaydırma/yeniden boyutlandırmada delik ve kart birlikte izler.\r\n * Bulunamayan hedef ortalanmış karta düşer (tur kırılmaz). Aynı anda tek tur; bitince odak\r\n * turdan önceki öğeye döner. Sonuç: `'completed'` ya da `'skipped'` (Esc, ×).\r\n */\r\n@Service()\r\nexport class TourService {\r\n private readonly injector = inject(Injector);\r\n private readonly document = inject(DOCUMENT);\r\n private active: Promise<TourResult> | null = null;\r\n\r\n get isActive(): boolean {\r\n return this.active !== null;\r\n }\r\n\r\n start(steps: readonly TourStep[], options: TourOptions = {}): Promise<TourResult> {\r\n if (this.active) return this.active;\r\n if (steps.length === 0) return Promise.resolve('completed');\r\n\r\n this.active = new Promise<TourResult>((resolve) => {\r\n const doc = this.document;\r\n const view = doc.defaultView;\r\n const padding = options.padding ?? DEFAULT_PADDING;\r\n const previousFocus = doc.activeElement as HTMLElement | null;\r\n const direction = isRtl(doc.documentElement) ? 'rtl' : 'ltr';\r\n let target: Element | null = null;\r\n let frame = 0;\r\n\r\n const run: TourRun = new TourRun(\r\n steps,\r\n (index) => show(index),\r\n (result) => finish(result),\r\n );\r\n const injector = Injector.create({\r\n providers: [{ provide: TourRun, useValue: run }],\r\n parent: this.injector,\r\n });\r\n\r\n const spotlight = createOverlayRef(this.injector, {\r\n positionStrategy: createGlobalPositionStrategy(this.injector),\r\n width: '100vw',\r\n height: '100vh',\r\n direction,\r\n });\r\n spotlight.attach(new ComponentPortal(TourSpotlight, null, injector));\r\n\r\n const card: OverlayRef = createOverlayRef(this.injector, { direction });\r\n\r\n const measure = () => {\r\n frame = 0;\r\n if (!target) {\r\n run.rect.set(null);\r\n return;\r\n }\r\n const box = target.getBoundingClientRect();\r\n run.rect.set({\r\n top: box.top - padding,\r\n left: box.left - padding,\r\n width: box.width + padding * 2,\r\n height: box.height + padding * 2,\r\n } satisfies SpotlightRect);\r\n card.updatePosition();\r\n };\r\n const schedule = () => {\r\n if (!frame) frame = view?.requestAnimationFrame(measure) ?? 0;\r\n };\r\n\r\n const place = (step: TourStep) => {\r\n const strategy = target\r\n ? createFlexibleConnectedPositionStrategy(this.injector, target as HTMLElement)\r\n .withPositions(POSITIONS[step.placement ?? 'bottom'])\r\n .withViewportMargin(12)\r\n .withPush(true)\r\n : createGlobalPositionStrategy(this.injector).centerHorizontally().centerVertically();\r\n card.updatePositionStrategy(strategy);\r\n card.updateScrollStrategy(createRepositionScrollStrategy(this.injector));\r\n };\r\n\r\n const show = (index: number) => {\r\n const step = steps[index]!;\r\n target = resolveTarget(step.target, doc);\r\n run.index.set(index);\r\n options.stepChange?.(index, step);\r\n if (target) {\r\n const reduced = view?.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? true;\r\n (target as HTMLElement).scrollIntoView?.({\r\n block: 'center',\r\n inline: 'nearest',\r\n behavior: reduced ? 'auto' : 'smooth',\r\n });\r\n }\r\n place(step);\r\n if (!card.hasAttached()) card.attach(new ComponentPortal(TourCard, null, injector));\r\n measure();\r\n };\r\n\r\n const finish = (result: TourResult) => {\r\n view?.removeEventListener('scroll', schedule, true);\r\n view?.removeEventListener('resize', schedule);\r\n if (frame) view?.cancelAnimationFrame(frame);\r\n card.dispose();\r\n spotlight.dispose();\r\n this.active = null;\r\n previousFocus?.focus?.();\r\n resolve(result);\r\n };\r\n\r\n view?.addEventListener('scroll', schedule, true);\r\n view?.addEventListener('resize', schedule);\r\n show(0);\r\n });\r\n\r\n return this.active;\r\n }\r\n}\r\n\r\nfunction resolveTarget(target: TourStep['target'], doc: Document): Element | null {\r\n if (!target) return null;\r\n if (typeof target === 'string') return doc.querySelector(target);\r\n return target instanceof ElementRef ? target.nativeElement : target;\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-tour.mjs","sources":["../../../projects/ui-kit/tour/tour.model.ts","../../../projects/ui-kit/tour/tour-card.ts","../../../projects/ui-kit/tour/tour-card.html","../../../projects/ui-kit/tour/tour-spotlight.ts","../../../projects/ui-kit/tour/tour.service.ts","../../../projects/ui-kit/tour/mesgflow-ui-kit-tour.ts"],"sourcesContent":["import { ElementRef, computed, signal } from '@angular/core';\r\n\r\nexport type TourPlacement = 'bottom' | 'top' | 'start' | 'end';\r\n\r\nexport interface TourStep {\r\n /**\r\n * Vurgulanacak öğe: CSS seçicisi, öğe ya da `ElementRef`. Verilmezse adım ekran ortasında\r\n * bir karşılama/kapanış kartı olarak gösterilir (spot ışığı deliksiz karartır).\r\n */\r\n target?: string | Element | ElementRef<Element>;\r\n title: string;\r\n content: string;\r\n /** Kartın hedefe göre yeri — mantıksal (`start`/`end` RTL'de yer değiştirir). Sığmazsa karşı taraf. */\r\n placement?: TourPlacement;\r\n}\r\n\r\nexport type TourResult = 'completed' | 'skipped';\r\n\r\nexport interface TourOptions {\r\n /** Hedefin çevresindeki boşluk (px). */\r\n padding?: number;\r\n /** Her adım değişiminde (0 tabanlı indeks) — analitik ya da hedefin görünür olması için. */\r\n stepChange?: (index: number, step: TourStep) => void;\r\n}\r\n\r\nexport interface SpotlightRect {\r\n top: number;\r\n left: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\n/** Bir tur çalışmasının durumu — servis ile spot ışığı ve kart bileşenleri bunu paylaşır. */\r\nexport class TourRun {\r\n readonly index = signal(0);\r\n /** Hedefin viewport'taki kutusu (padding dahil); hedefsiz adımda `null`. */\r\n readonly rect = signal<SpotlightRect | null>(null);\r\n\r\n readonly step = computed(() => this.steps[this.index()]!);\r\n readonly isFirst = computed(() => this.index() === 0);\r\n readonly isLast = computed(() => this.index() === this.steps.length - 1);\r\n\r\n constructor(\r\n readonly steps: readonly TourStep[],\r\n private readonly onNavigate: (index: number) => void,\r\n private readonly onFinish: (result: TourResult) => void,\r\n ) {}\r\n\r\n next(): void {\r\n if (this.isLast()) this.onFinish('completed');\r\n else this.onNavigate(this.index() + 1);\r\n }\r\n\r\n back(): void {\r\n if (!this.isFirst()) this.onNavigate(this.index() - 1);\r\n }\r\n\r\n skip(): void {\r\n this.onFinish('skipped');\r\n }\r\n}\r\n","import { A11yModule } from '@angular/cdk/a11y';\r\nimport { Component, ElementRef, afterRenderEffect, inject } from '@angular/core';\r\nimport { Button } from '@mesgflow/ui-kit/button';\r\nimport { MF_TOUR_LABELS } from '@mesgflow/ui-kit/core';\r\nimport { Icon } from '@mesgflow/ui-kit/icon';\r\nimport { TourRun } from './tour.model';\r\n\r\nlet tourCardIdSeq = 0;\r\n\r\n/**\r\n * Adım kartı — modal `role=\"dialog\"`, odak kartın içinde tutulur (`cdkTrapFocus`). Her adım\r\n * değişiminde odak kartın KENDİSİNE taşınır: ekran okuyucu `aria-labelledby` (başlık) +\r\n * `aria-describedby` (içerik) üzerinden yeni adımı baştan okur. Esc turu atlar.\r\n */\r\n@Component({\r\n selector: 'mf-tour-card',\r\n imports: [A11yModule, Button, Icon],\r\n templateUrl: './tour-card.html',\r\n})\r\nexport class TourCard {\r\n protected readonly run = inject(TourRun);\r\n protected readonly labels = inject(MF_TOUR_LABELS);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n\r\n private readonly id = `mf-tour-${++tourCardIdSeq}`;\r\n protected readonly titleId = `${this.id}-title`;\r\n protected readonly contentId = `${this.id}-content`;\r\n\r\n constructor() {\r\n afterRenderEffect(() => {\r\n this.run.index();\r\n this.host.nativeElement.querySelector<HTMLElement>('[role=\"dialog\"]')?.focus();\r\n });\r\n }\r\n}\r\n","<div\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n cdkTrapFocus\r\n [attr.aria-labelledby]=\"titleId\"\r\n [attr.aria-describedby]=\"contentId\"\r\n class=\"w-[min(20rem,calc(100vw-2rem))] animate-overlay-in rounded-xl border border-hairline bg-overlay p-4 shadow-3 outline-none\"\r\n (keydown.escape)=\"run.skip()\"\r\n>\r\n <div class=\"flex items-center justify-between gap-2\">\r\n <span class=\"font-mono text-eyebrow text-help uppercase tabular-nums\">\r\n {{ run.index() + 1 }} {{ labels().stepOf }} {{ run.steps.length }}\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"-me-1.5 inline-flex size-7 cursor-pointer appearance-none items-center justify-center rounded-md border-0 bg-transparent text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-state-hover hover:text-fg focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring\"\r\n [attr.aria-label]=\"labels().skip\"\r\n (click)=\"run.skip()\"\r\n >\r\n <span mfIcon [size]=\"16\">close</span>\r\n </button>\r\n </div>\r\n\r\n <h2 [id]=\"titleId\" class=\"mt-1.5 font-display text-base font-semibold text-fg\">\r\n {{ run.step().title }}\r\n </h2>\r\n <p [id]=\"contentId\" class=\"mt-1 text-sm text-fg-muted\">{{ run.step().content }}</p>\r\n\r\n <div class=\"mt-4 flex items-center gap-2\">\r\n <!-- İlerleme: adım başına bir çizgi; salt görsel, sayı zaten yukarıda. -->\r\n <div class=\"flex flex-1 items-center gap-1\" aria-hidden=\"true\">\r\n @for (step of run.steps; track $index) {\r\n <span\r\n class=\"h-1 flex-1 rounded-full transition-colors duration-base ease-emphasis\"\r\n [class]=\"$index <= run.index() ? 'bg-help' : 'bg-surface-alt'\"\r\n ></span>\r\n }\r\n </div>\r\n @if (!run.isFirst()) {\r\n <button\r\n mfButton\r\n appearance=\"text\"\r\n tone=\"neutral\"\r\n size=\"sm\"\r\n type=\"button\"\r\n (click)=\"run.back()\"\r\n >\r\n {{ labels().back }}\r\n </button>\r\n }\r\n <button mfButton tone=\"help\" size=\"sm\" type=\"button\" (click)=\"run.next()\">\r\n {{ run.isLast() ? labels().done : labels().next }}\r\n </button>\r\n </div>\r\n</div>\r\n","import { Component, inject } from '@angular/core';\r\nimport { TourRun } from './tour.model';\r\n\r\n/** Dialog arka planıyla aynı karartma (bkz. motion.css `.mf-dialog-backdrop`), biraz daha koyu. */\r\nconst SCRIM = 'color-mix(in srgb, var(--color-neutral-975) 55%, transparent)';\r\n\r\n/**\r\n * Tam ekran katman: tıklamaları yutar (tur modal) ve hedefin çevresi dışını karartır. Delik,\r\n * hedef kutusuna oturan bir öğenin çok büyük `box-shadow`'u — maske/SVG yolu gerekmez, konumu\r\n * `transition` ile adımlar arasında kayar. Hedefsiz adımda düz karartma.\r\n */\r\n@Component({\r\n selector: 'mf-tour-spotlight',\r\n host: { class: 'fixed inset-0 block' },\r\n template: `\r\n @if (run.rect(); as rect) {\r\n <div class=\"absolute inset-0\" aria-hidden=\"true\"></div>\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"pointer-events-none fixed rounded-lg outline outline-2 outline-offset-0 outline-help transition-[top,left,width,height] duration-base ease-emphasis\"\r\n [style.top.px]=\"rect.top\"\r\n [style.left.px]=\"rect.left\"\r\n [style.width.px]=\"rect.width\"\r\n [style.height.px]=\"rect.height\"\r\n [style.box-shadow]=\"'0 0 0 200vmax ' + scrim\"\r\n ></div>\r\n } @else {\r\n <div class=\"absolute inset-0\" aria-hidden=\"true\" [style.background-color]=\"scrim\"></div>\r\n }\r\n `,\r\n})\r\nexport class TourSpotlight {\r\n protected readonly run = inject(TourRun);\r\n protected readonly scrim = SCRIM;\r\n}\r\n","import {\r\n createFlexibleConnectedPositionStrategy,\r\n createGlobalPositionStrategy,\r\n createOverlayRef,\r\n createRepositionScrollStrategy,\r\n type OverlayRef,\r\n} from '@angular/cdk/overlay';\r\nimport { ComponentPortal } from '@angular/cdk/portal';\r\nimport { DOCUMENT, ElementRef, Injector, Service, inject } from '@angular/core';\r\nimport { isRtl, overlayPositions, type MfPlacement } from '@mesgflow/ui-kit/core';\r\nimport { TourCard } from './tour-card';\r\nimport {\r\n TourRun,\r\n type SpotlightRect,\r\n type TourOptions,\r\n type TourPlacement,\r\n type TourResult,\r\n type TourStep,\r\n} from './tour.model';\r\nimport { TourSpotlight } from './tour-spotlight';\r\n\r\nconst GAP = 12;\r\nconst DEFAULT_PADDING = 6;\r\n\r\n/** Tercih edilen taraf önce, sığmazsa karşısı — ortak üretici (anchor-origin panelClass dahil). */\r\nconst PLACEMENT: Record<TourPlacement, MfPlacement> = {\r\n bottom: 'bottom',\r\n top: 'top',\r\n end: 'right',\r\n start: 'left',\r\n};\r\n\r\n/**\r\n * `const result = await tour.start([{ target: '#new-campaign', title: '…', content: '…' }, …]);`\r\n *\r\n * Ürün turu / coachmark — `help` tonu tam bunun için. İki overlay: tam ekran spot ışığı (karartır,\r\n * tıklamaları yutar) ve hedefe bağlı adım kartı. Her adımda hedef görünür alana kaydırılır\r\n * (azaltılmış harekette anında), kaydırma/yeniden boyutlandırmada delik ve kart birlikte izler.\r\n * Bulunamayan hedef ortalanmış karta düşer (tur kırılmaz). Aynı anda tek tur; bitince odak\r\n * turdan önceki öğeye döner. Sonuç: `'completed'` ya da `'skipped'` (Esc, ×).\r\n */\r\n@Service()\r\nexport class TourService {\r\n private readonly injector = inject(Injector);\r\n private readonly document = inject(DOCUMENT);\r\n private active: Promise<TourResult> | null = null;\r\n\r\n get isActive(): boolean {\r\n return this.active !== null;\r\n }\r\n\r\n start(steps: readonly TourStep[], options: TourOptions = {}): Promise<TourResult> {\r\n if (this.active) return this.active;\r\n if (steps.length === 0) return Promise.resolve('completed');\r\n\r\n this.active = new Promise<TourResult>((resolve) => {\r\n const doc = this.document;\r\n const view = doc.defaultView;\r\n const padding = options.padding ?? DEFAULT_PADDING;\r\n const previousFocus = doc.activeElement as HTMLElement | null;\r\n const direction = isRtl(doc.documentElement) ? 'rtl' : 'ltr';\r\n let target: Element | null = null;\r\n let frame = 0;\r\n\r\n const run: TourRun = new TourRun(\r\n steps,\r\n (index) => show(index),\r\n (result) => finish(result),\r\n );\r\n const injector = Injector.create({\r\n providers: [{ provide: TourRun, useValue: run }],\r\n parent: this.injector,\r\n });\r\n\r\n const spotlight = createOverlayRef(this.injector, {\r\n positionStrategy: createGlobalPositionStrategy(this.injector),\r\n width: '100vw',\r\n height: '100vh',\r\n direction,\r\n });\r\n spotlight.attach(new ComponentPortal(TourSpotlight, null, injector));\r\n\r\n const card: OverlayRef = createOverlayRef(this.injector, { direction });\r\n\r\n const measure = () => {\r\n frame = 0;\r\n if (!target) {\r\n run.rect.set(null);\r\n return;\r\n }\r\n const box = target.getBoundingClientRect();\r\n run.rect.set({\r\n top: box.top - padding,\r\n left: box.left - padding,\r\n width: box.width + padding * 2,\r\n height: box.height + padding * 2,\r\n } satisfies SpotlightRect);\r\n card.updatePosition();\r\n };\r\n const schedule = () => {\r\n if (!frame) frame = view?.requestAnimationFrame(measure) ?? 0;\r\n };\r\n\r\n const place = (step: TourStep) => {\r\n const strategy = target\r\n ? createFlexibleConnectedPositionStrategy(this.injector, target as HTMLElement)\r\n .withPositions(overlayPositions(PLACEMENT[step.placement ?? 'bottom'], GAP))\r\n .withViewportMargin(12)\r\n .withPush(true)\r\n : createGlobalPositionStrategy(this.injector).centerHorizontally().centerVertically();\r\n card.updatePositionStrategy(strategy);\r\n card.updateScrollStrategy(createRepositionScrollStrategy(this.injector));\r\n };\r\n\r\n const show = (index: number) => {\r\n const step = steps[index]!;\r\n target = resolveTarget(step.target, doc);\r\n run.index.set(index);\r\n options.stepChange?.(index, step);\r\n if (target) {\r\n const reduced = view?.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? true;\r\n (target as HTMLElement).scrollIntoView?.({\r\n block: 'center',\r\n inline: 'nearest',\r\n behavior: reduced ? 'auto' : 'smooth',\r\n });\r\n }\r\n place(step);\r\n if (!card.hasAttached()) card.attach(new ComponentPortal(TourCard, null, injector));\r\n measure();\r\n };\r\n\r\n const finish = (result: TourResult) => {\r\n view?.removeEventListener('scroll', schedule, true);\r\n view?.removeEventListener('resize', schedule);\r\n if (frame) view?.cancelAnimationFrame(frame);\r\n card.dispose();\r\n spotlight.dispose();\r\n this.active = null;\r\n previousFocus?.focus?.();\r\n resolve(result);\r\n };\r\n\r\n view?.addEventListener('scroll', schedule, true);\r\n view?.addEventListener('resize', schedule);\r\n show(0);\r\n });\r\n\r\n return this.active;\r\n }\r\n}\r\n\r\nfunction resolveTarget(target: TourStep['target'], doc: Document): Element | null {\r\n if (!target) return null;\r\n if (typeof target === 'string') return doc.querySelector(target);\r\n return target instanceof ElementRef ? target.nativeElement : target;\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|