@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,154 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { model, input, inject, computed, signal, viewChild, effect, untracked, forwardRef, Component } from '@angular/core';
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { ValueAccessorBase, MF_SEARCH_INPUT_LABELS } from '@mesgflow/ui-kit/core';
|
|
5
|
+
import { Icon } from '@mesgflow/ui-kit/icon';
|
|
6
|
+
import { Input } from '@mesgflow/ui-kit/input';
|
|
7
|
+
import { Tooltip } from '@mesgflow/ui-kit/tooltip';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `<mf-search-input [(value)]="term" [loading]="fetching()" placeholder="Ara..." />`
|
|
11
|
+
*
|
|
12
|
+
* Kapalıyken sadece bir ikon-buton genişliğinde (ikon tıklanabilir/odaklanabilir
|
|
13
|
+
* — hem mouse hem klavye ile genişliyor), odak alınca/tıklanınca genişliyor.
|
|
14
|
+
* Yazarken debounce süresi boyunca VE (varsa) dışarıdan verilen `loading`
|
|
15
|
+
* true olduğu sürece dönen bir spinner gösteriyor — "arıyor" hissi debounce
|
|
16
|
+
* bitiminde kaybolmuyor, gerçek sorgu sonucu gelene kadar sürüyor.
|
|
17
|
+
*
|
|
18
|
+
* Component (directive değil) — Field/Switch gibi gerçek iç yapı (ikon+input+
|
|
19
|
+
* temizle butonu+genişleme animasyonu) gerektiriyor (bkz. projects/ui-kit/README.md
|
|
20
|
+
* "Directive mi, component mi?").
|
|
21
|
+
*/
|
|
22
|
+
class SearchInput extends ValueAccessorBase {
|
|
23
|
+
value = model('', /* @ts-ignore */
|
|
24
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
25
|
+
placeholder = input(/* @ts-ignore */
|
|
26
|
+
...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
27
|
+
ariaLabel = input(/* @ts-ignore */
|
|
28
|
+
...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
29
|
+
tooltipLabel = input(/* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [undefined, { debugName: "tooltipLabel" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/** Tüketicinin gerçek veri çekme durumu — debounce bittikten sonra da spinner'ı sürdürür. */
|
|
32
|
+
loading = input(false, /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
34
|
+
debounceMs = input(300, /* @ts-ignore */
|
|
35
|
+
...(ngDevMode ? [{ debugName: "debounceMs" }] : /* istanbul ignore next */ []));
|
|
36
|
+
/**
|
|
37
|
+
* `false` → her zaman tam genişlikte açık, ikon tıklanabilir bir "kapı"
|
|
38
|
+
* değil (bkz. `table/table.ts` — bir VERİ TABLOSUNDA arama gizlenmez,
|
|
39
|
+
* bu bir navbar deseni; Table `[collapsible]="false"` geçiyor).
|
|
40
|
+
* Varsayılan `true` — bu bileşenin bugünkü tek gerçek davranışı, henüz
|
|
41
|
+
* başka bir tüketici yok ama gelecekte navbar/toolbar gibi dar bağlamlarda
|
|
42
|
+
* ihtiyaç olabilir diye korunuyor.
|
|
43
|
+
*/
|
|
44
|
+
collapsible = input(true, /* @ts-ignore */
|
|
45
|
+
...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
|
|
46
|
+
/**
|
|
47
|
+
* `true` → kutu sabit `w-64` (256px) yerine kapsayıcısının TAM genişliğinde
|
|
48
|
+
* açılır — kutunun panelin geri kalanıyla (ör. yan yana duran bir sekme
|
|
49
|
+
* listesiyle) aynı genişlikte hizalanması gereken bağlamlar için.
|
|
50
|
+
* `collapsible` ile birlikte anlamlı (`[collapsible]="false"` olmadan
|
|
51
|
+
* daralmış hâl `w-10` sabit kalır, `fullWidth` sadece GENİŞLEMİŞ genişliği
|
|
52
|
+
* değiştirir). Varsayılan `false` — navbar/toolbar'daki bugünkü sabit
|
|
53
|
+
* genişlik davranışı değişmez.
|
|
54
|
+
*/
|
|
55
|
+
fullWidth = input(false, /* @ts-ignore */
|
|
56
|
+
...(ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []));
|
|
57
|
+
searchInputLabels = inject(MF_SEARCH_INPUT_LABELS);
|
|
58
|
+
effectivePlaceholder = computed(() => this.placeholder() ?? this.searchInputLabels().placeholder, /* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [{ debugName: "effectivePlaceholder" }] : /* istanbul ignore next */ []));
|
|
60
|
+
effectiveAriaLabel = computed(() => this.ariaLabel() ?? this.searchInputLabels().ariaLabel, /* @ts-ignore */
|
|
61
|
+
...(ngDevMode ? [{ debugName: "effectiveAriaLabel" }] : /* istanbul ignore next */ []));
|
|
62
|
+
effectiveTooltipLabel = computed(() => this.tooltipLabel() ?? this.searchInputLabels().ariaLabel, /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "effectiveTooltipLabel" }] : /* istanbul ignore next */ []));
|
|
64
|
+
effectiveClearAriaLabel = computed(() => this.searchInputLabels().clearAriaLabel, /* @ts-ignore */
|
|
65
|
+
...(ngDevMode ? [{ debugName: "effectiveClearAriaLabel" }] : /* istanbul ignore next */ []));
|
|
66
|
+
expandedState = signal(false, /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "expandedState" }] : /* istanbul ignore next */ []));
|
|
68
|
+
/** `collapsible()` false ise HER ZAMAN true — genişleme mekaniği devre dışı kalır ama `expandedState` yine de "odaklanınca tooltip'i kapat" gibi yan mantık için iç durumu takip etmeye devam eder. */
|
|
69
|
+
expanded = computed(() => !this.collapsible() || this.expandedState(), /* @ts-ignore */
|
|
70
|
+
...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
71
|
+
/** `w-64`/`w-10` yerine `w-full` — bkz. `fullWidth` doc yorumu. */
|
|
72
|
+
inputWidthClass = computed(() => this.fullWidth()
|
|
73
|
+
? 'w-full cursor-text pe-8 ps-9'
|
|
74
|
+
: this.expanded()
|
|
75
|
+
? 'w-64 cursor-text pe-8 ps-9'
|
|
76
|
+
: 'w-10 cursor-pointer caret-transparent pe-2 ps-9', /* @ts-ignore */
|
|
77
|
+
...(ngDevMode ? [{ debugName: "inputWidthClass" }] : /* istanbul ignore next */ []));
|
|
78
|
+
draft = signal('', /* @ts-ignore */
|
|
79
|
+
...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
80
|
+
pending = signal(false, /* @ts-ignore */
|
|
81
|
+
...(ngDevMode ? [{ debugName: "pending" }] : /* istanbul ignore next */ []));
|
|
82
|
+
showSpinner = computed(() => this.pending() || this.loading(), /* @ts-ignore */
|
|
83
|
+
...(ngDevMode ? [{ debugName: "showSpinner" }] : /* istanbul ignore next */ []));
|
|
84
|
+
inputEl = viewChild('inputEl', /* @ts-ignore */
|
|
85
|
+
...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
|
|
86
|
+
tooltipRef = viewChild(Tooltip, /* @ts-ignore */
|
|
87
|
+
...(ngDevMode ? [{ debugName: "tooltipRef" }] : /* istanbul ignore next */ []));
|
|
88
|
+
debounceHandle;
|
|
89
|
+
constructor() {
|
|
90
|
+
super();
|
|
91
|
+
// Dışarıdan (ör. "Filtreleri temizle") value() sıfırlanırsa draft de eşlensin.
|
|
92
|
+
effect(() => {
|
|
93
|
+
const current = this.value();
|
|
94
|
+
untracked(() => this.draft.set(current));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
writeValue(value) {
|
|
98
|
+
this.value.set(value);
|
|
99
|
+
}
|
|
100
|
+
expand() {
|
|
101
|
+
this.expandedState.set(true);
|
|
102
|
+
// Tooltip'in kendi `(focus)` dinleyicisi AYNI olayda tetiklendiğinden
|
|
103
|
+
// ("Ara..." balonu) genişlemiş, placeholder'ı zaten aynı metni gösteren
|
|
104
|
+
// input'un üstünde gereksiz kalıyordu — anında kapatılıyor (gerçek bulgu).
|
|
105
|
+
this.tooltipRef()?.hide();
|
|
106
|
+
}
|
|
107
|
+
collapseIfEmpty() {
|
|
108
|
+
if (!this.draft().trim())
|
|
109
|
+
this.expandedState.set(false);
|
|
110
|
+
}
|
|
111
|
+
onInput(raw) {
|
|
112
|
+
this.draft.set(raw);
|
|
113
|
+
this.pending.set(true);
|
|
114
|
+
this.onTouched();
|
|
115
|
+
clearTimeout(this.debounceHandle);
|
|
116
|
+
this.debounceHandle = setTimeout(() => {
|
|
117
|
+
this.pending.set(false);
|
|
118
|
+
this.value.set(raw);
|
|
119
|
+
this.onChange(raw);
|
|
120
|
+
}, this.debounceMs());
|
|
121
|
+
}
|
|
122
|
+
clear() {
|
|
123
|
+
clearTimeout(this.debounceHandle);
|
|
124
|
+
this.pending.set(false);
|
|
125
|
+
this.draft.set('');
|
|
126
|
+
this.value.set('');
|
|
127
|
+
this.onChange('');
|
|
128
|
+
this.onTouched();
|
|
129
|
+
this.inputEl()?.nativeElement.focus();
|
|
130
|
+
}
|
|
131
|
+
onEscape() {
|
|
132
|
+
if (this.draft())
|
|
133
|
+
this.clear();
|
|
134
|
+
else
|
|
135
|
+
this.inputEl()?.nativeElement.blur();
|
|
136
|
+
}
|
|
137
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SearchInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
138
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: SearchInput, isStandalone: true, selector: "mf-search-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, tooltipLabel: { classPropertyName: "tooltipLabel", publicName: "tooltipLabel", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.w-full": "fullWidth()" }, classAttribute: "inline-block" }, providers: [
|
|
139
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SearchInput), multi: true },
|
|
140
|
+
], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }, { propertyName: "tooltipRef", first: true, predicate: Tooltip, descendants: true, isSignal: true }], exportAs: ["mfSearchInput"], usesInheritance: true, ngImport: i0, template: "<div class=\"relative inline-flex items-center\" [class.w-full]=\"fullWidth()\">\r\n <span\r\n mfIcon\r\n [size]=\"18\"\r\n class=\"pointer-events-none absolute top-1/2 start-2.5 -translate-y-1/2 text-fg-subtle\"\r\n [class.animate-spin]=\"showSpinner()\"\r\n >{{ showSpinner() ? 'progress_activity' : 'search' }}</span\r\n >\r\n <input\r\n mfInput\r\n #inputEl\r\n type=\"text\"\r\n [class]=\"inputWidthClass()\"\r\n class=\"transition-[width] duration-base ease-out\"\r\n [value]=\"draft()\"\r\n [placeholder]=\"expanded() ? effectivePlaceholder() : ''\"\r\n [attr.aria-label]=\"effectiveAriaLabel()\"\r\n [mfTooltip]=\"expanded() ? '' : effectiveTooltipLabel()\"\r\n (focus)=\"expand()\"\r\n (input)=\"onInput($any($event.target).value)\"\r\n (blur)=\"collapseIfEmpty()\"\r\n (keydown.escape)=\"onEscape()\"\r\n />\r\n @if (expanded() && draft()) {\r\n <button\r\n type=\"button\"\r\n class=\"absolute top-1/2 end-2 -translate-y-1/2 appearance-none border-0 bg-transparent p-0 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"effectiveClearAriaLabel()\"\r\n >\r\n <span mfIcon [size]=\"16\">close</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: Input, selector: "input[mfInput]:not([type=checkbox]):not([type=radio]), textarea[mfInput]", inputs: ["size", "hasError", "autosize", "minRows", "maxRows"] }, { kind: "directive", type: Tooltip, selector: "[mfTooltip], [mfTooltipContent]", inputs: ["mfTooltip", "mfTooltipContent", "tooltipPosition"], exportAs: ["mfTooltip"] }] });
|
|
141
|
+
}
|
|
142
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SearchInput, decorators: [{
|
|
143
|
+
type: Component,
|
|
144
|
+
args: [{ selector: 'mf-search-input', exportAs: 'mfSearchInput', imports: [Icon, Input, Tooltip], host: { class: 'inline-block', '[class.w-full]': 'fullWidth()' }, providers: [
|
|
145
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SearchInput), multi: true },
|
|
146
|
+
], template: "<div class=\"relative inline-flex items-center\" [class.w-full]=\"fullWidth()\">\r\n <span\r\n mfIcon\r\n [size]=\"18\"\r\n class=\"pointer-events-none absolute top-1/2 start-2.5 -translate-y-1/2 text-fg-subtle\"\r\n [class.animate-spin]=\"showSpinner()\"\r\n >{{ showSpinner() ? 'progress_activity' : 'search' }}</span\r\n >\r\n <input\r\n mfInput\r\n #inputEl\r\n type=\"text\"\r\n [class]=\"inputWidthClass()\"\r\n class=\"transition-[width] duration-base ease-out\"\r\n [value]=\"draft()\"\r\n [placeholder]=\"expanded() ? effectivePlaceholder() : ''\"\r\n [attr.aria-label]=\"effectiveAriaLabel()\"\r\n [mfTooltip]=\"expanded() ? '' : effectiveTooltipLabel()\"\r\n (focus)=\"expand()\"\r\n (input)=\"onInput($any($event.target).value)\"\r\n (blur)=\"collapseIfEmpty()\"\r\n (keydown.escape)=\"onEscape()\"\r\n />\r\n @if (expanded() && draft()) {\r\n <button\r\n type=\"button\"\r\n class=\"absolute top-1/2 end-2 -translate-y-1/2 appearance-none border-0 bg-transparent p-0 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"effectiveClearAriaLabel()\"\r\n >\r\n <span mfIcon [size]=\"16\">close</span>\r\n </button>\r\n }\r\n</div>\r\n" }]
|
|
147
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], tooltipLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipLabel", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], tooltipRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => Tooltip), { isSignal: true }] }] } });
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Generated bundle index. Do not edit.
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
export { SearchInput };
|
|
154
|
+
//# sourceMappingURL=mesgflow-ui-kit-search-input.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-search-input.mjs","sources":["../../../projects/ui-kit/search-input/search-input.ts","../../../projects/ui-kit/search-input/search-input.html","../../../projects/ui-kit/search-input/mesgflow-ui-kit-search-input.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n computed,\r\n effect,\r\n forwardRef,\r\n inject,\r\n input,\r\n model,\r\n signal,\r\n untracked,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { NG_VALUE_ACCESSOR, type ControlValueAccessor } from '@angular/forms';\r\nimport { MF_SEARCH_INPUT_LABELS, ValueAccessorBase } from '@mesgflow/ui-kit/core';\r\nimport { Icon } from '@mesgflow/ui-kit/icon';\r\nimport { Input } from '@mesgflow/ui-kit/input';\r\nimport { Tooltip } from '@mesgflow/ui-kit/tooltip';\r\n\r\n/**\r\n * `<mf-search-input [(value)]=\"term\" [loading]=\"fetching()\" placeholder=\"Ara...\" />`\r\n *\r\n * Kapalıyken sadece bir ikon-buton genişliğinde (ikon tıklanabilir/odaklanabilir\r\n * — hem mouse hem klavye ile genişliyor), odak alınca/tıklanınca genişliyor.\r\n * Yazarken debounce süresi boyunca VE (varsa) dışarıdan verilen `loading`\r\n * true olduğu sürece dönen bir spinner gösteriyor — \"arıyor\" hissi debounce\r\n * bitiminde kaybolmuyor, gerçek sorgu sonucu gelene kadar sürüyor.\r\n *\r\n * Component (directive değil) — Field/Switch gibi gerçek iç yapı (ikon+input+\r\n * temizle butonu+genişleme animasyonu) gerektiriyor (bkz. projects/ui-kit/README.md\r\n * \"Directive mi, component mi?\").\r\n */\r\n@Component({\r\n selector: 'mf-search-input',\r\n exportAs: 'mfSearchInput',\r\n imports: [Icon, Input, Tooltip],\r\n host: { class: 'inline-block', '[class.w-full]': 'fullWidth()' },\r\n templateUrl: './search-input.html',\r\n providers: [\r\n { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SearchInput), multi: true },\r\n ],\r\n})\r\nexport class SearchInput extends ValueAccessorBase<string> implements ControlValueAccessor {\r\n readonly value = model('');\r\n readonly placeholder = input<string>();\r\n readonly ariaLabel = input<string>();\r\n readonly tooltipLabel = input<string>();\r\n /** Tüketicinin gerçek veri çekme durumu — debounce bittikten sonra da spinner'ı sürdürür. */\r\n readonly loading = input(false);\r\n readonly debounceMs = input(300);\r\n /**\r\n * `false` → her zaman tam genişlikte açık, ikon tıklanabilir bir \"kapı\"\r\n * değil (bkz. `table/table.ts` — bir VERİ TABLOSUNDA arama gizlenmez,\r\n * bu bir navbar deseni; Table `[collapsible]=\"false\"` geçiyor).\r\n * Varsayılan `true` — bu bileşenin bugünkü tek gerçek davranışı, henüz\r\n * başka bir tüketici yok ama gelecekte navbar/toolbar gibi dar bağlamlarda\r\n * ihtiyaç olabilir diye korunuyor.\r\n */\r\n readonly collapsible = input(true);\r\n /**\r\n * `true` → kutu sabit `w-64` (256px) yerine kapsayıcısının TAM genişliğinde\r\n * açılır — kutunun panelin geri kalanıyla (ör. yan yana duran bir sekme\r\n * listesiyle) aynı genişlikte hizalanması gereken bağlamlar için.\r\n * `collapsible` ile birlikte anlamlı (`[collapsible]=\"false\"` olmadan\r\n * daralmış hâl `w-10` sabit kalır, `fullWidth` sadece GENİŞLEMİŞ genişliği\r\n * değiştirir). Varsayılan `false` — navbar/toolbar'daki bugünkü sabit\r\n * genişlik davranışı değişmez.\r\n */\r\n readonly fullWidth = input(false);\r\n\r\n private readonly searchInputLabels = inject(MF_SEARCH_INPUT_LABELS);\r\n protected readonly effectivePlaceholder = computed(\r\n () => this.placeholder() ?? this.searchInputLabels().placeholder,\r\n );\r\n protected readonly effectiveAriaLabel = computed(\r\n () => this.ariaLabel() ?? this.searchInputLabels().ariaLabel,\r\n );\r\n protected readonly effectiveTooltipLabel = computed(\r\n () => this.tooltipLabel() ?? this.searchInputLabels().ariaLabel,\r\n );\r\n protected readonly effectiveClearAriaLabel = computed(\r\n () => this.searchInputLabels().clearAriaLabel,\r\n );\r\n\r\n private readonly expandedState = signal(false);\r\n /** `collapsible()` false ise HER ZAMAN true — genişleme mekaniği devre dışı kalır ama `expandedState` yine de \"odaklanınca tooltip'i kapat\" gibi yan mantık için iç durumu takip etmeye devam eder. */\r\n protected readonly expanded = computed(() => !this.collapsible() || this.expandedState());\r\n /** `w-64`/`w-10` yerine `w-full` — bkz. `fullWidth` doc yorumu. */\r\n protected readonly inputWidthClass = computed(() =>\r\n this.fullWidth()\r\n ? 'w-full cursor-text pe-8 ps-9'\r\n : this.expanded()\r\n ? 'w-64 cursor-text pe-8 ps-9'\r\n : 'w-10 cursor-pointer caret-transparent pe-2 ps-9',\r\n );\r\n protected readonly draft = signal('');\r\n protected readonly pending = signal(false);\r\n protected readonly showSpinner = computed(() => this.pending() || this.loading());\r\n\r\n private readonly inputEl = viewChild<ElementRef<HTMLInputElement>>('inputEl');\r\n private readonly tooltipRef = viewChild(Tooltip);\r\n private debounceHandle?: ReturnType<typeof setTimeout>;\r\n\r\n constructor() {\r\n super();\r\n // Dışarıdan (ör. \"Filtreleri temizle\") value() sıfırlanırsa draft de eşlensin.\r\n effect(() => {\r\n const current = this.value();\r\n untracked(() => this.draft.set(current));\r\n });\r\n }\r\n\r\n writeValue(value: string): void {\r\n this.value.set(value);\r\n }\r\n\r\n protected expand(): void {\r\n this.expandedState.set(true);\r\n // Tooltip'in kendi `(focus)` dinleyicisi AYNI olayda tetiklendiğinden\r\n // (\"Ara...\" balonu) genişlemiş, placeholder'ı zaten aynı metni gösteren\r\n // input'un üstünde gereksiz kalıyordu — anında kapatılıyor (gerçek bulgu).\r\n this.tooltipRef()?.hide();\r\n }\r\n\r\n protected collapseIfEmpty(): void {\r\n if (!this.draft().trim()) this.expandedState.set(false);\r\n }\r\n\r\n protected onInput(raw: string): void {\r\n this.draft.set(raw);\r\n this.pending.set(true);\r\n this.onTouched();\r\n clearTimeout(this.debounceHandle);\r\n this.debounceHandle = setTimeout(() => {\r\n this.pending.set(false);\r\n this.value.set(raw);\r\n this.onChange(raw);\r\n }, this.debounceMs());\r\n }\r\n\r\n protected clear(): void {\r\n clearTimeout(this.debounceHandle);\r\n this.pending.set(false);\r\n this.draft.set('');\r\n this.value.set('');\r\n this.onChange('');\r\n this.onTouched();\r\n this.inputEl()?.nativeElement.focus();\r\n }\r\n\r\n protected onEscape(): void {\r\n if (this.draft()) this.clear();\r\n else this.inputEl()?.nativeElement.blur();\r\n }\r\n}\r\n","<div class=\"relative inline-flex items-center\" [class.w-full]=\"fullWidth()\">\r\n <span\r\n mfIcon\r\n [size]=\"18\"\r\n class=\"pointer-events-none absolute top-1/2 start-2.5 -translate-y-1/2 text-fg-subtle\"\r\n [class.animate-spin]=\"showSpinner()\"\r\n >{{ showSpinner() ? 'progress_activity' : 'search' }}</span\r\n >\r\n <input\r\n mfInput\r\n #inputEl\r\n type=\"text\"\r\n [class]=\"inputWidthClass()\"\r\n class=\"transition-[width] duration-base ease-out\"\r\n [value]=\"draft()\"\r\n [placeholder]=\"expanded() ? effectivePlaceholder() : ''\"\r\n [attr.aria-label]=\"effectiveAriaLabel()\"\r\n [mfTooltip]=\"expanded() ? '' : effectiveTooltipLabel()\"\r\n (focus)=\"expand()\"\r\n (input)=\"onInput($any($event.target).value)\"\r\n (blur)=\"collapseIfEmpty()\"\r\n (keydown.escape)=\"onEscape()\"\r\n />\r\n @if (expanded() && draft()) {\r\n <button\r\n type=\"button\"\r\n class=\"absolute top-1/2 end-2 -translate-y-1/2 appearance-none border-0 bg-transparent p-0 text-fg-subtle transition-colors duration-fast ease-emphasis hover:text-fg\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"effectiveClearAriaLabel()\"\r\n >\r\n <span mfIcon [size]=\"16\">close</span>\r\n </button>\r\n }\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Toolbar, ToolbarWidgetGroup, ToolbarWidget } from '@angular/aria/toolbar';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { input, model, computed, forwardRef, Component } from '@angular/core';
|
|
4
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
5
|
+
import { ValueAccessorBase, cn } from '@mesgflow/ui-kit/core';
|
|
6
|
+
import { cva } from 'class-variance-authority';
|
|
7
|
+
|
|
8
|
+
const segmentedTrackVariants = cva('inline-flex items-center gap-0.5 rounded-md bg-surface-alt p-0.5', {
|
|
9
|
+
variants: {
|
|
10
|
+
size: {
|
|
11
|
+
sm: 'text-xs',
|
|
12
|
+
md: 'text-sm',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: { size: 'md' },
|
|
16
|
+
});
|
|
17
|
+
const segmentedItemVariants = cva('cursor-pointer appearance-none whitespace-nowrap rounded-sm border-0 bg-transparent px-2.5 py-1 text-fg-muted transition-colors duration-fast ease-emphasis active:scale-[0.99] ' +
|
|
18
|
+
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring', {
|
|
19
|
+
variants: {
|
|
20
|
+
selected: {
|
|
21
|
+
true: 'bg-surface text-fg shadow-1',
|
|
22
|
+
false: 'hover:text-fg',
|
|
23
|
+
},
|
|
24
|
+
disabled: {
|
|
25
|
+
true: 'pointer-events-none opacity-50 active:scale-100',
|
|
26
|
+
false: '',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: { selected: false, disabled: false },
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* `<mf-segmented-control [options]="opts" [(value)]="mode" />` — hizalama,
|
|
34
|
+
* cihaz önizlemesi gibi KISA/tek-seçimli seçenek kümeleri için. `Tabs`'tan
|
|
35
|
+
* farkı: içerik paneli YOK, sadece bir değer seçimi. ARIA/klavye (roving
|
|
36
|
+
* tabindex, ok tuşu navigasyonu) `@angular/aria/toolbar`'ın
|
|
37
|
+
* `Toolbar`/`ToolbarWidgetGroup`/`ToolbarWidget` pattern'inden geliyor —
|
|
38
|
+
* dokümantasyondaki kompozisyon şekli birebir izlendi (dıştaki `ngToolbar`,
|
|
39
|
+
* içteki `ngToolbarWidgetGroup [multi]="false"`).
|
|
40
|
+
*/
|
|
41
|
+
class SegmentedControl extends ValueAccessorBase {
|
|
42
|
+
options = input.required(/* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
44
|
+
value = model(null, /* @ts-ignore */
|
|
45
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
46
|
+
size = input('md', /* @ts-ignore */
|
|
47
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
48
|
+
ariaLabel = input('', /* @ts-ignore */
|
|
49
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
50
|
+
disabled = input(false, /* @ts-ignore */
|
|
51
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
52
|
+
toolbarValue = computed(() => this.value() == null ? [] : [this.value()], /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "toolbarValue" }] : /* istanbul ignore next */ []));
|
|
54
|
+
trackClasses = computed(() => cn(segmentedTrackVariants({ size: this.size() })), /* @ts-ignore */
|
|
55
|
+
...(ngDevMode ? [{ debugName: "trackClasses" }] : /* istanbul ignore next */ []));
|
|
56
|
+
writeValue(value) {
|
|
57
|
+
this.value.set(value);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `@angular/aria/toolbar`'ın kendi widget-kayıt döngüsü, gerçek bir tıklama
|
|
61
|
+
* OLMADAN da BOŞ bir dizi ile (`values: []`) tetiklenebiliyor (gerçek bulgu
|
|
62
|
+
* — bir seçeneğe tıklarken bile araya giren, seçimle ilgisiz iç kayıt
|
|
63
|
+
* event'leri). `this.value` her event'te güncellenir (görsel durum ETKİLENMEZ,
|
|
64
|
+
* zaten `values[0]` genelde mevcut değerle AYNI), ama CVA `onChange`/`onTouched`
|
|
65
|
+
* SADECE dolu bir dizi (gerçek bir seçim) geldiğinde tetiklenir — aksi halde
|
|
66
|
+
* Reactive Forms'a sahte "null'a değişti" bildirimleri sızardı.
|
|
67
|
+
*/
|
|
68
|
+
onToolbarValueChange(values) {
|
|
69
|
+
this.value.set(values[0] ?? null);
|
|
70
|
+
if (values.length > 0) {
|
|
71
|
+
this.onChange(values[0]);
|
|
72
|
+
this.onTouched();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
itemClasses(option) {
|
|
76
|
+
return cn(segmentedItemVariants({ selected: option.value === this.value(), disabled: this.disabled() }));
|
|
77
|
+
}
|
|
78
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SegmentedControl, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
79
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: SegmentedControl, isStandalone: true, selector: "mf-segmented-control", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "inline-block" }, providers: [
|
|
80
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SegmentedControl), multi: true },
|
|
81
|
+
], exportAs: ["mfSegmentedControl"], usesInheritance: true, ngImport: i0, template: "<div\r\n ngToolbar\r\n [disabled]=\"disabled()\"\r\n [value]=\"toolbarValue()\"\r\n (valueChange)=\"onToolbarValueChange($event)\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class]=\"trackClasses()\"\r\n>\r\n <div ngToolbarWidgetGroup [multi]=\"false\" [disabled]=\"disabled()\" class=\"contents\">\r\n @for (option of options(); track option.value) {\r\n <button type=\"button\" ngToolbarWidget [value]=\"option.value\" [class]=\"itemClasses(option)\">\r\n {{ option.label }}\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: Toolbar, selector: "[ngToolbar]", inputs: ["orientation", "softDisabled", "disabled", "wrap", "value"], outputs: ["valueChange"], exportAs: ["ngToolbar"] }, { kind: "directive", type: ToolbarWidgetGroup, selector: "[ngToolbarWidgetGroup]", inputs: ["disabled", "multi"], exportAs: ["ngToolbarWidgetGroup"] }, { kind: "directive", type: ToolbarWidget, selector: "[ngToolbarWidget]", inputs: ["id", "disabled", "value"], exportAs: ["ngToolbarWidget"] }] });
|
|
82
|
+
}
|
|
83
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SegmentedControl, decorators: [{
|
|
84
|
+
type: Component,
|
|
85
|
+
args: [{ selector: 'mf-segmented-control', exportAs: 'mfSegmentedControl', imports: [Toolbar, ToolbarWidgetGroup, ToolbarWidget], host: { class: 'inline-block' }, providers: [
|
|
86
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SegmentedControl), multi: true },
|
|
87
|
+
], template: "<div\r\n ngToolbar\r\n [disabled]=\"disabled()\"\r\n [value]=\"toolbarValue()\"\r\n (valueChange)=\"onToolbarValueChange($event)\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class]=\"trackClasses()\"\r\n>\r\n <div ngToolbarWidgetGroup [multi]=\"false\" [disabled]=\"disabled()\" class=\"contents\">\r\n @for (option of options(); track option.value) {\r\n <button type=\"button\" ngToolbarWidget [value]=\"option.value\" [class]=\"itemClasses(option)\">\r\n {{ option.label }}\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n" }]
|
|
88
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Generated bundle index. Do not edit.
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
export { SegmentedControl, segmentedItemVariants, segmentedTrackVariants };
|
|
95
|
+
//# sourceMappingURL=mesgflow-ui-kit-segmented-control.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-segmented-control.mjs","sources":["../../../projects/ui-kit/segmented-control/segmented-control.variants.ts","../../../projects/ui-kit/segmented-control/segmented-control.ts","../../../projects/ui-kit/segmented-control/segmented-control.html","../../../projects/ui-kit/segmented-control/mesgflow-ui-kit-segmented-control.ts"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\r\n\r\nexport const segmentedTrackVariants = cva(\r\n 'inline-flex items-center gap-0.5 rounded-md bg-surface-alt p-0.5',\r\n {\r\n variants: {\r\n size: {\r\n sm: 'text-xs',\r\n md: 'text-sm',\r\n },\r\n },\r\n defaultVariants: { size: 'md' },\r\n },\r\n);\r\n\r\nexport const segmentedItemVariants = cva(\r\n 'cursor-pointer appearance-none whitespace-nowrap rounded-sm border-0 bg-transparent px-2.5 py-1 text-fg-muted transition-colors duration-fast ease-emphasis active:scale-[0.99] ' +\r\n 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring',\r\n {\r\n variants: {\r\n selected: {\r\n true: 'bg-surface text-fg shadow-1',\r\n false: 'hover:text-fg',\r\n },\r\n disabled: {\r\n true: 'pointer-events-none opacity-50 active:scale-100',\r\n false: '',\r\n },\r\n },\r\n defaultVariants: { selected: false, disabled: false },\r\n },\r\n);\r\n\r\nexport type SegmentedControlSize = VariantProps<typeof segmentedTrackVariants>['size'];\r\n","import {\r\n Toolbar as AriaToolbar,\r\n ToolbarWidget as AriaToolbarWidget,\r\n ToolbarWidgetGroup as AriaToolbarWidgetGroup,\r\n} from '@angular/aria/toolbar';\r\nimport { Component, computed, forwardRef, input, model } from '@angular/core';\r\nimport { NG_VALUE_ACCESSOR, type ControlValueAccessor } from '@angular/forms';\r\nimport { ValueAccessorBase, cn } from '@mesgflow/ui-kit/core';\r\nimport {\r\n segmentedItemVariants,\r\n segmentedTrackVariants,\r\n type SegmentedControlSize,\r\n} from './segmented-control.variants';\r\n\r\nexport interface SegmentedOption<T> {\r\n label: string;\r\n value: T;\r\n}\r\n\r\n/**\r\n * `<mf-segmented-control [options]=\"opts\" [(value)]=\"mode\" />` — hizalama,\r\n * cihaz önizlemesi gibi KISA/tek-seçimli seçenek kümeleri için. `Tabs`'tan\r\n * farkı: içerik paneli YOK, sadece bir değer seçimi. ARIA/klavye (roving\r\n * tabindex, ok tuşu navigasyonu) `@angular/aria/toolbar`'ın\r\n * `Toolbar`/`ToolbarWidgetGroup`/`ToolbarWidget` pattern'inden geliyor —\r\n * dokümantasyondaki kompozisyon şekli birebir izlendi (dıştaki `ngToolbar`,\r\n * içteki `ngToolbarWidgetGroup [multi]=\"false\"`).\r\n */\r\n@Component({\r\n selector: 'mf-segmented-control',\r\n exportAs: 'mfSegmentedControl',\r\n imports: [AriaToolbar, AriaToolbarWidgetGroup, AriaToolbarWidget],\r\n host: { class: 'inline-block' },\r\n templateUrl: './segmented-control.html',\r\n providers: [\r\n { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SegmentedControl), multi: true },\r\n ],\r\n})\r\nexport class SegmentedControl<T>\r\n extends ValueAccessorBase<T | null>\r\n implements ControlValueAccessor\r\n{\r\n readonly options = input.required<SegmentedOption<T>[]>();\r\n readonly value = model<T | null>(null);\r\n readonly size = input<SegmentedControlSize>('md');\r\n readonly ariaLabel = input('');\r\n readonly disabled = input(false);\r\n\r\n protected readonly toolbarValue = computed<T[]>(() =>\r\n this.value() == null ? [] : [this.value() as T],\r\n );\r\n protected readonly trackClasses = computed(() =>\r\n cn(segmentedTrackVariants({ size: this.size() })),\r\n );\r\n\r\n writeValue(value: T | null): void {\r\n this.value.set(value);\r\n }\r\n\r\n /**\r\n * `@angular/aria/toolbar`'ın kendi widget-kayıt döngüsü, gerçek bir tıklama\r\n * OLMADAN da BOŞ bir dizi ile (`values: []`) tetiklenebiliyor (gerçek bulgu\r\n * — bir seçeneğe tıklarken bile araya giren, seçimle ilgisiz iç kayıt\r\n * event'leri). `this.value` her event'te güncellenir (görsel durum ETKİLENMEZ,\r\n * zaten `values[0]` genelde mevcut değerle AYNI), ama CVA `onChange`/`onTouched`\r\n * SADECE dolu bir dizi (gerçek bir seçim) geldiğinde tetiklenir — aksi halde\r\n * Reactive Forms'a sahte \"null'a değişti\" bildirimleri sızardı.\r\n */\r\n protected onToolbarValueChange(values: readonly T[]): void {\r\n this.value.set(values[0] ?? null);\r\n if (values.length > 0) {\r\n this.onChange(values[0]!);\r\n this.onTouched();\r\n }\r\n }\r\n\r\n protected itemClasses(option: SegmentedOption<T>): string {\r\n return cn(\r\n segmentedItemVariants({ selected: option.value === this.value(), disabled: this.disabled() }),\r\n );\r\n }\r\n}\r\n","<div\r\n ngToolbar\r\n [disabled]=\"disabled()\"\r\n [value]=\"toolbarValue()\"\r\n (valueChange)=\"onToolbarValueChange($event)\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class]=\"trackClasses()\"\r\n>\r\n <div ngToolbarWidgetGroup [multi]=\"false\" [disabled]=\"disabled()\" class=\"contents\">\r\n @for (option of options(); track option.value) {\r\n <button type=\"button\" ngToolbarWidget [value]=\"option.value\" [class]=\"itemClasses(option)\">\r\n {{ option.label }}\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["AriaToolbar","AriaToolbarWidgetGroup","AriaToolbarWidget"],"mappings":"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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import * as i1 from '@angular/cdk/overlay';
|
|
2
|
+
import { OverlayModule } from '@angular/cdk/overlay';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { input, model, inject, computed, signal, forwardRef, Component } from '@angular/core';
|
|
5
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
|
+
import { Chip } from '@mesgflow/ui-kit/chip';
|
|
7
|
+
import { Icon } from '@mesgflow/ui-kit/icon';
|
|
8
|
+
import { MF_SELECT_LABELS, cn } from '@mesgflow/ui-kit/core';
|
|
9
|
+
import { Popover } from '@mesgflow/ui-kit/popover';
|
|
10
|
+
import { cva } from 'class-variance-authority';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Bkz. `core/recipes.ts` `controlSurface` — aynı kabuk, tetikleyici bir
|
|
14
|
+
* <button>'a uygulanıyor. `focus:border-accent` — Input/Combobox'ın ZATEN
|
|
15
|
+
* sahip olduğu odak kenarlığı burada eksikti (gerçek bulgu): odaklı bir
|
|
16
|
+
* select yalnızca outline ile belli oluyordu, kenarlık aksanlanmıyordu.
|
|
17
|
+
*/
|
|
18
|
+
const selectTriggerVariants = cva(
|
|
19
|
+
/*
|
|
20
|
+
* `appearance-none`: bkz. button.variants.ts'teki aynı gerekçe — sıfırlamazsan
|
|
21
|
+
* tarayıcının varsayılan `<button>` kenarlığı+dolgusu bu cva'nın
|
|
22
|
+
* border/padding'iyle ÜST ÜSTE biner (gerçek bulgu, ilk ekran görüntüsünde
|
|
23
|
+
* kolon başlıklarındaki sıralama butonları yanlışlıkla select kutusu gibi
|
|
24
|
+
* göründü).
|
|
25
|
+
*/
|
|
26
|
+
'inline-flex w-full appearance-none items-center justify-between gap-2 rounded-md border border-border bg-surface text-fg shadow-control ' +
|
|
27
|
+
'transition-colors duration-fast ease-emphasis ' +
|
|
28
|
+
'hover:border-border-strong ' +
|
|
29
|
+
'focus:border-accent ' +
|
|
30
|
+
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring ' +
|
|
31
|
+
'disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none disabled:hover:border-border', {
|
|
32
|
+
variants: {
|
|
33
|
+
size: {
|
|
34
|
+
sm: 'h-control-sm px-2.5 text-sm',
|
|
35
|
+
md: 'h-control-md px-3 text-sm',
|
|
36
|
+
lg: 'h-control-lg px-3.5 text-base',
|
|
37
|
+
},
|
|
38
|
+
/** Input/NumberInput ile aynı emsal — `@angular/forms/signals` rezerve `invalid` yerine `hasError`. */
|
|
39
|
+
hasError: {
|
|
40
|
+
true: 'border-danger focus-visible:outline-danger',
|
|
41
|
+
false: '',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
defaultVariants: { size: 'md', hasError: false },
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* `<mf-select [options]="opts" [(value)]="chosen" placeholder="Seç" />`
|
|
49
|
+
* (tek-seçimli, varsayılan) veya `<mf-select multiple [options]="opts"
|
|
50
|
+
* [(values)]="chosen" />` (çoklu-seçim — tetikleyici seçilenleri Chip
|
|
51
|
+
* özeti olarak gösterir, bir seçeneğe tıklamak paneli KAPATMAZ, tekrar
|
|
52
|
+
* tıklamak seçimi KALDIRIR).
|
|
53
|
+
*
|
|
54
|
+
* `multiple` AÇIKKEN `value`/`(valueChange)` KULLANILMAZ — ayrı bir
|
|
55
|
+
* `values: model<T[]>` var (bkz. aşağıda). İkisini AYIRMANIN sebebi:
|
|
56
|
+
* `value`'nun TİPİNİ (`T | null`) tek-seçimli kullanım için DEĞİŞTİRMEDEN
|
|
57
|
+
* bırakmak — mevcut tüm `[(value)]="tekTip"` tüketicileri (Table'ın alan/
|
|
58
|
+
* operatör/sayfa-boyutu seçicileri, TableFilterBar'ın VE/VEYA seçicisi)
|
|
59
|
+
* BİREBİR aynı tipte kalıyor, çoklu-seçim EKLENTİ, DEĞİŞİKLİK değil.
|
|
60
|
+
*
|
|
61
|
+
* Bu kitin ilk overlay tabanlı primitifi — native `<select>` değil,
|
|
62
|
+
* çünkü açılır panelin kendisi (arka plan/kenarlık/hover rengi) native
|
|
63
|
+
* `<select>` popup'ında tarayıcı-bağımlı ve stillenemez kalıyordu; CDK Overlay
|
|
64
|
+
* + kendi listbox'ımız panel dahil her pikseli bizim token sistemimizle
|
|
65
|
+
* boyayabiliyor. `@angular/cdk` zaten bağımlı, ek paket gerekmedi — pozisyonlama
|
|
66
|
+
* CSS'i `styles.css`'teki resmi `@angular/cdk/overlay-prebuilt.css`
|
|
67
|
+
* import'undan geliyor (bkz. o import'un yanındaki not).
|
|
68
|
+
*
|
|
69
|
+
* Arama/virtual-scroll YOK — Table'ın alan/operatör/sayfa-boyutu
|
|
70
|
+
* seçicileri gibi kısa listeler için kasıtlı olarak minimal.
|
|
71
|
+
*/
|
|
72
|
+
class Select {
|
|
73
|
+
options = input.required(/* @ts-ignore */
|
|
74
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
75
|
+
value = model(null, /* @ts-ignore */
|
|
76
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
77
|
+
multiple = input(false, /* @ts-ignore */
|
|
78
|
+
...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
79
|
+
/** SADECE `multiple=true`'da kullanılır — bkz. sınıf üstündeki JSDoc. */
|
|
80
|
+
values = model([], /* @ts-ignore */
|
|
81
|
+
...(ngDevMode ? [{ debugName: "values" }] : /* istanbul ignore next */ []));
|
|
82
|
+
maxVisibleChips = input(3, /* @ts-ignore */
|
|
83
|
+
...(ngDevMode ? [{ debugName: "maxVisibleChips" }] : /* istanbul ignore next */ []));
|
|
84
|
+
placeholder = input(/* @ts-ignore */
|
|
85
|
+
...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
86
|
+
disabled = input(false, /* @ts-ignore */
|
|
87
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
88
|
+
size = input('md', /* @ts-ignore */
|
|
89
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
90
|
+
hasError = input(false, /* @ts-ignore */
|
|
91
|
+
...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
92
|
+
ariaLabel = input('', /* @ts-ignore */
|
|
93
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
94
|
+
// `ControlValueAccessor`'ın gerçek Angular arayüzü `any` kullanıyor (bkz.
|
|
95
|
+
// `@angular/forms`'un kendi tip tanımı) — burada `T | T[] | null` YAZMAK bu
|
|
96
|
+
// sözleşmeyi İHLAL ETMİYOR, sadece tek/çoklu iki modu TEK bir callback
|
|
97
|
+
// çiftinde (onChange/onTouched) taşımayı mümkün kılıyor.
|
|
98
|
+
onChange = () => { };
|
|
99
|
+
onTouched = () => { };
|
|
100
|
+
selectLabels = inject(MF_SELECT_LABELS);
|
|
101
|
+
effectivePlaceholder = computed(() => this.placeholder() ?? this.selectLabels().placeholder, /* @ts-ignore */
|
|
102
|
+
...(ngDevMode ? [{ debugName: "effectivePlaceholder" }] : /* istanbul ignore next */ []));
|
|
103
|
+
open = signal(false, /* @ts-ignore */
|
|
104
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
105
|
+
highlighted = signal(0, /* @ts-ignore */
|
|
106
|
+
...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
|
|
107
|
+
triggerClasses = computed(() => cn(selectTriggerVariants({ size: this.size(), hasError: this.hasError() })), /* @ts-ignore */
|
|
108
|
+
...(ngDevMode ? [{ debugName: "triggerClasses" }] : /* istanbul ignore next */ []));
|
|
109
|
+
selectedLabel = computed(() => {
|
|
110
|
+
const current = this.value();
|
|
111
|
+
return this.options().find((option) => option.value === current)?.label ?? '';
|
|
112
|
+
}, /* @ts-ignore */
|
|
113
|
+
...(ngDevMode ? [{ debugName: "selectedLabel" }] : /* istanbul ignore next */ []));
|
|
114
|
+
selectedOptions = computed(() => {
|
|
115
|
+
if (!this.multiple())
|
|
116
|
+
return [];
|
|
117
|
+
const selected = new Set(this.values());
|
|
118
|
+
return this.options().filter((o) => selected.has(o.value));
|
|
119
|
+
}, /* @ts-ignore */
|
|
120
|
+
...(ngDevMode ? [{ debugName: "selectedOptions" }] : /* istanbul ignore next */ []));
|
|
121
|
+
visibleChips = computed(() => this.selectedOptions().slice(0, this.maxVisibleChips()), /* @ts-ignore */
|
|
122
|
+
...(ngDevMode ? [{ debugName: "visibleChips" }] : /* istanbul ignore next */ []));
|
|
123
|
+
overflowChipCount = computed(() => Math.max(0, this.selectedOptions().length - this.maxVisibleChips()), /* @ts-ignore */
|
|
124
|
+
...(ngDevMode ? [{ debugName: "overflowChipCount" }] : /* istanbul ignore next */ []));
|
|
125
|
+
toggle() {
|
|
126
|
+
if (this.disabled())
|
|
127
|
+
return;
|
|
128
|
+
if (!this.open())
|
|
129
|
+
this.highlighted.set(Math.max(0, this.options().findIndex((o) => o.value === this.value())));
|
|
130
|
+
this.open.update((v) => !v);
|
|
131
|
+
}
|
|
132
|
+
close() {
|
|
133
|
+
this.open.set(false);
|
|
134
|
+
this.onTouched();
|
|
135
|
+
}
|
|
136
|
+
/** Tek-seçimli modda seçeneği commit eder VE paneli kapatır; çoklu-seçim modunda `toggleValue`'ya devreder (panel AÇIK kalır — bkz. `toggleValue`). */
|
|
137
|
+
select(option) {
|
|
138
|
+
if (this.multiple()) {
|
|
139
|
+
this.toggleValue(option.value);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this.value.set(option.value);
|
|
143
|
+
this.onChange(option.value);
|
|
144
|
+
this.close();
|
|
145
|
+
}
|
|
146
|
+
/** Çoklu-seçimde bir değeri ekler/çıkarır — panel KAPANMAZ, kullanıcı birden fazla seçim yapabilir (Escape/dışarı tıklama ile kapatır). */
|
|
147
|
+
toggleValue(v) {
|
|
148
|
+
const current = this.values();
|
|
149
|
+
const next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];
|
|
150
|
+
this.values.set(next);
|
|
151
|
+
this.onChange(next);
|
|
152
|
+
this.onTouched();
|
|
153
|
+
}
|
|
154
|
+
writeValue(value) {
|
|
155
|
+
if (this.multiple()) {
|
|
156
|
+
this.values.set(Array.isArray(value) ? value : []);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
this.value.set(Array.isArray(value) ? null : value);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
registerOnChange(fn) {
|
|
163
|
+
this.onChange = fn;
|
|
164
|
+
}
|
|
165
|
+
registerOnTouched(fn) {
|
|
166
|
+
this.onTouched = fn;
|
|
167
|
+
}
|
|
168
|
+
isSelected(option) {
|
|
169
|
+
if (this.multiple())
|
|
170
|
+
return this.values().includes(option.value);
|
|
171
|
+
return option.value === this.value();
|
|
172
|
+
}
|
|
173
|
+
optionClasses(option, index) {
|
|
174
|
+
return cn(
|
|
175
|
+
// `rounded-sm`(6px) — panelin kendi `rounded-lg`(12px) kapsayıcısı
|
|
176
|
+
// içindeki İÇ İÇE (nested) daha küçük radius, bkz. styles.css radius
|
|
177
|
+
// notu: menü öğesi gibi kontrol-içi satırlar bir kademe küçük kalıyor.
|
|
178
|
+
'flex cursor-pointer items-center justify-between gap-2 rounded-sm px-2.5 py-1.5 text-fg-muted transition-colors duration-fast ease-emphasis', index === this.highlighted() && !this.isSelected(option) && 'bg-surface-alt',
|
|
179
|
+
// Seçili satır Badge/Avatar'daki aynı tonal işaret rol token'ını
|
|
180
|
+
// konuşuyor (`color-mix()` tabanlı) — tutarlı "tint fill" imzası.
|
|
181
|
+
this.isSelected(option) && 'bg-primary-tint text-primary-tint-fg');
|
|
182
|
+
}
|
|
183
|
+
onTriggerKeydown(event) {
|
|
184
|
+
if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
|
|
185
|
+
event.preventDefault();
|
|
186
|
+
if (!this.open())
|
|
187
|
+
this.toggle();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
onPanelKeydown(event) {
|
|
191
|
+
const options = this.options();
|
|
192
|
+
if (event.key === 'Escape') {
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
this.close();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (event.key === 'ArrowDown') {
|
|
198
|
+
event.preventDefault();
|
|
199
|
+
this.highlighted.update((i) => Math.min(options.length - 1, i + 1));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (event.key === 'ArrowUp') {
|
|
203
|
+
event.preventDefault();
|
|
204
|
+
this.highlighted.update((i) => Math.max(0, i - 1));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
const option = options[this.highlighted()];
|
|
210
|
+
if (option)
|
|
211
|
+
this.select(option);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
215
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Select, isStandalone: true, selector: "mf-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleChips: { classPropertyName: "maxVisibleChips", publicName: "maxVisibleChips", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", values: "valuesChange" }, host: { classAttribute: "block" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Select), multi: true }], exportAs: ["mfSelect"], ngImport: i0, template: "<button\r\n type=\"button\"\r\n cdkOverlayOrigin\r\n #origin=\"cdkOverlayOrigin\"\r\n [class]=\"triggerClasses()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-expanded]=\"open()\"\r\n aria-haspopup=\"listbox\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n>\r\n @if (multiple()) {\r\n @if (selectedOptions().length > 0) {\r\n <span class=\"flex min-w-0 flex-1 flex-wrap items-center gap-1\">\r\n @for (option of visibleChips(); track option.label) {\r\n <mf-chip size=\"sm\">{{ option.label }}</mf-chip>\r\n }\r\n @if (overflowChipCount() > 0) {\r\n <mf-chip size=\"sm\">+{{ overflowChipCount() }}</mf-chip>\r\n }\r\n </span>\r\n } @else {\r\n <span class=\"truncate text-fg-subtle\">{{ effectivePlaceholder() }}</span>\r\n }\r\n } @else {\r\n <span class=\"truncate\" [class.text-fg-subtle]=\"!selectedLabel()\">\r\n {{ selectedLabel() || effectivePlaceholder() }}\r\n </span>\r\n }\r\n <span mfIcon [size]=\"18\" class=\"shrink-0 text-fg-subtle\">unfold_more</span>\r\n</button>\r\n\r\n<mf-popover\r\n [origin]=\"origin\"\r\n [open]=\"open()\"\r\n placement=\"bottom-start\"\r\n padding=\"sm\"\r\n [matchTriggerWidth]=\"true\"\r\n (closed)=\"close()\"\r\n>\r\n <ul\r\n role=\"listbox\"\r\n tabindex=\"0\"\r\n [attr.aria-multiselectable]=\"multiple() || null\"\r\n class=\"w-full max-h-64 min-w-[8rem] text-sm\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n >\r\n @for (option of options(); track option.label; let i = $index) {\r\n <!-- role=\"option\" B\u0130LEREK odaklanabilir de\u011Fil \u2014 klavye gezinmesi yukar\u0131daki listbox (keydown)'da merkezi. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <li\r\n role=\"option\"\r\n [attr.aria-selected]=\"isSelected(option)\"\r\n [class]=\"optionClasses(option, i)\"\r\n (mouseenter)=\"highlighted.set(i)\"\r\n (click)=\"select(option)\"\r\n >\r\n <span class=\"truncate\">{{ option.label }}</span>\r\n @if (isSelected(option)) {\r\n <span mfIcon [size]=\"16\">check</span>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</mf-popover>\r\n", dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: Icon, selector: "span[mfIcon]", inputs: ["size", "filled"] }, { kind: "component", type: Popover, selector: "mf-popover", inputs: ["origin", "open", "placement", "padding", "hasBackdrop", "matchTriggerWidth", "panelClass"], outputs: ["openChange", "closed"], exportAs: ["mfPopover"] }, { kind: "component", type: Chip, selector: "mf-chip", inputs: ["tone", "size", "selected", "disabled", "removable", "removeLabel"], outputs: ["removed"], exportAs: ["mfChip"] }] });
|
|
216
|
+
}
|
|
217
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Select, decorators: [{
|
|
218
|
+
type: Component,
|
|
219
|
+
args: [{ selector: 'mf-select', exportAs: 'mfSelect', imports: [OverlayModule, Icon, Popover, Chip], host: { class: 'block' }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Select), multi: true }], template: "<button\r\n type=\"button\"\r\n cdkOverlayOrigin\r\n #origin=\"cdkOverlayOrigin\"\r\n [class]=\"triggerClasses()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-expanded]=\"open()\"\r\n aria-haspopup=\"listbox\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n>\r\n @if (multiple()) {\r\n @if (selectedOptions().length > 0) {\r\n <span class=\"flex min-w-0 flex-1 flex-wrap items-center gap-1\">\r\n @for (option of visibleChips(); track option.label) {\r\n <mf-chip size=\"sm\">{{ option.label }}</mf-chip>\r\n }\r\n @if (overflowChipCount() > 0) {\r\n <mf-chip size=\"sm\">+{{ overflowChipCount() }}</mf-chip>\r\n }\r\n </span>\r\n } @else {\r\n <span class=\"truncate text-fg-subtle\">{{ effectivePlaceholder() }}</span>\r\n }\r\n } @else {\r\n <span class=\"truncate\" [class.text-fg-subtle]=\"!selectedLabel()\">\r\n {{ selectedLabel() || effectivePlaceholder() }}\r\n </span>\r\n }\r\n <span mfIcon [size]=\"18\" class=\"shrink-0 text-fg-subtle\">unfold_more</span>\r\n</button>\r\n\r\n<mf-popover\r\n [origin]=\"origin\"\r\n [open]=\"open()\"\r\n placement=\"bottom-start\"\r\n padding=\"sm\"\r\n [matchTriggerWidth]=\"true\"\r\n (closed)=\"close()\"\r\n>\r\n <ul\r\n role=\"listbox\"\r\n tabindex=\"0\"\r\n [attr.aria-multiselectable]=\"multiple() || null\"\r\n class=\"w-full max-h-64 min-w-[8rem] text-sm\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n >\r\n @for (option of options(); track option.label; let i = $index) {\r\n <!-- role=\"option\" B\u0130LEREK odaklanabilir de\u011Fil \u2014 klavye gezinmesi yukar\u0131daki listbox (keydown)'da merkezi. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <li\r\n role=\"option\"\r\n [attr.aria-selected]=\"isSelected(option)\"\r\n [class]=\"optionClasses(option, i)\"\r\n (mouseenter)=\"highlighted.set(i)\"\r\n (click)=\"select(option)\"\r\n >\r\n <span class=\"truncate\">{{ option.label }}</span>\r\n @if (isSelected(option)) {\r\n <span mfIcon [size]=\"16\">check</span>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</mf-popover>\r\n" }]
|
|
220
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }, { type: i0.Output, args: ["valuesChange"] }], maxVisibleChips: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleChips", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Generated bundle index. Do not edit.
|
|
224
|
+
*/
|
|
225
|
+
|
|
226
|
+
export { Select, selectTriggerVariants };
|
|
227
|
+
//# sourceMappingURL=mesgflow-ui-kit-select.mjs.map
|