@scania-nl/tegel-angular-extensions 0.0.1 → 0.0.4
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/esm2022/index.mjs +5 -0
- package/esm2022/lib/toast/models/toast-state.enum.mjs +19 -0
- package/esm2022/lib/toast/models/toast-type.mjs +5 -0
- package/esm2022/lib/toast/models/toast.model.mjs +2 -0
- package/esm2022/lib/toast/provide-toast.mjs +19 -0
- package/esm2022/lib/toast/toast.component.mjs +34 -0
- package/esm2022/lib/toast/toast.config.mjs +11 -0
- package/esm2022/lib/toast/toast.service.mjs +206 -0
- package/esm2022/lib/utils/bootstrap-global-component.mjs +43 -0
- package/esm2022/scania-nl-tegel-angular-extensions.mjs +5 -0
- package/{src/index.ts → index.d.ts} +1 -1
- package/lib/toast/models/toast-state.enum.d.ts +17 -0
- package/lib/toast/models/toast-type.d.ts +8 -0
- package/lib/toast/models/toast.model.d.ts +73 -0
- package/lib/toast/provide-toast.d.ts +3 -0
- package/lib/toast/toast.component.d.ts +24 -0
- package/lib/toast/toast.config.d.ts +35 -0
- package/lib/toast/toast.service.d.ts +98 -0
- package/lib/utils/bootstrap-global-component.d.ts +23 -0
- package/package.json +16 -2
- package/eslint.config.mjs +0 -48
- package/jest.config.ts +0 -21
- package/ng-package.json +0 -7
- package/project.json +0 -36
- package/src/lib/toast/models/toast-state.enum.ts +0 -19
- package/src/lib/toast/models/toast-type.ts +0 -9
- package/src/lib/toast/models/toast.model.ts +0 -87
- package/src/lib/toast/provide-toast.ts +0 -29
- package/src/lib/toast/toast.component.html +0 -41
- package/src/lib/toast/toast.component.scss +0 -118
- package/src/lib/toast/toast.component.spec.ts +0 -28
- package/src/lib/toast/toast.component.ts +0 -37
- package/src/lib/toast/toast.config.ts +0 -50
- package/src/lib/toast/toast.service.ts +0 -275
- package/src/lib/utils/bootstrap-global-component.ts +0 -73
- package/src/test-setup.ts +0 -6
- package/tsconfig.json +0 -28
- package/tsconfig.lib.json +0 -17
- package/tsconfig.lib.prod.json +0 -7
- package/tsconfig.spec.json +0 -16
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { computed, inject, Injectable, signal } from '@angular/core';
|
|
2
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
3
|
-
import { delay, filter, mergeMap, of, Subject, tap } from 'rxjs';
|
|
4
|
-
import { ToastState } from './models/toast-state.enum';
|
|
5
|
-
import { TOAST_TYPES } from './models/toast-type';
|
|
6
|
-
import { Toast, ToastOptions } from './models/toast.model';
|
|
7
|
-
import { TOAST_CONFIG, ToastConfig } from './toast.config';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Service for creating, managing, and removing toast notifications.
|
|
11
|
-
* Supports automatic dismissal, manual control, and lifecycle hooks.
|
|
12
|
-
*/
|
|
13
|
-
@Injectable({
|
|
14
|
-
providedIn: 'root',
|
|
15
|
-
})
|
|
16
|
-
export class ToastService {
|
|
17
|
-
private readonly config = inject<ToastConfig>(TOAST_CONFIG);
|
|
18
|
-
|
|
19
|
-
//*------------------------------------------------------------
|
|
20
|
-
//* Section: Internal variables
|
|
21
|
-
//*------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
/** Internal ID tracker for unique toast IDs */
|
|
24
|
-
private id = 0;
|
|
25
|
-
|
|
26
|
-
/** Signal state holding all toasts */
|
|
27
|
-
private readonly _toasts = signal<Toast[]>([]);
|
|
28
|
-
|
|
29
|
-
/** Public signal of all toasts */
|
|
30
|
-
readonly toasts = this._toasts.asReadonly();
|
|
31
|
-
|
|
32
|
-
/** Signal of toasts that are not yet closed (open or closing) */
|
|
33
|
-
readonly activeToasts = computed(() =>
|
|
34
|
-
this._toasts().filter((toast) => toast.state !== ToastState.Closed)
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
/** Internal stream for auto-closing toasts */
|
|
38
|
-
private readonly autoCloseSubject = new Subject<Toast>();
|
|
39
|
-
|
|
40
|
-
/** Internal stream for fade-out/removal of toasts */
|
|
41
|
-
private readonly closeSubject = new Subject<Toast>();
|
|
42
|
-
|
|
43
|
-
constructor() {
|
|
44
|
-
// Auto-close after toast.duration
|
|
45
|
-
this.autoCloseSubject
|
|
46
|
-
.pipe(
|
|
47
|
-
takeUntilDestroyed(),
|
|
48
|
-
filter((toast) => toast.duration > 0),
|
|
49
|
-
mergeMap((toast: Toast) =>
|
|
50
|
-
of(toast).pipe(
|
|
51
|
-
delay(toast.duration),
|
|
52
|
-
filter(() => this.shouldAutoClose(toast.id)),
|
|
53
|
-
tap(() => this.close(toast.id))
|
|
54
|
-
)
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
.subscribe();
|
|
58
|
-
|
|
59
|
-
// Remove after toast.closeDuration (fade-out)
|
|
60
|
-
this.closeSubject
|
|
61
|
-
.pipe(
|
|
62
|
-
takeUntilDestroyed(),
|
|
63
|
-
mergeMap((toast: Toast) =>
|
|
64
|
-
of(toast).pipe(
|
|
65
|
-
delay(toast.closeDuration),
|
|
66
|
-
filter(() => this.shouldRemove(toast.id)),
|
|
67
|
-
tap(() => this.remove(toast.id))
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
.subscribe();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
//*------------------------------------------------------------
|
|
75
|
-
//* Section: Public methods
|
|
76
|
-
//*------------------------------------------------------------
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Creates and adds a new toast.
|
|
80
|
-
* @param toastOptions Partial toast definition.
|
|
81
|
-
* @returns The toast's unique ID.
|
|
82
|
-
*/
|
|
83
|
-
create(toastOptions: Partial<ToastOptions>): number {
|
|
84
|
-
const id = this.createId();
|
|
85
|
-
const toast: Toast = {
|
|
86
|
-
...this.config,
|
|
87
|
-
...toastOptions,
|
|
88
|
-
id,
|
|
89
|
-
state: ToastState.Open,
|
|
90
|
-
duration: this.normalizeDuration(
|
|
91
|
-
toastOptions.duration,
|
|
92
|
-
this.config.duration
|
|
93
|
-
),
|
|
94
|
-
closeDuration: this.normalizeDuration(
|
|
95
|
-
toastOptions.closeDuration,
|
|
96
|
-
this.config.closeDuration
|
|
97
|
-
),
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
this.addToast(toast);
|
|
101
|
-
toast.onCreated?.(toast);
|
|
102
|
-
|
|
103
|
-
// Schedule auto-close if duration > 0
|
|
104
|
-
if (toast.duration > 0) {
|
|
105
|
-
this.autoCloseSubject.next(toast);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return id;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Initiates the fade-out transition for a toast.
|
|
113
|
-
* @param id The toast ID.
|
|
114
|
-
*/
|
|
115
|
-
close(id: number): void {
|
|
116
|
-
let toast = this.getToast(id);
|
|
117
|
-
if (!toast || toast.state !== ToastState.Open) return;
|
|
118
|
-
|
|
119
|
-
toast = this.updateToastState(toast.id, ToastState.Closing);
|
|
120
|
-
toast?.onClose?.(toast);
|
|
121
|
-
|
|
122
|
-
// Schedule removal after close duration
|
|
123
|
-
if (toast) this.closeSubject.next(toast);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Immediately marks a toast as closed and removes it from display.
|
|
128
|
-
* @param id The toast ID.
|
|
129
|
-
*/
|
|
130
|
-
remove(id: number): void {
|
|
131
|
-
const toast = this.updateToastState(id, ToastState.Closed);
|
|
132
|
-
toast?.onRemoved?.(toast);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Closes and removes all toasts immediately without fade-out.
|
|
137
|
-
*/
|
|
138
|
-
removeAll(): void {
|
|
139
|
-
const closedToasts: Toast[] = [];
|
|
140
|
-
|
|
141
|
-
this._toasts.update((toasts) =>
|
|
142
|
-
toasts.map((toast) => {
|
|
143
|
-
if (toast.state !== ToastState.Closed) {
|
|
144
|
-
const updated = { ...toast, state: ToastState.Closed };
|
|
145
|
-
closedToasts.push(updated);
|
|
146
|
-
return updated;
|
|
147
|
-
}
|
|
148
|
-
return toast;
|
|
149
|
-
})
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
closedToasts.forEach((toast) => toast.onRemoved?.(toast));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Initiates closing process for all open toasts.
|
|
157
|
-
*/
|
|
158
|
-
closeAll(): void {
|
|
159
|
-
const openToasts = this.toasts().filter(
|
|
160
|
-
(toast) => toast.state === ToastState.Open
|
|
161
|
-
);
|
|
162
|
-
openToasts.forEach((toast) => this.close(toast.id));
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Gets a toast by ID.
|
|
167
|
-
* @param id The toast ID.
|
|
168
|
-
* @returns The toast instance or undefined.
|
|
169
|
-
*/
|
|
170
|
-
getToast(id: number): Toast | undefined {
|
|
171
|
-
return this._toasts().find((toast) => toast.id === id);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
//*------------------------------------------------------------
|
|
175
|
-
//* Section: Internal methods
|
|
176
|
-
//*------------------------------------------------------------
|
|
177
|
-
|
|
178
|
-
/** Whether the toast is eligible for auto-closing */
|
|
179
|
-
private shouldAutoClose(id: number): boolean {
|
|
180
|
-
const currentToast = this.getToast(id);
|
|
181
|
-
return currentToast?.state === ToastState.Open;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/** Whether the toast is eligible for final removal */
|
|
185
|
-
private shouldRemove(id: number): boolean {
|
|
186
|
-
const currentToast = this.getToast(id);
|
|
187
|
-
return currentToast?.state === ToastState.Closing;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/** Add toast to signal list */
|
|
191
|
-
private addToast(toast: Toast): void {
|
|
192
|
-
this._toasts.update((prev) => [...prev, toast]);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Updates the state of a toast.
|
|
197
|
-
* @param id Toast ID
|
|
198
|
-
* @param state New state
|
|
199
|
-
* @returns The updated toast or undefined
|
|
200
|
-
*/
|
|
201
|
-
private updateToastState(id: number, state: ToastState): Toast | undefined {
|
|
202
|
-
let updatedToast: Toast | undefined;
|
|
203
|
-
|
|
204
|
-
this._toasts.update((prev) =>
|
|
205
|
-
prev.map((toast) => {
|
|
206
|
-
if (toast.id === id) {
|
|
207
|
-
updatedToast = { ...toast, state };
|
|
208
|
-
return updatedToast;
|
|
209
|
-
}
|
|
210
|
-
return toast;
|
|
211
|
-
})
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
return updatedToast;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Creates a unique id
|
|
219
|
-
* @returns New id
|
|
220
|
-
*/
|
|
221
|
-
private createId(): number {
|
|
222
|
-
return ++this.id;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
//*------------------------------------------------------------
|
|
226
|
-
//* Section: Public convenience methods
|
|
227
|
-
//*------------------------------------------------------------
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Creates a success toast.
|
|
231
|
-
* @param props Toast props without type.
|
|
232
|
-
*/
|
|
233
|
-
readonly success = (props: Partial<Omit<ToastOptions, 'type'>> = {}) =>
|
|
234
|
-
this.create({ ...props, type: 'success' });
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Creates an error toast.
|
|
238
|
-
* @param props Toast props without type.
|
|
239
|
-
*/
|
|
240
|
-
readonly error = (props: Partial<Omit<ToastOptions, 'type'>> = {}) =>
|
|
241
|
-
this.create({ ...props, type: 'error' });
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Creates a warning toast.
|
|
245
|
-
* @param props Toast props without type.
|
|
246
|
-
*/
|
|
247
|
-
readonly warning = (props: Partial<Omit<ToastOptions, 'type'>> = {}) =>
|
|
248
|
-
this.create({ ...props, type: 'warning' });
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Creates an informational toast.
|
|
252
|
-
* @param props Toast props without type.
|
|
253
|
-
*/
|
|
254
|
-
readonly info = (props: Partial<Omit<ToastOptions, 'type'>> = {}) =>
|
|
255
|
-
this.create({ ...props, type: 'information' });
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Creates a random toast for testing/demo purposes.
|
|
259
|
-
* @param props Optional overrides
|
|
260
|
-
*/
|
|
261
|
-
readonly createRandomToast = (props: Partial<ToastOptions> = {}) =>
|
|
262
|
-
this.create({
|
|
263
|
-
type: TOAST_TYPES[~~(Math.random() * 4)],
|
|
264
|
-
title: `Random Toast ${Math.random().toString(36).substring(7)}`,
|
|
265
|
-
...props,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
//*------------------------------------------------------------
|
|
269
|
-
//* Section: Helper methods
|
|
270
|
-
//*------------------------------------------------------------
|
|
271
|
-
private normalizeDuration(value: unknown, fallback: number): number {
|
|
272
|
-
const num = typeof value === 'number' ? value : fallback;
|
|
273
|
-
return !Number.isFinite(num) || num < 0 ? 0 : num;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ApplicationRef,
|
|
3
|
-
ComponentRef,
|
|
4
|
-
EmbeddedViewRef,
|
|
5
|
-
EnvironmentInjector,
|
|
6
|
-
Type,
|
|
7
|
-
createComponent,
|
|
8
|
-
inject,
|
|
9
|
-
} from '@angular/core';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Internal map to track which global components have been bootstrapped.
|
|
13
|
-
*/
|
|
14
|
-
const bootstrappedComponents = new WeakMap<
|
|
15
|
-
Type<unknown>,
|
|
16
|
-
ComponentRef<unknown>
|
|
17
|
-
>();
|
|
18
|
-
|
|
19
|
-
interface BootstrapGlobalComponentOptions {
|
|
20
|
-
/**
|
|
21
|
-
* If true, avoids re-creating the component if it's already mounted.
|
|
22
|
-
*/
|
|
23
|
-
reuseIfExists?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Bootstraps a global Angular component directly into the <body> element.
|
|
28
|
-
* Useful for toasts, modals, and other global overlays.
|
|
29
|
-
*
|
|
30
|
-
* @param component - The component class to bootstrap.
|
|
31
|
-
* @param options - Optional settings like preventing duplicates.
|
|
32
|
-
* @returns The created ComponentRef.
|
|
33
|
-
*/
|
|
34
|
-
export function bootstrapGlobalComponent<T>(
|
|
35
|
-
component: Type<T>,
|
|
36
|
-
options?: BootstrapGlobalComponentOptions
|
|
37
|
-
): ComponentRef<T> {
|
|
38
|
-
const appRef = inject(ApplicationRef);
|
|
39
|
-
const injector = inject(EnvironmentInjector);
|
|
40
|
-
|
|
41
|
-
const existing = bootstrappedComponents.get(component);
|
|
42
|
-
if (existing && options?.reuseIfExists) {
|
|
43
|
-
return existing as ComponentRef<T>;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const cmpRef = createComponent(component, {
|
|
47
|
-
environmentInjector: injector,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
appRef.attachView(cmpRef.hostView);
|
|
51
|
-
|
|
52
|
-
const viewRef = cmpRef.hostView as EmbeddedViewRef<unknown>;
|
|
53
|
-
const element = viewRef.rootNodes[0] as HTMLElement;
|
|
54
|
-
|
|
55
|
-
document.body.appendChild(element);
|
|
56
|
-
|
|
57
|
-
bootstrappedComponents.set(component, cmpRef);
|
|
58
|
-
|
|
59
|
-
return cmpRef;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Destroys a previously bootstrapped global component.
|
|
64
|
-
*
|
|
65
|
-
* @param component - The component class to remove from DOM.
|
|
66
|
-
*/
|
|
67
|
-
export function destroyGlobalComponent<T>(component: Type<T>): void {
|
|
68
|
-
const cmpRef = bootstrappedComponents.get(component);
|
|
69
|
-
if (cmpRef) {
|
|
70
|
-
cmpRef.destroy();
|
|
71
|
-
bootstrappedComponents.delete(component);
|
|
72
|
-
}
|
|
73
|
-
}
|
package/src/test-setup.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2022",
|
|
4
|
-
"forceConsistentCasingInFileNames": true,
|
|
5
|
-
"strict": true,
|
|
6
|
-
"noImplicitOverride": true,
|
|
7
|
-
"noPropertyAccessFromIndexSignature": true,
|
|
8
|
-
"noImplicitReturns": true,
|
|
9
|
-
"noFallthroughCasesInSwitch": true
|
|
10
|
-
},
|
|
11
|
-
"files": [],
|
|
12
|
-
"include": [],
|
|
13
|
-
"references": [
|
|
14
|
-
{
|
|
15
|
-
"path": "./tsconfig.lib.json"
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"path": "./tsconfig.spec.json"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"extends": "../../tsconfig.base.json",
|
|
22
|
-
"angularCompilerOptions": {
|
|
23
|
-
"enableI18nLegacyMessageIdFormat": false,
|
|
24
|
-
"strictInjectionParameters": true,
|
|
25
|
-
"strictInputAccessModifiers": true,
|
|
26
|
-
"strictTemplates": true
|
|
27
|
-
}
|
|
28
|
-
}
|
package/tsconfig.lib.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "../../dist/out-tsc",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"declarationMap": true,
|
|
7
|
-
"inlineSources": true,
|
|
8
|
-
"types": []
|
|
9
|
-
},
|
|
10
|
-
"exclude": [
|
|
11
|
-
"src/**/*.spec.ts",
|
|
12
|
-
"src/test-setup.ts",
|
|
13
|
-
"jest.config.ts",
|
|
14
|
-
"src/**/*.test.ts"
|
|
15
|
-
],
|
|
16
|
-
"include": ["src/**/*.ts"]
|
|
17
|
-
}
|
package/tsconfig.lib.prod.json
DELETED
package/tsconfig.spec.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "../../dist/out-tsc",
|
|
5
|
-
"module": "commonjs",
|
|
6
|
-
"target": "es2016",
|
|
7
|
-
"types": ["jest", "node"]
|
|
8
|
-
},
|
|
9
|
-
"files": ["src/test-setup.ts"],
|
|
10
|
-
"include": [
|
|
11
|
-
"jest.config.ts",
|
|
12
|
-
"src/**/*.test.ts",
|
|
13
|
-
"src/**/*.spec.ts",
|
|
14
|
-
"src/**/*.d.ts"
|
|
15
|
-
]
|
|
16
|
-
}
|