@stisocial/ui 0.2.0 → 0.2.1

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/TimeSlotPicker/TimeSlotPicker.d.ts +1 -11
  3. package/dist/components/TimeSlotPicker/TimeSlotPicker.js +2 -24
  4. package/dist/components/TimeSlotPicker/index.d.ts +3 -2
  5. package/dist/components/TimeSlotPicker/timeSlots.d.ts +12 -0
  6. package/dist/components/TimeSlotPicker/timeSlots.js +25 -0
  7. package/dist/id/AccountMenu/AccountMenu.css +128 -44
  8. package/dist/id/AccountMenu/AccountMenu.d.ts +37 -9
  9. package/dist/id/AccountMenu/AccountMenu.js +138 -65
  10. package/dist/id/AccountMenu/AccountMenu.module.js +16 -9
  11. package/dist/id/AccountMenu/index.d.ts +2 -2
  12. package/dist/id/AppSwitcher/AppSwitcher.css +153 -31
  13. package/dist/id/AppSwitcher/AppSwitcher.d.ts +31 -6
  14. package/dist/id/AppSwitcher/AppSwitcher.js +90 -37
  15. package/dist/id/AppSwitcher/AppSwitcher.module.js +12 -6
  16. package/dist/id/AppSwitcher/index.d.ts +2 -2
  17. package/dist/id/OrgSwitcher/OrgSwitcher.css +129 -17
  18. package/dist/id/OrgSwitcher/OrgSwitcher.d.ts +30 -5
  19. package/dist/id/OrgSwitcher/OrgSwitcher.js +110 -74
  20. package/dist/id/OrgSwitcher/OrgSwitcher.module.js +11 -7
  21. package/dist/id/OrgSwitcher/index.d.ts +2 -2
  22. package/dist/id/PermissionGate/PermissionGate.css +25 -14
  23. package/dist/id/PermissionGate/PermissionGate.d.ts +3 -1
  24. package/dist/id/PermissionGate/PermissionGate.js +15 -8
  25. package/dist/id/PermissionGate/PermissionGate.module.js +6 -5
  26. package/dist/id/SignInButton/SignInButton.css +179 -0
  27. package/dist/id/SignInButton/SignInButton.d.ts +12 -3
  28. package/dist/id/SignInButton/SignInButton.js +37 -18
  29. package/dist/id/SignInButton/SignInButton.module.js +10 -0
  30. package/dist/id/_internal/StiMark/StiMark.css +28 -0
  31. package/dist/id/_internal/StiMark/StiMark.js +37 -0
  32. package/dist/id/_internal/StiMark/StiMark.module.js +8 -0
  33. package/dist/id/index.d.ts +4 -4
  34. package/dist/id/index.js +4 -4
  35. package/dist/index.d.ts +3 -2
  36. package/dist/index.js +2 -1
  37. package/dist/messages/messages.d.ts +7 -0
  38. package/dist/messages/messages.js +14 -0
  39. package/dist/styles.css +644 -106
  40. package/dist/text/text.d.ts +5 -1
  41. package/dist/text/text.js +8 -2
  42. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
3
3
  Sürüm numaraları anlamlıdır: kırıcı değişiklik yalnız büyük sürümde, önceden kullanımdan kaldırma
4
4
  uyarısıyla gelir. `1.0`'a kadar (dalga 2 sonu) küçük sürümler de kırıcı olabilir; burada yazılır.
5
5
 
