@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.
- package/dist/base/base-component.d.ts +18 -0
- package/dist/base/base-component.js +36 -0
- package/dist/base/interaction.utils.d.ts +7 -0
- package/dist/base/interaction.utils.js +34 -0
- package/dist/base/interaction.utils.test.d.ts +1 -0
- package/dist/base/interaction.utils.test.js +25 -0
- package/dist/components/accordion.component.d.ts +32 -0
- package/dist/components/accordion.component.js +337 -0
- package/dist/components/badge.component.d.ts +10 -0
- package/dist/components/badge.component.js +112 -0
- package/dist/components/button.component.d.ts +33 -0
- package/dist/components/button.component.js +272 -0
- package/dist/components/card.component.d.ts +29 -0
- package/dist/components/card.component.js +236 -0
- package/dist/components/chart.component.d.ts +39 -0
- package/dist/components/chart.component.js +307 -0
- package/dist/components/icon.component.d.ts +18 -0
- package/dist/components/icon.component.js +144 -0
- package/dist/components/input.component.d.ts +50 -0
- package/dist/components/input.component.js +383 -0
- package/dist/components/modal.component.d.ts +46 -0
- package/dist/components/modal.component.js +404 -0
- package/dist/components/nav-link.component.d.ts +11 -0
- package/dist/components/nav-link.component.js +121 -0
- package/dist/components/notification-menu.component.d.ts +68 -0
- package/dist/components/notification-menu.component.js +695 -0
- package/dist/components/select.component.d.ts +52 -0
- package/dist/components/select.component.js +395 -0
- package/dist/components/table.component.d.ts +55 -0
- package/dist/components/table.component.js +643 -0
- package/dist/components/text.component.d.ts +8 -0
- package/dist/components/text.component.js +58 -0
- package/dist/components/toast.component.d.ts +27 -0
- package/dist/components/toast.component.js +260 -0
- package/dist/directives/animation.directive.d.ts +5 -0
- package/dist/directives/animation.directive.js +34 -0
- package/dist/directives/theme-vars.directive.d.ts +7 -0
- package/dist/directives/theme-vars.directive.js +70 -0
- package/dist/directives/wallpaper.directive.d.ts +28 -0
- package/dist/directives/wallpaper.directive.js +195 -0
- package/dist/effects/confetti.plugin.d.ts +1 -0
- package/dist/effects/confetti.plugin.js +151 -0
- package/dist/effects/extra-effects.plugin.d.ts +3 -0
- package/dist/effects/extra-effects.plugin.js +288 -0
- package/dist/effects/hearts.plugin.d.ts +1 -0
- package/dist/effects/hearts.plugin.js +172 -0
- package/dist/effects/register-all.d.ts +1 -0
- package/dist/effects/register-all.js +16 -0
- package/dist/effects/ui-effects.plugin.d.ts +1 -0
- package/dist/effects/ui-effects.plugin.js +134 -0
- package/dist/icons/providers/fontawesome.provider.d.ts +3 -0
- package/dist/icons/providers/fontawesome.provider.js +25 -0
- package/dist/icons/providers/mdi.provider.d.ts +3 -0
- package/dist/icons/providers/mdi.provider.js +13 -0
- package/dist/icons/providers/phosphor.provider.d.ts +3 -0
- package/dist/icons/providers/phosphor.provider.js +17 -0
- package/dist/icons/registry.d.ts +22 -0
- package/dist/icons/registry.js +12 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +29 -0
- package/dist/layouts/layout.component.d.ts +24 -0
- package/dist/layouts/layout.component.js +255 -0
- package/dist/layouts/slot.component.d.ts +61 -0
- package/dist/layouts/slot.component.js +937 -0
- package/dist/providers.d.ts +12 -0
- package/dist/providers.js +18 -0
- package/dist/services/fylib.service.d.ts +31 -0
- package/dist/services/fylib.service.js +214 -0
- package/dist/services/notification.service.d.ts +27 -0
- package/dist/services/notification.service.js +118 -0
- package/dist/services/sse.service.d.ts +16 -0
- package/dist/services/sse.service.js +109 -0
- package/dist/services/webclient.service.d.ts +38 -0
- package/dist/services/webclient.service.js +144 -0
- package/package.json +43 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InjectionToken, EnvironmentProviders } from '@angular/core';
|
|
2
|
+
import { AppConfig } from '@fylib/config';
|
|
3
|
+
/**
|
|
4
|
+
* Injection Token para a configuração global do fyLib no Angular.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FYLIB_CONFIG: InjectionToken<Partial<AppConfig>>;
|
|
7
|
+
/**
|
|
8
|
+
* Provedor de ambiente para inicializar o fyLib com uma configuração customizada.
|
|
9
|
+
*
|
|
10
|
+
* @param config Configuração parcial do fyLib (temas, animações, logs, sse, etc).
|
|
11
|
+
*/
|
|
12
|
+
export declare function provideFyLib(config: Partial<AppConfig>): EnvironmentProviders;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InjectionToken, makeEnvironmentProviders } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Injection Token para a configuração global do fyLib no Angular.
|
|
4
|
+
*/
|
|
5
|
+
export const FYLIB_CONFIG = new InjectionToken('FYLIB_CONFIG');
|
|
6
|
+
/**
|
|
7
|
+
* Provedor de ambiente para inicializar o fyLib com uma configuração customizada.
|
|
8
|
+
*
|
|
9
|
+
* @param config Configuração parcial do fyLib (temas, animações, logs, sse, etc).
|
|
10
|
+
*/
|
|
11
|
+
export function provideFyLib(config) {
|
|
12
|
+
return makeEnvironmentProviders([
|
|
13
|
+
{
|
|
14
|
+
provide: FYLIB_CONFIG,
|
|
15
|
+
useValue: config
|
|
16
|
+
}
|
|
17
|
+
]);
|
|
18
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Signal } from '@angular/core';
|
|
2
|
+
import { AppConfig, ComponentSelector, UIEventKey } from '@fylib/config';
|
|
3
|
+
import { DesignTokens } from '@fylib/core';
|
|
4
|
+
export declare class FyLibService {
|
|
5
|
+
private platformId;
|
|
6
|
+
private configSignal;
|
|
7
|
+
private themeVersion;
|
|
8
|
+
readonly config: Signal<AppConfig>;
|
|
9
|
+
readonly tokens: Signal<DesignTokens>;
|
|
10
|
+
constructor(configFromProvider: Partial<AppConfig>);
|
|
11
|
+
private watchConfigFile;
|
|
12
|
+
setTheme(name: string): void;
|
|
13
|
+
setMode(mode: 'light' | 'dark'): void;
|
|
14
|
+
getMode(): import("@fylib/theme").ThemeMode;
|
|
15
|
+
getTokens(): DesignTokens;
|
|
16
|
+
getThemeBackgroundEffect(): {
|
|
17
|
+
name: string;
|
|
18
|
+
intensity?: number;
|
|
19
|
+
speed?: number;
|
|
20
|
+
loop?: boolean;
|
|
21
|
+
} | undefined;
|
|
22
|
+
getThemeWallpaper(): import("@fylib/core").WallpaperDefinition | undefined;
|
|
23
|
+
triggerEffect(name: string, params?: Record<string, any>): void;
|
|
24
|
+
triggerEffectForEvent(eventKey: UIEventKey, componentSelector?: ComponentSelector, instanceFlag?: boolean | null): void;
|
|
25
|
+
playAnimation(name: string): void;
|
|
26
|
+
isAnimationsEnabledFor(componentSelector: ComponentSelector): boolean;
|
|
27
|
+
isEffectsEnabledFor(componentSelector: ComponentSelector, instanceFlag: boolean | null | undefined): boolean;
|
|
28
|
+
getComponentAnimation(componentSelector: ComponentSelector, event: string): string | undefined;
|
|
29
|
+
private deepMerge;
|
|
30
|
+
private isObject;
|
|
31
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Injectable, signal, computed, inject, PLATFORM_ID, Optional, Inject } from '@angular/core';
|
|
14
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
15
|
+
import { themeEngine, defaultTheme } from '@fylib/theme';
|
|
16
|
+
import { animationEngine } from '@fylib/animation';
|
|
17
|
+
import { configManager } from '@fylib/config';
|
|
18
|
+
import { logger } from '@fylib/logger';
|
|
19
|
+
import { registerAllEffects } from '../effects/register-all';
|
|
20
|
+
import { FYLIB_CONFIG } from '../providers';
|
|
21
|
+
import { registerPhosphorProvider } from '../icons/providers/phosphor.provider';
|
|
22
|
+
import { registerFontAwesomeProvider } from '../icons/providers/fontawesome.provider';
|
|
23
|
+
import { registerMdiProvider } from '../icons/providers/mdi.provider';
|
|
24
|
+
let FyLibService = class FyLibService {
|
|
25
|
+
constructor(configFromProvider) {
|
|
26
|
+
this.platformId = inject(PLATFORM_ID);
|
|
27
|
+
this.configSignal = signal(configManager.getConfig());
|
|
28
|
+
this.themeVersion = signal(0);
|
|
29
|
+
this.config = this.configSignal.asReadonly();
|
|
30
|
+
this.tokens = computed(() => {
|
|
31
|
+
this.themeVersion();
|
|
32
|
+
try {
|
|
33
|
+
return themeEngine.getTokens();
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
return defaultTheme.tokens;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// Se existir configuração via provider (provideFyLib), aplica imediatamente
|
|
40
|
+
// ANTES de qualquer outro log para garantir que o estado do logger (enabled/disabled) seja respeitado
|
|
41
|
+
if (configFromProvider) {
|
|
42
|
+
configManager.updateConfig(configFromProvider);
|
|
43
|
+
}
|
|
44
|
+
logger.info('AngularAdapter', 'FyLibService initialized');
|
|
45
|
+
// Garante que o tema padrão esteja registrado
|
|
46
|
+
try {
|
|
47
|
+
themeEngine.registerTheme(defaultTheme);
|
|
48
|
+
}
|
|
49
|
+
catch (e) { }
|
|
50
|
+
themeEngine.registerPlugin({
|
|
51
|
+
name: 'config-token-overrides',
|
|
52
|
+
apply: (tokens) => {
|
|
53
|
+
const config = this.configSignal();
|
|
54
|
+
const overrides = config.theme?.tokenOverrides;
|
|
55
|
+
if (!overrides) {
|
|
56
|
+
return tokens;
|
|
57
|
+
}
|
|
58
|
+
return this.deepMerge(tokens, overrides);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Providers de ícones default
|
|
62
|
+
try {
|
|
63
|
+
registerPhosphorProvider();
|
|
64
|
+
}
|
|
65
|
+
catch (e) { }
|
|
66
|
+
try {
|
|
67
|
+
registerFontAwesomeProvider();
|
|
68
|
+
}
|
|
69
|
+
catch (e) { }
|
|
70
|
+
try {
|
|
71
|
+
registerMdiProvider();
|
|
72
|
+
}
|
|
73
|
+
catch (e) { }
|
|
74
|
+
// Sincroniza tema se mudou
|
|
75
|
+
configManager.subscribe(config => {
|
|
76
|
+
if (!config)
|
|
77
|
+
return;
|
|
78
|
+
const oldConfig = this.configSignal();
|
|
79
|
+
this.configSignal.set(config);
|
|
80
|
+
const themeName = config.theme?.theme;
|
|
81
|
+
if (themeName && themeName !== oldConfig.theme?.theme) {
|
|
82
|
+
try {
|
|
83
|
+
this.setTheme(themeName);
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
logger.error('Theme', `Erro ao carregar tema: ${themeName}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
91
|
+
registerAllEffects();
|
|
92
|
+
// Regra de precedência:
|
|
93
|
+
// 1. Se __FYLIB_DISABLE_CONFIG_POLL__ estiver ativo no window, desabilita.
|
|
94
|
+
// 2. Se houver configuração vinda do provider (e não for um objeto vazio),
|
|
95
|
+
// o provider "vence" e desabilita o polling automático por padrão.
|
|
96
|
+
const hasProviderConfig = configFromProvider && Object.keys(configFromProvider).length > 0;
|
|
97
|
+
const disablePoll = (typeof window !== 'undefined' && window.__FYLIB_DISABLE_CONFIG_POLL__ === true) ||
|
|
98
|
+
hasProviderConfig;
|
|
99
|
+
if (!disablePoll) {
|
|
100
|
+
this.watchConfigFile();
|
|
101
|
+
}
|
|
102
|
+
else if (hasProviderConfig) {
|
|
103
|
+
logger.info('AngularAdapter', 'Polling desabilitado: utilizando configuração estática do provider');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async watchConfigFile() {
|
|
108
|
+
const fetchConfig = async () => {
|
|
109
|
+
try {
|
|
110
|
+
const response = await fetch('/fylib/theme-control/theme-controller.json');
|
|
111
|
+
if (response.ok) {
|
|
112
|
+
const newConfig = await response.json();
|
|
113
|
+
configManager.updateConfig(newConfig);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
// Arquivo pode não existir ainda
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
fetchConfig();
|
|
121
|
+
setInterval(fetchConfig, 3000); // Polling a cada 3s para exemplo
|
|
122
|
+
}
|
|
123
|
+
setTheme(name) {
|
|
124
|
+
themeEngine.setTheme(name);
|
|
125
|
+
this.themeVersion.update(v => v + 1);
|
|
126
|
+
}
|
|
127
|
+
setMode(mode) {
|
|
128
|
+
themeEngine.setMode(mode);
|
|
129
|
+
this.themeVersion.update(v => v + 1);
|
|
130
|
+
}
|
|
131
|
+
getMode() {
|
|
132
|
+
return themeEngine.getMode();
|
|
133
|
+
}
|
|
134
|
+
getTokens() {
|
|
135
|
+
return themeEngine.getTokens();
|
|
136
|
+
}
|
|
137
|
+
getThemeBackgroundEffect() {
|
|
138
|
+
return themeEngine.getBackgroundEffect();
|
|
139
|
+
}
|
|
140
|
+
getThemeWallpaper() {
|
|
141
|
+
return themeEngine.getWallpaper();
|
|
142
|
+
}
|
|
143
|
+
triggerEffect(name, params) {
|
|
144
|
+
animationEngine.triggerEffect(name, params);
|
|
145
|
+
}
|
|
146
|
+
triggerEffectForEvent(eventKey, componentSelector, instanceFlag) {
|
|
147
|
+
const config = this.configSignal();
|
|
148
|
+
const effectNameFromConfig = config.theme?.effectTriggers?.[eventKey];
|
|
149
|
+
if (effectNameFromConfig) {
|
|
150
|
+
this.triggerEffect(effectNameFromConfig);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
playAnimation(name) {
|
|
154
|
+
animationEngine.playAnimation(name);
|
|
155
|
+
}
|
|
156
|
+
isAnimationsEnabledFor(componentSelector) {
|
|
157
|
+
const config = this.configSignal();
|
|
158
|
+
if (!config.theme?.animationsEnabled)
|
|
159
|
+
return false;
|
|
160
|
+
if (config.theme?.disableAnimationsForComponents?.includes(componentSelector))
|
|
161
|
+
return false;
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
isEffectsEnabledFor(componentSelector, instanceFlag) {
|
|
165
|
+
const config = this.configSignal();
|
|
166
|
+
if (config.theme?.effectsEnabled === false)
|
|
167
|
+
return false;
|
|
168
|
+
if (config.theme?.disableEffectsForComponents?.includes(componentSelector))
|
|
169
|
+
return false;
|
|
170
|
+
if (instanceFlag === false)
|
|
171
|
+
return false;
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
getComponentAnimation(componentSelector, event) {
|
|
175
|
+
const config = this.configSignal();
|
|
176
|
+
const byComponent = config.theme?.componentAnimationsOverrides?.[componentSelector];
|
|
177
|
+
const override = byComponent ? byComponent[event] : undefined;
|
|
178
|
+
if (override) {
|
|
179
|
+
return override;
|
|
180
|
+
}
|
|
181
|
+
return themeEngine.getComponentAnimation(componentSelector, event);
|
|
182
|
+
}
|
|
183
|
+
deepMerge(target, source) {
|
|
184
|
+
const output = { ...target };
|
|
185
|
+
if (this.isObject(target) && this.isObject(source)) {
|
|
186
|
+
Object.keys(source).forEach(key => {
|
|
187
|
+
if (this.isObject(source[key])) {
|
|
188
|
+
if (!(key in target)) {
|
|
189
|
+
Object.assign(output, { [key]: source[key] });
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
output[key] = this.deepMerge(target[key], source[key]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
Object.assign(output, { [key]: source[key] });
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return output;
|
|
201
|
+
}
|
|
202
|
+
isObject(item) {
|
|
203
|
+
return item && typeof item === 'object' && !Array.isArray(item);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
FyLibService = __decorate([
|
|
207
|
+
Injectable({
|
|
208
|
+
providedIn: 'root'
|
|
209
|
+
}),
|
|
210
|
+
__param(0, Optional()),
|
|
211
|
+
__param(0, Inject(FYLIB_CONFIG)),
|
|
212
|
+
__metadata("design:paramtypes", [Object])
|
|
213
|
+
], FyLibService);
|
|
214
|
+
export { FyLibService };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ComponentRef } from '@angular/core';
|
|
2
|
+
import { ToastProps } from '@fylib/catalog';
|
|
3
|
+
import { FyToastComponent } from '../components/toast.component';
|
|
4
|
+
import { NotificationItem } from '@fylib/catalog';
|
|
5
|
+
export interface ToastOptions extends Partial<Omit<ToastProps, 'message'>> {
|
|
6
|
+
message: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class FyNotificationService {
|
|
9
|
+
private appRef;
|
|
10
|
+
private injector;
|
|
11
|
+
private document;
|
|
12
|
+
private containerMap;
|
|
13
|
+
private toasts;
|
|
14
|
+
private _notifications;
|
|
15
|
+
readonly notifications: import("@angular/core").Signal<NotificationItem[]>;
|
|
16
|
+
addNotification(notification: NotificationItem): void;
|
|
17
|
+
clearNotifications(): void;
|
|
18
|
+
markAsRead(id: string): void;
|
|
19
|
+
markAllAsRead(): void;
|
|
20
|
+
show(options: ToastOptions | string): ComponentRef<FyToastComponent>;
|
|
21
|
+
success(message: string, title?: string, options?: Partial<ToastOptions>): ComponentRef<FyToastComponent>;
|
|
22
|
+
error(message: string, title?: string, options?: Partial<ToastOptions>): ComponentRef<FyToastComponent>;
|
|
23
|
+
warning(message: string, title?: string, options?: Partial<ToastOptions>): ComponentRef<FyToastComponent>;
|
|
24
|
+
info(message: string, title?: string, options?: Partial<ToastOptions>): ComponentRef<FyToastComponent>;
|
|
25
|
+
private destroyToast;
|
|
26
|
+
private getOrCreateContainer;
|
|
27
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
import { Injectable, signal, inject, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
|
|
8
|
+
import { FyToastComponent } from '../components/toast.component';
|
|
9
|
+
import { DOCUMENT } from '@angular/common';
|
|
10
|
+
let FyNotificationService = class FyNotificationService {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.appRef = inject(ApplicationRef);
|
|
13
|
+
this.injector = inject(EnvironmentInjector);
|
|
14
|
+
this.document = inject(DOCUMENT);
|
|
15
|
+
this.containerMap = new Map();
|
|
16
|
+
this.toasts = signal([]);
|
|
17
|
+
this._notifications = signal([]);
|
|
18
|
+
this.notifications = this._notifications.asReadonly();
|
|
19
|
+
}
|
|
20
|
+
addNotification(notification) {
|
|
21
|
+
this._notifications.update(current => [notification, ...current]);
|
|
22
|
+
}
|
|
23
|
+
clearNotifications() {
|
|
24
|
+
this._notifications.set([]);
|
|
25
|
+
}
|
|
26
|
+
markAsRead(id) {
|
|
27
|
+
this._notifications.update(current => current.map(n => n.id === id ? { ...n, read: true } : n));
|
|
28
|
+
}
|
|
29
|
+
markAllAsRead() {
|
|
30
|
+
this._notifications.update(current => current.map(n => ({ ...n, read: true })));
|
|
31
|
+
}
|
|
32
|
+
show(options) {
|
|
33
|
+
const props = typeof options === 'string' ? { message: options } : options;
|
|
34
|
+
const position = props.position || 'top-right';
|
|
35
|
+
const container = this.getOrCreateContainer(position);
|
|
36
|
+
// Create component without host element
|
|
37
|
+
const componentRef = createComponent(FyToastComponent, {
|
|
38
|
+
environmentInjector: this.injector
|
|
39
|
+
});
|
|
40
|
+
// Set inputs
|
|
41
|
+
Object.assign(componentRef.instance, props);
|
|
42
|
+
// Handle close
|
|
43
|
+
const sub = componentRef.instance.fyClose.subscribe(() => {
|
|
44
|
+
this.destroyToast(componentRef);
|
|
45
|
+
sub.unsubscribe();
|
|
46
|
+
});
|
|
47
|
+
// Manually trigger change detection
|
|
48
|
+
componentRef.changeDetectorRef.detectChanges();
|
|
49
|
+
// Attach to appRef so it's part of the Angular component tree
|
|
50
|
+
this.appRef.attachView(componentRef.hostView);
|
|
51
|
+
// Append the native element to the container
|
|
52
|
+
const domElem = componentRef.hostView.rootNodes[0];
|
|
53
|
+
container.appendChild(domElem);
|
|
54
|
+
this.toasts.update(current => [...current, componentRef]);
|
|
55
|
+
return componentRef;
|
|
56
|
+
}
|
|
57
|
+
success(message, title, options) {
|
|
58
|
+
return this.show({ ...options, message, title, type: 'success' });
|
|
59
|
+
}
|
|
60
|
+
error(message, title, options) {
|
|
61
|
+
return this.show({ ...options, message, title, type: 'error' });
|
|
62
|
+
}
|
|
63
|
+
warning(message, title, options) {
|
|
64
|
+
return this.show({ ...options, message, title, type: 'warning' });
|
|
65
|
+
}
|
|
66
|
+
info(message, title, options) {
|
|
67
|
+
return this.show({ ...options, message, title, type: 'info' });
|
|
68
|
+
}
|
|
69
|
+
destroyToast(ref) {
|
|
70
|
+
this.toasts.update(current => current.filter(r => r !== ref));
|
|
71
|
+
// Remove from DOM manually since we appended it manually
|
|
72
|
+
const domElem = ref.hostView.rootNodes[0];
|
|
73
|
+
if (domElem && domElem.parentNode) {
|
|
74
|
+
domElem.parentNode.removeChild(domElem);
|
|
75
|
+
}
|
|
76
|
+
this.appRef.detachView(ref.hostView);
|
|
77
|
+
ref.destroy();
|
|
78
|
+
}
|
|
79
|
+
getOrCreateContainer(position) {
|
|
80
|
+
if (this.containerMap.has(position)) {
|
|
81
|
+
return this.containerMap.get(position);
|
|
82
|
+
}
|
|
83
|
+
const container = this.document.createElement('div');
|
|
84
|
+
container.className = `fy-toast-container fy-toast-container--${position}`;
|
|
85
|
+
// Style the container
|
|
86
|
+
Object.assign(container.style, {
|
|
87
|
+
position: 'fixed',
|
|
88
|
+
zIndex: '9999',
|
|
89
|
+
display: 'flex',
|
|
90
|
+
flexDirection: 'column',
|
|
91
|
+
pointerEvents: 'none',
|
|
92
|
+
padding: '16px'
|
|
93
|
+
});
|
|
94
|
+
// Position styles
|
|
95
|
+
const [y, x] = position.split('-');
|
|
96
|
+
if (y === 'top')
|
|
97
|
+
container.style.top = '0';
|
|
98
|
+
else
|
|
99
|
+
container.style.bottom = '0';
|
|
100
|
+
if (x === 'left')
|
|
101
|
+
container.style.left = '0';
|
|
102
|
+
else if (x === 'right')
|
|
103
|
+
container.style.right = '0';
|
|
104
|
+
else {
|
|
105
|
+
container.style.left = '50%';
|
|
106
|
+
container.style.transform = 'translateX(-50%)';
|
|
107
|
+
}
|
|
108
|
+
this.document.body.appendChild(container);
|
|
109
|
+
this.containerMap.set(position, container);
|
|
110
|
+
return container;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
FyNotificationService = __decorate([
|
|
114
|
+
Injectable({
|
|
115
|
+
providedIn: 'root'
|
|
116
|
+
})
|
|
117
|
+
], FyNotificationService);
|
|
118
|
+
export { FyNotificationService };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OnDestroy } from '@angular/core';
|
|
2
|
+
export declare class FySSEService implements OnDestroy {
|
|
3
|
+
private platformId;
|
|
4
|
+
private fylib;
|
|
5
|
+
private notification;
|
|
6
|
+
private eventSource;
|
|
7
|
+
private reconnectTimeout;
|
|
8
|
+
private config;
|
|
9
|
+
constructor();
|
|
10
|
+
private initFromConfig;
|
|
11
|
+
connect(): void;
|
|
12
|
+
private handleEvent;
|
|
13
|
+
private reconnect;
|
|
14
|
+
disconnect(): void;
|
|
15
|
+
ngOnDestroy(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
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 { Injectable, inject, PLATFORM_ID } from '@angular/core';
|
|
11
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
12
|
+
import { FyLibService } from './fylib.service';
|
|
13
|
+
import { FyNotificationService } from './notification.service';
|
|
14
|
+
import { logger } from '@fylib/logger';
|
|
15
|
+
let FySSEService = class FySSEService {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.platformId = inject(PLATFORM_ID);
|
|
18
|
+
this.fylib = inject(FyLibService);
|
|
19
|
+
this.notification = inject(FyNotificationService);
|
|
20
|
+
this.eventSource = null;
|
|
21
|
+
this.reconnectTimeout = null;
|
|
22
|
+
this.config = null;
|
|
23
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
24
|
+
this.initFromConfig();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
initFromConfig() {
|
|
28
|
+
const config = this.fylib.config();
|
|
29
|
+
if (config.sse && config.sse.enabled) {
|
|
30
|
+
this.config = config.sse;
|
|
31
|
+
this.connect();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
connect() {
|
|
35
|
+
if (!this.config || !isPlatformBrowser(this.platformId))
|
|
36
|
+
return;
|
|
37
|
+
this.disconnect();
|
|
38
|
+
try {
|
|
39
|
+
this.eventSource = new EventSource(this.config.endpoint, {
|
|
40
|
+
withCredentials: this.config.withCredentials ?? false
|
|
41
|
+
});
|
|
42
|
+
this.eventSource.onopen = () => {
|
|
43
|
+
logger.info('SSE', 'SSE Connected to:', this.config?.endpoint);
|
|
44
|
+
};
|
|
45
|
+
this.eventSource.onerror = (error) => {
|
|
46
|
+
logger.error('SSE', 'SSE Error:', error);
|
|
47
|
+
this.reconnect();
|
|
48
|
+
};
|
|
49
|
+
// Registrar eventos mapeados
|
|
50
|
+
if (this.config.events) {
|
|
51
|
+
Object.keys(this.config.events).forEach(eventName => {
|
|
52
|
+
this.eventSource?.addEventListener(eventName, (event) => {
|
|
53
|
+
try {
|
|
54
|
+
const data = JSON.parse(event.data);
|
|
55
|
+
this.handleEvent(eventName, data);
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
this.handleEvent(eventName, event.data);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
logger.error('SSE', 'Failed to create EventSource:', e);
|
|
66
|
+
this.reconnect();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
handleEvent(eventName, data) {
|
|
70
|
+
if (!this.config?.events || !this.config.events[eventName])
|
|
71
|
+
return;
|
|
72
|
+
logger.debug('SSE', `Received event: ${eventName}`, data);
|
|
73
|
+
// Executa a função mapeada passando os serviços necessários
|
|
74
|
+
this.config.events[eventName](data, {
|
|
75
|
+
notification: this.notification,
|
|
76
|
+
// O menu de notificações será integrado via um serviço de estado global ou via FyNotificationService
|
|
77
|
+
menu: this.notification
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
reconnect() {
|
|
81
|
+
if (this.reconnectTimeout)
|
|
82
|
+
clearTimeout(this.reconnectTimeout);
|
|
83
|
+
const delay = this.config?.reconnectDelay ?? 5000;
|
|
84
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
85
|
+
logger.info('SSE', 'SSE Reconnecting...');
|
|
86
|
+
this.connect();
|
|
87
|
+
}, delay);
|
|
88
|
+
}
|
|
89
|
+
disconnect() {
|
|
90
|
+
if (this.eventSource) {
|
|
91
|
+
this.eventSource.close();
|
|
92
|
+
this.eventSource = null;
|
|
93
|
+
}
|
|
94
|
+
if (this.reconnectTimeout) {
|
|
95
|
+
clearTimeout(this.reconnectTimeout);
|
|
96
|
+
this.reconnectTimeout = null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
ngOnDestroy() {
|
|
100
|
+
this.disconnect();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
FySSEService = __decorate([
|
|
104
|
+
Injectable({
|
|
105
|
+
providedIn: 'root'
|
|
106
|
+
}),
|
|
107
|
+
__metadata("design:paramtypes", [])
|
|
108
|
+
], FySSEService);
|
|
109
|
+
export { FySSEService };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { HttpHeaders, HttpParams } from '@angular/common/http';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
export interface FyHttpRequestOptions {
|
|
4
|
+
headers?: HttpHeaders | Record<string, string | string[]>;
|
|
5
|
+
params?: HttpParams | Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>>;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
retries?: number;
|
|
8
|
+
retryDelay?: number;
|
|
9
|
+
cryptoEnabled?: boolean;
|
|
10
|
+
autoNotify?: boolean;
|
|
11
|
+
responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';
|
|
12
|
+
}
|
|
13
|
+
export declare class FyWebClientService {
|
|
14
|
+
private http;
|
|
15
|
+
private fylib;
|
|
16
|
+
private notify;
|
|
17
|
+
/**
|
|
18
|
+
* Realiza uma requisição GET reativa
|
|
19
|
+
*/
|
|
20
|
+
get<T = any>(url: string, options?: FyHttpRequestOptions): Observable<T>;
|
|
21
|
+
/**
|
|
22
|
+
* Realiza uma requisição POST reativa
|
|
23
|
+
*/
|
|
24
|
+
post<T = any>(url: string, body: any, options?: FyHttpRequestOptions): Observable<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Realiza uma requisição PUT reativa
|
|
27
|
+
*/
|
|
28
|
+
put<T = any>(url: string, body: any, options?: FyHttpRequestOptions): Observable<T>;
|
|
29
|
+
/**
|
|
30
|
+
* Realiza uma requisição DELETE reativa
|
|
31
|
+
*/
|
|
32
|
+
delete<T = any>(url: string, options?: FyHttpRequestOptions): Observable<T>;
|
|
33
|
+
private buildUrl;
|
|
34
|
+
private mergeOptions;
|
|
35
|
+
private processOutgoingData;
|
|
36
|
+
private processIncomingData;
|
|
37
|
+
private handleError;
|
|
38
|
+
}
|