@sentropic/design-system-svelte 0.23.0 → 0.25.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.
@@ -0,0 +1,197 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+
4
+ export interface AppHeaderProps {
5
+ /**
6
+ * Force le mode compact (burger). Calque la source : le burger est à GAUCHE
7
+ * et la nav desktop est masquée quand `compact` est vrai.
8
+ */
9
+ compact?: boolean;
10
+ /** État ouvert du panneau burger (contrôlé). */
11
+ menuOpen?: boolean;
12
+ /** Callback de bascule du burger (clic sur le bouton compact). */
13
+ onMenuToggle?: () => void;
14
+ /** aria-label du bouton burger. */
15
+ menuLabel?: string;
16
+ /** Logo (décision actée : logo SENT + sous-titre). */
17
+ logo?: Snippet;
18
+ /** Liens de navigation (rendus dans le <nav> desktop). */
19
+ nav?: Snippet;
20
+ /** Contenu à droite (typiquement LanguageToggle + IdentityMenu). */
21
+ actions?: Snippet;
22
+ /** Contenu du tiroir compact (nav + langue + identité en accordéon). */
23
+ drawer?: Snippet;
24
+ class?: string;
25
+ }
26
+ </script>
27
+
28
+ <script lang="ts">
29
+ import { Menu, X } from "@lucide/svelte";
30
+
31
+ let {
32
+ compact = false,
33
+ menuOpen = false,
34
+ onMenuToggle,
35
+ menuLabel = "Menu",
36
+ logo,
37
+ nav,
38
+ actions,
39
+ drawer,
40
+ class: className,
41
+ }: AppHeaderProps = $props();
42
+
43
+ const classes = () => ["st-appHeader", className].filter(Boolean).join(" ");
44
+ </script>
45
+
46
+ <header class={classes()}>
47
+ <div class="st-appHeader__bar">
48
+ <!-- Burger à GAUCHE (calque exact de la source ~L176-191). -->
49
+ {#if compact}
50
+ <div class="st-appHeader__burger">
51
+ <button
52
+ type="button"
53
+ class="st-appHeader__burgerButton"
54
+ onclick={onMenuToggle}
55
+ aria-label={menuLabel}
56
+ aria-expanded={menuOpen}
57
+ aria-haspopup="menu"
58
+ >
59
+ {#if menuOpen}
60
+ <X class="st-appHeader__burgerIcon" size={20} aria-hidden="true" />
61
+ {:else}
62
+ <Menu class="st-appHeader__burgerIcon" size={20} aria-hidden="true" />
63
+ {/if}
64
+ </button>
65
+ </div>
66
+ {:else}
67
+ <!-- Nav desktop (masquée en mode compact). -->
68
+ <nav class="st-appHeader__nav" aria-label="Primary">
69
+ {#if nav}{@render nav()}{/if}
70
+ </nav>
71
+ {/if}
72
+
73
+ {#if logo}
74
+ <div class="st-appHeader__logo">{@render logo()}</div>
75
+ {/if}
76
+
77
+ <!-- Contrôles de droite (masqués en mode compact). -->
78
+ {#if !compact}
79
+ <div class="st-appHeader__actions">
80
+ {#if actions}{@render actions()}{/if}
81
+ </div>
82
+ {/if}
83
+ </div>
84
+ </header>
85
+
86
+ {#if compact && menuOpen && drawer}
87
+ <button
88
+ type="button"
89
+ class="st-appHeader__scrim"
90
+ aria-label={menuLabel}
91
+ onclick={onMenuToggle}
92
+ ></button>
93
+ <aside class="st-appHeader__drawer">
94
+ {@render drawer()}
95
+ </aside>
96
+ {/if}
97
+
98
+ <style>
99
+ .st-appHeader {
100
+ background: var(--st-semantic-surface-default);
101
+ border-bottom: 1px solid var(--st-semantic-border-subtle);
102
+ color: var(--st-semantic-text-primary);
103
+ font-family: var(--st-font-sans);
104
+ width: 100%;
105
+ }
106
+
107
+ .st-appHeader__bar {
108
+ align-items: center;
109
+ display: flex;
110
+ gap: var(--st-spacing-4, 1rem);
111
+ height: 3.5rem;
112
+ justify-content: space-between;
113
+ margin: 0 auto;
114
+ max-width: 80rem;
115
+ padding: 0 var(--st-spacing-4, 1rem);
116
+ width: 100%;
117
+ }
118
+
119
+ .st-appHeader__nav {
120
+ align-items: center;
121
+ display: flex;
122
+ flex: 1 1 auto;
123
+ flex-wrap: wrap;
124
+ font-size: 0.875rem;
125
+ font-weight: 500;
126
+ gap: var(--st-spacing-4, 1rem);
127
+ min-width: 0;
128
+ }
129
+
130
+ .st-appHeader__burger {
131
+ align-items: center;
132
+ display: flex;
133
+ flex: 1 1 auto;
134
+ justify-content: flex-start;
135
+ }
136
+
137
+ .st-appHeader__burgerButton {
138
+ align-items: center;
139
+ background: transparent;
140
+ border: 0;
141
+ border-radius: var(--st-radius-sm, 0.375rem);
142
+ color: var(--st-semantic-text-primary);
143
+ cursor: pointer;
144
+ display: inline-flex;
145
+ justify-content: center;
146
+ padding: var(--st-spacing-2, 0.5rem);
147
+ }
148
+
149
+ .st-appHeader__burgerButton:hover {
150
+ background: var(--st-semantic-surface-subtle);
151
+ }
152
+
153
+ .st-appHeader__burgerButton:focus-visible {
154
+ box-shadow: 0 0 0 2px var(--st-semantic-border-interactive);
155
+ outline: none;
156
+ }
157
+
158
+ .st-appHeader__burgerIcon {
159
+ display: block;
160
+ }
161
+
162
+ .st-appHeader__logo {
163
+ align-items: center;
164
+ display: inline-flex;
165
+ flex: 0 0 auto;
166
+ }
167
+
168
+ .st-appHeader__actions {
169
+ align-items: center;
170
+ display: flex;
171
+ flex: 0 0 auto;
172
+ gap: var(--st-spacing-3, 0.75rem);
173
+ }
174
+
175
+ .st-appHeader__scrim {
176
+ background: transparent;
177
+ border: 0;
178
+ cursor: default;
179
+ inset: 0;
180
+ padding: 0;
181
+ position: fixed;
182
+ z-index: var(--st-zindex-overlay, 80);
183
+ }
184
+
185
+ .st-appHeader__drawer {
186
+ background: var(--st-semantic-surface-default);
187
+ border: 1px solid var(--st-semantic-border-subtle);
188
+ box-shadow: var(--st-shadow-medium, 0 8px 24px rgb(15 23 42 / 0.12));
189
+ left: 0;
190
+ max-height: 100vh;
191
+ overflow-y: auto;
192
+ position: fixed;
193
+ top: 0;
194
+ width: min(22rem, 85vw);
195
+ z-index: calc(var(--st-zindex-overlay, 80) + 10);
196
+ }
197
+ </style>
@@ -0,0 +1,27 @@
1
+ import type { Snippet } from "svelte";
2
+ export interface AppHeaderProps {
3
+ /**
4
+ * Force le mode compact (burger). Calque la source : le burger est à GAUCHE
5
+ * et la nav desktop est masquée quand `compact` est vrai.
6
+ */
7
+ compact?: boolean;
8
+ /** État ouvert du panneau burger (contrôlé). */
9
+ menuOpen?: boolean;
10
+ /** Callback de bascule du burger (clic sur le bouton compact). */
11
+ onMenuToggle?: () => void;
12
+ /** aria-label du bouton burger. */
13
+ menuLabel?: string;
14
+ /** Logo (décision actée : logo SENT + sous-titre). */
15
+ logo?: Snippet;
16
+ /** Liens de navigation (rendus dans le <nav> desktop). */
17
+ nav?: Snippet;
18
+ /** Contenu à droite (typiquement LanguageToggle + IdentityMenu). */
19
+ actions?: Snippet;
20
+ /** Contenu du tiroir compact (nav + langue + identité en accordéon). */
21
+ drawer?: Snippet;
22
+ class?: string;
23
+ }
24
+ declare const AppHeader: import("svelte").Component<AppHeaderProps, {}, "">;
25
+ type AppHeader = ReturnType<typeof AppHeader>;
26
+ export default AppHeader;
27
+ //# sourceMappingURL=AppHeader.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppHeader.svelte.d.ts","sourceRoot":"","sources":["../src/lib/AppHeader.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0DAA0D;IAC1D,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAqEH,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -0,0 +1,406 @@
1
+ <script lang="ts" module>
2
+ export interface IdentityUser {
3
+ displayName: string;
4
+ email?: string;
5
+ id?: string;
6
+ }
7
+
8
+ export interface IdentityMenuProps {
9
+ /** Identité connectée (contrôlé). `null` quand anonyme. */
10
+ user?: IdentityUser | null;
11
+ /** État d'authentification (contrôlé : aucun état auth interne). */
12
+ isAuthenticated?: boolean;
13
+ /** État ouvert du dropdown (optionnellement contrôlé). */
14
+ open?: boolean;
15
+ /** Notifié au clic « Se connecter ». */
16
+ onLogin?: () => void;
17
+ /** Notifié au clic « Se déconnecter ». */
18
+ onLogout?: () => void;
19
+ /** Lien « Appareils ». */
20
+ devicesHref?: string;
21
+ /** Lien « Paramètres ». */
22
+ settingsHref?: string;
23
+ /** Libellé du bouton de connexion. */
24
+ loginLabel?: string;
25
+ /** Libellé « Appareils ». */
26
+ devicesLabel?: string;
27
+ /** Libellé « Paramètres ». */
28
+ settingsLabel?: string;
29
+ /** Libellé « Se déconnecter ». */
30
+ logoutLabel?: string;
31
+ /**
32
+ * Variante d'affichage :
33
+ * - `dropdown` (défaut) : déclencheur + menu flottant (header desktop).
34
+ * - `accordion` : déclencheur + liste inline (tiroir mobile).
35
+ */
36
+ variant?: "dropdown" | "accordion";
37
+ class?: string;
38
+ }
39
+
40
+ /** Première lettre du displayName, en majuscule (calque de la source). */
41
+ export function identityInitial(user: IdentityUser | null | undefined): string {
42
+ const source = user?.displayName || user?.email || "U";
43
+ return source.charAt(0).toUpperCase();
44
+ }
45
+ </script>
46
+
47
+ <script lang="ts">
48
+ import { ChevronDown } from "@lucide/svelte";
49
+
50
+ let {
51
+ user = null,
52
+ isAuthenticated = false,
53
+ open = $bindable(false),
54
+ onLogin,
55
+ onLogout,
56
+ devicesHref = "#",
57
+ settingsHref = "#",
58
+ loginLabel = "Se connecter",
59
+ devicesLabel = "Appareils",
60
+ settingsLabel = "Paramètres",
61
+ logoutLabel = "Se déconnecter",
62
+ variant = "dropdown",
63
+ class: className,
64
+ }: IdentityMenuProps = $props();
65
+
66
+ let root: HTMLDivElement | undefined = $state();
67
+ let triggerEl: HTMLButtonElement | undefined = $state();
68
+
69
+ const classes = () => ["st-identityMenu", className].filter(Boolean).join(" ");
70
+ const initial = $derived(identityInitial(user));
71
+ const displayName = $derived(user?.displayName || user?.email || "User");
72
+
73
+ function getMenuItems(): HTMLElement[] {
74
+ return Array.from(
75
+ root?.querySelectorAll<HTMLElement>('[role="menuitem"]') ?? []
76
+ );
77
+ }
78
+
79
+ function focusItem(index: number) {
80
+ const items = getMenuItems();
81
+ if (!items.length) return;
82
+ const len = items.length;
83
+ const target = ((index % len) + len) % len;
84
+ items[target]?.focus();
85
+ }
86
+
87
+ function toggle() {
88
+ open = !open;
89
+ }
90
+
91
+ function closeAndFocusTrigger() {
92
+ open = false;
93
+ triggerEl?.focus();
94
+ }
95
+
96
+ function onTriggerKeydown(event: KeyboardEvent) {
97
+ if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
98
+ event.preventDefault();
99
+ if (!open) open = true;
100
+ queueMicrotask(() => focusItem(0));
101
+ return;
102
+ }
103
+ if (event.key === "ArrowUp") {
104
+ event.preventDefault();
105
+ if (!open) open = true;
106
+ queueMicrotask(() => focusItem(-1));
107
+ }
108
+ }
109
+
110
+ function onMenuKeydown(event: KeyboardEvent) {
111
+ const items = getMenuItems();
112
+ const current = items.indexOf(document.activeElement as HTMLElement);
113
+ if (event.key === "ArrowDown") {
114
+ event.preventDefault();
115
+ focusItem(current + 1);
116
+ return;
117
+ }
118
+ if (event.key === "ArrowUp") {
119
+ event.preventDefault();
120
+ focusItem(current - 1);
121
+ return;
122
+ }
123
+ if (event.key === "Home") {
124
+ event.preventDefault();
125
+ focusItem(0);
126
+ return;
127
+ }
128
+ if (event.key === "End") {
129
+ event.preventDefault();
130
+ focusItem(items.length - 1);
131
+ return;
132
+ }
133
+ if (event.key === "Escape") {
134
+ event.preventDefault();
135
+ closeAndFocusTrigger();
136
+ }
137
+ }
138
+
139
+ function handleLogout() {
140
+ open = false;
141
+ onLogout?.();
142
+ }
143
+ </script>
144
+
145
+ <svelte:window
146
+ onpointerdown={(e) => {
147
+ if (open && root && e.target instanceof Node && !root.contains(e.target)) open = false;
148
+ }}
149
+ />
150
+
151
+ {#if isAuthenticated && user}
152
+ <div
153
+ class={classes()}
154
+ class:st-identityMenu--accordion={variant === "accordion"}
155
+ bind:this={root}
156
+ >
157
+ <button
158
+ type="button"
159
+ class="st-identityMenu__trigger"
160
+ bind:this={triggerEl}
161
+ aria-haspopup="menu"
162
+ aria-expanded={open}
163
+ aria-label={`Compte de ${displayName}`}
164
+ onclick={toggle}
165
+ onkeydown={onTriggerKeydown}
166
+ >
167
+ <span class="st-identityMenu__avatar" aria-hidden="true">{initial}</span>
168
+ <span class="st-identityMenu__meta">
169
+ <span class="st-identityMenu__name">{displayName}</span>
170
+ {#if variant === "accordion" && user.email}
171
+ <span class="st-identityMenu__email">{user.email}</span>
172
+ {/if}
173
+ </span>
174
+ <ChevronDown
175
+ class={`st-identityMenu__chevron${open ? " st-identityMenu__chevron--open" : ""}`}
176
+ size={16}
177
+ aria-hidden="true"
178
+ />
179
+ </button>
180
+
181
+ {#if open}
182
+ <div
183
+ class="st-identityMenu__menu"
184
+ role="menu"
185
+ tabindex="-1"
186
+ aria-label={`Menu de ${displayName}`}
187
+ onkeydown={onMenuKeydown}
188
+ >
189
+ <a
190
+ href={devicesHref}
191
+ class="st-identityMenu__item"
192
+ role="menuitem"
193
+ tabindex="-1"
194
+ onclick={() => (open = false)}
195
+ >
196
+ {devicesLabel}
197
+ </a>
198
+ <a
199
+ href={settingsHref}
200
+ class="st-identityMenu__item"
201
+ role="menuitem"
202
+ tabindex="-1"
203
+ onclick={() => (open = false)}
204
+ >
205
+ {settingsLabel}
206
+ </a>
207
+ <div class="st-identityMenu__divider" role="separator" aria-hidden="true"></div>
208
+ <button
209
+ type="button"
210
+ class="st-identityMenu__item st-identityMenu__item--danger"
211
+ role="menuitem"
212
+ tabindex="-1"
213
+ onclick={handleLogout}
214
+ >
215
+ {logoutLabel}
216
+ </button>
217
+ </div>
218
+ {/if}
219
+ </div>
220
+ {:else}
221
+ <button
222
+ type="button"
223
+ class="st-identityMenu__login"
224
+ class:st-identityMenu__login--accordion={variant === "accordion"}
225
+ onclick={() => onLogin?.()}
226
+ >
227
+ {loginLabel}
228
+ </button>
229
+ {/if}
230
+
231
+ <style>
232
+ .st-identityMenu {
233
+ font-family: var(--st-font-sans);
234
+ position: relative;
235
+ }
236
+
237
+ .st-identityMenu--accordion {
238
+ width: 100%;
239
+ }
240
+
241
+ .st-identityMenu__trigger {
242
+ align-items: center;
243
+ background: transparent;
244
+ border: 0;
245
+ border-radius: var(--st-radius-sm, 0.375rem);
246
+ color: var(--st-semantic-text-primary);
247
+ cursor: pointer;
248
+ display: inline-flex;
249
+ font: inherit;
250
+ font-family: var(--st-font-sans);
251
+ font-size: 0.875rem;
252
+ font-weight: 500;
253
+ gap: var(--st-spacing-2, 0.5rem);
254
+ padding: var(--st-spacing-1, 0.25rem) var(--st-spacing-3, 0.75rem);
255
+ }
256
+
257
+ .st-identityMenu--accordion .st-identityMenu__trigger {
258
+ padding: var(--st-spacing-2, 0.5rem) var(--st-spacing-3, 0.75rem);
259
+ width: 100%;
260
+ }
261
+
262
+ .st-identityMenu__trigger:hover {
263
+ background: var(--st-semantic-surface-subtle);
264
+ }
265
+
266
+ .st-identityMenu__trigger:focus-visible {
267
+ box-shadow: 0 0 0 2px var(--st-semantic-border-interactive);
268
+ outline: none;
269
+ }
270
+
271
+ .st-identityMenu__avatar {
272
+ align-items: center;
273
+ background: var(--st-semantic-action-primary);
274
+ border-radius: var(--st-radius-pill, 9999px);
275
+ color: var(--st-semantic-action-primaryText);
276
+ display: inline-flex;
277
+ flex: 0 0 auto;
278
+ font-weight: 500;
279
+ height: 2rem;
280
+ justify-content: center;
281
+ width: 2rem;
282
+ }
283
+
284
+ .st-identityMenu__meta {
285
+ display: grid;
286
+ gap: 0.05rem;
287
+ min-width: 0;
288
+ text-align: left;
289
+ }
290
+
291
+ .st-identityMenu--accordion .st-identityMenu__meta {
292
+ flex: 1 1 auto;
293
+ }
294
+
295
+ .st-identityMenu__name {
296
+ color: var(--st-semantic-text-primary);
297
+ overflow: hidden;
298
+ text-overflow: ellipsis;
299
+ white-space: nowrap;
300
+ }
301
+
302
+ .st-identityMenu__email {
303
+ color: var(--st-semantic-text-secondary);
304
+ font-size: 0.75rem;
305
+ overflow: hidden;
306
+ text-overflow: ellipsis;
307
+ white-space: nowrap;
308
+ }
309
+
310
+ .st-identityMenu :global(.st-identityMenu__chevron) {
311
+ color: var(--st-semantic-text-secondary);
312
+ flex: 0 0 auto;
313
+ transition: transform var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
314
+ }
315
+
316
+ .st-identityMenu :global(.st-identityMenu__chevron--open) {
317
+ transform: rotate(180deg);
318
+ }
319
+
320
+ .st-identityMenu__menu {
321
+ background: var(--st-semantic-surface-raised);
322
+ border: 1px solid var(--st-semantic-border-subtle);
323
+ border-radius: var(--st-radius-md, 0.375rem);
324
+ box-shadow: var(--st-shadow-medium, 0 8px 24px rgb(15 23 42 / 0.12));
325
+ display: grid;
326
+ margin-top: var(--st-spacing-2, 0.5rem);
327
+ min-width: 12rem;
328
+ padding: var(--st-spacing-1, 0.25rem);
329
+ position: absolute;
330
+ right: 0;
331
+ top: 100%;
332
+ z-index: var(--st-zindex-overlay, 80);
333
+ }
334
+
335
+ /* En accordéon, le menu est inline (pas flottant). */
336
+ .st-identityMenu--accordion .st-identityMenu__menu {
337
+ box-shadow: none;
338
+ margin-top: var(--st-spacing-1, 0.25rem);
339
+ position: static;
340
+ width: 100%;
341
+ }
342
+
343
+ .st-identityMenu__item {
344
+ background: transparent;
345
+ border: 0;
346
+ border-radius: var(--st-radius-sm, 0.375rem);
347
+ color: var(--st-semantic-text-primary);
348
+ cursor: pointer;
349
+ display: block;
350
+ font: inherit;
351
+ font-family: var(--st-font-sans);
352
+ font-size: 0.875rem;
353
+ font-weight: 500;
354
+ padding: var(--st-spacing-2, 0.5rem) var(--st-spacing-3, 0.75rem);
355
+ text-align: left;
356
+ text-decoration: none;
357
+ width: 100%;
358
+ }
359
+
360
+ .st-identityMenu__item:hover {
361
+ background: var(--st-semantic-surface-subtle);
362
+ }
363
+
364
+ .st-identityMenu__item:focus-visible {
365
+ box-shadow: 0 0 0 2px var(--st-semantic-border-interactive);
366
+ outline: none;
367
+ }
368
+
369
+ .st-identityMenu__item--danger {
370
+ color: var(--st-semantic-action-danger);
371
+ }
372
+
373
+ .st-identityMenu__divider {
374
+ background: var(--st-semantic-border-subtle);
375
+ height: 1px;
376
+ margin: var(--st-spacing-1, 0.25rem) 0;
377
+ }
378
+
379
+ .st-identityMenu__login {
380
+ background: var(--st-semantic-action-primary);
381
+ border: 0;
382
+ border-radius: var(--st-radius-md, 0.375rem);
383
+ color: var(--st-semantic-action-primaryText);
384
+ cursor: pointer;
385
+ font: inherit;
386
+ font-family: var(--st-font-sans);
387
+ font-size: 0.875rem;
388
+ padding: var(--st-spacing-1, 0.25rem) var(--st-spacing-3, 0.75rem);
389
+ }
390
+
391
+ .st-identityMenu__login--accordion {
392
+ display: block;
393
+ padding: var(--st-spacing-2, 0.5rem) var(--st-spacing-3, 0.75rem);
394
+ text-align: center;
395
+ width: 100%;
396
+ }
397
+
398
+ .st-identityMenu__login:hover {
399
+ background: var(--st-semantic-action-primaryHover);
400
+ }
401
+
402
+ .st-identityMenu__login:focus-visible {
403
+ box-shadow: 0 0 0 2px var(--st-semantic-border-interactive);
404
+ outline: none;
405
+ }
406
+ </style>
@@ -0,0 +1,42 @@
1
+ export interface IdentityUser {
2
+ displayName: string;
3
+ email?: string;
4
+ id?: string;
5
+ }
6
+ export interface IdentityMenuProps {
7
+ /** Identité connectée (contrôlé). `null` quand anonyme. */
8
+ user?: IdentityUser | null;
9
+ /** État d'authentification (contrôlé : aucun état auth interne). */
10
+ isAuthenticated?: boolean;
11
+ /** État ouvert du dropdown (optionnellement contrôlé). */
12
+ open?: boolean;
13
+ /** Notifié au clic « Se connecter ». */
14
+ onLogin?: () => void;
15
+ /** Notifié au clic « Se déconnecter ». */
16
+ onLogout?: () => void;
17
+ /** Lien « Appareils ». */
18
+ devicesHref?: string;
19
+ /** Lien « Paramètres ». */
20
+ settingsHref?: string;
21
+ /** Libellé du bouton de connexion. */
22
+ loginLabel?: string;
23
+ /** Libellé « Appareils ». */
24
+ devicesLabel?: string;
25
+ /** Libellé « Paramètres ». */
26
+ settingsLabel?: string;
27
+ /** Libellé « Se déconnecter ». */
28
+ logoutLabel?: string;
29
+ /**
30
+ * Variante d'affichage :
31
+ * - `dropdown` (défaut) : déclencheur + menu flottant (header desktop).
32
+ * - `accordion` : déclencheur + liste inline (tiroir mobile).
33
+ */
34
+ variant?: "dropdown" | "accordion";
35
+ class?: string;
36
+ }
37
+ /** Première lettre du displayName, en majuscule (calque de la source). */
38
+ export declare function identityInitial(user: IdentityUser | null | undefined): string;
39
+ declare const IdentityMenu: import("svelte").Component<IdentityMenuProps, {}, "open">;
40
+ type IdentityMenu = ReturnType<typeof IdentityMenu>;
41
+ export default IdentityMenu;
42
+ //# sourceMappingURL=IdentityMenu.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IdentityMenu.svelte.d.ts","sourceRoot":"","sources":["../src/lib/IdentityMenu.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAG7E;AAmJH,QAAA,MAAM,YAAY,2DAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}