@fylib/adapter-angular 0.1.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.
Files changed (75) hide show
  1. package/dist/base/base-component.d.ts +18 -0
  2. package/dist/base/base-component.js +36 -0
  3. package/dist/base/interaction.utils.d.ts +7 -0
  4. package/dist/base/interaction.utils.js +34 -0
  5. package/dist/base/interaction.utils.test.d.ts +1 -0
  6. package/dist/base/interaction.utils.test.js +25 -0
  7. package/dist/components/accordion.component.d.ts +32 -0
  8. package/dist/components/accordion.component.js +337 -0
  9. package/dist/components/badge.component.d.ts +10 -0
  10. package/dist/components/badge.component.js +112 -0
  11. package/dist/components/button.component.d.ts +33 -0
  12. package/dist/components/button.component.js +272 -0
  13. package/dist/components/card.component.d.ts +29 -0
  14. package/dist/components/card.component.js +236 -0
  15. package/dist/components/chart.component.d.ts +39 -0
  16. package/dist/components/chart.component.js +307 -0
  17. package/dist/components/icon.component.d.ts +18 -0
  18. package/dist/components/icon.component.js +144 -0
  19. package/dist/components/input.component.d.ts +50 -0
  20. package/dist/components/input.component.js +383 -0
  21. package/dist/components/modal.component.d.ts +46 -0
  22. package/dist/components/modal.component.js +404 -0
  23. package/dist/components/nav-link.component.d.ts +11 -0
  24. package/dist/components/nav-link.component.js +121 -0
  25. package/dist/components/notification-menu.component.d.ts +68 -0
  26. package/dist/components/notification-menu.component.js +695 -0
  27. package/dist/components/select.component.d.ts +52 -0
  28. package/dist/components/select.component.js +395 -0
  29. package/dist/components/table.component.d.ts +55 -0
  30. package/dist/components/table.component.js +643 -0
  31. package/dist/components/text.component.d.ts +8 -0
  32. package/dist/components/text.component.js +58 -0
  33. package/dist/components/toast.component.d.ts +27 -0
  34. package/dist/components/toast.component.js +260 -0
  35. package/dist/directives/animation.directive.d.ts +5 -0
  36. package/dist/directives/animation.directive.js +34 -0
  37. package/dist/directives/theme-vars.directive.d.ts +7 -0
  38. package/dist/directives/theme-vars.directive.js +70 -0
  39. package/dist/directives/wallpaper.directive.d.ts +28 -0
  40. package/dist/directives/wallpaper.directive.js +195 -0
  41. package/dist/effects/confetti.plugin.d.ts +1 -0
  42. package/dist/effects/confetti.plugin.js +151 -0
  43. package/dist/effects/extra-effects.plugin.d.ts +3 -0
  44. package/dist/effects/extra-effects.plugin.js +288 -0
  45. package/dist/effects/hearts.plugin.d.ts +1 -0
  46. package/dist/effects/hearts.plugin.js +172 -0
  47. package/dist/effects/register-all.d.ts +1 -0
  48. package/dist/effects/register-all.js +16 -0
  49. package/dist/effects/ui-effects.plugin.d.ts +1 -0
  50. package/dist/effects/ui-effects.plugin.js +134 -0
  51. package/dist/icons/providers/fontawesome.provider.d.ts +3 -0
  52. package/dist/icons/providers/fontawesome.provider.js +25 -0
  53. package/dist/icons/providers/mdi.provider.d.ts +3 -0
  54. package/dist/icons/providers/mdi.provider.js +13 -0
  55. package/dist/icons/providers/phosphor.provider.d.ts +3 -0
  56. package/dist/icons/providers/phosphor.provider.js +17 -0
  57. package/dist/icons/registry.d.ts +22 -0
  58. package/dist/icons/registry.js +12 -0
  59. package/dist/index.d.ts +29 -0
  60. package/dist/index.js +29 -0
  61. package/dist/layouts/layout.component.d.ts +24 -0
  62. package/dist/layouts/layout.component.js +255 -0
  63. package/dist/layouts/slot.component.d.ts +61 -0
  64. package/dist/layouts/slot.component.js +937 -0
  65. package/dist/providers.d.ts +12 -0
  66. package/dist/providers.js +18 -0
  67. package/dist/services/fylib.service.d.ts +31 -0
  68. package/dist/services/fylib.service.js +214 -0
  69. package/dist/services/notification.service.d.ts +27 -0
  70. package/dist/services/notification.service.js +118 -0
  71. package/dist/services/sse.service.d.ts +16 -0
  72. package/dist/services/sse.service.js +109 -0
  73. package/dist/services/webclient.service.d.ts +38 -0
  74. package/dist/services/webclient.service.js +144 -0
  75. package/package.json +43 -0
