@mesgflow/ui-kit 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -5
- package/fesm2022/mesgflow-ui-kit-accordion.mjs +9 -8
- package/fesm2022/mesgflow-ui-kit-accordion.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-agenda.mjs +208 -0
- package/fesm2022/mesgflow-ui-kit-agenda.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-alert.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-aspect-ratio.mjs +37 -0
- package/fesm2022/mesgflow-ui-kit-aspect-ratio.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-avatar-group.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-avatar.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-badge.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-banner.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-blocks.mjs +207 -0
- package/fesm2022/mesgflow-ui-kit-blocks.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-box-input.mjs +4 -4
- package/fesm2022/mesgflow-ui-kit-box-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-brand.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-breadcrumb.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-button-group.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-button.mjs +190 -244
- package/fesm2022/mesgflow-ui-kit-button.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-card.mjs +48 -27
- package/fesm2022/mesgflow-ui-kit-card.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-carousel.mjs +308 -0
- package/fesm2022/mesgflow-ui-kit-carousel.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-chart.mjs +12 -12
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs +18 -23
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-chip.mjs +5 -5
- package/fesm2022/mesgflow-ui-kit-chip.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-code-block.mjs +11 -7
- package/fesm2022/mesgflow-ui-kit-code-block.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-collapsible.mjs +9 -9
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs +9 -7
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-combobox.mjs +147 -67
- package/fesm2022/mesgflow-ui-kit-combobox.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-command.mjs +15 -16
- package/fesm2022/mesgflow-ui-kit-command.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs +7 -9
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-copy-button.mjs +6 -6
- package/fesm2022/mesgflow-ui-kit-core.mjs +446 -128
- package/fesm2022/mesgflow-ui-kit-core.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-countdown.mjs +149 -0
- package/fesm2022/mesgflow-ui-kit-countdown.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs +140 -19
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-description-list.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-dialog.mjs +310 -64
- package/fesm2022/mesgflow-ui-kit-dialog.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-divider.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-drawer.mjs +109 -0
- package/fesm2022/mesgflow-ui-kit-drawer.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs +6 -6
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-empty-state.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-field.mjs +55 -14
- package/fesm2022/mesgflow-ui-kit-field.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-file-upload.mjs +356 -0
- package/fesm2022/mesgflow-ui-kit-file-upload.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-hover-card.mjs +6 -6
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs +135 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-icon.mjs +8 -3
- package/fesm2022/mesgflow-ui-kit-icon.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-icons-lucide.mjs +371 -0
- package/fesm2022/mesgflow-ui-kit-icons-lucide.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-inline-edit.mjs +279 -0
- package/fesm2022/mesgflow-ui-kit-inline-edit.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-input.mjs +162 -19
- package/fesm2022/mesgflow-ui-kit-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-kbd.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-lightbox.mjs +299 -0
- package/fesm2022/mesgflow-ui-kit-lightbox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-link.mjs +5 -5
- package/fesm2022/mesgflow-ui-kit-link.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-listbox.mjs +151 -0
- package/fesm2022/mesgflow-ui-kit-listbox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-mention.mjs +283 -0
- package/fesm2022/mesgflow-ui-kit-mention.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-menu.mjs +178 -14
- package/fesm2022/mesgflow-ui-kit-menu.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-nav-menu.mjs +276 -0
- package/fesm2022/mesgflow-ui-kit-nav-menu.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-notification-center.mjs +281 -0
- package/fesm2022/mesgflow-ui-kit-notification-center.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-number-input.mjs +9 -6
- package/fesm2022/mesgflow-ui-kit-number-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-otp-input.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-page-header.mjs +6 -6
- package/fesm2022/mesgflow-ui-kit-pagination.mjs +7 -6
- package/fesm2022/mesgflow-ui-kit-pagination.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-password-input.mjs +38 -68
- package/fesm2022/mesgflow-ui-kit-password-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-popover.mjs +12 -52
- package/fesm2022/mesgflow-ui-kit-popover.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-progress.mjs +164 -23
- package/fesm2022/mesgflow-ui-kit-progress.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-qr-code.mjs +766 -0
- package/fesm2022/mesgflow-ui-kit-qr-code.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-radio.mjs +10 -12
- package/fesm2022/mesgflow-ui-kit-radio.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-rating.mjs +4 -4
- package/fesm2022/mesgflow-ui-kit-rating.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-scroll-area.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-search-input.mjs +11 -7
- package/fesm2022/mesgflow-ui-kit-search-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs +15 -11
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-select.mjs +6 -5
- package/fesm2022/mesgflow-ui-kit-select.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs +24 -21
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs +6 -5
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-slider.mjs +253 -6
- package/fesm2022/mesgflow-ui-kit-slider.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-sortable.mjs +526 -0
- package/fesm2022/mesgflow-ui-kit-sortable.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-spinner.mjs +44 -15
- package/fesm2022/mesgflow-ui-kit-spinner.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-split-button.mjs +205 -0
- package/fesm2022/mesgflow-ui-kit-split-button.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-splitter.mjs +213 -6
- package/fesm2022/mesgflow-ui-kit-splitter.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs +13 -6
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-stepper.mjs +171 -64
- package/fesm2022/mesgflow-ui-kit-stepper.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-switch.mjs +4 -4
- package/fesm2022/mesgflow-ui-kit-switch.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-table.mjs +34 -28
- package/fesm2022/mesgflow-ui-kit-table.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tabs.mjs +421 -180
- package/fesm2022/mesgflow-ui-kit-tabs.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs +9 -4
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-theme-switcher.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-theming.mjs +7 -7
- package/fesm2022/mesgflow-ui-kit-theming.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs +6 -6
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-timeline.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-toast.mjs +118 -35
- package/fesm2022/mesgflow-ui-kit-toast.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-toggle.mjs +12 -11
- package/fesm2022/mesgflow-ui-kit-toggle.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs +13 -11
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs +76 -53
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-tour.mjs +17 -29
- package/fesm2022/mesgflow-ui-kit-tour.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-transfer-list.mjs +288 -0
- package/fesm2022/mesgflow-ui-kit-transfer-list.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tree-select.mjs +3 -3
- package/fesm2022/mesgflow-ui-kit-tree.mjs +4 -4
- package/fesm2022/mesgflow-ui-kit-tree.mjs.map +1 -1
- package/fesm2022/mesgflow-ui-kit-virtual-list.mjs +109 -0
- package/fesm2022/mesgflow-ui-kit-virtual-list.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit.mjs +93 -12836
- package/fesm2022/mesgflow-ui-kit.mjs.map +1 -1
- package/package.json +91 -3
- package/schematics/collection.json +10 -0
- package/schematics/migration.json +10 -0
- package/schematics/migrations/v0-7.cjs +70 -0
- package/schematics/ng-add/index.cjs +234 -0
- package/schematics/ng-add/schema.json +43 -0
- package/tokens/color.css +96 -0
- package/tokens/controls.css +145 -0
- package/tokens/elevation.css +62 -6
- package/tokens/motion.css +304 -66
- package/tokens/radius.css +14 -0
- package/tokens.css +1 -0
- package/tokens.json +1583 -0
- package/types/mesgflow-ui-kit-agenda.d.ts +49 -0
- package/types/mesgflow-ui-kit-aspect-ratio.d.ts +18 -0
- package/types/mesgflow-ui-kit-blocks.d.ts +128 -0
- package/types/mesgflow-ui-kit-button.d.ts +23 -38
- package/types/mesgflow-ui-kit-card.d.ts +26 -16
- package/types/mesgflow-ui-kit-carousel.d.ts +51 -0
- package/types/mesgflow-ui-kit-checkbox.d.ts +8 -5
- package/types/mesgflow-ui-kit-code-block.d.ts +4 -1
- package/types/mesgflow-ui-kit-combobox.d.ts +47 -22
- package/types/mesgflow-ui-kit-command.d.ts +2 -2
- package/types/mesgflow-ui-kit-core.d.ts +279 -21
- package/types/mesgflow-ui-kit-countdown.d.ts +47 -0
- package/types/mesgflow-ui-kit-date-picker.d.ts +31 -1
- package/types/mesgflow-ui-kit-dialog.d.ts +122 -14
- package/types/mesgflow-ui-kit-drawer.d.ts +45 -0
- package/types/mesgflow-ui-kit-field.d.ts +17 -8
- package/types/mesgflow-ui-kit-file-upload.d.ts +64 -0
- package/types/mesgflow-ui-kit-hover-card.d.ts +2 -2
- package/types/mesgflow-ui-kit-icons-lucide.d.ts +27 -0
- package/types/mesgflow-ui-kit-inline-edit.d.ts +42 -0
- package/types/mesgflow-ui-kit-input.d.ts +64 -2
- package/types/mesgflow-ui-kit-lightbox.d.ts +54 -0
- package/types/mesgflow-ui-kit-listbox.d.ts +30 -0
- package/types/mesgflow-ui-kit-mention.d.ts +59 -0
- package/types/mesgflow-ui-kit-menu.d.ts +41 -2
- package/types/mesgflow-ui-kit-nav-menu.d.ts +58 -0
- package/types/mesgflow-ui-kit-notification-center.d.ts +41 -0
- package/types/mesgflow-ui-kit-number-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-password-input.d.ts +35 -5
- package/types/mesgflow-ui-kit-popover.d.ts +13 -5
- package/types/mesgflow-ui-kit-progress.d.ts +33 -12
- package/types/mesgflow-ui-kit-qr-code.d.ts +160 -0
- package/types/mesgflow-ui-kit-radio.d.ts +2 -2
- package/types/mesgflow-ui-kit-search-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-segmented-control.d.ts +4 -0
- package/types/mesgflow-ui-kit-sidebar.d.ts +1 -1
- package/types/mesgflow-ui-kit-slider.d.ts +60 -1
- package/types/mesgflow-ui-kit-sortable.d.ts +103 -0
- package/types/mesgflow-ui-kit-spinner.d.ts +5 -8
- package/types/mesgflow-ui-kit-split-button.d.ts +47 -0
- package/types/mesgflow-ui-kit-splitter.d.ts +64 -1
- package/types/mesgflow-ui-kit-stat-tile.d.ts +3 -0
- package/types/mesgflow-ui-kit-stepper.d.ts +54 -32
- package/types/mesgflow-ui-kit-table.d.ts +2 -0
- package/types/mesgflow-ui-kit-tabs.d.ts +193 -93
- package/types/mesgflow-ui-kit-tag-input.d.ts +3 -1
- package/types/mesgflow-ui-kit-toast.d.ts +48 -22
- package/types/mesgflow-ui-kit-tooltip.d.ts +15 -12
- package/types/mesgflow-ui-kit-transfer-list.d.ts +34 -0
- package/types/mesgflow-ui-kit-virtual-list.d.ts +35 -0
- package/types/mesgflow-ui-kit.d.ts +88 -5444
|
@@ -1,51 +1,102 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { input, computed, Component } from '@angular/core';
|
|
3
|
-
import { cn } from '@mesgflow/ui-kit/core';
|
|
3
|
+
import { focusRecipe, disabledRecipe, cn } from '@mesgflow/ui-kit/core';
|
|
4
4
|
import { Icon } from '@mesgflow/ui-kit/icon';
|
|
5
5
|
import { Spinner } from '@mesgflow/ui-kit/spinner';
|
|
6
6
|
import { cva } from 'class-variance-authority';
|
|
7
7
|
|
|
8
|
+
const TONES = ['primary', 'neutral', 'success', 'warning', 'danger', 'info', 'help'];
|
|
9
|
+
/** Tonun "renkli metin" rolü — primary `accent`, diğerleri çıplak rol adı (moda göre takas olur). */
|
|
10
|
+
const INK = {
|
|
11
|
+
primary: 'accent',
|
|
12
|
+
neutral: 'fg-muted',
|
|
13
|
+
success: 'success',
|
|
14
|
+
warning: 'warning',
|
|
15
|
+
danger: 'danger',
|
|
16
|
+
info: 'info',
|
|
17
|
+
help: 'help',
|
|
18
|
+
};
|
|
8
19
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
20
|
+
* Altı görünüm × yedi ton — her hücre `compoundVariants`'ta açık (üretilmiş,
|
|
21
|
+
* ama tek bir tabloda okunur). Görünüm hiyerarşisi (en vurgulu → en sessiz):
|
|
22
|
+
*
|
|
23
|
+
* - `filled` — birincil eylem. Dolu rol zemini (`X-fill`), primary'de dark
|
|
24
|
+
* modda emerald `shadow-glow`, diğer tonlarda `shadow-filled`.
|
|
25
|
+
* - `soft` — tonal (Radix "soft", M3 "tonal"): `X-tint` zemin + `X-tint-fg`
|
|
26
|
+
* metin. Kart içi ikincil eylemler, filtre çipleri, "Taslak kaydet".
|
|
27
|
+
* - `outlined` — rengin kendisinin düşük opaklıklı kenarlığı (jenerik gri
|
|
28
|
+
* DEĞİL — gri çizgi "90'lar form elemanı" hissi veriyordu).
|
|
29
|
+
* - `ghost` — kenarlıksız, zeminsiz; hover'da NÖTR state layer
|
|
30
|
+
* (`bg-state-hover`, cam/renkli zeminde de doğru). Araç çubuğu/ikon butonları.
|
|
31
|
+
* - `text` — `ghost`'un renkli-hover'lı hali (geriye dönük uyumluluk).
|
|
32
|
+
* - `link` — satır içi bağlantı gibi: yükseklik/dolgu yok, altı çizili hover.
|
|
12
33
|
*
|
|
13
34
|
* Gloss/iç-highlight YOK — 2 kez reddedildi.
|
|
14
|
-
* `outlined` kenarlığı bilinçli olarak jenerik gri DEĞİL, rengin kendisinin
|
|
15
|
-
* düşük opaklıklı hali (`border-accent/30` gibi) — düz gri çizgi "90'lar
|
|
16
|
-
* form elemanı" hissi veriyordu, renkli-şeffaf kenarlık modern/kasıtlı durur.
|
|
17
|
-
* Bu opaklık artık TEK bir class'ta iki modu birden doğru veriyor: `accent`/
|
|
18
|
-
* `success`/`warning`/`danger`/`info` çıplak isimleri `styles.css`'te
|
|
19
|
-
* moda göre takas olan rol token'ları (600 basamağı light, 400 basamağı
|
|
20
|
-
* dark) — `dark:` ikizi yazmaya gerek YOK.
|
|
21
35
|
*/
|
|
22
|
-
|
|
36
|
+
function toneMatrix() {
|
|
37
|
+
const rows = [];
|
|
38
|
+
for (const tone of TONES) {
|
|
39
|
+
const ink = INK[tone];
|
|
40
|
+
// ---- filled ----
|
|
41
|
+
const filled = tone === 'primary'
|
|
42
|
+
? 'bg-accent-fill text-fg-on-accent shadow-glow hover:bg-accent-fill-hover'
|
|
43
|
+
: tone === 'neutral'
|
|
44
|
+
? 'bg-neutral-fill text-neutral-fill-fg hover:bg-neutral-fill-hover'
|
|
45
|
+
: `bg-${tone}-fill text-${tone}-fill-fg shadow-filled hover:bg-${tone}-fill-hover`;
|
|
46
|
+
rows.push({ tone, appearance: 'filled', class: filled });
|
|
47
|
+
// ---- soft ----
|
|
48
|
+
const soft = tone === 'primary'
|
|
49
|
+
? 'bg-primary-tint text-primary-tint-fg hover:bg-accent/20'
|
|
50
|
+
: tone === 'neutral'
|
|
51
|
+
? 'bg-state-selected text-fg hover:bg-state-pressed'
|
|
52
|
+
: `bg-${tone}-tint text-${tone}-tint-fg hover:bg-${tone}/20`;
|
|
53
|
+
rows.push({ tone, appearance: 'soft', class: soft });
|
|
54
|
+
// ---- outlined ----
|
|
55
|
+
const outlined = tone === 'neutral'
|
|
56
|
+
? 'border-border text-fg bg-surface shadow-control hover:bg-state-hover hover:border-border-strong'
|
|
57
|
+
: `border-${ink}/30 text-${ink} hover:bg-${ink}/5 hover:border-${ink}/50`;
|
|
58
|
+
rows.push({ tone, appearance: 'outlined', class: outlined });
|
|
59
|
+
// ---- ghost ----
|
|
60
|
+
const ghost = tone === 'neutral'
|
|
61
|
+
? 'text-fg-muted hover:bg-state-hover hover:text-fg active:bg-state-pressed'
|
|
62
|
+
: `text-${ink} hover:bg-state-hover active:bg-state-pressed`;
|
|
63
|
+
rows.push({ tone, appearance: 'ghost', class: ghost });
|
|
64
|
+
// ---- text ----
|
|
65
|
+
const text = tone === 'neutral'
|
|
66
|
+
? 'text-fg-muted hover:bg-state-hover hover:text-fg'
|
|
67
|
+
: `text-${ink} hover:bg-${ink}/5`;
|
|
68
|
+
rows.push({ tone, appearance: 'text', class: text });
|
|
69
|
+
// ---- link ----
|
|
70
|
+
const link = tone === 'neutral' ? 'text-fg hover:text-fg' : `text-${ink}`;
|
|
71
|
+
rows.push({ tone, appearance: 'link', class: link });
|
|
72
|
+
}
|
|
73
|
+
return rows;
|
|
74
|
+
}
|
|
23
75
|
/*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
76
|
+
* Tailwind sınıf tarayıcısı üretilmiş string'leri GÖREMEZ (`bg-${tone}-fill`).
|
|
77
|
+
* Aşağıdaki liste yalnızca tarayıcı için — derlenen CSS'e girmelerini garanti eder.
|
|
78
|
+
* bg-success-fill bg-warning-fill bg-danger-fill bg-info-fill bg-help-fill
|
|
79
|
+
* text-success-fill-fg text-warning-fill-fg text-danger-fill-fg text-info-fill-fg text-help-fill-fg
|
|
80
|
+
* hover:bg-success-fill-hover hover:bg-warning-fill-hover hover:bg-danger-fill-hover hover:bg-info-fill-hover hover:bg-help-fill-hover
|
|
81
|
+
* bg-success-tint bg-warning-tint bg-danger-tint bg-info-tint bg-help-tint
|
|
82
|
+
* text-success-tint-fg text-warning-tint-fg text-danger-tint-fg text-info-tint-fg text-help-tint-fg
|
|
83
|
+
* hover:bg-success/20 hover:bg-warning/20 hover:bg-danger/20 hover:bg-info/20 hover:bg-help/20
|
|
84
|
+
* border-accent/30 border-success/30 border-warning/30 border-danger/30 border-info/30 border-help/30
|
|
85
|
+
* hover:border-accent/50 hover:border-success/50 hover:border-warning/50 hover:border-danger/50 hover:border-info/50 hover:border-help/50
|
|
86
|
+
* text-accent text-success text-warning text-danger text-info text-help
|
|
87
|
+
* hover:bg-accent/5 hover:bg-success/5 hover:bg-warning/5 hover:bg-danger/5 hover:bg-info/5 hover:bg-help/5
|
|
31
88
|
*/
|
|
89
|
+
const buttonVariants = cva(
|
|
32
90
|
/*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* kırpılmıyor, ve modern tarayıcılar outline'ı elementin kendi
|
|
38
|
-
* border-radius'una göre otomatik yuvarlıyor. Renk artık TÜM primitifler
|
|
39
|
-
* genelinde TEK bir kaynak: `outline-focus-ring` (styles.css'te tanımlı,
|
|
40
|
-
* moda göre 600/400 basamağı arasında takas olur) — eskiden her tone
|
|
41
|
-
* kendi `focus-visible:outline-X/50`'sini taşıyordu (input'ta `ring-4`,
|
|
42
|
-
* checkbox'ta `ring-2 ring-offset-2` gibi üç farklı mekanizma da vardı),
|
|
43
|
-
* artık tüm primitifler bu tek mekanizmaya bağlı.
|
|
91
|
+
* `border border-transparent` — border width TEK kaynaktan; outlined
|
|
92
|
+
* yalnızca rengini değiştirir. Geçiş: renkler + gölge + `scale` (basma
|
|
93
|
+
* hissi artık anlık değil, `duration-fast` ile yumuşak).
|
|
94
|
+
* Focus: `outline` tabanlı TEK mekanizma (`focusRecipe`, bkz. core/recipes.ts).
|
|
44
95
|
*/
|
|
45
|
-
'inline-flex appearance-none items-center justify-center gap-2 border border-transparent font-medium tracking-label
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
|
|
96
|
+
'relative inline-flex shrink-0 appearance-none items-center justify-center gap-2 border border-transparent font-medium tracking-label whitespace-nowrap select-none ' +
|
|
97
|
+
'transition-[color,background-color,border-color,box-shadow,scale,opacity] duration-fast ease-emphasis ' +
|
|
98
|
+
'active:scale-[0.98] disabled:active:scale-100 ' +
|
|
99
|
+
`${focusRecipe} ${disabledRecipe}`, {
|
|
49
100
|
variants: {
|
|
50
101
|
tone: {
|
|
51
102
|
primary: '',
|
|
@@ -58,48 +109,33 @@ const buttonVariants = cva(
|
|
|
58
109
|
},
|
|
59
110
|
appearance: {
|
|
60
111
|
filled: '',
|
|
112
|
+
soft: '',
|
|
61
113
|
outlined: 'bg-transparent',
|
|
114
|
+
ghost: 'bg-transparent',
|
|
62
115
|
text: 'bg-transparent',
|
|
116
|
+
link: 'bg-transparent underline-offset-4 hover:underline active:scale-100',
|
|
63
117
|
},
|
|
64
118
|
/*
|
|
65
|
-
* Yoğunluk sıkılaştırıldı: md 40px→36px (kurumsal panellerde 40px iri
|
|
66
|
-
* duruyordu, Linear/Vercel/GitHub yoğunluğuna çekildi). Radius
|
|
67
|
-
* `rounded-lg`(eski 8px) → `rounded-md`(yeni 8px) — görünüş AYNI,
|
|
68
|
-
* sadece isim değişti (bkz. radius.css'teki "nested radius" notu:
|
|
69
|
-
* kart/panel gibi KAPSAYICILAR artık `rounded-lg`de kalıp otomatik
|
|
70
|
-
* 12px'e büyüyor, kontroller bu satırda `rounded-md`ye taşınarak eski
|
|
71
|
-
* görünümü koruyor).
|
|
72
|
-
*
|
|
73
119
|
* `h-control-*` (bkz. radius.css) — TEK kontrol-yükseklik kaynağı,
|
|
74
|
-
* Input/Select
|
|
75
|
-
*
|
|
76
|
-
* (BREAKING — CHANGELOG'a bkz.): 44px sm/md'ye göre orantısız iriydi,
|
|
77
|
-
* yeni üçlü tutarlı bir 32/36/40 merdiveni.
|
|
120
|
+
* Input/Select/... ile PAYLAŞILAN merdiven: xs 28 · sm 32 · md 36 ·
|
|
121
|
+
* lg 40 · xl 48 (density ile birlikte ölçeklenir).
|
|
78
122
|
*/
|
|
79
123
|
size: {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
124
|
+
xs: 'h-control-xs gap-1.5 rounded-md px-2.5 text-xs',
|
|
125
|
+
sm: 'h-control-sm gap-1.5 rounded-md px-3 text-sm',
|
|
126
|
+
md: 'h-control-md rounded-md px-4 text-sm',
|
|
127
|
+
lg: 'h-control-lg rounded-md px-5 text-base',
|
|
128
|
+
xl: 'h-control-xl rounded-lg px-6 text-base',
|
|
83
129
|
/*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* yanındaki 18px ikonla görsel ağırlığı uyuşmuyordu.
|
|
88
|
-
*
|
|
89
|
-
* Şekil (yuvarlak/köşeli) ve dolayısıyla focus mekanizması artık
|
|
90
|
-
* `shape` eksenine taşındı (aşağıda) — bu satır sadece boyut/tipografi
|
|
91
|
-
* taşıyor, `rounded-*` YOK. Yükseklik `md` ile aynı (36px).
|
|
130
|
+
* Kare ikon butonları — yükseklik ilgili kontrol basamağıyla aynı.
|
|
131
|
+
* `text-xs font-semibold`: ikon butonu kısa metin de taşıyabilir
|
|
132
|
+
* (dil değiştiricinin "EN"/"TR" etiketi).
|
|
92
133
|
*/
|
|
93
|
-
icon: '
|
|
134
|
+
'icon-sm': 'aspect-square h-control-sm text-xs font-semibold',
|
|
135
|
+
icon: 'aspect-square h-control-md text-xs font-semibold',
|
|
136
|
+
'icon-lg': 'aspect-square h-control-lg text-sm font-semibold',
|
|
94
137
|
},
|
|
95
|
-
/**
|
|
96
|
-
* `size="icon"` için şekil ekseni — diğer boyutlarda (sm/md/lg) etkisiz
|
|
97
|
-
* (boş string). Kullanıcı geri bildirimi: yuvarlak ikon-buton hover'ı
|
|
98
|
-
* "her yerde aynı" duruyordu, GitHub/Linear tarzı köşeli (rounded-md)
|
|
99
|
-
* bir hover/şekil de istendi — toolbar aksiyonları (Filtreler, satır
|
|
100
|
-
* düzenle/sil vb.) `square`, avatar-yanı ikonlar (tema/dil değiştirici)
|
|
101
|
-
* `round` (varsayılan) kullanıyor.
|
|
102
|
-
*/
|
|
138
|
+
/** Yalnızca ikon boyutlarında etkili — `round` (avatar yanı) / `square` (araç çubuğu). */
|
|
103
139
|
shape: {
|
|
104
140
|
round: '',
|
|
105
141
|
square: '',
|
|
@@ -107,173 +143,49 @@ const buttonVariants = cva(
|
|
|
107
143
|
},
|
|
108
144
|
compoundVariants: [
|
|
109
145
|
/*
|
|
110
|
-
* round: native `outline` `rounded-full`'u izlediği için
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* daire ("bullseye"/ripple'ı andıran) görünürdü. Bunun yerine kendi
|
|
114
|
-
* `rounded-md` (köşeli) radius'una sahip bağımsız bir `::after` pseudo-
|
|
115
|
-
* element kare/köşeli bir çerçeve çiziyor, rengi de artık tek kaynaklı
|
|
116
|
-
* `outline-focus-ring` — eskiden "ink/paper" sabit zıtlığı (light:
|
|
117
|
-
* dark-canvas, dark: slate-100) kullanılıyordu çünkü `outline-current`
|
|
118
|
-
* filled+beyaz-metin butonlarda beyaz zeminde beyaza karışıyordu; yeni
|
|
119
|
-
* `focus-ring` token'ı zaten primary-600/400 (arkaplandan bağımsız
|
|
120
|
-
* yüksek kontrastlı bir marka rengi) olduğu için aynı sorunu yaşamıyor.
|
|
121
|
-
*
|
|
122
|
-
* square: buton zaten `rounded-md` olduğundan native `outline` fazladan
|
|
123
|
-
* bir teknik gerektirmeden doğru köşeli çerçeveyi otomatik veriyor —
|
|
124
|
-
* base class'taki `focus-visible:outline` mekanizması yeterli, ek bir
|
|
125
|
-
* şey eklemeye GEREK YOK.
|
|
146
|
+
* round: native `outline` `rounded-full`'u izlediği için doğrudan buton
|
|
147
|
+
* üzerinde "daire içinde daire" görünürdü — köşeli bağımsız bir
|
|
148
|
+
* `::after` çerçeve çiziliyor. square: buton zaten `rounded-md`.
|
|
126
149
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
size: '
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
// NOT: primary'nin dolu bloğu `bg-accent-fill`/`hover:bg-accent-fill-hover`
|
|
139
|
-
// (color.css'te tanımlı rol token'ları) KULLANIR, ham basamak DEĞİL —
|
|
140
|
-
// LIGHT'ta primary-900 (`#062c22`, spec'in "Forest Emerald" CTA'sı),
|
|
141
|
-
// DARK'ta primary-400 (`#10b981`, spec'in canlı zümrüt CTA'sı) + DARK'ta
|
|
142
|
-
// mürekkep metin (`--mf-fg-on-accent`, beyaz `#10B981` üstünde 2.54:1
|
|
143
|
-
// AA altı olduğundan). Diğer dört semantik ton (success/warning/danger/
|
|
144
|
-
// info/help) da AYNI beşli rol desenini paylaşır: `bg-X-fill
|
|
145
|
-
// text-X-fill-fg shadow-filled hover:bg-X-fill-hover` — light'ta
|
|
146
|
-
// danger/help/info beyaz metin taşır, success/warning HER ZAMAN
|
|
147
|
-
// mürekkep (spec'in beş rengi de dark modda beyazla AA'yı geçmiyor,
|
|
148
|
-
// bu yüzden dark'ta hepsi mürekkep). `shadow-filled` (elevation.css) —
|
|
149
|
-
// `shadow-1` kapsayıcı gölgesidir, kontrol ödünç almaz; nötr filled
|
|
150
|
-
// (spec'in "Secondary"si, `neutral-fill` rol token'ı) gölgesiz kalır.
|
|
151
|
-
{
|
|
152
|
-
tone: 'primary',
|
|
153
|
-
appearance: 'filled',
|
|
154
|
-
class: 'bg-accent-fill text-fg-on-accent shadow-glow hover:bg-accent-fill-hover',
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
tone: 'neutral',
|
|
158
|
-
appearance: 'filled',
|
|
159
|
-
class: 'bg-neutral-fill text-neutral-fill-fg hover:bg-neutral-fill-hover',
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
tone: 'danger',
|
|
163
|
-
appearance: 'filled',
|
|
164
|
-
class: 'bg-danger-fill text-danger-fill-fg shadow-filled hover:bg-danger-fill-hover',
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
tone: 'info',
|
|
168
|
-
appearance: 'filled',
|
|
169
|
-
class: 'bg-info-fill text-info-fill-fg shadow-filled hover:bg-info-fill-hover',
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
tone: 'success',
|
|
173
|
-
appearance: 'filled',
|
|
174
|
-
class: 'bg-success-fill text-success-fill-fg shadow-filled hover:bg-success-fill-hover',
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
tone: 'warning',
|
|
178
|
-
appearance: 'filled',
|
|
179
|
-
class: 'bg-warning-fill text-warning-fill-fg shadow-filled hover:bg-warning-fill-hover',
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
tone: 'help',
|
|
183
|
-
appearance: 'filled',
|
|
184
|
-
class: 'bg-help-fill text-help-fill-fg shadow-filled hover:bg-help-fill-hover',
|
|
185
|
-
},
|
|
186
|
-
// ---- outlined ----
|
|
187
|
-
{
|
|
188
|
-
tone: 'primary',
|
|
189
|
-
appearance: 'outlined',
|
|
190
|
-
class: 'border-accent/30 text-accent hover:bg-accent/5',
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
tone: 'neutral',
|
|
194
|
-
appearance: 'outlined',
|
|
195
|
-
class: 'border-border text-fg-muted hover:bg-surface-alt',
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
tone: 'success',
|
|
199
|
-
appearance: 'outlined',
|
|
200
|
-
class: 'border-success/30 text-success hover:bg-success/5',
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
tone: 'warning',
|
|
204
|
-
appearance: 'outlined',
|
|
205
|
-
class: 'border-warning/30 text-warning hover:bg-warning/5',
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
tone: 'danger',
|
|
209
|
-
appearance: 'outlined',
|
|
210
|
-
class: 'border-danger/30 text-danger hover:bg-danger/5',
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
tone: 'info',
|
|
214
|
-
appearance: 'outlined',
|
|
215
|
-
class: 'border-info/30 text-info hover:bg-info/5',
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
tone: 'help',
|
|
219
|
-
appearance: 'outlined',
|
|
220
|
-
class: 'border-help/30 text-help hover:bg-help/5',
|
|
221
|
-
},
|
|
222
|
-
// ---- text ----
|
|
223
|
-
{
|
|
224
|
-
tone: 'primary',
|
|
225
|
-
appearance: 'text',
|
|
226
|
-
class: 'text-accent hover:bg-accent/5',
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
tone: 'neutral',
|
|
230
|
-
appearance: 'text',
|
|
231
|
-
class: 'text-fg-muted hover:bg-surface-alt',
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
tone: 'success',
|
|
235
|
-
appearance: 'text',
|
|
236
|
-
class: 'text-success hover:bg-success/5',
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
tone: 'warning',
|
|
240
|
-
appearance: 'text',
|
|
241
|
-
class: 'text-warning hover:bg-warning/5',
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
tone: 'danger',
|
|
245
|
-
appearance: 'text',
|
|
246
|
-
class: 'text-danger hover:bg-danger/5',
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
tone: 'info',
|
|
250
|
-
appearance: 'text',
|
|
251
|
-
class: 'text-info hover:bg-info/5',
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
tone: 'help',
|
|
255
|
-
appearance: 'text',
|
|
256
|
-
class: 'text-help hover:bg-help/5',
|
|
257
|
-
},
|
|
150
|
+
...['icon-sm', 'icon', 'icon-lg'].flatMap((size) => [
|
|
151
|
+
{
|
|
152
|
+
size,
|
|
153
|
+
shape: 'round',
|
|
154
|
+
class: "rounded-full focus-visible:outline-none after:pointer-events-none after:absolute after:-inset-1 after:rounded-md after:opacity-0 after:outline after:outline-2 after:outline-focus-ring after:transition-opacity after:duration-fast after:content-[''] focus-visible:after:opacity-100",
|
|
155
|
+
},
|
|
156
|
+
{ size, shape: 'square', class: 'rounded-md' },
|
|
157
|
+
]),
|
|
158
|
+
// `link` boyut ekseninin yüksekliğini/dolgusunu ezer — satır içi akar.
|
|
159
|
+
{ appearance: 'link', class: 'h-auto rounded-sm p-0' },
|
|
160
|
+
...toneMatrix(),
|
|
258
161
|
],
|
|
259
162
|
defaultVariants: { tone: 'primary', appearance: 'filled', size: 'md', shape: 'round' },
|
|
260
163
|
});
|
|
261
164
|
|
|
165
|
+
/** İkon boyutu buton boyutuyla ölçeklenir. */
|
|
166
|
+
const ICON_PX = {
|
|
167
|
+
xs: 14,
|
|
168
|
+
sm: 16,
|
|
169
|
+
md: 18,
|
|
170
|
+
lg: 20,
|
|
171
|
+
xl: 20,
|
|
172
|
+
'icon-sm': 16,
|
|
173
|
+
icon: 18,
|
|
174
|
+
'icon-lg': 20,
|
|
175
|
+
};
|
|
262
176
|
/**
|
|
263
177
|
* `<button mfButton>`/`<a mfButton>` — selector native elemanın KENDİSİNİ
|
|
264
178
|
* hedefler (`button[mfButton], a[mfButton]`), bir SARMALAYICI etiket
|
|
265
|
-
* (`<mf-button>`) DEĞİL
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* içeriği `<ng-content />` ile AYNEN korunur.
|
|
179
|
+
* (`<mf-button>`) DEĞİL — tüketicinin `class="..."` ile verdiği static
|
|
180
|
+
* class doğrudan gerçek native elemana düşer. Component olmasının TEK
|
|
181
|
+
* sebebi: `loading`'i gerçek bir `<mf-spinner>`'a, `iconStart`/`iconEnd`'i
|
|
182
|
+
* gerçek ikon element'lerine bağlayabilmek için bir ŞABLONA ihtiyaç duyması.
|
|
183
|
+
*
|
|
184
|
+
* `tone` (renk) × `appearance` (filled/soft/outlined/ghost/text/link) ×
|
|
185
|
+
* `size` (xs…xl, icon-sm/icon/icon-lg) bağımsız eksenler.
|
|
273
186
|
*
|
|
274
|
-
* `
|
|
275
|
-
*
|
|
276
|
-
* gösteren, kenarlıksız bir sil butonu için.
|
|
187
|
+
* Mikro-etkileşimler: basınca `scale(0.98)` (yumuşak geçişli), `iconEnd`
|
|
188
|
+
* hover'da 2px ileri kayar (RTL'de geri), loading genişliği korur.
|
|
277
189
|
*/
|
|
278
190
|
class Button {
|
|
279
191
|
tone = input('primary', /* @ts-ignore */
|
|
@@ -282,25 +194,24 @@ class Button {
|
|
|
282
194
|
...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
|
|
283
195
|
size = input('md', /* @ts-ignore */
|
|
284
196
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
285
|
-
/** Sadece `
|
|
197
|
+
/** Sadece ikon boyutlarında (`icon-sm`/`icon`/`icon-lg`) etkili — bkz. button.variants.ts. */
|
|
286
198
|
shape = input('round', /* @ts-ignore */
|
|
287
199
|
...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
288
200
|
/** Native <button> varsayılan type="submit" sürprizini önlemek için — <a>'da yok sayılır. */
|
|
289
201
|
type = input('button', /* @ts-ignore */
|
|
290
202
|
...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
291
203
|
/**
|
|
292
|
-
* `true` iken
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
* `[disabled]="loading() || ..."` ile kendi bağlar.
|
|
204
|
+
* `true` iken: `iconStart` varsa spinner onun YERİNE geçer (metin görünür
|
|
205
|
+
* kalır); yoksa spinner ortaya biner ve içerik saydamlaşır — iki durumda da
|
|
206
|
+
* buton genişliği DEĞİŞMEZ. `disabled`'ı KENDİLİĞİNDEN yönetmez —
|
|
207
|
+
* tüketici `[disabled]="loading() || ..."` ile kendi bağlar.
|
|
297
208
|
*/
|
|
298
209
|
loading = input(false, /* @ts-ignore */
|
|
299
210
|
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
300
|
-
/**
|
|
211
|
+
/** İkon adı (bkz. `Icon`) — içeriğin ÖNÜNE eklenir. `loading=true` iken spinner onun YERİNE geçer. */
|
|
301
212
|
iconStart = input('', /* @ts-ignore */
|
|
302
213
|
...(ngDevMode ? [{ debugName: "iconStart" }] : /* istanbul ignore next */ []));
|
|
303
|
-
/**
|
|
214
|
+
/** İkon adı — içeriğin ARDINA eklenir, hover'da ileri kayar. `loading=true` iken GİZLENİR. */
|
|
304
215
|
iconEnd = input('', /* @ts-ignore */
|
|
305
216
|
...(ngDevMode ? [{ debugName: "iconEnd" }] : /* istanbul ignore next */ []));
|
|
306
217
|
classes = computed(() => cn(buttonVariants({
|
|
@@ -308,24 +219,43 @@ class Button {
|
|
|
308
219
|
appearance: this.appearance(),
|
|
309
220
|
size: this.size(),
|
|
310
221
|
shape: this.shape(),
|
|
311
|
-
}), this.loading() ? 'cursor-wait' : ''), /* @ts-ignore */
|
|
222
|
+
}), 'group/btn', this.loading() ? 'cursor-wait' : ''), /* @ts-ignore */
|
|
312
223
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
313
224
|
nativeType = computed(() => this.type(), /* @ts-ignore */
|
|
314
225
|
...(ngDevMode ? [{ debugName: "nativeType" }] : /* istanbul ignore next */ []));
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
226
|
+
iconPx = computed(() => ICON_PX[this.size() ?? 'md'], /* @ts-ignore */
|
|
227
|
+
...(ngDevMode ? [{ debugName: "iconPx" }] : /* istanbul ignore next */ []));
|
|
228
|
+
contentClass = computed(() => cn('inline-flex min-w-0 items-center gap-[inherit] empty:hidden', this.loading() && !this.iconStart() ? 'opacity-0' : ''), /* @ts-ignore */
|
|
229
|
+
...(ngDevMode ? [{ debugName: "contentClass" }] : /* istanbul ignore next */ []));
|
|
230
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: Button, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
231
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: Button, isStandalone: true, selector: "button[mfButton], a[mfButton]", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, iconStart: { classPropertyName: "iconStart", publicName: "iconStart", isSignal: true, isRequired: false, transformFunction: null }, iconEnd: { classPropertyName: "iconEnd", publicName: "iconEnd", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.type": "nativeType()", "attr.aria-busy": "loading() || null", "attr.data-appearance": "appearance()" } }, exportAs: ["mfButton"], ngImport: i0, template: `
|
|
232
|
+
@if (loading() && !iconStart()) {
|
|
233
|
+
<!--
|
|
234
|
+
İkon yuvası yoksa spinner ORTAYA biner ve içerik saydamlaşır — buton
|
|
235
|
+
genişliği DEĞİŞMEZ (layout shift yok). Metin erişilebilirlik ağacında
|
|
236
|
+
KALIR (opacity, visibility değil).
|
|
237
|
+
-->
|
|
238
|
+
<span class="absolute inset-0 flex items-center justify-center" aria-hidden="true">
|
|
239
|
+
<mf-spinner size="xs" />
|
|
240
|
+
</span>
|
|
241
|
+
}
|
|
242
|
+
@if (loading() && iconStart()) {
|
|
318
243
|
<mf-spinner size="xs" />
|
|
319
244
|
} @else if (iconStart()) {
|
|
320
|
-
<span mfIcon [size]="
|
|
245
|
+
<span mfIcon [size]="iconPx()">{{ iconStart() }}</span>
|
|
321
246
|
}
|
|
322
|
-
<ng-content
|
|
247
|
+
<span [class]="contentClass()"><ng-content /></span>
|
|
323
248
|
@if (!loading() && iconEnd()) {
|
|
324
|
-
<span
|
|
249
|
+
<span
|
|
250
|
+
mfIcon
|
|
251
|
+
[size]="iconPx()"
|
|
252
|
+
class="transition-transform duration-fast ease-emphasis group-hover/btn:translate-x-0.5 rtl:-scale-x-100 rtl:group-hover/btn:-translate-x-0.5"
|
|
253
|
+
>{{ iconEnd() }}</span
|
|
254
|
+
>
|
|
325
255
|
}
|
|
326
256
|
`, isInline: true, dependencies: [{ kind: "directive", type: Icon, selector: "span[mfIcon]", inputs: ["size", "filled"] }, { kind: "component", type: Spinner, selector: "mf-spinner", inputs: ["size", "tone", "ariaLabel"], exportAs: ["mfSpinner"] }] });
|
|
327
257
|
}
|
|
328
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
258
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: Button, decorators: [{
|
|
329
259
|
type: Component,
|
|
330
260
|
args: [{
|
|
331
261
|
// eslint-disable-next-line @angular-eslint/component-selector -- BİLEREK native eleman + attribute (bkz. yukarıdaki JSDoc)
|
|
@@ -336,16 +266,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
336
266
|
'[class]': 'classes()',
|
|
337
267
|
'[attr.type]': 'nativeType()',
|
|
338
268
|
'[attr.aria-busy]': 'loading() || null',
|
|
269
|
+
'[attr.data-appearance]': 'appearance()',
|
|
339
270
|
},
|
|
340
271
|
template: `
|
|
341
|
-
@if (loading()) {
|
|
272
|
+
@if (loading() && !iconStart()) {
|
|
273
|
+
<!--
|
|
274
|
+
İkon yuvası yoksa spinner ORTAYA biner ve içerik saydamlaşır — buton
|
|
275
|
+
genişliği DEĞİŞMEZ (layout shift yok). Metin erişilebilirlik ağacında
|
|
276
|
+
KALIR (opacity, visibility değil).
|
|
277
|
+
-->
|
|
278
|
+
<span class="absolute inset-0 flex items-center justify-center" aria-hidden="true">
|
|
279
|
+
<mf-spinner size="xs" />
|
|
280
|
+
</span>
|
|
281
|
+
}
|
|
282
|
+
@if (loading() && iconStart()) {
|
|
342
283
|
<mf-spinner size="xs" />
|
|
343
284
|
} @else if (iconStart()) {
|
|
344
|
-
<span mfIcon [size]="
|
|
285
|
+
<span mfIcon [size]="iconPx()">{{ iconStart() }}</span>
|
|
345
286
|
}
|
|
346
|
-
<ng-content
|
|
287
|
+
<span [class]="contentClass()"><ng-content /></span>
|
|
347
288
|
@if (!loading() && iconEnd()) {
|
|
348
|
-
<span
|
|
289
|
+
<span
|
|
290
|
+
mfIcon
|
|
291
|
+
[size]="iconPx()"
|
|
292
|
+
class="transition-transform duration-fast ease-emphasis group-hover/btn:translate-x-0.5 rtl:-scale-x-100 rtl:group-hover/btn:-translate-x-0.5"
|
|
293
|
+
>{{ iconEnd() }}</span
|
|
294
|
+
>
|
|
349
295
|
}
|
|
350
296
|
`,
|
|
351
297
|
}]
|