@mesgflow/ui-kit 0.6.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/LICENSE +21 -0
- package/README.md +200 -0
- package/fesm2022/mesgflow-ui-kit-accordion.mjs +75 -0
- package/fesm2022/mesgflow-ui-kit-accordion.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-alert.mjs +165 -0
- package/fesm2022/mesgflow-ui-kit-alert.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-avatar-group.mjs +88 -0
- package/fesm2022/mesgflow-ui-kit-avatar-group.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-avatar.mjs +123 -0
- package/fesm2022/mesgflow-ui-kit-avatar.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-badge.mjs +68 -0
- package/fesm2022/mesgflow-ui-kit-badge.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-banner.mjs +111 -0
- package/fesm2022/mesgflow-ui-kit-banner.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-box-input.mjs +78 -0
- package/fesm2022/mesgflow-ui-kit-box-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-brand.mjs +120 -0
- package/fesm2022/mesgflow-ui-kit-brand.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-breadcrumb.mjs +84 -0
- package/fesm2022/mesgflow-ui-kit-breadcrumb.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-button-group.mjs +37 -0
- package/fesm2022/mesgflow-ui-kit-button-group.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-button.mjs +359 -0
- package/fesm2022/mesgflow-ui-kit-button.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-card.mjs +128 -0
- package/fesm2022/mesgflow-ui-kit-card.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-chart.mjs +538 -0
- package/fesm2022/mesgflow-ui-kit-chart.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs +45 -0
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-chip.mjs +123 -0
- package/fesm2022/mesgflow-ui-kit-chip.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-code-block.mjs +71 -0
- package/fesm2022/mesgflow-ui-kit-code-block.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-collapsible.mjs +89 -0
- package/fesm2022/mesgflow-ui-kit-collapsible.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs +210 -0
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-combobox.mjs +181 -0
- package/fesm2022/mesgflow-ui-kit-combobox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-command.mjs +491 -0
- package/fesm2022/mesgflow-ui-kit-command.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs +92 -0
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-copy-button.mjs +167 -0
- package/fesm2022/mesgflow-ui-kit-copy-button.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-core.mjs +624 -0
- package/fesm2022/mesgflow-ui-kit-core.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs +643 -0
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-description-list.mjs +76 -0
- package/fesm2022/mesgflow-ui-kit-description-list.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-dialog.mjs +700 -0
- package/fesm2022/mesgflow-ui-kit-dialog.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-divider.mjs +62 -0
- package/fesm2022/mesgflow-ui-kit-divider.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs +126 -0
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-empty-state.mjs +70 -0
- package/fesm2022/mesgflow-ui-kit-empty-state.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-field.mjs +42 -0
- package/fesm2022/mesgflow-ui-kit-field.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-hover-card.mjs +171 -0
- package/fesm2022/mesgflow-ui-kit-hover-card.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs +258 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-icon.mjs +174 -0
- package/fesm2022/mesgflow-ui-kit-icon.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-input.mjs +448 -0
- package/fesm2022/mesgflow-ui-kit-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-kbd.mjs +24 -0
- package/fesm2022/mesgflow-ui-kit-kbd.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-link.mjs +48 -0
- package/fesm2022/mesgflow-ui-kit-link.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-menu.mjs +105 -0
- package/fesm2022/mesgflow-ui-kit-menu.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-number-input.mjs +153 -0
- package/fesm2022/mesgflow-ui-kit-number-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-otp-input.mjs +164 -0
- package/fesm2022/mesgflow-ui-kit-otp-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-page-header.mjs +83 -0
- package/fesm2022/mesgflow-ui-kit-page-header.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-pagination.mjs +99 -0
- package/fesm2022/mesgflow-ui-kit-pagination.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-password-input.mjs +120 -0
- package/fesm2022/mesgflow-ui-kit-password-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-popover.mjs +213 -0
- package/fesm2022/mesgflow-ui-kit-popover.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-progress.mjs +82 -0
- package/fesm2022/mesgflow-ui-kit-progress.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-radio.mjs +123 -0
- package/fesm2022/mesgflow-ui-kit-radio.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-rating.mjs +116 -0
- package/fesm2022/mesgflow-ui-kit-rating.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-scroll-area.mjs +84 -0
- package/fesm2022/mesgflow-ui-kit-scroll-area.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-search-input.mjs +154 -0
- package/fesm2022/mesgflow-ui-kit-search-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs +95 -0
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-select.mjs +227 -0
- package/fesm2022/mesgflow-ui-kit-select.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs +449 -0
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs +74 -0
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-slider.mjs +179 -0
- package/fesm2022/mesgflow-ui-kit-slider.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-spinner.mjs +67 -0
- package/fesm2022/mesgflow-ui-kit-spinner.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-splitter.mjs +97 -0
- package/fesm2022/mesgflow-ui-kit-splitter.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs +98 -0
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-stepper.mjs +133 -0
- package/fesm2022/mesgflow-ui-kit-stepper.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-switch.mjs +73 -0
- package/fesm2022/mesgflow-ui-kit-switch.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-table.mjs +1783 -0
- package/fesm2022/mesgflow-ui-kit-table.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tabs.mjs +569 -0
- package/fesm2022/mesgflow-ui-kit-tabs.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs +138 -0
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-theme-switcher.mjs +53 -0
- package/fesm2022/mesgflow-ui-kit-theme-switcher.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-theming.mjs +1016 -0
- package/fesm2022/mesgflow-ui-kit-theming.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs +138 -0
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-timeline.mjs +91 -0
- package/fesm2022/mesgflow-ui-kit-timeline.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-toast.mjs +202 -0
- package/fesm2022/mesgflow-ui-kit-toast.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-toggle.mjs +243 -0
- package/fesm2022/mesgflow-ui-kit-toggle.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs +99 -0
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs +160 -0
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tour.mjs +272 -0
- package/fesm2022/mesgflow-ui-kit-tour.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tree-select.mjs +177 -0
- package/fesm2022/mesgflow-ui-kit-tree-select.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tree.mjs +82 -0
- package/fesm2022/mesgflow-ui-kit-tree.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit.mjs +12851 -0
- package/fesm2022/mesgflow-ui-kit.mjs.map +1 -0
- package/package.json +374 -0
- package/preset.css +20 -0
- package/tokens/color.css +693 -0
- package/tokens/contrast.css +68 -0
- package/tokens/elevation.css +68 -0
- package/tokens/motion.css +277 -0
- package/tokens/radius.css +69 -0
- package/tokens/typography.css +127 -0
- package/tokens.css +41 -0
- package/types/mesgflow-ui-kit-accordion.d.ts +42 -0
- package/types/mesgflow-ui-kit-alert.d.ts +60 -0
- package/types/mesgflow-ui-kit-avatar-group.d.ts +28 -0
- package/types/mesgflow-ui-kit-avatar.d.ts +23 -0
- package/types/mesgflow-ui-kit-badge.d.ts +39 -0
- package/types/mesgflow-ui-kit-banner.d.ts +42 -0
- package/types/mesgflow-ui-kit-box-input.d.ts +45 -0
- package/types/mesgflow-ui-kit-brand.d.ts +48 -0
- package/types/mesgflow-ui-kit-breadcrumb.d.ts +26 -0
- package/types/mesgflow-ui-kit-button-group.d.ts +17 -0
- package/types/mesgflow-ui-kit-button.d.ts +75 -0
- package/types/mesgflow-ui-kit-card.d.ts +71 -0
- package/types/mesgflow-ui-kit-chart.d.ts +242 -0
- package/types/mesgflow-ui-kit-checkbox.d.ts +17 -0
- package/types/mesgflow-ui-kit-chip.d.ts +46 -0
- package/types/mesgflow-ui-kit-code-block.d.ts +56 -0
- package/types/mesgflow-ui-kit-collapsible.d.ts +39 -0
- package/types/mesgflow-ui-kit-color-picker.d.ts +78 -0
- package/types/mesgflow-ui-kit-combobox.d.ts +74 -0
- package/types/mesgflow-ui-kit-command.d.ts +185 -0
- package/types/mesgflow-ui-kit-context-menu.d.ts +40 -0
- package/types/mesgflow-ui-kit-copy-button.d.ts +47 -0
- package/types/mesgflow-ui-kit-core.d.ts +508 -0
- package/types/mesgflow-ui-kit-date-picker.d.ts +215 -0
- package/types/mesgflow-ui-kit-description-list.d.ts +23 -0
- package/types/mesgflow-ui-kit-dialog.d.ts +342 -0
- package/types/mesgflow-ui-kit-divider.d.ts +23 -0
- package/types/mesgflow-ui-kit-dropzone.d.ts +47 -0
- package/types/mesgflow-ui-kit-empty-state.d.ts +18 -0
- package/types/mesgflow-ui-kit-field.d.ts +26 -0
- package/types/mesgflow-ui-kit-hover-card.d.ts +52 -0
- package/types/mesgflow-ui-kit-i18n-tr.d.ts +14 -0
- package/types/mesgflow-ui-kit-icon.d.ts +76 -0
- package/types/mesgflow-ui-kit-input.d.ts +186 -0
- package/types/mesgflow-ui-kit-kbd.d.ts +9 -0
- package/types/mesgflow-ui-kit-link.d.ts +20 -0
- package/types/mesgflow-ui-kit-menu.d.ts +53 -0
- package/types/mesgflow-ui-kit-number-input.d.ts +55 -0
- package/types/mesgflow-ui-kit-otp-input.d.ts +44 -0
- package/types/mesgflow-ui-kit-page-header.d.ts +31 -0
- package/types/mesgflow-ui-kit-pagination.d.ts +50 -0
- package/types/mesgflow-ui-kit-password-input.d.ts +33 -0
- package/types/mesgflow-ui-kit-popover.d.ts +62 -0
- package/types/mesgflow-ui-kit-progress.d.ts +32 -0
- package/types/mesgflow-ui-kit-radio.d.ts +59 -0
- package/types/mesgflow-ui-kit-rating.d.ts +56 -0
- package/types/mesgflow-ui-kit-scroll-area.d.ts +27 -0
- package/types/mesgflow-ui-kit-search-input.d.ts +72 -0
- package/types/mesgflow-ui-kit-segmented-control.d.ts +54 -0
- package/types/mesgflow-ui-kit-select.d.ts +89 -0
- package/types/mesgflow-ui-kit-sidebar.d.ts +224 -0
- package/types/mesgflow-ui-kit-skeleton.d.ts +29 -0
- package/types/mesgflow-ui-kit-slider.d.ts +40 -0
- package/types/mesgflow-ui-kit-spinner.d.ts +31 -0
- package/types/mesgflow-ui-kit-splitter.d.ts +40 -0
- package/types/mesgflow-ui-kit-stat-tile.d.ts +54 -0
- package/types/mesgflow-ui-kit-stepper.d.ts +48 -0
- package/types/mesgflow-ui-kit-switch.d.ts +34 -0
- package/types/mesgflow-ui-kit-table.d.ts +805 -0
- package/types/mesgflow-ui-kit-tabs.d.ts +269 -0
- package/types/mesgflow-ui-kit-tag-input.d.ts +33 -0
- package/types/mesgflow-ui-kit-theme-switcher.d.ts +27 -0
- package/types/mesgflow-ui-kit-theming.d.ts +745 -0
- package/types/mesgflow-ui-kit-time-picker.d.ts +54 -0
- package/types/mesgflow-ui-kit-timeline.d.ts +27 -0
- package/types/mesgflow-ui-kit-toast.d.ts +94 -0
- package/types/mesgflow-ui-kit-toggle.d.ts +110 -0
- package/types/mesgflow-ui-kit-toolbar.d.ts +52 -0
- package/types/mesgflow-ui-kit-tooltip.d.ts +55 -0
- package/types/mesgflow-ui-kit-tour.d.ts +66 -0
- package/types/mesgflow-ui-kit-tree-select.d.ts +65 -0
- package/types/mesgflow-ui-kit-tree.d.ts +44 -0
- package/types/mesgflow-ui-kit.d.ts +5444 -0
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, input, computed, signal, DestroyRef, afterNextRender, effect, Directive, viewChild, afterRenderEffect, Component, model, output } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/aria/tabs';
|
|
4
|
+
import { TabList as TabList$1, Tab as Tab$1, TabPanel as TabPanel$1, Tabs as Tabs$1 } from '@angular/aria/tabs';
|
|
5
|
+
import { isRtl, scrollFromInlineStart, MF_TABS_LABELS, cn } from '@mesgflow/ui-kit/core';
|
|
6
|
+
import { Button } from '@mesgflow/ui-kit/button';
|
|
7
|
+
import { Icon } from '@mesgflow/ui-kit/icon';
|
|
8
|
+
import { cva } from 'class-variance-authority';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `<div mfTabScroller>` — taşan bir sekme şeridini kaydırılabilir yapar:
|
|
12
|
+
* native scrollbar'ı gizler, kenar "solma" maskesini (`mask-image`)
|
|
13
|
+
* kaydırılabilir yöne göre günceller, `canScrollStart`/`canScrollEnd`
|
|
14
|
+
* sinyallerini dışarı verir (ok butonlarının görünürlüğü için — bkz.
|
|
15
|
+
* `tab-list.html`/`tab-strip.html`, ikisi de bu directive'i paylaşıyor).
|
|
16
|
+
*
|
|
17
|
+
* `orientation` varsayılanı `'horizontal'` — `TabStrip` (üst sekme çubuğu)
|
|
18
|
+
* bunu hiç geçmez, davranışı DEĞİŞMEZ. Dikey bir grup rayı gerektiren
|
|
19
|
+
* tüketiciler `orientation="vertical"` geçer (bkz. `tab-list.ts`).
|
|
20
|
+
*
|
|
21
|
+
* `mask-image` template'te `[style.mask-image]` ile DEĞİL, doğrudan
|
|
22
|
+
* `style.setProperty` ile yazılıyor — Angular'ın stil binding sözdizimi
|
|
23
|
+
* tire içeren (`-webkit-`) property adlarını binding adı olarak kabul
|
|
24
|
+
* etmiyor, ikisini TEK yerden (burada) senkron yazmak için imperatif yol
|
|
25
|
+
* daha güvenli (bkz. Tooltip'in de DOM'a doğrudan yazdığı emsal).
|
|
26
|
+
*/
|
|
27
|
+
class TabScroller {
|
|
28
|
+
el = inject(ElementRef);
|
|
29
|
+
orientation = input('horizontal', /* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
31
|
+
vertical = computed(() => this.orientation() === 'vertical', /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "vertical" }] : /* istanbul ignore next */ []));
|
|
33
|
+
canScrollStart = signal(false, /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "canScrollStart" }] : /* istanbul ignore next */ []));
|
|
35
|
+
canScrollEnd = signal(false, /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "canScrollEnd" }] : /* istanbul ignore next */ []));
|
|
37
|
+
constructor() {
|
|
38
|
+
const destroyRef = inject(DestroyRef);
|
|
39
|
+
afterNextRender(() => {
|
|
40
|
+
this.updateEdges();
|
|
41
|
+
if (typeof ResizeObserver === 'undefined')
|
|
42
|
+
return;
|
|
43
|
+
const observer = new ResizeObserver(() => this.updateEdges());
|
|
44
|
+
observer.observe(this.el.nativeElement);
|
|
45
|
+
destroyRef.onDestroy(() => observer.disconnect());
|
|
46
|
+
});
|
|
47
|
+
effect(() => {
|
|
48
|
+
const start = this.canScrollStart() ? 24 : 0;
|
|
49
|
+
const end = this.canScrollEnd() ? 24 : 0;
|
|
50
|
+
// Maske satır başından sonuna — RTL'de başlangıç sağ kenar.
|
|
51
|
+
const direction = this.vertical()
|
|
52
|
+
? 'to bottom'
|
|
53
|
+
: isRtl(this.el.nativeElement)
|
|
54
|
+
? 'to left'
|
|
55
|
+
: 'to right';
|
|
56
|
+
const mask = `linear-gradient(${direction}, transparent, black ${start}px, black calc(100% - ${end}px), transparent 100%)`;
|
|
57
|
+
this.el.nativeElement.style.setProperty('mask-image', mask);
|
|
58
|
+
this.el.nativeElement.style.setProperty('-webkit-mask-image', mask);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
scrollByDir(dir) {
|
|
62
|
+
const node = this.el.nativeElement;
|
|
63
|
+
if (this.vertical())
|
|
64
|
+
node.scrollBy({ top: dir * node.clientHeight * 0.8, behavior: 'smooth' });
|
|
65
|
+
else {
|
|
66
|
+
// `dir` mantıksal (−1 başa, +1 sona); RTL'de sona gitmek scrollLeft'i AZALTIR.
|
|
67
|
+
const sign = isRtl(node) ? -1 : 1;
|
|
68
|
+
node.scrollBy({ left: sign * dir * node.clientWidth * 0.8, behavior: 'smooth' });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
scrollIntoViewIfNeeded(target) {
|
|
72
|
+
// jsdom (birim testleri) Element.scrollIntoView'ı UYGULAMIYOR — ResizeObserver'daki
|
|
73
|
+
// AYNI savunma deseni (bkz. constructor), gerçek tarayıcıda etkisiz bir NO-OP.
|
|
74
|
+
target.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
|
|
75
|
+
}
|
|
76
|
+
updateEdges() {
|
|
77
|
+
const node = this.el.nativeElement;
|
|
78
|
+
if (this.vertical()) {
|
|
79
|
+
const max = node.scrollHeight - node.clientHeight;
|
|
80
|
+
this.canScrollStart.set(node.scrollTop > 1);
|
|
81
|
+
this.canScrollEnd.set(max > 1 && node.scrollTop < max - 1);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const max = node.scrollWidth - node.clientWidth;
|
|
85
|
+
const offset = scrollFromInlineStart(node); // RTL'de scrollLeft negatif
|
|
86
|
+
this.canScrollStart.set(offset > 1);
|
|
87
|
+
this.canScrollEnd.set(max > 1 && offset < max - 1);
|
|
88
|
+
}
|
|
89
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabScroller, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
90
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: TabScroller, isStandalone: true, selector: "[mfTabScroller]", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "scroll": "updateEdges()" }, properties: { "class.flex": "orientation() === \"horizontal\"", "class.min-w-0": "orientation() === \"horizontal\"", "class.overflow-x-auto": "orientation() === \"horizontal\"", "class.min-h-0": "orientation() === \"vertical\"", "class.overflow-y-auto": "orientation() === \"vertical\"" }, classAttribute: "[scrollbar-width:none] [&::-webkit-scrollbar]:hidden" }, ngImport: i0 });
|
|
91
|
+
}
|
|
92
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabScroller, decorators: [{
|
|
93
|
+
type: Directive,
|
|
94
|
+
args: [{
|
|
95
|
+
selector: '[mfTabScroller]',
|
|
96
|
+
host: {
|
|
97
|
+
class: '[scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
|
|
98
|
+
'[class.flex]': 'orientation() === "horizontal"',
|
|
99
|
+
'[class.min-w-0]': 'orientation() === "horizontal"',
|
|
100
|
+
'[class.overflow-x-auto]': 'orientation() === "horizontal"',
|
|
101
|
+
'[class.min-h-0]': 'orientation() === "vertical"',
|
|
102
|
+
'[class.overflow-y-auto]': 'orientation() === "vertical"',
|
|
103
|
+
'(scroll)': 'updateEdges()',
|
|
104
|
+
},
|
|
105
|
+
}]
|
|
106
|
+
}], ctorParameters: () => [], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Bkz. `tab-list.ts`. `underline`'da ray AYRI, kayan bir `<span>` (JS ile
|
|
110
|
+
* konumlanır — bkz. `TabList.positionIndicator`); `card`'da ray HER sekmenin
|
|
111
|
+
* kendi `box-shadow`'unda yaşar (bkz. `tabVariants` compound'u), çünkü
|
|
112
|
+
* `card` görünümünde her sekme zaten kendi kenarlığıyla ayrık bir kutu —
|
|
113
|
+
* kayan tek bir gösterge o kutuların üstünden "kayarak" geçmezdi, doğal
|
|
114
|
+
* durmazdı. `relative` — kayan gösterge `absolute` konumlanıyor buna göre.
|
|
115
|
+
*
|
|
116
|
+
* `orientation` ekseni sol dikey grup rayı gerektiren ekranlar için eklendi —
|
|
117
|
+
* `@angular/aria/tabs`'ın ARIA/klavye desteği zaten yön-agnostik
|
|
118
|
+
* (`hostDirectives`'in `orientation` girdisi, bkz. `tab-list.ts`), eksik
|
|
119
|
+
* olan sadece bu görsel katmandı.
|
|
120
|
+
*/
|
|
121
|
+
const tabListVariants = cva('relative flex', {
|
|
122
|
+
variants: {
|
|
123
|
+
variant: {
|
|
124
|
+
underline: 'gap-1',
|
|
125
|
+
card: 'gap-1.5',
|
|
126
|
+
},
|
|
127
|
+
orientation: {
|
|
128
|
+
horizontal: 'min-w-max items-center',
|
|
129
|
+
vertical: 'w-full flex-col items-stretch',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
defaultVariants: { variant: 'underline', orientation: 'horizontal' },
|
|
133
|
+
});
|
|
134
|
+
/**
|
|
135
|
+
* `selected`/`disabled` burada `aria-selected`/`aria-disabled` CSS
|
|
136
|
+
* seçicileriyle DEĞİL, `Tab`'ın kendi `computed()`'ıyla (bkz. `tab.ts`)
|
|
137
|
+
* okunan sinyal değerleriyle besleniyor — kod tabanındaki yerleşik desen
|
|
138
|
+
* (Select'in `optionClasses`, Table'ın `rowClasses`) TS'te hesaplanan koşullu
|
|
139
|
+
* class, CSS attribute-selector değil.
|
|
140
|
+
*/
|
|
141
|
+
const tabVariants = cva('relative inline-flex shrink-0 cursor-pointer appearance-none items-center gap-1.5 whitespace-nowrap border-0 bg-transparent text-sm text-fg-muted transition-colors duration-fast ease-emphasis active:scale-[0.99] ' +
|
|
142
|
+
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring', {
|
|
143
|
+
variants: {
|
|
144
|
+
variant: {
|
|
145
|
+
underline: 'rounded-sm px-3 py-2',
|
|
146
|
+
card: 'rounded-sm border border-transparent px-3 py-1.5',
|
|
147
|
+
},
|
|
148
|
+
orientation: {
|
|
149
|
+
horizontal: '',
|
|
150
|
+
vertical: 'w-full justify-start text-start',
|
|
151
|
+
},
|
|
152
|
+
selected: {
|
|
153
|
+
true: '',
|
|
154
|
+
false: 'hover:bg-surface-alt hover:text-fg',
|
|
155
|
+
},
|
|
156
|
+
disabled: {
|
|
157
|
+
true: 'pointer-events-none opacity-50 active:scale-100',
|
|
158
|
+
false: '',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
compoundVariants: [
|
|
162
|
+
{ variant: 'underline', selected: true, class: 'text-fg font-semibold' },
|
|
163
|
+
/*
|
|
164
|
+
* `card` — aktif sekme `bg-canvas` (içerik zeminiyle birleşir) + 2px dolu
|
|
165
|
+
* ray. Yatayda alt kenar, dikeyde ön (sol) kenar — dikey grup rayı bunu
|
|
166
|
+
* kullanıyor. Ray rengi `--mf-accent-fill` (mode-swapped: light 900 /
|
|
167
|
+
* dark 400) — diğer TÜM "ray" kullanımlarıyla (Sidebar aktif nav,
|
|
168
|
+
* Table seçili satır, ikisi de `border-s-accent-fill`) TUTARLI. `var()`
|
|
169
|
+
* `@theme inline`'ın `--color-accent-fill` katmanını DEĞİL doğrudan
|
|
170
|
+
* `--mf-*`'i hedefliyor — `box-shadow` arbitrary value'su bir utility
|
|
171
|
+
* DEĞİL, Tailwind'in "bu inline değişkeni emit et" taramasına
|
|
172
|
+
* güvenmek yerine kaynağa doğrudan bağlanmak daha sağlam.
|
|
173
|
+
*/
|
|
174
|
+
{
|
|
175
|
+
variant: 'card',
|
|
176
|
+
orientation: 'horizontal',
|
|
177
|
+
selected: true,
|
|
178
|
+
class: 'border-border bg-canvas text-fg font-semibold shadow-[inset_0_-2px_0_0_var(--mf-accent-fill)]',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
variant: 'card',
|
|
182
|
+
orientation: 'vertical',
|
|
183
|
+
selected: true,
|
|
184
|
+
class: 'border-border bg-canvas text-fg font-semibold shadow-[inset_2px_0_0_0_var(--mf-accent-fill)]',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
defaultVariants: {
|
|
188
|
+
variant: 'underline',
|
|
189
|
+
orientation: 'horizontal',
|
|
190
|
+
selected: false,
|
|
191
|
+
disabled: false,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* `<mf-tab-list [(selectedTab)]="active" variant="underline">…</mf-tab-list>`
|
|
197
|
+
* — `mf-tabs` içine konur, `mfTab` butonlarını sarar. ARIA/klavye
|
|
198
|
+
* (Ok tuşları/Home/End) `@angular/aria/tabs`'ın `TabList` pattern'inden
|
|
199
|
+
* `hostDirectives` ile geliyor (bkz. `tabs.ts` üstündeki not).
|
|
200
|
+
*
|
|
201
|
+
* İki premium detay burada yaşıyor:
|
|
202
|
+
* 1. **Kayan ray göstergesi** (`underline` varyantı) — aktif sekme
|
|
203
|
+
* değişince `positionIndicator()` DOM'dan `[aria-selected="true"]`
|
|
204
|
+
* elemanın `offsetLeft`/`offsetWidth`'ini (yatayda) ya da `offsetTop`/
|
|
205
|
+
* `offsetHeight`'ını (dikeyde) ölçüp göstergeyi kaydırıyor (emsal:
|
|
206
|
+
* `table-pagination.ts`'in odak restorasyonundaki `afterRenderEffect` +
|
|
207
|
+
* `viewChild(ElementRef)` deseni). `ResizeObserver` yeniden boyutlanmada
|
|
208
|
+
* (font yüklenmesi, viewport) yeniden ölçer. `card` varyantında AYRI bir
|
|
209
|
+
* gösterge YOK — ray her sekmenin kendi `box-shadow`'unda yaşıyor
|
|
210
|
+
* (bkz. tabs.variants.ts).
|
|
211
|
+
* 2. **Taşma yönetimi** — `mfTabScroller` (bkz. o dosya) kaydırma+kenar
|
|
212
|
+
* solma maskesi sağlıyor; ok butonları SADECE o yönde taşma varken
|
|
213
|
+
* render edilir. Aktif sekme değişince görünür alana kaydırılır.
|
|
214
|
+
*
|
|
215
|
+
* `tab-list.html`'deki sarmalayıcı `<div>`'in çapraz eksen hizalaması BİLEREK
|
|
216
|
+
* yöne göre koşullu: dikeyde (`flex-col`) çapraz eksen GENİŞLİK olur, `items-
|
|
217
|
+
* center` orada "çocukları raya GERME, kendi içerik genişliğine küçült" demek
|
|
218
|
+
* — bu, genişliğin `mfTabScroller`/`#row`/butonlara hiç iletilmemesine ve
|
|
219
|
+
* `truncate`'in (role-form.html'deki İngilizce grup adlarıyla canlı
|
|
220
|
+
* doğrulandı) hiç devreye girmeden ham/elipsissiz kırpılmasına yol açan
|
|
221
|
+
* GERÇEK bir bugdu. `items-stretch` çapraz ekseni doğru şekilde geriyor —
|
|
222
|
+
* bunu tekrar `items-center`'a "sadeleştirme".
|
|
223
|
+
*
|
|
224
|
+
* `orientation` girdisi `@angular/aria`'nın `TabList` pattern'inden
|
|
225
|
+
* `hostDirectives` ile geliyor (ARIA/klavye zaten yön-agnostik) — burada
|
|
226
|
+
* ikinci kez `input()` olarak TANIMLANMIYOR (NG2017, bkz. `TabPanel.
|
|
227
|
+
* preserveContent`'teki aynı kısıt), `ariaTabList.orientation()` üzerinden
|
|
228
|
+
* `protected readonly orientation` olarak okunuyor; `Tab` (tab.ts) bunu
|
|
229
|
+
* `variant()` ile aynı `inject()` deseniyle ebeveynden alıyor.
|
|
230
|
+
*/
|
|
231
|
+
class TabList {
|
|
232
|
+
variant = input('underline', /* @ts-ignore */
|
|
233
|
+
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
234
|
+
scrollStartLabel = input(/* @ts-ignore */
|
|
235
|
+
...(ngDevMode ? [undefined, { debugName: "scrollStartLabel" }] : /* istanbul ignore next */ []));
|
|
236
|
+
scrollEndLabel = input(/* @ts-ignore */
|
|
237
|
+
...(ngDevMode ? [undefined, { debugName: "scrollEndLabel" }] : /* istanbul ignore next */ []));
|
|
238
|
+
tabsLabels = inject(MF_TABS_LABELS);
|
|
239
|
+
effectiveScrollStartLabel = computed(() => this.scrollStartLabel() ?? this.tabsLabels().scrollStart, /* @ts-ignore */
|
|
240
|
+
...(ngDevMode ? [{ debugName: "effectiveScrollStartLabel" }] : /* istanbul ignore next */ []));
|
|
241
|
+
effectiveScrollEndLabel = computed(() => this.scrollEndLabel() ?? this.tabsLabels().scrollEnd, /* @ts-ignore */
|
|
242
|
+
...(ngDevMode ? [{ debugName: "effectiveScrollEndLabel" }] : /* istanbul ignore next */ []));
|
|
243
|
+
/** `mfTab` (bkz. tab.ts) varyantı buradan `inject()` ile okuyor — tek kaynak. */
|
|
244
|
+
ariaTabList = inject(TabList$1);
|
|
245
|
+
/** `Tab` (tab.ts) bunu `variant()` ile aynı `inject()` deseniyle okuyor — bu yüzden `public`. */
|
|
246
|
+
orientation = computed(() => this.ariaTabList.orientation(), /* @ts-ignore */
|
|
247
|
+
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
248
|
+
isVertical = computed(() => this.orientation() === 'vertical', /* @ts-ignore */
|
|
249
|
+
...(ngDevMode ? [{ debugName: "isVertical" }] : /* istanbul ignore next */ []));
|
|
250
|
+
listClasses = computed(() => cn(tabListVariants({ variant: this.variant(), orientation: this.orientation() })), /* @ts-ignore */
|
|
251
|
+
...(ngDevMode ? [{ debugName: "listClasses" }] : /* istanbul ignore next */ []));
|
|
252
|
+
indicatorClasses = computed(() => cn('pointer-events-none absolute rounded-full bg-accent-fill opacity-0 transition-[transform,width,height,opacity] duration-base ease-emphasis', this.isVertical() ? 'top-0 left-0 w-0.5' : 'bottom-0 left-0 h-0.5'), /* @ts-ignore */
|
|
253
|
+
...(ngDevMode ? [{ debugName: "indicatorClasses" }] : /* istanbul ignore next */ []));
|
|
254
|
+
scroller = viewChild(TabScroller, /* @ts-ignore */
|
|
255
|
+
...(ngDevMode ? [{ debugName: "scroller" }] : /* istanbul ignore next */ []));
|
|
256
|
+
showStartArrow = computed(() => this.scroller()?.canScrollStart() ?? false, /* @ts-ignore */
|
|
257
|
+
...(ngDevMode ? [{ debugName: "showStartArrow" }] : /* istanbul ignore next */ []));
|
|
258
|
+
showEndArrow = computed(() => this.scroller()?.canScrollEnd() ?? false, /* @ts-ignore */
|
|
259
|
+
...(ngDevMode ? [{ debugName: "showEndArrow" }] : /* istanbul ignore next */ []));
|
|
260
|
+
rowEl = viewChild('row', /* @ts-ignore */
|
|
261
|
+
...(ngDevMode ? [{ debugName: "rowEl" }] : /* istanbul ignore next */ []));
|
|
262
|
+
indicatorEl = viewChild('indicator', /* @ts-ignore */
|
|
263
|
+
...(ngDevMode ? [{ debugName: "indicatorEl" }] : /* istanbul ignore next */ []));
|
|
264
|
+
constructor() {
|
|
265
|
+
const destroyRef = inject(DestroyRef);
|
|
266
|
+
afterRenderEffect(() => {
|
|
267
|
+
this.ariaTabList.selectedTab();
|
|
268
|
+
this.positionIndicator();
|
|
269
|
+
});
|
|
270
|
+
afterNextRender(() => {
|
|
271
|
+
const row = this.rowEl()?.nativeElement;
|
|
272
|
+
if (!row || typeof ResizeObserver === 'undefined')
|
|
273
|
+
return;
|
|
274
|
+
const observer = new ResizeObserver(() => this.positionIndicator());
|
|
275
|
+
observer.observe(row);
|
|
276
|
+
destroyRef.onDestroy(() => observer.disconnect());
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
positionIndicator() {
|
|
280
|
+
const row = this.rowEl()?.nativeElement;
|
|
281
|
+
const indicator = this.indicatorEl()?.nativeElement;
|
|
282
|
+
if (!row || !indicator)
|
|
283
|
+
return;
|
|
284
|
+
const active = row.querySelector('[aria-selected="true"]');
|
|
285
|
+
if (!active) {
|
|
286
|
+
indicator.style.opacity = '0';
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
indicator.style.opacity = '1';
|
|
290
|
+
if (this.isVertical()) {
|
|
291
|
+
indicator.style.transform = `translateY(${active.offsetTop}px)`;
|
|
292
|
+
indicator.style.height = `${active.offsetHeight}px`;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
indicator.style.transform = `translateX(${active.offsetLeft}px)`;
|
|
296
|
+
indicator.style.width = `${active.offsetWidth}px`;
|
|
297
|
+
}
|
|
298
|
+
this.scroller()?.scrollIntoViewIfNeeded(active);
|
|
299
|
+
}
|
|
300
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
301
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: TabList, isStandalone: true, selector: "mf-tab-list", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, scrollStartLabel: { classPropertyName: "scrollStartLabel", publicName: "scrollStartLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollEndLabel: { classPropertyName: "scrollEndLabel", publicName: "scrollEndLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: TabScroller, descendants: true, isSignal: true }, { propertyName: "rowEl", first: true, predicate: ["row"], descendants: true, isSignal: true }, { propertyName: "indicatorEl", first: true, predicate: ["indicator"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.TabList, inputs: ["orientation", "orientation", "wrap", "wrap", "softDisabled", "softDisabled", "focusMode", "focusMode", "selectionMode", "selectionMode", "disabled", "disabled", "selectedTab", "selectedTab"], outputs: ["selectedTabChange", "selectedTabChange"] }], ngImport: i0, template: "<div\r\n class=\"flex gap-1\"\r\n [class.flex-col]=\"isVertical()\"\r\n [class.items-center]=\"!isVertical()\"\r\n [class.items-stretch]=\"isVertical()\"\r\n>\r\n @if (showStartArrow()) {\r\n <button\r\n mfButton\r\n tone=\"neutral\"\r\n appearance=\"text\"\r\n size=\"icon\"\r\n shape=\"square\"\r\n type=\"button\"\r\n class=\"shrink-0\"\r\n [attr.aria-label]=\"effectiveScrollStartLabel()\"\r\n (click)=\"scroller()?.scrollByDir(-1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">{{\r\n isVertical() ? 'keyboard_arrow_up' : 'chevron_left'\r\n }}</span>\r\n </button>\r\n }\r\n\r\n <div mfTabScroller [orientation]=\"orientation()\">\r\n <div #row [class]=\"listClasses()\">\r\n <ng-content />\r\n @if (variant() === 'underline') {\r\n <span #indicator [class]=\"indicatorClasses()\"></span>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (showEndArrow()) {\r\n <button\r\n mfButton\r\n tone=\"neutral\"\r\n appearance=\"text\"\r\n size=\"icon\"\r\n shape=\"square\"\r\n type=\"button\"\r\n class=\"shrink-0\"\r\n [attr.aria-label]=\"effectiveScrollEndLabel()\"\r\n (click)=\"scroller()?.scrollByDir(1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">{{\r\n isVertical() ? 'keyboard_arrow_down' : 'chevron_right'\r\n }}</span>\r\n </button>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "component", type: Button, selector: "button[mfButton], a[mfButton]", inputs: ["tone", "appearance", "size", "shape", "type", "loading", "iconStart", "iconEnd"], exportAs: ["mfButton"] }, { kind: "directive", type: Icon, selector: "span[mfIcon]", inputs: ["size", "filled"] }, { kind: "directive", type: TabScroller, selector: "[mfTabScroller]", inputs: ["orientation"] }] });
|
|
302
|
+
}
|
|
303
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabList, decorators: [{
|
|
304
|
+
type: Component,
|
|
305
|
+
args: [{ selector: 'mf-tab-list', imports: [Button, Icon, TabScroller], hostDirectives: [
|
|
306
|
+
{
|
|
307
|
+
directive: TabList$1,
|
|
308
|
+
inputs: [
|
|
309
|
+
'orientation',
|
|
310
|
+
'wrap',
|
|
311
|
+
'softDisabled',
|
|
312
|
+
'focusMode',
|
|
313
|
+
'selectionMode',
|
|
314
|
+
'disabled',
|
|
315
|
+
'selectedTab',
|
|
316
|
+
],
|
|
317
|
+
outputs: ['selectedTabChange'],
|
|
318
|
+
},
|
|
319
|
+
], host: { class: 'block' }, template: "<div\r\n class=\"flex gap-1\"\r\n [class.flex-col]=\"isVertical()\"\r\n [class.items-center]=\"!isVertical()\"\r\n [class.items-stretch]=\"isVertical()\"\r\n>\r\n @if (showStartArrow()) {\r\n <button\r\n mfButton\r\n tone=\"neutral\"\r\n appearance=\"text\"\r\n size=\"icon\"\r\n shape=\"square\"\r\n type=\"button\"\r\n class=\"shrink-0\"\r\n [attr.aria-label]=\"effectiveScrollStartLabel()\"\r\n (click)=\"scroller()?.scrollByDir(-1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">{{\r\n isVertical() ? 'keyboard_arrow_up' : 'chevron_left'\r\n }}</span>\r\n </button>\r\n }\r\n\r\n <div mfTabScroller [orientation]=\"orientation()\">\r\n <div #row [class]=\"listClasses()\">\r\n <ng-content />\r\n @if (variant() === 'underline') {\r\n <span #indicator [class]=\"indicatorClasses()\"></span>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (showEndArrow()) {\r\n <button\r\n mfButton\r\n tone=\"neutral\"\r\n appearance=\"text\"\r\n size=\"icon\"\r\n shape=\"square\"\r\n type=\"button\"\r\n class=\"shrink-0\"\r\n [attr.aria-label]=\"effectiveScrollEndLabel()\"\r\n (click)=\"scroller()?.scrollByDir(1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">{{\r\n isVertical() ? 'keyboard_arrow_down' : 'chevron_right'\r\n }}</span>\r\n </button>\r\n }\r\n</div>\r\n" }]
|
|
320
|
+
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], scrollStartLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollStartLabel", required: false }] }], scrollEndLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollEndLabel", required: false }] }], scroller: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TabScroller), { isSignal: true }] }], rowEl: [{ type: i0.ViewChild, args: ['row', { isSignal: true }] }], indicatorEl: [{ type: i0.ViewChild, args: ['indicator', { isSignal: true }] }] } });
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* `<button mfTab value="genel">Genel</button>` — bir `mf-tab-list` içine
|
|
324
|
+
* konur. ARIA/klavye/seçim davranışı `@angular/aria/tabs`'ın `Tab`
|
|
325
|
+
* pattern'inden `hostDirectives` ile geliyor (bkz. `tabs.ts` üstündeki not);
|
|
326
|
+
* bu directive sadece görsel katmanı ekliyor. `value`/`disabled`/`id`
|
|
327
|
+
* girdileri `hostDirectives`'in `inputs` listesiyle dışarı açıldı — tüketici
|
|
328
|
+
* doğrudan `[value]`/`[disabled]` bağlar, `ngTab` attribute'unu YAZMAZ.
|
|
329
|
+
*
|
|
330
|
+
* Varyant (`underline`/`card`) ebeveyn `mf-tab-list`'ten `inject()` ile
|
|
331
|
+
* okunuyor — `Tab` kendi varyant girdisini TAŞIMIYOR, tek kaynak listede.
|
|
332
|
+
*/
|
|
333
|
+
class Tab {
|
|
334
|
+
ariaTab = inject(Tab$1);
|
|
335
|
+
tabList = inject(TabList, { optional: true });
|
|
336
|
+
classes = computed(() => cn(tabVariants({
|
|
337
|
+
variant: this.tabList?.variant() ?? 'underline',
|
|
338
|
+
orientation: this.tabList?.orientation() ?? 'horizontal',
|
|
339
|
+
selected: this.ariaTab.selected(),
|
|
340
|
+
disabled: this.ariaTab.disabled(),
|
|
341
|
+
})), /* @ts-ignore */
|
|
342
|
+
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
343
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tab, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
344
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: Tab, isStandalone: true, selector: "button[mfTab]", host: { properties: { "attr.type": "'button'", "class": "classes()" } }, hostDirectives: [{ directive: i1.Tab, inputs: ["value", "value", "disabled", "disabled", "id", "id"] }], ngImport: i0 });
|
|
345
|
+
}
|
|
346
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tab, decorators: [{
|
|
347
|
+
type: Directive,
|
|
348
|
+
args: [{
|
|
349
|
+
selector: 'button[mfTab]',
|
|
350
|
+
hostDirectives: [{ directive: Tab$1, inputs: ['value', 'disabled', 'id'] }],
|
|
351
|
+
host: { '[attr.type]': "'button'", '[class]': 'classes()' },
|
|
352
|
+
}]
|
|
353
|
+
}] });
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* ```html
|
|
357
|
+
* <mf-tab-panel value="genel">
|
|
358
|
+
* <ng-template ngTabContent>İçerik…</ng-template>
|
|
359
|
+
* </mf-tab-panel>
|
|
360
|
+
* ```
|
|
361
|
+
*
|
|
362
|
+
* `ngTabContent` (`@angular/aria/tabs`'ın `TabContent`'i) doğrudan
|
|
363
|
+
* kullanılır — ayrı bir `appTabContent` sarmalayıcı YOK, tek katmanlı bir
|
|
364
|
+
* yapıya sarmalayıcı eklemenin karşılığı yok (bkz. `TabContent`'in kendi
|
|
365
|
+
* `DeferredContent` mekanizması, panel aktif olana kadar içeriği hiç
|
|
366
|
+
* oluşturmaz — lazy). `<ng-content />` bilerek TEK satır: panelin kendi
|
|
367
|
+
* `role="tabpanel"`/`tabindex`/`inert` host bağlamaları `hostDirectives`'ten
|
|
368
|
+
* geliyor, ekstra bir sarmalayıcıya gerek yok.
|
|
369
|
+
*
|
|
370
|
+
* `[class.hidden]` ELLE eklendi — `AriaTabPanel`'in `inert` attribute'u
|
|
371
|
+
* elemanı erişilebilirlik ağacından/etkileşimden çıkarıyor ama GÖRSEL olarak
|
|
372
|
+
* gizlemiyor (kütüphanenin kendi dokümantasyonu: "Proper styling is required
|
|
373
|
+
* for visual hiding" — gerçek bulgu, ui-kit'te pasif panellerin boş
|
|
374
|
+
* dolgulu kutular olarak GÖRÜNÜR kaldığı görüldü).
|
|
375
|
+
*/
|
|
376
|
+
class TabPanel {
|
|
377
|
+
ariaTabPanel = inject(TabPanel$1);
|
|
378
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
379
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: TabPanel, isStandalone: true, selector: "mf-tab-panel", host: { properties: { "class.hidden": "!ariaTabPanel.visible()" }, classAttribute: "block focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring" }, hostDirectives: [{ directive: i1.TabPanel, inputs: ["value", "value", "id", "id"] }], ngImport: i0, template: '<ng-content />', isInline: true });
|
|
380
|
+
}
|
|
381
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabPanel, decorators: [{
|
|
382
|
+
type: Component,
|
|
383
|
+
args: [{
|
|
384
|
+
selector: 'mf-tab-panel',
|
|
385
|
+
hostDirectives: [{ directive: TabPanel$1, inputs: ['value', 'id'] }],
|
|
386
|
+
host: {
|
|
387
|
+
class: 'block focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring',
|
|
388
|
+
'[class.hidden]': '!ariaTabPanel.visible()',
|
|
389
|
+
},
|
|
390
|
+
template: '<ng-content />',
|
|
391
|
+
}]
|
|
392
|
+
}] });
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* `<mf-tab-strip [items]="items()" [(activeKey)]="active" (close)="onClose($event)" />`
|
|
396
|
+
*
|
|
397
|
+
* `mf-tabs`/`mf-tab-list` (bkz. `tabs.ts`) ARIA `tabs` pattern'i PANEL
|
|
398
|
+
* varsayar (`aria-controls` gerçek bir `role=tabpanel`'e işaret eder) — bu
|
|
399
|
+
* şerit ise bir ROTA/DOKÜMAN şeridi: panel yok, içerik `router-outlet`'ten
|
|
400
|
+
* gelir, sekmeler kapatılabilir. Bu yüzden `@angular/aria/tabs`'ı DEĞİL,
|
|
401
|
+
* elle roving tabindex kullanıyor (emsal: `table-pagination.ts`'in
|
|
402
|
+
* `onNavKeydown`'ı) — ARIA `tab` rolü/`aria-selected` yine de elle
|
|
403
|
+
* uygulanıyor, sadece pattern motoru YOK.
|
|
404
|
+
*
|
|
405
|
+
* Ok tuşları SADECE odağı taşır (`activeKey` DEĞİŞMEZ) — her ok vuruşunda
|
|
406
|
+
* gerçek bir router navigasyonu tetiklemek (bkz. `TabsStore.activate`)
|
|
407
|
+
* pahalı/istenmeyen bir yan etki olurdu. `Enter`/`Space` ya da tık asıl
|
|
408
|
+
* seçimi commit eder. `Delete` odaktaki (kapatılabilir) sekmeyi kapatır.
|
|
409
|
+
*
|
|
410
|
+
* Kapatma butonu gerçek bir `<button>` ama tab elemanının kendisi `role=tab`
|
|
411
|
+
* taşıyan bir `<div>` — `mfTab`'ın (aria Tabs sisteminin) aksine burada bir
|
|
412
|
+
* `<button>` İÇİNE başka bir interaktif eleman GÖMÜLMÜYOR (geçersiz HTML
|
|
413
|
+
* olurdu, bkz. `table-filter-bar.html`'deki chip deseni — aynı gerekçeyle
|
|
414
|
+
* orada da İKİ KARDEŞ buton var, iç içe değil). Kapatma butonu bilerek
|
|
415
|
+
* `tabindex="-1"` — birincil roving-tabindex sırasının parçası değil (fare/
|
|
416
|
+
* dokunma birincil, `Delete` tuşu klavye eşdeğeri).
|
|
417
|
+
*
|
|
418
|
+
* Sağ tık menüsü TAMAMEN tüketiciye ait — bu bileşen belirli bir dropdown
|
|
419
|
+
* kütüphanesini BİLMİYOR (bkz. projects/ui-kit/README.md "Directive mi, component
|
|
420
|
+
* mi?" ruhu — dropdown-agnostik kalma), sadece ham `(itemContextMenu)` olayını
|
|
421
|
+
* yukarı veriyor.
|
|
422
|
+
*/
|
|
423
|
+
class TabStrip {
|
|
424
|
+
items = input.required(/* @ts-ignore */
|
|
425
|
+
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
426
|
+
activeKey = model.required(/* @ts-ignore */
|
|
427
|
+
...(ngDevMode ? [{ debugName: "activeKey" }] : /* istanbul ignore next */ []));
|
|
428
|
+
/** Verilirse aktif sekmenin `aria-controls`'ü buna işaret eder (tek bir paylaşımlı içerik bölgesi — router-outlet). */
|
|
429
|
+
contentId = input(null, /* @ts-ignore */
|
|
430
|
+
...(ngDevMode ? [{ debugName: "contentId" }] : /* istanbul ignore next */ []));
|
|
431
|
+
scrollStartLabel = input(/* @ts-ignore */
|
|
432
|
+
...(ngDevMode ? [undefined, { debugName: "scrollStartLabel" }] : /* istanbul ignore next */ []));
|
|
433
|
+
scrollEndLabel = input(/* @ts-ignore */
|
|
434
|
+
...(ngDevMode ? [undefined, { debugName: "scrollEndLabel" }] : /* istanbul ignore next */ []));
|
|
435
|
+
/** Kapatma butonunun `aria-label`'ı — sekmenin kendi etiketiyle birleştirilir (ör. "Close: Roles"). */
|
|
436
|
+
closeLabel = input(/* @ts-ignore */
|
|
437
|
+
...(ngDevMode ? [undefined, { debugName: "closeLabel" }] : /* istanbul ignore next */ []));
|
|
438
|
+
tabsLabels = inject(MF_TABS_LABELS);
|
|
439
|
+
effectiveScrollStartLabel = computed(() => this.scrollStartLabel() ?? this.tabsLabels().scrollStart, /* @ts-ignore */
|
|
440
|
+
...(ngDevMode ? [{ debugName: "effectiveScrollStartLabel" }] : /* istanbul ignore next */ []));
|
|
441
|
+
effectiveScrollEndLabel = computed(() => this.scrollEndLabel() ?? this.tabsLabels().scrollEnd, /* @ts-ignore */
|
|
442
|
+
...(ngDevMode ? [{ debugName: "effectiveScrollEndLabel" }] : /* istanbul ignore next */ []));
|
|
443
|
+
effectiveCloseLabel = computed(() => this.closeLabel() ?? this.tabsLabels().close, /* @ts-ignore */
|
|
444
|
+
...(ngDevMode ? [{ debugName: "effectiveCloseLabel" }] : /* istanbul ignore next */ []));
|
|
445
|
+
// `close` adı native DOM `close` olayıyla çakışıyor (@angular-eslint/no-output-native);
|
|
446
|
+
// mevcut public API — yeniden adlandırma kırıcı, ileri bir sürümde ele alınacak.
|
|
447
|
+
// eslint-disable-next-line @angular-eslint/no-output-native
|
|
448
|
+
close = output();
|
|
449
|
+
itemContextMenu = output();
|
|
450
|
+
focusedKey = signal(null, /* @ts-ignore */
|
|
451
|
+
...(ngDevMode ? [{ debugName: "focusedKey" }] : /* istanbul ignore next */ []));
|
|
452
|
+
scroller = viewChild(TabScroller, /* @ts-ignore */
|
|
453
|
+
...(ngDevMode ? [{ debugName: "scroller" }] : /* istanbul ignore next */ []));
|
|
454
|
+
showStartArrow = computed(() => this.scroller()?.canScrollStart() ?? false, /* @ts-ignore */
|
|
455
|
+
...(ngDevMode ? [{ debugName: "showStartArrow" }] : /* istanbul ignore next */ []));
|
|
456
|
+
showEndArrow = computed(() => this.scroller()?.canScrollEnd() ?? false, /* @ts-ignore */
|
|
457
|
+
...(ngDevMode ? [{ debugName: "showEndArrow" }] : /* istanbul ignore next */ []));
|
|
458
|
+
rowEl = viewChild('row', /* @ts-ignore */
|
|
459
|
+
...(ngDevMode ? [{ debugName: "rowEl" }] : /* istanbul ignore next */ []));
|
|
460
|
+
tabClasses(item) {
|
|
461
|
+
return cn(tabVariants({ variant: 'card', selected: item.key === this.activeKey(), disabled: false }), 'pe-1.5');
|
|
462
|
+
}
|
|
463
|
+
tabIndexFor(item) {
|
|
464
|
+
const focused = this.focusedKey() ?? this.activeKey();
|
|
465
|
+
return item.key === focused ? 0 : -1;
|
|
466
|
+
}
|
|
467
|
+
select(key) {
|
|
468
|
+
this.focusedKey.set(key);
|
|
469
|
+
this.activeKey.set(key);
|
|
470
|
+
}
|
|
471
|
+
onCloseClick(event, key) {
|
|
472
|
+
event.stopPropagation();
|
|
473
|
+
this.close.emit(key);
|
|
474
|
+
}
|
|
475
|
+
onContextMenu(event, item) {
|
|
476
|
+
event.preventDefault();
|
|
477
|
+
this.itemContextMenu.emit({ event, item });
|
|
478
|
+
}
|
|
479
|
+
onKeydown(event) {
|
|
480
|
+
const items = this.items();
|
|
481
|
+
if (items.length === 0)
|
|
482
|
+
return;
|
|
483
|
+
const currentKey = this.focusedKey() ?? this.activeKey();
|
|
484
|
+
const index = items.findIndex((i) => i.key === currentKey);
|
|
485
|
+
switch (event.key) {
|
|
486
|
+
case 'ArrowLeft':
|
|
487
|
+
event.preventDefault();
|
|
488
|
+
this.focusIndex(index <= 0 ? items.length - 1 : index - 1);
|
|
489
|
+
break;
|
|
490
|
+
case 'ArrowRight':
|
|
491
|
+
event.preventDefault();
|
|
492
|
+
this.focusIndex(index === -1 || index === items.length - 1 ? 0 : index + 1);
|
|
493
|
+
break;
|
|
494
|
+
case 'Home':
|
|
495
|
+
event.preventDefault();
|
|
496
|
+
this.focusIndex(0);
|
|
497
|
+
break;
|
|
498
|
+
case 'End':
|
|
499
|
+
event.preventDefault();
|
|
500
|
+
this.focusIndex(items.length - 1);
|
|
501
|
+
break;
|
|
502
|
+
case 'Enter':
|
|
503
|
+
case ' ':
|
|
504
|
+
event.preventDefault();
|
|
505
|
+
if (index !== -1)
|
|
506
|
+
this.select(items[index].key);
|
|
507
|
+
break;
|
|
508
|
+
case 'Delete':
|
|
509
|
+
if (index !== -1 && items[index].closable) {
|
|
510
|
+
event.preventDefault();
|
|
511
|
+
this.close.emit(items[index].key);
|
|
512
|
+
}
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
focusIndex(index) {
|
|
517
|
+
const item = this.items()[index];
|
|
518
|
+
if (!item)
|
|
519
|
+
return;
|
|
520
|
+
this.focusedKey.set(item.key);
|
|
521
|
+
queueMicrotask(() => {
|
|
522
|
+
const btn = this.rowEl()?.nativeElement.querySelector(`[data-tab-key="${item.key}"]`);
|
|
523
|
+
btn?.focus();
|
|
524
|
+
if (btn)
|
|
525
|
+
this.scroller()?.scrollIntoViewIfNeeded(btn);
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabStrip, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
529
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: TabStrip, isStandalone: true, selector: "mf-tab-strip", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: true, transformFunction: null }, contentId: { classPropertyName: "contentId", publicName: "contentId", isSignal: true, isRequired: false, transformFunction: null }, scrollStartLabel: { classPropertyName: "scrollStartLabel", publicName: "scrollStartLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollEndLabel: { classPropertyName: "scrollEndLabel", publicName: "scrollEndLabel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeKey: "activeKeyChange", close: "close", itemContextMenu: "itemContextMenu" }, host: { attributes: { "role": "tablist" }, classAttribute: "block" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: TabScroller, descendants: true, isSignal: true }, { propertyName: "rowEl", first: true, predicate: ["row"], descendants: true, isSignal: true }], exportAs: ["mfTabStrip"], ngImport: i0, template: "<div class=\"flex items-center gap-1\">\r\n @if (showStartArrow()) {\r\n <button\r\n type=\"button\"\r\n class=\"shrink-0 appearance-none border-0 bg-transparent p-1 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n [attr.aria-label]=\"effectiveScrollStartLabel()\"\r\n (click)=\"scroller()?.scrollByDir(-1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">chevron_left</span>\r\n </button>\r\n }\r\n\r\n <!-- Kayd\u0131rma kapsay\u0131c\u0131s\u0131 odaklanabilir de\u011Fil \u2014 ok tu\u015Fu gezinmesi burada delege; ger\u00E7ek odak roving tabindex ile alt sekmelerde. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div mfTabScroller (keydown)=\"onKeydown($event)\">\r\n <div #row class=\"flex items-center gap-1 py-1\">\r\n @for (item of items(); track item.key) {\r\n <!-- Enter/Space se\u00E7imi \u00FCstteki kapsay\u0131c\u0131n\u0131n (keydown)'\u0131nda y\u00F6netiliyor (roving tabindex deseni). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div\r\n role=\"tab\"\r\n [attr.data-tab-key]=\"item.key\"\r\n [attr.aria-selected]=\"item.key === activeKey()\"\r\n [attr.aria-controls]=\"item.key === activeKey() ? contentId() : null\"\r\n [tabindex]=\"tabIndexFor(item)\"\r\n [class]=\"tabClasses(item)\"\r\n (click)=\"select(item.key)\"\r\n (contextmenu)=\"onContextMenu($event, item)\"\r\n >\r\n @if (item.icon) {\r\n <span mfIcon [size]=\"14\">{{ item.icon }}</span>\r\n }\r\n <span class=\"truncate\">{{ item.label }}</span>\r\n @if (item.closable) {\r\n <button\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n class=\"ms-0.5 inline-flex h-4 w-4 shrink-0 appearance-none items-center justify-center rounded-xs border-0 bg-transparent p-0 text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-active hover:text-fg\"\r\n [attr.aria-label]=\"effectiveCloseLabel() + ': ' + item.label\"\r\n (click)=\"onCloseClick($event, item.key)\"\r\n >\r\n <span mfIcon [size]=\"13\">close</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (showEndArrow()) {\r\n <button\r\n type=\"button\"\r\n class=\"shrink-0 appearance-none border-0 bg-transparent p-1 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n [attr.aria-label]=\"effectiveScrollEndLabel()\"\r\n (click)=\"scroller()?.scrollByDir(1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">chevron_right</span>\r\n </button>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "directive", type: Icon, selector: "span[mfIcon]", inputs: ["size", "filled"] }, { kind: "directive", type: TabScroller, selector: "[mfTabScroller]", inputs: ["orientation"] }] });
|
|
530
|
+
}
|
|
531
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TabStrip, decorators: [{
|
|
532
|
+
type: Component,
|
|
533
|
+
args: [{ selector: 'mf-tab-strip', exportAs: 'mfTabStrip', imports: [Icon, TabScroller], host: { class: 'block', role: 'tablist' }, template: "<div class=\"flex items-center gap-1\">\r\n @if (showStartArrow()) {\r\n <button\r\n type=\"button\"\r\n class=\"shrink-0 appearance-none border-0 bg-transparent p-1 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n [attr.aria-label]=\"effectiveScrollStartLabel()\"\r\n (click)=\"scroller()?.scrollByDir(-1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">chevron_left</span>\r\n </button>\r\n }\r\n\r\n <!-- Kayd\u0131rma kapsay\u0131c\u0131s\u0131 odaklanabilir de\u011Fil \u2014 ok tu\u015Fu gezinmesi burada delege; ger\u00E7ek odak roving tabindex ile alt sekmelerde. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div mfTabScroller (keydown)=\"onKeydown($event)\">\r\n <div #row class=\"flex items-center gap-1 py-1\">\r\n @for (item of items(); track item.key) {\r\n <!-- Enter/Space se\u00E7imi \u00FCstteki kapsay\u0131c\u0131n\u0131n (keydown)'\u0131nda y\u00F6netiliyor (roving tabindex deseni). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div\r\n role=\"tab\"\r\n [attr.data-tab-key]=\"item.key\"\r\n [attr.aria-selected]=\"item.key === activeKey()\"\r\n [attr.aria-controls]=\"item.key === activeKey() ? contentId() : null\"\r\n [tabindex]=\"tabIndexFor(item)\"\r\n [class]=\"tabClasses(item)\"\r\n (click)=\"select(item.key)\"\r\n (contextmenu)=\"onContextMenu($event, item)\"\r\n >\r\n @if (item.icon) {\r\n <span mfIcon [size]=\"14\">{{ item.icon }}</span>\r\n }\r\n <span class=\"truncate\">{{ item.label }}</span>\r\n @if (item.closable) {\r\n <button\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n class=\"ms-0.5 inline-flex h-4 w-4 shrink-0 appearance-none items-center justify-center rounded-xs border-0 bg-transparent p-0 text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-active hover:text-fg\"\r\n [attr.aria-label]=\"effectiveCloseLabel() + ': ' + item.label\"\r\n (click)=\"onCloseClick($event, item.key)\"\r\n >\r\n <span mfIcon [size]=\"13\">close</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (showEndArrow()) {\r\n <button\r\n type=\"button\"\r\n class=\"shrink-0 appearance-none border-0 bg-transparent p-1 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n [attr.aria-label]=\"effectiveScrollEndLabel()\"\r\n (click)=\"scroller()?.scrollByDir(1)\"\r\n >\r\n <span mfIcon [size]=\"16\" class=\"rtl:-scale-x-100\">chevron_right</span>\r\n </button>\r\n }\r\n</div>\r\n" }]
|
|
534
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], activeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeKey", required: true }] }, { type: i0.Output, args: ["activeKeyChange"] }], contentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentId", required: false }] }], scrollStartLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollStartLabel", required: false }] }], scrollEndLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollEndLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], itemContextMenu: [{ type: i0.Output, args: ["itemContextMenu"] }], scroller: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TabScroller), { isSignal: true }] }], rowEl: [{ type: i0.ViewChild, args: ['row', { isSignal: true }] }] } });
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* `<mf-tabs><mf-tab-list>...</mf-tab-list><mf-tab-panel>...</mf-tab-panel></mf-tabs>`
|
|
538
|
+
*
|
|
539
|
+
* Salt bir kapsayıcı — tüm ARIA/klavye/state mantığı `@angular/aria/tabs`'ın
|
|
540
|
+
* `Tabs` pattern'inden `hostDirectives` ile ödünç alınıyor (bkz.
|
|
541
|
+
* projects/ui-kit/README.md "a11y checklist": "mümkün olduğunca `@angular/aria`...
|
|
542
|
+
* elle ARIA yazmak son çare"). `hostDirectives`, ana bileşenin (`mf-tabs`)
|
|
543
|
+
* host elemanına `Tabs`'ın DI sağlayıcısını (`TABS` token) ekliyor — alttaki
|
|
544
|
+
* `mf-tab-list`/`mf-tab-panel` bunu `inject()` ile bulup kendini
|
|
545
|
+
* kaydediyor, template'te `ngTabs` attribute'unu ELLE yazmaya gerek yok
|
|
546
|
+
* (`hostDirectives`'te selector yok sayılır, bkz. Angular directive
|
|
547
|
+
* composition API).
|
|
548
|
+
*/
|
|
549
|
+
class Tabs {
|
|
550
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
551
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: Tabs, isStandalone: true, selector: "mf-tabs", host: { classAttribute: "block" }, exportAs: ["mfTabs"], hostDirectives: [{ directive: i1.Tabs }], ngImport: i0, template: '<ng-content />', isInline: true });
|
|
552
|
+
}
|
|
553
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tabs, decorators: [{
|
|
554
|
+
type: Component,
|
|
555
|
+
args: [{
|
|
556
|
+
selector: 'mf-tabs',
|
|
557
|
+
exportAs: 'mfTabs',
|
|
558
|
+
hostDirectives: [Tabs$1],
|
|
559
|
+
host: { class: 'block' },
|
|
560
|
+
template: '<ng-content />',
|
|
561
|
+
}]
|
|
562
|
+
}] });
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Generated bundle index. Do not edit.
|
|
566
|
+
*/
|
|
567
|
+
|
|
568
|
+
export { Tab, TabList, TabPanel, TabScroller, TabStrip, Tabs, tabListVariants, tabVariants };
|
|
569
|
+
//# sourceMappingURL=mesgflow-ui-kit-tabs.mjs.map
|