@@ -0,0 +1,937 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Component, Input, ViewEncapsulation, HostBinding, inject } from '@angular/core';
11
+ import { CommonModule } from '@angular/common';
12
+ import { FyLibService } from '../services/fylib.service';
13
+ import { FyIconComponent } from '../components/icon.component';
14
+ import { FyBadgeComponent } from '../components/badge.component';
15
+ import { resolveAnimationsActive, triggerEffectForEvent, styleString } from '../base/interaction.utils';
16
+ let FySlotComponent = class FySlotComponent {
17
+ get currentYear() {
18
+ return new Date().getFullYear();
19
+ }
20
+ get animationsDisabled() {
21
+ return !resolveAnimationsActive(this.fylib, 'fy-slot', this.activeAnimations);
22
+ }
23
+ get hostStyles() {
24
+ return styleString(this.customStyles);
25
+ }
26
+ get hostClass() {
27
+ const fixedClass = this.name === 'sidebar' && this.fixedSidebar ? ' fy-slot--sidebar-fixed' : '';
28
+ return `fy-slot fy-slot--${this.name}${fixedClass}`;
29
+ }
30
+ get computedHeaderLogoFilter() {
31
+ const mode = this.fylib.getMode?.() || 'light';
32
+ const target = mode === 'dark' ? this.headerLogoColorDark : this.headerLogoColorLight;
33
+ const base = this.filterFromTargetColor(target);
34
+ if (!base)
35
+ return null;
36
+ if (mode === 'dark') {
37
+ const op = this.getLogoDarkOpacity('header');
38
+ return `${base} opacity(${op})`;
39
+ }
40
+ return base;
41
+ }
42
+ get computedSidebarLogoFilter() {
43
+ const mode = this.fylib.getMode?.() || 'light';
44
+ const target = mode === 'dark'
45
+ ? this.sidebarLogoColorDark
46
+ : this.sidebarLogoColorLight;
47
+ const base = this.filterFromTargetColor(target);
48
+ if (!base)
49
+ return null;
50
+ if (mode === 'dark') {
51
+ const op = this.getLogoDarkOpacity('sidebar');
52
+ return `${base} opacity(${op})`;
53
+ }
54
+ return base;
55
+ }
56
+ filterFromTargetColor(color) {
57
+ if (!color)
58
+ return null;
59
+ const c = String(color).trim().toLowerCase();
60
+ if (c === 'white' || c === '#fff' || c === '#ffffff') {
61
+ return 'brightness(0) invert(1)';
62
+ }
63
+ if (c === 'black' || c === '#000' || c === '#000000') {
64
+ return 'brightness(0) saturate(100%)';
65
+ }
66
+ return null;
67
+ }
68
+ getLogoDarkOpacity(slot) {
69
+ const t = this.fylib.tokens();
70
+ const layout = (t?.layout || {});
71
+ const v = (layout?.[slot] || {})?.logoFilterDarkOpacity;
72
+ const num = parseFloat(String(v ?? '0.85'));
73
+ const safe = isNaN(num) ? 0.85 : Math.min(Math.max(num, 0), 1);
74
+ return String(safe);
75
+ }
76
+ toggleSidebar() {
77
+ if (this.name === 'sidebar' && resolveAnimationsActive(this.fylib, 'fy-slot', this.activeAnimations)) {
78
+ const event = this.sidebarOpen ? 'close' : 'open';
79
+ const animationName = this.fylib.getComponentAnimation('fy-slot:sidebar', event);
80
+ if (animationName) {
81
+ this.fylib.playAnimation(animationName);
82
+ }
83
+ const enabled = this.fylib.isEffectsEnabledFor('fy-slot:sidebar', this.activeEffects);
84
+ if (enabled) {
85
+ const inst = event === 'open' ? this.openEffect : this.closeEffect;
86
+ if (inst) {
87
+ this.fylib.triggerEffect(inst);
88
+ }
89
+ else {
90
+ triggerEffectForEvent(this.fylib, `fy-slot:sidebar.${event}`, 'fy-slot:sidebar', this.activeEffects);
91
+ }
92
+ }
93
+ }
94
+ this.sidebarOpen = !this.sidebarOpen;
95
+ this.updateBodyScroll();
96
+ const t = this.fylib.tokens();
97
+ const sidebarToggle = (t.layout || {}).sidebar?.toggle || {};
98
+ const openIcon = sidebarToggle.openIcon || 'x';
99
+ const closedIcon = sidebarToggle.icon || 'menu';
100
+ this.sidebarToggleIconName = this.sidebarOpen ? openIcon : closedIcon;
101
+ }
102
+ toggleHeaderMenu() {
103
+ if (this.name !== 'header') {
104
+ return;
105
+ }
106
+ const event = this.headerMenuOpen ? 'close' : 'open';
107
+ if (resolveAnimationsActive(this.fylib, 'fy-slot', this.activeAnimations)) {
108
+ const configured = this.fylib.getComponentAnimation('fy-slot:header', event);
109
+ const fallback = event === 'open' ? this.headerMenuAnimationOpen || undefined : this.headerMenuAnimationClose || undefined;
110
+ const animationName = configured || fallback;
111
+ if (animationName) {
112
+ this.fylib.playAnimation(animationName);
113
+ }
114
+ // Atribui classe CSS correspondente para animar o contêiner do header (mobile)
115
+ const nameToClass = {
116
+ 'sidebar-slide-in': 'fy-anim-header-menu-slide-in',
117
+ 'sidebar-slide-out': 'fy-anim-header-menu-slide-out',
118
+ 'sidebar-macos-slide-in': 'fy-anim-header-menu-macos-slide-in',
119
+ 'sidebar-macos-slide-out': 'fy-anim-header-menu-macos-slide-out',
120
+ 'header-menu-slide-in': 'fy-anim-header-menu-slide-in',
121
+ 'header-menu-slide-out': 'fy-anim-header-menu-slide-out',
122
+ 'header-menu-macos-slide-in': 'fy-anim-header-menu-macos-slide-in',
123
+ 'header-menu-macos-slide-out': 'fy-anim-header-menu-macos-slide-out'
124
+ };
125
+ const cls = animationName ? nameToClass[animationName] : undefined;
126
+ if (cls) {
127
+ this.headerMenuAnimClass = cls;
128
+ // limpa após o término para permitir re-disparo
129
+ setTimeout(() => { this.headerMenuAnimClass = ''; }, 350);
130
+ }
131
+ // Dispara efeito semântico para o header
132
+ triggerEffectForEvent(this.fylib, `fy-slot:header.${event}`, 'fy-slot:header', this.activeEffects);
133
+ }
134
+ this.headerMenuOpen = !this.headerMenuOpen;
135
+ this.updateBodyScroll();
136
+ const t = this.fylib.tokens();
137
+ const headerToggle = (t.layout || {}).header?.toggle || {};
138
+ const openIcon = headerToggle.openIcon || 'x';
139
+ const closedIcon = headerToggle.icon || 'menu';
140
+ this.headerToggleIconName = this.headerMenuOpen ? openIcon : closedIcon;
141
+ }
142
+ constructor() {
143
+ this.fylib = inject(FyLibService);
144
+ this.activeAnimations = null;
145
+ this.activeEffects = null;
146
+ this.customStyles = null;
147
+ this.fixedSidebar = null;
148
+ this.copyrightText = null;
149
+ this.copyrightShineDuration = '12s';
150
+ this.sidebarOpen = false;
151
+ this.headerMenuOpen = false;
152
+ this.headerToggleIconName = 'menu';
153
+ this.sidebarToggleIconName = 'menu';
154
+ this.sidebarToggleMode = 'floating';
155
+ this.sidebarTonguePos = 'bottom';
156
+ this.headerMenuAnimClass = '';
157
+ /** Deprecated: use fy-header-links-center/right slots */
158
+ this.headerLinksAlign = 'center';
159
+ this.sidebarLogoBadgeShine = false;
160
+ const t = this.fylib.tokens();
161
+ const headerToggle = (t.layout || {}).header?.toggle || {};
162
+ const sidebarToggle = (t.layout || {}).sidebar?.toggle || {};
163
+ this.headerToggleIconName = headerToggle.icon || 'menu';
164
+ this.sidebarToggleIconName = sidebarToggle.icon || 'menu';
165
+ this.sidebarToggleMode = sidebarToggle.mode || 'floating';
166
+ this.sidebarTonguePos = sidebarToggle.tonguePosition || 'bottom';
167
+ }
168
+ ngOnDestroy() {
169
+ if (typeof document !== 'undefined') {
170
+ document.body.classList.remove('fy-no-scroll');
171
+ }
172
+ }
173
+ resolveAnimationsActive() {
174
+ return resolveAnimationsActive(this.fylib, 'fy-slot', this.activeAnimations);
175
+ }
176
+ updateBodyScroll() {
177
+ if (typeof document === 'undefined')
178
+ return;
179
+ // Pequeno timeout para garantir que as classes de 'open' já estejam no DOM se necessário
180
+ setTimeout(() => {
181
+ const anyOpen = !!document.querySelector('.fy-slot__panel--open, .fy-slot__header-menus--open');
182
+ if (anyOpen && window.innerWidth <= 768) {
183
+ document.body.classList.add('fy-no-scroll');
184
+ }
185
+ else {
186
+ document.body.classList.remove('fy-no-scroll');
187
+ }
188
+ }, 0);
189
+ }
190
+ };
191
+ __decorate([
192
+ Input(),
193
+ __metadata("design:type", String)
194
+ ], FySlotComponent.prototype, "name", void 0);
195
+ __decorate([
196
+ Input(),
197
+ __metadata("design:type", Object)
198
+ ], FySlotComponent.prototype, "activeAnimations", void 0);
199
+ __decorate([
200
+ Input(),
201
+ __metadata("design:type", Object)
202
+ ], FySlotComponent.prototype, "activeEffects", void 0);
203
+ __decorate([
204
+ Input(),
205
+ __metadata("design:type", Object)
206
+ ], FySlotComponent.prototype, "customStyles", void 0);
207
+ __decorate([
208
+ Input(),
209
+ __metadata("design:type", Object)
210
+ ], FySlotComponent.prototype, "fixedSidebar", void 0);
211
+ __decorate([
212
+ Input(),
213
+ __metadata("design:type", Object)
214
+ ], FySlotComponent.prototype, "copyrightText", void 0);
215
+ __decorate([
216
+ Input(),
217
+ __metadata("design:type", String)
218
+ ], FySlotComponent.prototype, "copyrightShineDuration", void 0);
219
+ __decorate([
220
+ Input(),
221
+ __metadata("design:type", String)
222
+ ], FySlotComponent.prototype, "openEffect", void 0);
223
+ __decorate([
224
+ Input(),
225
+ __metadata("design:type", String)
226
+ ], FySlotComponent.prototype, "closeEffect", void 0);
227
+ __decorate([
228
+ Input(),
229
+ __metadata("design:type", Object)
230
+ ], FySlotComponent.prototype, "headerMenuAnimationOpen", void 0);
231
+ __decorate([
232
+ Input(),
233
+ __metadata("design:type", Object)
234
+ ], FySlotComponent.prototype, "headerMenuAnimationClose", void 0);
235
+ __decorate([
236
+ Input(),
237
+ __metadata("design:type", String)
238
+ ], FySlotComponent.prototype, "headerLinksAlign", void 0);
239
+ __decorate([
240
+ Input(),
241
+ __metadata("design:type", Object)
242
+ ], FySlotComponent.prototype, "headerLogoImgSrc", void 0);
243
+ __decorate([
244
+ Input(),
245
+ __metadata("design:type", Object)
246
+ ], FySlotComponent.prototype, "headerLogoSvgSrc", void 0);
247
+ __decorate([
248
+ Input(),
249
+ __metadata("design:type", Object)
250
+ ], FySlotComponent.prototype, "headerLogoAlt", void 0);
251
+ __decorate([
252
+ Input(),
253
+ __metadata("design:type", Object)
254
+ ], FySlotComponent.prototype, "headerLogoBadgeText", void 0);
255
+ __decorate([
256
+ Input(),
257
+ __metadata("design:type", Object)
258
+ ], FySlotComponent.prototype, "headerLogoBadgeBG", void 0);
259
+ __decorate([
260
+ Input(),
261
+ __metadata("design:type", Object)
262
+ ], FySlotComponent.prototype, "headerLogoBadgeTextColor", void 0);
263
+ __decorate([
264
+ Input(),
265
+ __metadata("design:type", Object)
266
+ ], FySlotComponent.prototype, "headerLogoBadgeRadius", void 0);
267
+ __decorate([
268
+ Input(),
269
+ __metadata("design:type", Object)
270
+ ], FySlotComponent.prototype, "headerLogoBadgeShine", void 0);
271
+ __decorate([
272
+ Input(),
273
+ __metadata("design:type", Object)
274
+ ], FySlotComponent.prototype, "headerLogoColorLight", void 0);
275
+ __decorate([
276
+ Input(),
277
+ __metadata("design:type", Object)
278
+ ], FySlotComponent.prototype, "headerLogoColorDark", void 0);
279
+ __decorate([
280
+ Input(),
281
+ __metadata("design:type", Object)
282
+ ], FySlotComponent.prototype, "sidebarLogoImgSrc", void 0);
283
+ __decorate([
284
+ Input(),
285
+ __metadata("design:type", Object)
286
+ ], FySlotComponent.prototype, "sidebarLogoSvgSrc", void 0);
287
+ __decorate([
288
+ Input(),
289
+ __metadata("design:type", Object)
290
+ ], FySlotComponent.prototype, "sidebarLogoAlt", void 0);
291
+ __decorate([
292
+ Input(),
293
+ __metadata("design:type", Object)
294
+ ], FySlotComponent.prototype, "headerLogoFilter", void 0);
295
+ __decorate([
296
+ Input(),
297
+ __metadata("design:type", Object)
298
+ ], FySlotComponent.prototype, "sidebarLogoFilter", void 0);
299
+ __decorate([
300
+ Input(),
301
+ __metadata("design:type", Object)
302
+ ], FySlotComponent.prototype, "sidebarLogoColorLight", void 0);
303
+ __decorate([
304
+ Input(),
305
+ __metadata("design:type", Object)
306
+ ], FySlotComponent.prototype, "sidebarLogoColorDark", void 0);
307
+ __decorate([
308
+ Input(),
309
+ __metadata("design:type", Object)
310
+ ], FySlotComponent.prototype, "sidebarLogoBadgeText", void 0);
311
+ __decorate([
312
+ Input(),
313
+ __metadata("design:type", Object)
314
+ ], FySlotComponent.prototype, "sidebarLogoBadgeBG", void 0);
315
+ __decorate([
316
+ Input(),
317
+ __metadata("design:type", Object)
318
+ ], FySlotComponent.prototype, "sidebarLogoBadgeTextColor", void 0);
319
+ __decorate([
320
+ Input(),
321
+ __metadata("design:type", Object)
322
+ ], FySlotComponent.prototype, "sidebarLogoBadgeRadius", void 0);
323
+ __decorate([
324
+ Input(),
325
+ __metadata("design:type", Object)
326
+ ], FySlotComponent.prototype, "sidebarLogoBadgeShine", void 0);
327
+ __decorate([
328
+ HostBinding('class.fy-animations-disabled'),
329
+ __metadata("design:type", Boolean),
330
+ __metadata("design:paramtypes", [])
331
+ ], FySlotComponent.prototype, "animationsDisabled", null);
332
+ __decorate([
333
+ HostBinding('style'),
334
+ __metadata("design:type", String),
335
+ __metadata("design:paramtypes", [])
336
+ ], FySlotComponent.prototype, "hostStyles", null);
337
+ FySlotComponent = __decorate([
338
+ Component({
339
+ selector: 'fy-slot',
340
+ standalone: true,
341
+ imports: [CommonModule, FyIconComponent, FyBadgeComponent],
342
+ template: `
343
+ <ng-template #projected>
344
+ <ng-content></ng-content>
345
+ </ng-template>
346
+
347
+ @switch (name) {
348
+ @case ('sidebar') {
349
+ <button
350
+ type="button"
351
+ class="fy-sidebar-toggle"
352
+ [class.fy-sidebar-toggle--tongue]="sidebarToggleMode === 'tongue'"
353
+ [attr.data-tongue-pos]="sidebarTonguePos"
354
+ (click)="toggleSidebar()"
355
+ >
356
+ <fy-icon [name]="sidebarToggleIconName"></fy-icon>
357
+ </button>
358
+ <div class="fy-slot__overlay" [class.fy-slot__overlay--open]="sidebarOpen" (click)="toggleSidebar()"></div>
359
+ <div class="fy-slot__panel" [class.fy-slot__panel--open]="sidebarOpen">
360
+ <div class="fy-slot__sidebar-inner">
361
+ @if (sidebarLogoImgSrc || sidebarLogoSvgSrc) {
362
+ <div class="fy-slot__sidebar-logo">
363
+ <div class="fy-logo">
364
+ <div class="fy-logo__image" [style.filter]="sidebarLogoFilter || computedSidebarLogoFilter || null">
365
+ @if (sidebarLogoImgSrc) {
366
+ <img [src]="sidebarLogoImgSrc" [alt]="sidebarLogoAlt || 'Logo'">
367
+ } @else if (sidebarLogoSvgSrc) {
368
+ <img [src]="sidebarLogoSvgSrc" [alt]="sidebarLogoAlt || 'Logo'">
369
+ }
370
+ </div>
371
+ @if (sidebarLogoBadgeText) {
372
+ <fy-badge
373
+ [text]="sidebarLogoBadgeText"
374
+ [background]="sidebarLogoBadgeBG ?? headerLogoBadgeBG ?? null"
375
+ [textColor]="sidebarLogoBadgeTextColor ?? headerLogoBadgeTextColor ?? null"
376
+ [borderRadius]="sidebarLogoBadgeRadius ?? headerLogoBadgeRadius ?? null"
377
+ [shine]="(sidebarLogoBadgeShine ?? headerLogoBadgeShine) ?? null"></fy-badge>
378
+ }
379
+ </div>
380
+ </div>
381
+ } @else {
382
+ <div class="fy-slot__sidebar-logo">
383
+ <div class="fy-logo">
384
+ <div class="fy-logo__image" [style.filter]="sidebarLogoFilter || computedSidebarLogoFilter || null">
385
+ <ng-content select="[fy-sidebar-logo]"></ng-content>
386
+ </div>
387
+ @if (sidebarLogoBadgeText) {
388
+ <fy-badge
389
+ [text]="sidebarLogoBadgeText"
390
+ [background]="sidebarLogoBadgeBG ?? headerLogoBadgeBG ?? null"
391
+ [textColor]="sidebarLogoBadgeTextColor ?? headerLogoBadgeTextColor ?? null"
392
+ [borderRadius]="sidebarLogoBadgeRadius ?? headerLogoBadgeRadius ?? null"
393
+ [shine]="(sidebarLogoBadgeShine ?? headerLogoBadgeShine) ?? null"></fy-badge>
394
+ }
395
+ </div>
396
+ </div>
397
+ }
398
+ <div class="fy-slot__sidebar-header">
399
+ <ng-content select="[fy-sidebar-header]"></ng-content>
400
+ </div>
401
+ <div class="fy-slot__sidebar-links">
402
+ <ng-content select="[fy-sidebar-links]"></ng-content>
403
+ </div>
404
+ <div class="fy-slot__sidebar-footer">
405
+ <ng-content select="[fy-sidebar-footer]"></ng-content>
406
+ @if (copyrightText) {
407
+ <div class="fy-slot__copyright" [style.--fy-copyright-shine-duration]="copyrightShineDuration">
408
+ <span class="fy-slot__copyright-text">&copy; {{ copyrightText }} · {{ currentYear }}</span>
409
+ </div>
410
+ }
411
+ </div>
412
+ </div>
413
+ </div>
414
+ }
415
+ @case ('header') {
416
+ <div class="fy-slot__overlay" [class.fy-slot__overlay--open]="headerMenuOpen" (click)="toggleHeaderMenu()"></div>
417
+ <header class="fy-slot__header-shell">
418
+ <div class="fy-slot__header-left">
419
+ @if (headerLogoImgSrc || headerLogoSvgSrc) {
420
+ <div class="fy-logo">
421
+ <div class="fy-logo__image" [style.filter]="headerLogoFilter || computedHeaderLogoFilter || null">
422
+ @if (headerLogoImgSrc) {
423
+ <img [src]="headerLogoImgSrc" [alt]="headerLogoAlt || 'Logo'">
424
+ } @else if (headerLogoSvgSrc) {
425
+ <img [src]="headerLogoSvgSrc" [alt]="headerLogoAlt || 'Logo'">
426
+ }
427
+ </div>
428
+ @if (headerLogoBadgeText) {
429
+ <fy-badge
430
+ [text]="headerLogoBadgeText"
431
+ [background]="headerLogoBadgeBG || null"
432
+ [textColor]="headerLogoBadgeTextColor || null"
433
+ [borderRadius]="headerLogoBadgeRadius || null"
434
+ [shine]="headerLogoBadgeShine ?? null"></fy-badge>
435
+ }
436
+ </div>
437
+ } @else {
438
+ <div class="fy-logo">
439
+ <div class="fy-logo__image" [style.filter]="headerLogoFilter || computedHeaderLogoFilter || null">
440
+ <ng-content select="[fy-header-logo]"></ng-content>
441
+ </div>
442
+ @if (headerLogoBadgeText) {
443
+ <fy-badge
444
+ [text]="headerLogoBadgeText"
445
+ [background]="headerLogoBadgeBG || null"
446
+ [textColor]="headerLogoBadgeTextColor || null"
447
+ [borderRadius]="headerLogoBadgeRadius || null"
448
+ [shine]="headerLogoBadgeShine ?? null"></fy-badge>
449
+ }
450
+ </div>
451
+ }
452
+ </div>
453
+ <div class="fy-slot__header-menus"
454
+ [class.fy-slot__header-menus--open]="headerMenuOpen"
455
+ [class.fy-anim-header-menu-slide-in]="headerMenuAnimClass==='fy-anim-header-menu-slide-in'"
456
+ [class.fy-anim-header-menu-slide-out]="headerMenuAnimClass==='fy-anim-header-menu-slide-out'"
457
+ [class.fy-anim-header-menu-macos-slide-in]="headerMenuAnimClass==='fy-anim-header-menu-macos-slide-in'"
458
+ [class.fy-anim-header-menu-macos-slide-out]="headerMenuAnimClass==='fy-anim-header-menu-macos-slide-out'">
459
+ <nav class="fy-slot__header-links fy-slot__header-links--center">
460
+ <ng-content select="[fy-header-links],[fy-header-links-center]"></ng-content>
461
+ </nav>
462
+ <nav class="fy-slot__header-links fy-slot__header-links--right">
463
+ <ng-content select="[fy-header-links-right]"></ng-content>
464
+ </nav>
465
+
466
+ <!-- Copyright dentro do menu no mobile -->
467
+ @if (copyrightText) {
468
+ <div class="fy-slot__copyright fy-slot__copyright--mobile" [style.--fy-copyright-shine-duration]="copyrightShineDuration">
469
+ <span class="fy-slot__copyright-text">&copy; {{ copyrightText }} · {{ currentYear }}</span>
470
+ </div>
471
+ }
472
+ </div>
473
+ <div class="fy-slot__header-meta">
474
+ <!-- Espaço para elementos meta projetados (como notification-menu) -->
475
+ <ng-content select="[fy-header-meta]"></ng-content>
476
+
477
+ <!-- Outros links de cabeçalho que não são meta -->
478
+ <div class="fy-slot__header-links-right-meta">
479
+ <ng-content select="[fy-header-links-right]"></ng-content>
480
+ </div>
481
+
482
+ <!-- Copyright fora do menu no desktop -->
483
+ @if (copyrightText) {
484
+ <div class="fy-slot__copyright fy-slot__copyright--desktop" [style.--fy-copyright-shine-duration]="copyrightShineDuration">
485
+ <span class="fy-slot__copyright-text">&copy; {{ copyrightText }} · {{ currentYear }}</span>
486
+ </div>
487
+ }
488
+ <button type="button" class="fy-slot__header-toggle" (click)="toggleHeaderMenu()">
489
+ <fy-icon [name]="sidebarToggleIconName"></fy-icon>
490
+ </button>
491
+ </div>
492
+ </header>
493
+ }
494
+
495
+ @default {
496
+ <ng-container [ngTemplateOutlet]="projected"></ng-container>
497
+ }
498
+ }
499
+ `,
500
+ host: {
501
+ '[style.grid-area]': 'name',
502
+ '[class]': 'hostClass',
503
+ '[attr.data-slot]': 'name'
504
+ },
505
+ styles: [`
506
+ .fy-slot { display: block; position: relative; }
507
+
508
+ body.fy-no-scroll {
509
+ overflow: hidden !important;
510
+ }
511
+
512
+ .fy-slot__overlay {
513
+ position: fixed;
514
+ top: 0;
515
+ left: 0;
516
+ width: 100vw;
517
+ height: 100vh;
518
+ background-color: rgba(0, 0, 0, 0.45);
519
+ opacity: 0;
520
+ pointer-events: none;
521
+ transition: opacity 0.25s ease;
522
+ z-index: 100;
523
+ }
524
+
525
+ .fy-slot__overlay--open {
526
+ opacity: 1;
527
+ pointer-events: auto;
528
+ }
529
+
530
+ .fy-slot--header {
531
+ z-index: 110;
532
+ min-height: var(--fy-layout-header-height, 64px);
533
+ padding: 0;
534
+ display: flex;
535
+ align-items: center;
536
+ }
537
+
538
+ .fy-slot__header-shell {
539
+ display: grid;
540
+ grid-auto-flow: column;
541
+ grid-template-columns: auto 1fr auto auto;
542
+ align-items: center;
543
+ gap: var(--fy-spacing-md, 16px);
544
+ width: 100%;
545
+ position: relative;
546
+ z-index: 110;
547
+ min-height: inherit;
548
+ padding: var(--fy-layout-header-padding, 0 24px);
549
+ background-color: var(--fy-layout-header-background, var(--fy-colors-surface, #fff));
550
+ border-bottom: 1px solid var(--fy-colors-border, rgba(0,0,0,0.08));
551
+ box-shadow: var(--fy-layout-header-shadow, 0 1px 0 rgba(0,0,0,0.06));
552
+ }
553
+
554
+ .fy-slot__header-left { display: flex; align-items: center; gap: var(--fy-spacing-md, 16px); flex-shrink: 0; }
555
+ .fy-slot__header-menus { display: contents; }
556
+ .fy-slot__header-links {
557
+ display: flex;
558
+ align-items: center;
559
+ gap: var(--fy-spacing-md, 16px);
560
+ min-width: 0;
561
+ width: max-content;
562
+ }
563
+ .fy-slot__header-links.fy-slot__header-links--left { justify-self: start; justify-content: flex-start; }
564
+ .fy-slot__header-links.fy-slot__header-links--center { justify-self: center; justify-content: center; }
565
+ .fy-slot__header-links.fy-slot__header-links--right { justify-self: end; justify-content: flex-end; }
566
+ .fy-slot__header-left .fy-logo { position: relative; display: inline-block; }
567
+ .fy-slot__header-left .fy-logo__image img,
568
+ .fy-slot__header-left .fy-logo__image svg { display: block; height: 28px; width: auto; }
569
+ .fy-slot__header-left .fy-logo fy-badge { position: absolute; top: -6px; right: -6px; z-index: 1; }
570
+ .fy-slot__header-left .fy-logo fy-badge .fy-badge { position: static; }
571
+
572
+ .fy-slot__header-meta {
573
+ display: flex;
574
+ align-items: center;
575
+ gap: var(--fy-spacing-md, 16px);
576
+ flex-shrink: 0;
577
+ }
578
+
579
+ .fy-slot__header-links-right-meta {
580
+ display: none;
581
+ }
582
+
583
+ .fy-slot__header-meta ::ng-deep fy-notification-menu {
584
+ display: block;
585
+ }
586
+
587
+ .fy-slot__header-toggle {
588
+ display: none;
589
+ width: 40px;
590
+ height: 40px;
591
+ border-radius: var(--fy-layout-header-toggle-borderRadius, 999px);
592
+ border: 1px solid var(--fy-layout-header-toggle-borderColor, transparent);
593
+ background-color: var(--fy-layout-header-toggle-background, var(--fy-colors-primary, #2563eb));
594
+ color: var(--fy-layout-header-toggle-textColor, #fff);
595
+ align-items: center;
596
+ justify-content: center;
597
+ cursor: pointer;
598
+ font-size: 18px;
599
+ }
600
+
601
+ .fy-slot__header-toggle .fy-icon { font-size: 18px; }
602
+ .fy-slot__header-shell {
603
+ color: var(--fy-colors-textOverlay, var(--fy-colors-text));
604
+ }
605
+ .fy-slot--header .fy-nav-link {
606
+ color: var(--fy-colors-textOverlay, var(--fy-colors-text));
607
+ }
608
+
609
+ .fy-slot--sidebar {
610
+ min-width: var(--fy-layout-sidebar-width, 260px);
611
+ padding: var(--fy-layout-sidebar-padding, 16px 0);
612
+ border-right: 1px solid var(--fy-colors-border, rgba(0,0,0,0.1));
613
+ background-color: var(--fy-layout-sidebar-background, var(--fy-colors-surface, transparent));
614
+ }
615
+
616
+ .fy-slot--sidebar-fixed {
617
+ height: 100%;
618
+ max-height: 100%;
619
+ overflow: hidden;
620
+ display: flex;
621
+ flex-direction: column;
622
+ }
623
+
624
+ .fy-slot--sidebar .fy-slot__panel {
625
+ height: 100%;
626
+ display: block;
627
+ background-color: var(--fy-layout-sidebar-background, var(--fy-colors-surface, #fff));
628
+ box-shadow: var(--fy-layout-sidebar-shadow, none);
629
+ color: var(--fy-colors-textOverlay, var(--fy-colors-text, inherit));
630
+ }
631
+
632
+ .fy-slot__sidebar-inner {
633
+ height: 100%;
634
+ display: flex;
635
+ flex-direction: column;
636
+ }
637
+ .fy-slot__sidebar-logo {
638
+ padding: var(--fy-spacing-md, 16px);
639
+ border-bottom: 1px solid var(--fy-colors-border, rgba(0,0,0,0.08));
640
+ color: var(--fy-colors-textOverlay, var(--fy-colors-text));
641
+ }
642
+ .fy-slot__sidebar-logo .fy-logo {
643
+ position: relative;
644
+ display: inline-block;
645
+ color: var(--fy-colors-textOverlay, var(--fy-colors-text));
646
+ }
647
+ .fy-slot__sidebar-logo .fy-logo__image img,
648
+ .fy-slot__sidebar-logo .fy-logo__image svg {
649
+ display: block;
650
+ height: 32px;
651
+ width: auto;
652
+ }
653
+ .fy-slot__sidebar-logo .fy-logo fy-badge { position: absolute; top: -6px; right: -6px; z-index: 1; }
654
+ .fy-slot__sidebar-logo .fy-logo fy-badge .fy-badge { position: static; }
655
+
656
+ .fy-slot__sidebar-links {
657
+ flex: 1 1 auto;
658
+ overflow-y: auto;
659
+ padding-inline: var(--fy-spacing-md, 16px);
660
+ padding-top: var(--fy-spacing-md, 16px);
661
+ padding-bottom: var(--fy-spacing-md, 16px);
662
+ display: flex;
663
+ flex-direction: column;
664
+ gap: var(--fy-spacing-sm, 8px);
665
+ }
666
+ .fy-slot__sidebar-links > * {
667
+ display: flex;
668
+ flex-direction: column;
669
+ gap: var(--fy-spacing-sm, 8px);
670
+ }
671
+ .fy-slot--sidebar .fy-nav-link {
672
+ width: 100%;
673
+ color: var(--fy-colors-textOverlay, var(--fy-colors-text));
674
+ }
675
+
676
+ .fy-slot__sidebar-footer {
677
+ flex-shrink: 0;
678
+ border-top: 1px solid var(--fy-colors-border, rgba(0,0,0,0.08));
679
+ padding: var(--fy-spacing-md, 16px);
680
+ display: flex;
681
+ flex-direction: column;
682
+ gap: var(--fy-spacing-sm, 8px);
683
+ }
684
+
685
+ .fy-slot__copyright--mobile { display: none; }
686
+ .fy-slot__copyright--desktop { display: block; }
687
+
688
+ .fy-slot__copyright {
689
+ font-size: var(--fy-typography-fontSize-sm, 12px);
690
+ color: var(--fy-colors-secondary, #6b7280);
691
+ }
692
+
693
+ .fy-slot__copyright-text {
694
+ position: relative;
695
+ display: inline-block;
696
+ font-weight: var(--fy-typography-fontWeight-bold, 600);
697
+ background: linear-gradient(
698
+ 120deg,
699
+ var(--fy-colors-secondary, #6b7280) 0%,
700
+ var(--fy-colors-secondary, #6b7280) 40%,
701
+ var(--fy-colors-white, #ffffff) 50%,
702
+ var(--fy-colors-secondary, #6b7280) 60%,
703
+ var(--fy-colors-secondary, #6b7280) 100%
704
+ );
705
+ background-size: 200% auto;
706
+ -webkit-background-clip: text;
707
+ -webkit-text-fill-color: transparent;
708
+ color: transparent;
709
+ animation: fy-copyright-shine var(--fy-copyright-shine-duration, 12s) linear infinite;
710
+ }
711
+
712
+ @keyframes fy-copyright-shine {
713
+ 0% { background-position: 200% center; }
714
+ 100% { background-position: -200% center; }
715
+ }
716
+
717
+ .fy-animations-disabled .fy-slot__copyright-text {
718
+ animation: none;
719
+ background: none;
720
+ -webkit-background-clip: initial;
721
+ -webkit-text-fill-color: initial;
722
+ color: var(--fy-colors-secondary, #6b7280);
723
+ }
724
+
725
+ .fy-sidebar-toggle {
726
+ display: none;
727
+ border-radius: var(--fy-layout-sidebar-toggle-borderRadius, 999px);
728
+ background-color: var(--fy-layout-sidebar-toggle-background, var(--fy-colors-primary, #2563eb));
729
+ color: var(--fy-layout-sidebar-toggle-textColor, #fff);
730
+ }
731
+
732
+ .fy-slot--content {
733
+ padding: var(--fy-layout-content-padding, var(--fy-spacing-lg, 24px));
734
+ overflow-y: auto;
735
+ }
736
+
737
+ @keyframes fy-copyright-shimmer {
738
+ 0% {
739
+ background-position: 0% 50%;
740
+ }
741
+ 50% {
742
+ background-position: 100% 50%;
743
+ }
744
+ 100% {
745
+ background-position: 0% 50%;
746
+ }
747
+ }
748
+
749
+ @media (max-width: 768px) {
750
+ .fy-slot--header {
751
+ padding: 0;
752
+ }
753
+ .fy-slot__header-shell {
754
+ align-items: center;
755
+ padding: 0 var(--fy-spacing-md, 16px);
756
+ background-color: var(--fy-layout-header-background, var(--fy-colors-surface, #ffffff));
757
+ z-index: 110;
758
+ }
759
+ .fy-slot__header-left {
760
+ flex: 0 0 auto;
761
+ position: relative;
762
+ z-index: 110;
763
+ }
764
+ .fy-slot__header-menus {
765
+ position: absolute;
766
+ top: 100%;
767
+ left: 0;
768
+ right: 0;
769
+ width: 100vw;
770
+ display: flex;
771
+ flex-direction: column;
772
+ align-items: center;
773
+ background-color: inherit;
774
+ border-bottom: 1px solid var(--fy-colors-border, rgba(0,0,0,0.08));
775
+ padding: var(--fy-spacing-md, 16px);
776
+ max-height: 0;
777
+ overflow: hidden;
778
+ opacity: 0;
779
+ transform: translateY(-8px);
780
+ transition: max-height 0.25s ease, opacity 0.25s ease, transform 0.25s ease;
781
+ z-index: 110;
782
+ gap: var(--fy-spacing-lg, 24px);
783
+ }
784
+ .fy-slot__header-menus--open {
785
+ max-height: 80vh;
786
+ opacity: 1;
787
+ transform: translateY(0);
788
+ overflow: visible;
789
+ }
790
+ .fy-slot__header-links {
791
+ display: flex;
792
+ flex-direction: column;
793
+ gap: var(--fy-spacing-md, 16px);
794
+ width: 100%;
795
+ align-items: stretch;
796
+ }
797
+ .fy-slot__header-links .fy-nav-link {
798
+ width: 100%;
799
+ justify-content: center;
800
+ }
801
+
802
+ .fy-slot__header-meta {
803
+ flex: 1;
804
+ justify-content: flex-end;
805
+ position: relative;
806
+ z-index: 110;
807
+ }
808
+
809
+ .fy-slot__header-links-right-meta {
810
+ display: block !important;
811
+ width: 100%;
812
+ }
813
+
814
+ .fy-slot__header-links-right-meta .fy-nav-link {
815
+ width: 100%;
816
+ justify-content: center;
817
+ }
818
+
819
+ .fy-slot__header-meta ::ng-deep fy-notification-menu {
820
+ display: block !important;
821
+ }
822
+
823
+ .fy-slot__header-menus ::ng-deep fy-notification-menu {
824
+ display: none !important;
825
+ }
826
+
827
+ .fy-slot__copyright--mobile {
828
+ display: block;
829
+ margin-top: auto;
830
+ padding-top: var(--fy-spacing-md);
831
+ border-top: 1px solid var(--fy-colors-border, rgba(0,0,0,0.05));
832
+ width: 100%;
833
+ text-align: center;
834
+ }
835
+ .fy-slot__copyright--desktop {
836
+ display: none;
837
+ }
838
+
839
+ .fy-slot__header-toggle {
840
+ display: inline-flex;
841
+ }
842
+ .fy-slot--sidebar {
843
+ height: 0;
844
+ grid-area: unset !important;
845
+ min-width: 0 !important;
846
+ width: 0 !important;
847
+ overflow: hidden !important;
848
+ }
849
+
850
+ .fy-slot--sidebar .fy-slot__panel {
851
+ position: fixed;
852
+ top: 0;
853
+ left: 0;
854
+ bottom: 0;
855
+ width: var(--fy-layout-sidebar-width, 260px);
856
+ max-width: 80vw;
857
+ background-color: var(--fy-colors-surface, #fff);
858
+ transform: translateX(-100%);
859
+ opacity: 0;
860
+ transition: transform 0.25s ease-out, opacity 0.25s ease-out;
861
+ z-index: 110;
862
+ overflow-y: auto;
863
+ pointer-events: none;
864
+ }
865
+
866
+ .fy-slot--sidebar .fy-slot__panel.fy-slot__panel--open {
867
+ transform: translateX(0);
868
+ opacity: 1;
869
+ box-shadow: 0 10px 40px rgba(0,0,0,0.35);
870
+ pointer-events: auto;
871
+ }
872
+
873
+ .fy-layout--app-layout .fy-slot--content {
874
+ width: 100%;
875
+ }
876
+
877
+ .fy-sidebar-toggle {
878
+ position: fixed;
879
+ bottom: 16px;
880
+ left: 16px;
881
+ width: 40px;
882
+ height: 40px;
883
+ border-radius: var(--fy-layout-sidebar-toggle-borderRadius, 999px);
884
+ border: 1px solid var(--fy-layout-sidebar-toggle-borderColor, transparent);
885
+ display: inline-flex;
886
+ align-items: center;
887
+ justify-content: center;
888
+ background-color: var(--fy-layout-sidebar-toggle-background, var(--fy-colors-primary, #2563eb));
889
+ color: var(--fy-layout-sidebar-toggle-textColor, #fff);
890
+ box-shadow: 0 8px 24px rgba(0,0,0,0.2);
891
+ cursor: pointer;
892
+ z-index: 120;
893
+ }
894
+
895
+ .fy-sidebar-toggle.fy-sidebar-toggle--tongue {
896
+ left: 0;
897
+ transform: translateX(-50%);
898
+ bottom: auto;
899
+ }
900
+ .fy-sidebar-toggle.fy-sidebar-toggle--tongue[data-tongue-pos="top"] { top: 16px; }
901
+ .fy-sidebar-toggle.fy-sidebar-toggle--tongue[data-tongue-pos="middle"] { top: 50%; transform: translate(-50%, -50%); }
902
+ .fy-sidebar-toggle.fy-sidebar-toggle--tongue[data-tongue-pos="bottom"] { top: auto; bottom: 16px; }
903
+
904
+ .fy-sidebar-toggle span {
905
+ display: inline;
906
+ }
907
+
908
+ .fy-sidebar-toggle .fy-icon { font-size: 18px; }
909
+ }
910
+
911
+ @media (min-width: 769px) {
912
+ .fy-slot__header-menus { display: contents; }
913
+ .fy-slot__header-links { max-height: none; opacity: 1; transform: none; position: static; padding: 0; border: 0; display: flex; }
914
+
915
+ .fy-slot__header-toggle {
916
+ display: none;
917
+ }
918
+ .fy-slot--sidebar .fy-slot__panel {
919
+ position: relative;
920
+ transform: none;
921
+ box-shadow: none;
922
+ width: 100%;
923
+ max-width: none;
924
+ opacity: 1;
925
+ pointer-events: auto;
926
+ }
927
+
928
+ .fy-sidebar-toggle {
929
+ display: none;
930
+ }
931
+ }
932
+ `],
933
+ encapsulation: ViewEncapsulation.None
934
+ }),
935
+ __metadata("design:paramtypes", [])
936
+ ], FySlotComponent);
937
+ export { FySlotComponent };