6
+ ## 0.2.1 — 2026-11-13
7
+
8
+ - **STI ID parçaları yeniden tasarlandı** (`/id`; mevcut API korunur, eklemeler):
9
+ - **AccountMenu:** tetikleyici esnek üst çubukta artık dikeyde uzamıyor. Panel dışa açık `AccountMenuPanel` oldu: ortalanmış kimlik ve "Merhaba, Elif" selamlaması, hesap yönetimi, gruplu bağlantılar, diğer hesaplar (`otherAccounts`, `onSwitchAccount`), hesap ekleme (`addAccountHref` / `onAddAccount`), oturumu kapatma, yasal bağlantılar (`privacyHref`, `termsHref`).
10
+ - **AppSwitcher:** dışa açık `AppSwitcherPanel`; başlık, alt zeminli ızgara, uygulamaya göre kalıcı renkli karolar (`color`), anlamlı kısaltma (`appMonogram`: "STI ID" → "ID", "STI Office" → "O"), "Tüm uygulamalar" bağlantısı (`moreHref`), sağdan sola ok gezinmesi.
11
+ - **OrgSwitcher:** dışa açık `OrgSwitcherPanel`; kuruluşlar türün ikonuyla kalıcı renkli karoda (harf yazılmaz, WCAG 2.5.3), liste satırı ölçüsünde "Yeni kuruluş oluşturun" (`createHref` eklendi).
12
+ - **SignInButton:** kendi marka düğmesi: başta STI monogramı (kalkan ikonu yerine), tam genişlikte ortalanmış metin, beklerken monogramın yerinde dönen gösterge ve görünür "Oturum açılıyor" metni.
13
+ - **PermissionGate:** yetki kutusuna eylem (`deniedAction`, "Yetki isteyin"); kesik kenar yerine ince kenar ve amber kilit karosu.
14
+ - Katalog örnekleri gerçek kullanımı gösterir: üst çubukta tetikleyiciler ve açık paneller.
15
+ - **Baş harfler:** rakamla başlayan sözcük baş harf vermez ("Müşteri 04" → "M"; önce "M0").
16
+ - **Katalog koruması:** örnek dosyası istemci modülünden yalnız bileşen alabilir; veri ya da yardımcı işlev alınırsa birim testi kırılır (önceki denetimdeki bozuk düzenli ifade düzeltildi).
17
+ - **TimeSlotPicker:** `timeSlots()` yardımcısı istemci yönergesi olmayan ayrı modüle taşındı; artık sunucu bileşeninde de çağrılabilir (0.2.0'da sunucuda çağrıldığında hata veriyordu). İçe aktarma yolu değişmedi.
18
+ - **Katalog:** işleyici gerektiren 12 bileşenin örnekleri (Alert, BackLink, Chip, ConfirmButton, DownloadButton, ActionBar ve yapay zekâ bileşenleri) sunucuda işlev geçirdiği için katalog sayfası açılmıyordu; örnekler istemci sarmalayıcısına alındı. Örnek dosyalarının sunucuda çalışabilirliği artık birim testiyle denetlenir.
19
+
6
20
  ## 0.2.0 — 2026-11-13
7
21
 
8
22
  93 yeni bileşen; hazır sayısı 339/485. Yeni alt yollar ana girişe girmez, yalnız kendi yolundan içe aktarılır: `/charts`, `/id`, `/ai`, `/media`, `/editor`, `/agency`, `/site`, `/commerce`, `/maps`, `/email`, `/document`.
@@ -1,10 +1,5 @@
1
+ import { TimeSlot } from "./timeSlots.js";
1
2
  import { ReactNode } from "react";
2
- export interface TimeSlot {
3
- /** Başlangıç saati ("09:30"). */
4
- time: string;
5
- /** Dolu ya da kapalı saat (seçilemez, görünür kalır). */
6
- isUnavailable?: boolean;
7
- }
8
3
  export interface TimeSlotPickerProps {
9
4
  label: ReactNode;
10
5
  description?: ReactNode;
@@ -28,11 +23,6 @@ export interface TimeSlotPickerProps {
28
23
  className?: string;
29
24
  id?: string;
30
25
  }
31
- /**
32
- * Aralıktan saatler: `timeSlots("09:00", "17:00", 30)` → 09:00, 09:30 … 16:30 (bitiş dahil
33
- * değildir: son randevu bitişte biter). `unavailable` dolu saatleri işaretler.
34
- */
35
- export declare function timeSlots(start: string, end: string, stepMinutes: number, unavailable?: readonly string[]): TimeSlot[];
36
26
  /**
37
27
  * Randevu saati seçimi: saatler hap biçiminde ızgarada (React Aria ListBox, `layout="grid"`);
38
28
  * dolu saatler üstü çizili ve seçilemez, sabah, öğleden sonra ve akşam başlıklarıyla gruplu. Oklar
@@ -4,33 +4,11 @@ import { template } from "../../text/text.js";
4
4
  import { AlertCircleIcon } from "../../icons/generated/AlertCircleIcon.js";
5
5
  import { fieldStyles } from "../Field/Field.js";
6
6
  import TimeSlotPicker_module_default from "./TimeSlotPicker.module.js";
7
+ import { toMinutes, toTime } from "./timeSlots.js";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  import { useEffect, useId, useMemo, useRef, useState } from "react";
9
10
  import { Header, ListBox, ListBoxItem, ListBoxSection } from "react-aria-components";
10
11
  // src/components/TimeSlotPicker/TimeSlotPicker.tsx
11
- const toMinutes = (t) => {
12
- const m = /^(\d{1,2}):(\d{2})$/.exec(t);
13
- return m ? Number(m[1]) * 60 + Number(m[2]) : NaN;
14
- };
15
- const toTime = (min) => `${String(Math.floor(min / 60) % 24).padStart(2, "0")}:${String(min % 60).padStart(2, "0")}`;
16
- /**
17
- * Aralıktan saatler: `timeSlots("09:00", "17:00", 30)` → 09:00, 09:30 … 16:30 (bitiş dahil
18
- * değildir: son randevu bitişte biter). `unavailable` dolu saatleri işaretler.
19
- */
20
- function timeSlots(start, end, stepMinutes, unavailable = []) {
21
- const from = toMinutes(start);
22
- const to = toMinutes(end);
23
- if (!Number.isFinite(from) || !Number.isFinite(to) || stepMinutes <= 0) return [];
24
- const out = [];
25
- for (let m = from; m + stepMinutes <= to; m += stepMinutes) {
26
- const time = toTime(m);
27
- out.push({
28
- time,
29
- isUnavailable: unavailable.includes(time)
30
- });
31
- }
32
- return out;
33
- }
34
12
  const partOf = (t) => {
35
13
  const m = toMinutes(t);
36
14
  return m < 720 ? "morning" : m < 1020 ? "afternoon" : "evening";
@@ -159,4 +137,4 @@ function TimeSlotPicker({ label, description, errorMessage, slots, value, defaul
159
137
  ]
160
138
  });
161
139
  }
162
- export { TimeSlotPicker, timeSlots };
140
+ export { TimeSlotPicker };
@@ -1,2 +1,3 @@
1
- import { TimeSlot, TimeSlotPicker, TimeSlotPickerProps, timeSlots } from "./TimeSlotPicker.js";
2
- export { TimeSlot, TimeSlotPicker, TimeSlotPickerProps, timeSlots };
1
+ import { TimeSlot, timeSlots } from "./timeSlots.js";
2
+ import { TimeSlotPicker, TimeSlotPickerProps } from "./TimeSlotPicker.js";
3
+ export { type TimeSlot, TimeSlotPicker, TimeSlotPickerProps, timeSlots };
@@ -0,0 +1,12 @@
1
+ /** Saat aralığı yardımcıları: istemci yönergesi yoktur, sunucu bileşeninden de çağrılır. */
2
+ export interface TimeSlot {
3
+ /** Başlangıç saati ("09:30"). */
4
+ time: string;
5
+ /** Dolu ya da kapalı saat (seçilemez, görünür kalır). */
6
+ isUnavailable?: boolean;
7
+ }
8
+ /**
9
+ * Aralıktan saatler: `timeSlots("09:00", "17:00", 30)` → 09:00, 09:30 … 16:30 (bitiş dahil
10
+ * değildir: son randevu bitişte biter). `unavailable` dolu saatleri işaretler.
11
+ */
12
+ export declare function timeSlots(start: string, end: string, stepMinutes: number, unavailable?: readonly string[]): TimeSlot[];
@@ -0,0 +1,25 @@
1
+ // src/components/TimeSlotPicker/timeSlots.ts
2
+ const toMinutes = (t) => {
3
+ const m = /^(\d{1,2}):(\d{2})$/.exec(t);
4
+ return m ? Number(m[1]) * 60 + Number(m[2]) : NaN;
5
+ };
6
+ const toTime = (min) => `${String(Math.floor(min / 60) % 24).padStart(2, "0")}:${String(min % 60).padStart(2, "0")}`;
7
+ /**
8
+ * Aralıktan saatler: `timeSlots("09:00", "17:00", 30)` → 09:00, 09:30 … 16:30 (bitiş dahil
9
+ * değildir: son randevu bitişte biter). `unavailable` dolu saatleri işaretler.
10
+ */
11
+ function timeSlots(start, end, stepMinutes, unavailable = []) {
12
+ const from = toMinutes(start);
13
+ const to = toMinutes(end);
14
+ if (!Number.isFinite(from) || !Number.isFinite(to) || stepMinutes <= 0) return [];
15
+ const out = [];
16
+ for (let m = from; m + stepMinutes <= to; m += stepMinutes) {
17
+ const time = toTime(m);
18
+ out.push({
19
+ time,
20
+ isUnavailable: unavailable.includes(time)
21
+ });
22
+ }
23
+ return out;
24
+ }
25
+ export { timeSlots, toMinutes, toTime };
@@ -1,94 +1,93 @@
1
1
  @layer sti.reset, sti.tokens, sti.base, sti.components, sti.variants, sti.utilities;
2
2
  @layer sti.components {
3
- .sti-AccountMenu-trigger-cc23b {
3
+ .sti-AccountMenu-trigger-b7836 {
4
4
  --sti-account-menu-ring: var(--sti-border-subtle);
5
5
  box-sizing: border-box;
6
+ block-size: max-content;
7
+ inline-size: max-content;
6
8
  padding: var(--sti-space-0-5);
7
9
  border: var(--sti-border-width) solid var(--sti-account-menu-ring);
8
10
  border-radius: var(--sti-radius-pill);
9
11
  cursor: pointer;
10
12
  -webkit-tap-highlight-color: transparent;
11
13
  transition: border-color var(--sti-duration-fast) var(--sti-ease-snap),
12
- background-color var(--sti-duration-fast) var(--sti-ease-snap);
14
+ background-color var(--sti-duration-fast) var(--sti-ease-snap),
15
+ box-shadow var(--sti-duration-fast) var(--sti-ease-snap);
13
16
  background: none;
14
17
  flex: none;
15
18
  justify-content: center;
19
+ align-self: center;
16
20
  align-items: center;
21
+ margin: 0;
17
22
  display: inline-flex;
18
23
  }
19
24
 
20
25
  @media (hover: hover) {
21
- .sti-AccountMenu-trigger-cc23b[data-hovered] {
26
+ .sti-AccountMenu-trigger-b7836[data-hovered] {
22
27
  --sti-account-menu-ring: var(--sti-border-accent);
23
28
  }
24
29
  }
25
30
 
26
- .sti-AccountMenu-trigger-cc23b[data-pressed], .sti-AccountMenu-trigger-cc23b[data-pressed][data-hovered] {
31
+ .sti-AccountMenu-trigger-b7836[data-pressed] {
27
32
  background: var(--sti-bg-surface-active);
28
33
  }
29
34
 
30
- .sti-AccountMenu-trigger-cc23b[data-focus-visible] {
31
- outline: var(--sti-focus-ring-width) solid var(--sti-focus-ring);
32
- outline-offset: var(--sti-focus-ring-offset);
35
+ .sti-AccountMenu-trigger-b7836[data-expanded] {
36
+ --sti-account-menu-ring: var(--sti-border-selected);
37
+ box-shadow: 0 0 0 var(--sti-border-width) var(--sti-border-selected);
33
38
  }
34
39
 
35
- .sti-AccountMenu-trigger-cc23b[data-expanded] {
36
- --sti-account-menu-ring: var(--sti-border-selected);
40
+ .sti-AccountMenu-trigger-b7836[data-focus-visible] {
41
+ outline: var(--sti-focus-ring-width) solid var(--sti-focus-ring);
42
+ outline-offset: var(--sti-focus-ring-offset);
37
43
  }
38
44
 
39
45
  @media (pointer: coarse) {
40
- .sti-AccountMenu-trigger-cc23b {
46
+ .sti-AccountMenu-trigger-b7836 {
41
47
  min-block-size: 2.75rem;
42
48
  min-inline-size: 2.75rem;
43
49
  }
44
50
  }
45
51
 
46
- @media (forced-colors: active) {
47
- .sti-AccountMenu-trigger-cc23b[data-focus-visible] {
48
- outline-color: highlight;
49
- }
50
- }
51
-
52
- @media (prefers-reduced-motion: reduce) {
53
- .sti-AccountMenu-trigger-cc23b {
54
- transition: none;
55
- }
52
+ .sti-AccountMenu-card-5ba55 {
53
+ --sti-floating-w: 22.5rem;
56
54
  }
57
55
 
58
- .sti-AccountMenu-card-db0a8 {
59
- min-inline-size: 0;
60
- }
61
-
62
- .sti-AccountMenu-body-cd3ae {
63
- gap: var(--sti-space-4);
56
+ .sti-AccountMenu-panel-697e1 {
57
+ gap: var(--sti-space-3);
64
58
  min-inline-size: 0;
59
+ color: var(--sti-fg);
65
60
  font-family: var(--sti-font-text);
66
61
  display: grid;
67
62
  }
68
63
 
69
- .sti-AccountMenu-identity-5173a {
70
- align-items: center;
71
- gap: var(--sti-space-3);
72
- min-inline-size: 0;
73
- display: flex;
64
+ .sti-AccountMenu-identity-42ef2 {
65
+ padding-block: var(--sti-space-2) var(--sti-space-1);
66
+ text-align: center;
67
+ justify-items: center;
68
+ display: grid;
74
69
  }
75
70
 
76
- .sti-AccountMenu-names-17aee {
77
- gap: var(--sti-space-0-5);
78
- min-inline-size: 0;
79
- display: grid;
71
+ .sti-AccountMenu-greeting-ced99 {
72
+ margin: var(--sti-space-3) 0 0;
73
+ font-family: var(--sti-font-display);
74
+ font-size: var(--sti-font-size-xl);
75
+ font-weight: var(--sti-font-weight-semibold);
76
+ line-height: var(--sti-line-height-xl);
77
+ letter-spacing: var(--sti-tracking-xl);
78
+ overflow-wrap: anywhere;
80
79
  }
81
80
 
82
- .sti-AccountMenu-name-28b79 {
81
+ .sti-AccountMenu-fullName-7a91b {
82
+ margin: var(--sti-space-1) 0 0;
83
83
  color: var(--sti-fg);
84
- font-size: var(--sti-font-size-md);
85
- font-weight: var(--sti-font-weight-semibold);
86
- line-height: var(--sti-line-height-md);
84
+ font-size: var(--sti-font-size-sm);
85
+ font-weight: var(--sti-font-weight-medium);
86
+ line-height: var(--sti-line-height-sm);
87
87
  overflow-wrap: anywhere;
88
- margin: 0;
89
88
  }
90
89
 
91
- .sti-AccountMenu-email-aafda {
90
+ .sti-AccountMenu-email-c7b78 {
92
91
  color: var(--sti-fg-muted);
93
92
  font-size: var(--sti-font-size-sm);
94
93
  line-height: var(--sti-line-height-sm);
@@ -96,7 +95,22 @@
96
95
  margin: 0;
97
96
  }
98
97
 
99
- .sti-AccountMenu-items-efec6 {
98
+ .sti-AccountMenu-manage-2a04e {
99
+ max-inline-size: 100%;
100
+ margin-block-start: var(--sti-space-4);
101
+ }
102
+
103
+ .sti-AccountMenu-group-8f65f {
104
+ gap: var(--sti-space-0-5);
105
+ padding: var(--sti-space-1);
106
+ border-radius: var(--sti-radius-lg);
107
+ background: var(--sti-bg-subtle);
108
+ margin: 0;
109
+ list-style: none;
110
+ display: grid;
111
+ }
112
+
113
+ .sti-AccountMenu-list-0d7e5 {
100
114
  gap: var(--sti-space-0-5);
101
115
  margin: 0;
102
116
  padding: 0;
@@ -104,7 +118,77 @@
104
118
  display: grid;
105
119
  }
106
120
 
107
- .sti-AccountMenu-item-b7ab2 {
108
- min-inline-size: 0;
121
+ .sti-AccountMenu-groupTitle-3bc6e {
122
+ padding: var(--sti-space-2) var(--sti-space-3) var(--sti-space-1);
123
+ color: var(--sti-fg-muted);
124
+ font-size: var(--sti-font-size-xs);
125
+ font-weight: var(--sti-font-weight-semibold);
126
+ line-height: var(--sti-line-height-xs);
127
+ margin: 0;
128
+ }
129
+
130
+ .sti-AccountMenu-accountRow-2470c > span:first-child {
131
+ background: none;
132
+ }
133
+
134
+ .sti-AccountMenu-legal-3b18a {
135
+ justify-content: center;
136
+ gap: var(--sti-space-1);
137
+ padding-block: var(--sti-space-1) 0;
138
+ color: var(--sti-fg-muted);
139
+ font-size: var(--sti-font-size-xs);
140
+ line-height: var(--sti-line-height-xs);
141
+ flex-wrap: wrap;
142
+ margin: 0;
143
+ display: flex;
144
+ }
145
+
146
+ .sti-AccountMenu-legalItem-5deef {
147
+ gap: var(--sti-space-1);
148
+ display: inline-flex;
149
+ }
150
+
151
+ .sti-AccountMenu-dot-af8da {
152
+ color: var(--sti-fg-muted);
153
+ }
154
+
155
+ .sti-AccountMenu-legalLink-e2e81 {
156
+ border-radius: var(--sti-radius-xs);
157
+ color: var(--sti-fg-muted);
158
+ cursor: pointer;
159
+ text-decoration: none;
160
+ }
161
+
162
+ @media (hover: hover) {
163
+ .sti-AccountMenu-legalLink-e2e81[data-hovered] {
164
+ color: var(--sti-fg);
165
+ text-underline-offset: .2em;
166
+ text-decoration: underline;
167
+ }
168
+ }
169
+
170
+ .sti-AccountMenu-legalLink-e2e81[data-focus-visible] {
171
+ outline: var(--sti-focus-ring-width) solid var(--sti-focus-ring);
172
+ outline-offset: var(--sti-focus-ring-offset);
173
+ }
174
+
175
+ @media (forced-colors: active) {
176
+ .sti-AccountMenu-trigger-b7836[data-expanded] {
177
+ border-color: highlight;
178
+ }
179
+
180
+ .sti-AccountMenu-trigger-b7836[data-focus-visible], .sti-AccountMenu-legalLink-e2e81[data-focus-visible] {
181
+ outline-color: highlight;
182
+ }
183
+
184
+ .sti-AccountMenu-group-8f65f {
185
+ border: var(--sti-border-width) solid CanvasText;
186
+ }
187
+ }
188
+
189
+ @media (prefers-reduced-motion: reduce) {
190
+ .sti-AccountMenu-trigger-b7836 {
191
+ transition: none;
192
+ }
109
193
  }
110
194
  }
@@ -9,6 +9,13 @@ export interface AccountMenuAccount {
9
9
  /** Profil fotoğrafı; yoksa baş harfler çizilir. */
10
10
  avatarSrc?: string;
11
11
  }
12
+ /** Aynı tarayıcıda oturumu açık başka bir hesap. */
13
+ export interface AccountMenuOtherAccount extends AccountMenuAccount {
14
+ /** Kalıcı anahtar. */
15
+ id: string;
16
+ /** Verilirse hesaba geçiş bağlantıdır; verilmezse `onSwitchAccount` çağrılır. */
17
+ href?: string;
18
+ }
12
19
  export interface AccountMenuItem {
13
20
  /** Kalıcı anahtar. */
14
21
  id: string;
@@ -19,27 +26,48 @@ export interface AccountMenuItem {
19
26
  href?: string;
20
27
  onPress?: () => void;
21
28
  }
22
- export interface AccountMenuProps {
29
+ export interface AccountMenuPanelProps {
23
30
  account: AccountMenuAccount;
24
- /** Hesap bilgisinin altındaki bağlantı ve eylemler ("Güvenlik", "Faturalama"). */
31
+ /** Hesap yönetiminin altındaki bağlantı ve eylemler ("Güvenlik", "Faturalama"). */
25
32
  items?: readonly AccountMenuItem[];
26
33
  /** "STI ID hesabınızı yönetin" düğmesinin adresi; verilmezse düğme çizilmez. */
27
34
  manageHref?: string;
28
- /** Oturumu kapatma eylemi; adres (`signOutHref`) ya da işlev. */
29
- onSignOut?: () => void;
35
+ /** Oturumu açık diğer hesaplar; verilirse "Diğer hesaplar" bölümü çizilir. */
36
+ otherAccounts?: readonly AccountMenuOtherAccount[];
37
+ onSwitchAccount?: (id: string) => void;
38
+ /** "Başka bir hesap ekleyin" satırı: adres ya da işlev. */
39
+ addAccountHref?: string;
40
+ onAddAccount?: () => void;
41
+ /** Oturumu kapatma eylemi: adres (`signOutHref`) ya da işlev. */
30
42
  signOutHref?: string;
43
+ onSignOut?: () => void;
44
+ /** Panelin dibindeki yasal bağlantılar. */
45
+ privacyHref?: string;
46
+ termsHref?: string;
47
+ /** Bir eylem seçildiğinde çağrılır; açılır kutuda paneli kapatır. */
48
+ onAction?: () => void;
49
+ className?: string;
50
+ id?: string;
51
+ }
52
+ export interface AccountMenuProps extends Omit<AccountMenuPanelProps, "onAction" | "id"> {
31
53
  /** Tetikleyicinin avatar boyu. */
32
54
  size?: "sm" | "md" | "lg";
33
55
  placement?: Placement;
34
56
  isOpen?: boolean;
35
57
  defaultOpen?: boolean;
36
58
  onOpenChange?: (open: boolean) => void;
37
- className?: string;
59
+ /** Tetikleyici düğmenin kimliği. */
38
60
  id?: string;
39
61
  }
40
62
  /**
41
- * Hesap menüsü: avatar düğmesi, altında hesabın adı ve e-postası, hesap yönetimi, bağlantılar ve
42
- * oturumu kapatma. APG Dialog kalıbı (kipsiz açılır kutu): Enter ya da Boşluk açar, Tab içeride
43
- * dolaşır, Escape kapatır ve odak düğmeye döner.
63
+ * Hesap panelinin içeriği: kimlik (büyük avatar, selamlama, e-posta), hesap yönetimi, bağlantılar,
64
+ * diğer hesaplar, hesap ekleme, oturumu kapatma ve yasal bağlantılar. `AccountMenu` bunu açılır
65
+ * kutuda çizer; uygulama dar ekran çekmecesinde ya da hesap sayfasında doğrudan kullanabilir.
66
+ */
67
+ export declare function AccountMenuPanel({ account, items, manageHref, otherAccounts, onSwitchAccount, addAccountHref, onAddAccount, signOutHref, onSignOut, privacyHref, termsHref, onAction, className, id }: AccountMenuPanelProps): import("react").JSX.Element;
68
+ /**
69
+ * Hesap menüsü: avatar düğmesi ve açılır hesap paneli (`AccountMenuPanel`). APG Dialog kalıbı
70
+ * (kipsiz açılır kutu): Enter ya da Boşluk açar, Tab içeride dolaşır, Escape kapatır ve odak
71
+ * düğmeye döner.
44
72
  */
45
- export declare function AccountMenu({ account, items, manageHref, onSignOut, signOutHref, size, placement, isOpen, defaultOpen, onOpenChange, className, id }: AccountMenuProps): import("react").JSX.Element;
73
+ export declare function AccountMenu({ size, placement, isOpen, defaultOpen, onOpenChange, className, id, ...panel }: AccountMenuProps): import("react").JSX.Element;
@@ -6,17 +6,142 @@ import { Button as Button$1 } from "../../components/Button/Button.js";
6
6
  import { Avatar } from "../../components/Avatar/Avatar.js";
7
7
  import { Popover as Popover$1 } from "../../components/Popover/Popover.js";
8
8
  import { LogOutIcon } from "../../icons/generated/LogOutIcon.js";
9
+ import { UserPlusIcon } from "../../icons/generated/UserPlusIcon.js";
9
10
  import { ActionItem } from "../_internal/ActionItem/ActionItem.js";
10
11
  import AccountMenu_module_default from "./AccountMenu.module.js";
11
- import { jsx, jsxs } from "react/jsx-runtime";
12
- import { Button } from "react-aria-components";
12
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
+ import { Button, Link } from "react-aria-components";
13
14
  // src/id/AccountMenu/AccountMenu.tsx
14
15
  /**
15
- * Hesap menüsü: avatar düğmesi, altında hesabın adı ve e-postası, hesap yönetimi, bağlantılar ve
16
- * oturumu kapatma. APG Dialog kalıbı (kipsiz açılır kutu): Enter ya da Boşluk açar, Tab içeride
17
- * dolaşır, Escape kapatır ve odak düğmeye döner.
16
+ * Hesap panelinin içeriği: kimlik (büyük avatar, selamlama, e-posta), hesap yönetimi, bağlantılar,
17
+ * diğer hesaplar, hesap ekleme, oturumu kapatma ve yasal bağlantılar. `AccountMenu` bunu açılır
18
+ * kutuda çizer; uygulama dar ekran çekmecesinde ya da hesap sayfasında doğrudan kullanabilir.
18
19
  */
19
- function AccountMenu({ account, items = [], manageHref, onSignOut, signOutHref, size = "md", placement = "bottom end", isOpen, defaultOpen, onOpenChange, className, id }) {
20
+ function AccountMenuPanel({ account, items = [], manageHref, otherAccounts = [], onSwitchAccount, addAccountHref, onAddAccount, signOutHref, onSignOut, privacyHref, termsHref, onAction, className, id }) {
21
+ const t = useMessages();
22
+ const run = (fn) => () => {
23
+ onAction?.();
24
+ fn?.();
25
+ };
26
+ const canAdd = addAccountHref !== void 0 || onAddAccount !== void 0;
27
+ const canSignOut = signOutHref !== void 0 || onSignOut !== void 0;
28
+ const legal = [privacyHref ? {
29
+ href: privacyHref,
30
+ label: t.idAccountPrivacy
31
+ } : null, termsHref ? {
32
+ href: termsHref,
33
+ label: t.idAccountTerms
34
+ } : null].filter((l) => l !== null);
35
+ return /* @__PURE__ */ jsxs("div", {
36
+ id,
37
+ className: [AccountMenu_module_default.panel, className].filter(Boolean).join(" "),
38
+ children: [
39
+ /* @__PURE__ */ jsxs("div", {
40
+ className: AccountMenu_module_default.identity,
41
+ children: [
42
+ /* @__PURE__ */ jsx(Avatar, {
43
+ name: account.name,
44
+ src: account.avatarSrc,
45
+ size: "xl",
46
+ isDecorative: true
47
+ }),
48
+ /* @__PURE__ */ jsx("p", {
49
+ className: AccountMenu_module_default.greeting,
50
+ children: template(t.idAccountGreeting, { name: firstName(account.name) })
51
+ }),
52
+ /* @__PURE__ */ jsx("p", {
53
+ className: AccountMenu_module_default.fullName,
54
+ children: account.name
55
+ }),
56
+ /* @__PURE__ */ jsx("p", {
57
+ className: AccountMenu_module_default.email,
58
+ children: account.email
59
+ }),
60
+ manageHref ? /* @__PURE__ */ jsx(Button$1, {
61
+ variant: "secondary",
62
+ size: "sm",
63
+ href: manageHref,
64
+ className: AccountMenu_module_default.manage,
65
+ children: t.idAccountManage
66
+ }) : null
67
+ ]
68
+ }),
69
+ items.length > 0 ? /* @__PURE__ */ jsx("ul", {
70
+ className: AccountMenu_module_default.group,
71
+ children: items.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(ActionItem, {
72
+ label: item.label,
73
+ icon: item.icon,
74
+ href: item.href,
75
+ onPress: run(item.onPress)
76
+ }) }, item.id))
77
+ }) : null,
78
+ otherAccounts.length > 0 || canAdd ? /* @__PURE__ */ jsxs("section", {
79
+ className: AccountMenu_module_default.group,
80
+ "aria-label": t.idAccountOthers,
81
+ children: [otherAccounts.length > 0 ? /* @__PURE__ */ jsx("p", {
82
+ className: AccountMenu_module_default.groupTitle,
83
+ "aria-hidden": "true",
84
+ children: t.idAccountOthers
85
+ }) : null, /* @__PURE__ */ jsxs("ul", {
86
+ className: AccountMenu_module_default.list,
87
+ children: [otherAccounts.map((other) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(ActionItem, {
88
+ label: /* @__PURE__ */ jsxs(Fragment, { children: [other.name, /* @__PURE__ */ jsxs(VisuallyHidden, { children: [", ", t.idAccountSwitch] })] }),
89
+ description: other.email,
90
+ icon: /* @__PURE__ */ jsx(Avatar, {
91
+ name: other.name,
92
+ src: other.avatarSrc,
93
+ size: "sm",
94
+ isDecorative: true
95
+ }),
96
+ className: AccountMenu_module_default.accountRow,
97
+ href: other.href,
98
+ onPress: run(() => onSwitchAccount?.(other.id))
99
+ }) }, other.id)), canAdd ? /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(ActionItem, {
100
+ label: t.idAccountAdd,
101
+ icon: /* @__PURE__ */ jsx(UserPlusIcon, {}),
102
+ href: addAccountHref,
103
+ onPress: run(onAddAccount)
104
+ }) }) : null]
105
+ })]
106
+ }) : null,
107
+ canSignOut ? /* @__PURE__ */ jsx("div", {
108
+ className: AccountMenu_module_default.group,
109
+ children: /* @__PURE__ */ jsx(ActionItem, {
110
+ label: t.idAccountSignOut,
111
+ icon: /* @__PURE__ */ jsx(LogOutIcon, {}),
112
+ href: signOutHref,
113
+ onPress: run(onSignOut)
114
+ })
115
+ }) : null,
116
+ legal.length > 0 ? /* @__PURE__ */ jsx("p", {
117
+ className: AccountMenu_module_default.legal,
118
+ children: legal.map((link, i) => /* @__PURE__ */ jsxs("span", {
119
+ className: AccountMenu_module_default.legalItem,
120
+ children: [i > 0 ? /* @__PURE__ */ jsx("span", {
121
+ className: AccountMenu_module_default.dot,
122
+ "aria-hidden": "true",
123
+ children: "·"
124
+ }) : null, /* @__PURE__ */ jsx(Link, {
125
+ href: link.href,
126
+ className: AccountMenu_module_default.legalLink,
127
+ onPress: onAction,
128
+ children: link.label
129
+ })]
130
+ }, link.href))
131
+ }) : null
132
+ ]
133
+ });
134
+ }
135
+ /** Selamlamadaki ad: ilk sözcük ("Elif Yıldırım" → "Elif"). */
136
+ function firstName(name) {
137
+ return name.trim().split(/\s+/)[0] ?? name;
138
+ }
139
+ /**
140
+ * Hesap menüsü: avatar düğmesi ve açılır hesap paneli (`AccountMenuPanel`). APG Dialog kalıbı
141
+ * (kipsiz açılır kutu): Enter ya da Boşluk açar, Tab içeride dolaşır, Escape kapatır ve odak
142
+ * düğmeye döner.
143
+ */
144
+ function AccountMenu({ size = "md", placement = "bottom end", isOpen, defaultOpen, onOpenChange, className, id, ...panel }) {
20
145
  const t = useMessages();
21
146
  return /* @__PURE__ */ jsx(Popover$1, {
22
147
  isOpen,
@@ -31,68 +156,16 @@ function AccountMenu({ account, items = [], manageHref, onSignOut, signOutHref,
31
156
  className: [AccountMenu_module_default.trigger, className].filter(Boolean).join(" "),
32
157
  "data-size": size,
33
158
  children: [/* @__PURE__ */ jsx(Avatar, {
34
- name: account.name,
35
- src: account.avatarSrc,
159
+ name: panel.account.name,
160
+ src: panel.account.avatarSrc,
36
161
  size,
37
162
  isDecorative: true
38
- }), /* @__PURE__ */ jsx(VisuallyHidden, { children: template(t.idAccountMenuFor, { name: account.name }) })]
163
+ }), /* @__PURE__ */ jsx(VisuallyHidden, { children: template(t.idAccountMenuFor, { name: panel.account.name }) })]
39
164
  }),
40
- footer: (close) => onSignOut || signOutHref ? /* @__PURE__ */ jsx(Button$1, {
41
- variant: "ghost",
42
- size: "sm",
43
- fullWidth: true,
44
- iconStart: /* @__PURE__ */ jsx(LogOutIcon, {}),
45
- ...signOutHref ? { href: signOutHref } : { onPress: () => {
46
- close();
47
- onSignOut?.();
48
- } },
49
- children: t.idAccountSignOut
50
- }) : null,
51
- children: (close) => /* @__PURE__ */ jsxs("div", {
52
- className: AccountMenu_module_default.body,
53
- children: [
54
- /* @__PURE__ */ jsxs("div", {
55
- className: AccountMenu_module_default.identity,
56
- children: [/* @__PURE__ */ jsx(Avatar, {
57
- name: account.name,
58
- src: account.avatarSrc,
59
- size: "lg",
60
- isDecorative: true
61
- }), /* @__PURE__ */ jsxs("div", {
62
- className: AccountMenu_module_default.names,
63
- children: [/* @__PURE__ */ jsx("p", {
64
- className: AccountMenu_module_default.name,
65
- children: account.name
66
- }), /* @__PURE__ */ jsx("p", {
67
- className: AccountMenu_module_default.email,
68
- children: account.email
69
- })]
70
- })]
71
- }),
72
- manageHref ? /* @__PURE__ */ jsx(Button$1, {
73
- variant: "secondary",
74
- size: "sm",
75
- fullWidth: true,
76
- href: manageHref,
77
- children: t.idAccountManage
78
- }) : null,
79
- items.length > 0 ? /* @__PURE__ */ jsx("ul", {
80
- className: AccountMenu_module_default.items,
81
- children: items.map((item) => /* @__PURE__ */ jsx("li", {
82
- className: AccountMenu_module_default.item,
83
- children: /* @__PURE__ */ jsx(ActionItem, {
84
- label: item.label,
85
- icon: item.icon,
86
- href: item.href,
87
- onPress: () => {
88
- close();
89
- item.onPress?.();
90
- }
91
- })
92
- }, item.id))
93
- }) : null
94
- ]
165
+ children: (close) => /* @__PURE__ */ jsx(AccountMenuPanel, {
166
+ ...panel,
167
+ onAction: close
95
168
  })
96
169
  });
97
170
  }
98
- export { AccountMenu };
171
+ export { AccountMenu, AccountMenuPanel };