@scania-nl/tegel-angular-extensions 0.0.7 → 0.0.8
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/README.md +410 -54
- package/esm2022/index.mjs +7 -1
- package/esm2022/lib/env/angular/provide-runtime-config.mjs +7 -5
- package/esm2022/lib/modal/components/modal/modal.component.mjs +121 -0
- package/esm2022/lib/modal/components/modal-host/modal-host.component.mjs +32 -0
- package/esm2022/lib/modal/directives/dynamic-component.directive.mjs +135 -0
- package/esm2022/lib/modal/modal.service.mjs +156 -0
- package/esm2022/lib/modal/provide-modal.mjs +25 -0
- package/esm2022/lib/modal/schema/modal-ref.mjs +2 -0
- package/esm2022/lib/modal/schema/modal.config.mjs +15 -0
- package/esm2022/lib/modal/schema/modal.model.mjs +2 -0
- package/esm2022/lib/modal/schema/modal.types.mjs +3 -0
- package/esm2022/lib/toast/provide-toast.mjs +7 -1
- package/esm2022/lib/utils/angular-component-io.mjs +2 -0
- package/index.d.ts +246 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,24 +5,30 @@
|
|
|
5
5
|
|
|
6
6
|
# @scania-nl/tegel-angular-extensions
|
|
7
7
|
|
|
8
|
-
Angular services for working with the [Tegel Angular 17](https://www.npmjs.com/package/@scania/tegel-angular-17) component library.
|
|
9
|
-
Provides simple wrappers for toast and modal
|
|
8
|
+
Angular components, services, and directives for working with the [Tegel Angular 17](https://www.npmjs.com/package/@scania/tegel-angular-17) component library.
|
|
9
|
+
Provides simple wrappers for toast and modal functionality using Angular 19+ **standalone components** and **dependency injection configuration**.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Features
|
|
14
16
|
|
|
15
17
|
1. **Runtime environment configuration**
|
|
16
18
|
- Schema-driven configuration and validation using Zod
|
|
17
19
|
- Deep-partial runtime overrides
|
|
18
20
|
- Runtime-required key enforcements
|
|
19
21
|
- Strong TypeScript inference
|
|
20
|
-
2. **
|
|
21
|
-
- Drop-in UI integrations for Tegel Angular
|
|
22
|
+
2. **Toast management**
|
|
22
23
|
- Signal-based `ToastService` for displaying toasts
|
|
23
24
|
- Customizable toast appearance and behavior
|
|
24
|
-
3. **
|
|
25
|
-
|
|
25
|
+
3. **Modal management**
|
|
26
|
+
- Strongly typed modal API
|
|
27
|
+
- Dynamic body content (string, template, or component)
|
|
28
|
+
- Configurable actions and lifecycle callbacks
|
|
29
|
+
4. **Standalone components and directives**
|
|
30
|
+
- Drop-in UI integrations for Tegel Angular
|
|
31
|
+
5. **Default Nginx config**
|
|
26
32
|
|
|
27
33
|
- Zero boilerplate - no Angular modules required
|
|
28
34
|
- Fully typed and configurable via DI
|
|
@@ -30,10 +36,12 @@ Provides simple wrappers for toast and modal (TBC) functionality using Angular 1
|
|
|
30
36
|
|
|
31
37
|
---
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Table of Contents
|
|
34
42
|
|
|
35
|
-
1. [Installation](
|
|
36
|
-
2. [Environment Configuration Overview](
|
|
43
|
+
1. [Installation](#installation)
|
|
44
|
+
2. [Environment Configuration Overview](#environment-configuration-overview)
|
|
37
45
|
1. [Defining your schema with createEnvKit](#defining-your-schema-with-createenvkit)
|
|
38
46
|
2. [Defining Static Environments (Dev/Prod)](#defining-static-environments-devprod)
|
|
39
47
|
3. [Providing Runtime Configuration](#providing-runtime-configuration)
|
|
@@ -43,28 +51,39 @@ Provides simple wrappers for toast and modal (TBC) functionality using Angular 1
|
|
|
43
51
|
2. [`extract-env-vars.sh`](#extract-env-varssh)
|
|
44
52
|
3. [`nginx.conf`](#nginxconf)
|
|
45
53
|
4. [Example Docker Commands](#example-docker-commands)
|
|
46
|
-
3. [Toasts](
|
|
47
|
-
1. [Quick Start](
|
|
54
|
+
3. [Toasts](#toasts)
|
|
55
|
+
1. [Quick Start](#quick-start)
|
|
48
56
|
1. [Add Providers](#add-providers)
|
|
49
57
|
2. [Use in components](#use-in-components)
|
|
50
|
-
2. [Configuration Options](
|
|
51
|
-
3. [ToastService API](
|
|
52
|
-
1. [ToastService Properties](
|
|
53
|
-
2. [ToastService Methods](
|
|
54
|
-
3. [Toast Lifecycle Hooks](
|
|
55
|
-
4. [
|
|
56
|
-
1. [
|
|
58
|
+
2. [Toast Configuration Options](#toast-configuration-options)
|
|
59
|
+
3. [ToastService API](#toastservice-api)
|
|
60
|
+
1. [ToastService Properties](#toastservice-properties)
|
|
61
|
+
2. [ToastService Methods](#toastservice-methods)
|
|
62
|
+
3. [Toast Lifecycle Hooks](#toast-lifecycle-hooks)
|
|
63
|
+
4. [Modals](#modals)
|
|
64
|
+
1. [Quick Start](#quick-start-1)
|
|
65
|
+
1. [Add Providers](#add-providers-1)
|
|
66
|
+
2. [Use in components](#use-in-components-1)
|
|
67
|
+
2. [Modal Configuration Options](#modal-configuration-options)
|
|
68
|
+
3. [ModalService API](#modalservice-api)
|
|
69
|
+
1. [ModalService Properties](#modalservice-properties)
|
|
70
|
+
2. [ModalService Methods](#modalservice-methods)
|
|
71
|
+
3. [Modal Lifecycle Hooks](#modal-lifecycle-hooks)
|
|
72
|
+
5. [Components & Directives](#components--directives)
|
|
73
|
+
1. [Components](#components)
|
|
57
74
|
1. [Footer](#footer-component-tae-footer)
|
|
58
|
-
2. [Directives](
|
|
75
|
+
2. [Directives](#directives)
|
|
59
76
|
1. [Hard Refresh](#hard-refresh-directive-taehardrefresh)
|
|
60
77
|
2. [Barcode Scanner](#barcode-scanner-directive-taebarcodescanner)
|
|
61
|
-
|
|
78
|
+
6. [Appendix](#appendix)
|
|
62
79
|
1. [Dockerfile Example](#runtime-config-dockerfile-example)
|
|
63
|
-
|
|
80
|
+
7. [License](#license)
|
|
64
81
|
|
|
65
82
|
---
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# Installation
|
|
68
87
|
|
|
69
88
|
```bash
|
|
70
89
|
npm install @scania-nl/tegel-angular-extensions @scania/tegel-angular-17 @traversable/zod zod
|
|
@@ -76,16 +95,18 @@ When creating an Angular project, the following dependencies already should have
|
|
|
76
95
|
|
|
77
96
|
```json
|
|
78
97
|
{
|
|
79
|
-
"@angular/common": "
|
|
80
|
-
"@angular/core": "
|
|
81
|
-
"@angular/router": "
|
|
98
|
+
"@angular/common": ">=19",
|
|
99
|
+
"@angular/core": ">=19",
|
|
100
|
+
"@angular/router": ">=19",
|
|
82
101
|
"rxjs": ">=7.8.0"
|
|
83
102
|
}
|
|
84
103
|
```
|
|
85
104
|
|
|
86
105
|
---
|
|
87
106
|
|
|
88
|
-
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Environment Configuration Overview
|
|
89
110
|
|
|
90
111
|
The runtime-config system provides:
|
|
91
112
|
|
|
@@ -94,6 +115,8 @@ The runtime-config system provides:
|
|
|
94
115
|
- Runtime overrides via .env files (shell scripts included)
|
|
95
116
|
- Guaranteed config availability before app bootstrap
|
|
96
117
|
|
|
118
|
+
|
|
119
|
+
|
|
97
120
|
## Defining your schema with createEnvKit
|
|
98
121
|
|
|
99
122
|
Create a local file: `src/environments/environment-config.ts`
|
|
@@ -207,7 +230,7 @@ This setup involves several key steps:
|
|
|
207
230
|
- At application startup, the code loads `/env/runtime.env`, parses any overrides using Zod (via a deep-partial schema), and merges them with the static configuration.
|
|
208
231
|
- Required configuration keys are enforced **only** in production.
|
|
209
232
|
- The validated configuration is exposed through Angular DI using the `ENV_CONFIG` InjectionToken.
|
|
210
|
-
- The `environment` file is referenced directly here. Angular
|
|
233
|
+
- The `environment` file is referenced directly here. Angular's build process replaces the `development` environment with the `production` environment via file replacement based on the selected build configuration.
|
|
211
234
|
|
|
212
235
|
> The `/env/runtime.env` file must be generated by the container during startup.
|
|
213
236
|
> Shell script binaries to support this are included the package.
|
|
@@ -218,12 +241,16 @@ This setup involves several key steps:
|
|
|
218
241
|
|
|
219
242
|
This package ships with two lightweight shell scripts used to generate a runtime configuration file inside the container. They enable true runtime configurability without rebuilding the Angular image. Additionally, the package contains a default `nginx.conf` optimized for Angular application. The files are located in the `/docker` directory.
|
|
220
243
|
|
|
244
|
+
|
|
245
|
+
|
|
221
246
|
### `docker-entrypoint.sh`
|
|
222
247
|
|
|
223
248
|
- Entry point executed every time the container starts
|
|
224
249
|
- Calls the `extract-env-vars.sh` to generate a fresh `runtime.env`
|
|
225
250
|
- Lastly, executes the provided Dockerfile `CMD`
|
|
226
251
|
|
|
252
|
+
|
|
253
|
+
|
|
227
254
|
### `extract-env-vars.sh`
|
|
228
255
|
|
|
229
256
|
- Reads all container environment variables matching a prefix (default: `NG__`)
|
|
@@ -231,6 +258,8 @@ This package ships with two lightweight shell scripts used to generate a runtime
|
|
|
231
258
|
- Supports nested keys via ** (e.g., `NG**myFeature\_\_myThreshold`)
|
|
232
259
|
- Defaults output to `/usr/share/nginx/html/env/runtime.env`
|
|
233
260
|
|
|
261
|
+
|
|
262
|
+
|
|
234
263
|
### `nginx.conf`
|
|
235
264
|
|
|
236
265
|
A default Nginx configuration optimized for Angular applications. It provides:
|
|
@@ -240,6 +269,8 @@ A default Nginx configuration optimized for Angular applications. It provides:
|
|
|
240
269
|
- Gzip compression where supported
|
|
241
270
|
- Automatic fallback to `index.html` for client-side routing
|
|
242
271
|
|
|
272
|
+
|
|
273
|
+
|
|
243
274
|
### **Example Docker Commands**
|
|
244
275
|
|
|
245
276
|
```Dockerfile
|
|
@@ -255,21 +286,24 @@ CMD ["nginx", "-g", "daemon off;"]
|
|
|
255
286
|
|
|
256
287
|
For a complete Dockerfile example with the shipped `nginx.conf` config, refer to [Runtime Config Dockerfile Example](#runtime-config-dockerfile-example)
|
|
257
288
|
|
|
258
|
-
|
|
259
|
-
|
|
260
289
|
---
|
|
261
290
|
|
|
262
|
-
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# Toasts
|
|
263
294
|
|
|
264
295
|
A lightweight, standalone toast system that integrates seamlessly with Tegel Angular. Provides configurable, signal-driven notifications for success, error, warning, and information messages.
|
|
265
296
|
|
|
266
|
-
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
## Quick Start
|
|
267
300
|
|
|
268
301
|
### Add Providers
|
|
269
302
|
|
|
270
303
|
In your `app.config.ts`, specify the provider with `provideToast()`:
|
|
271
304
|
|
|
272
305
|
```ts
|
|
306
|
+
// app.config.ts
|
|
273
307
|
import { provideToast } from '@scania-nl/tegel-angular-extensions';
|
|
274
308
|
|
|
275
309
|
export const appConfig: ApplicationConfig = {
|
|
@@ -288,6 +322,8 @@ export const appConfig: ApplicationConfig = {
|
|
|
288
322
|
|
|
289
323
|
> Note: The configuration is optional, all values shown above are the default settings.
|
|
290
324
|
|
|
325
|
+
|
|
326
|
+
|
|
291
327
|
### Use in components
|
|
292
328
|
|
|
293
329
|
In any standalone component:
|
|
@@ -315,7 +351,7 @@ export class MyToastDemoComponent {
|
|
|
315
351
|
|
|
316
352
|
|
|
317
353
|
|
|
318
|
-
##
|
|
354
|
+
## Toast Configuration Options
|
|
319
355
|
|
|
320
356
|
You can configure the default appearance and behavior of toasts by passing a `ToastConfig` object to `provideToast()` in your `app.config.ts`.
|
|
321
357
|
|
|
@@ -336,22 +372,22 @@ All options are optional. Defaults will be applied if values are not provided.
|
|
|
336
372
|
|
|
337
373
|
|
|
338
374
|
|
|
339
|
-
##
|
|
375
|
+
## ToastService API
|
|
340
376
|
|
|
341
377
|
The `ToastService` provides a signal-based API to create, manage, and dismiss toast notifications in Angular standalone apps. It is automatically available after registering `provideToast()` in your `app.config.ts`.
|
|
342
378
|
|
|
343
|
-
|
|
379
|
+
|
|
344
380
|
|
|
345
|
-
###
|
|
381
|
+
### ToastService Properties
|
|
346
382
|
|
|
347
383
|
| Property | Type | Description |
|
|
348
384
|
| -------------- | ----------------- | ----------------------------------------------------- |
|
|
349
385
|
| `toasts` | `Signal<Toast[]>` | Read-only list of all toasts (including closed) |
|
|
350
386
|
| `activeToasts` | `Signal<Toast[]>` | List of currently active toasts (`Open` or `Closing`) |
|
|
351
387
|
|
|
352
|
-
|
|
388
|
+
|
|
353
389
|
|
|
354
|
-
###
|
|
390
|
+
### ToastService Methods
|
|
355
391
|
|
|
356
392
|
#### `create(toastOptions: Partial<ToastOptions>): number`
|
|
357
393
|
|
|
@@ -425,7 +461,9 @@ Force-removes all toasts instantly (no animations).
|
|
|
425
461
|
|
|
426
462
|
---
|
|
427
463
|
|
|
428
|
-
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
### Toast Lifecycle Hooks
|
|
429
467
|
|
|
430
468
|
Each toast supports optional lifecycle callbacks:
|
|
431
469
|
|
|
@@ -449,12 +487,328 @@ toastService.success({
|
|
|
449
487
|
|
|
450
488
|
|
|
451
489
|
|
|
452
|
-
#
|
|
490
|
+
# Modals
|
|
491
|
+
|
|
492
|
+
Standalone modal service + host for Tegel's `tds-modal`, with strongly‑typed options and dynamic body support.
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
## Quick Start
|
|
497
|
+
|
|
498
|
+
### Add Providers
|
|
499
|
+
|
|
500
|
+
In your `app.config.ts`, specify the provider with `provideModal()`:
|
|
501
|
+
|
|
502
|
+
```ts
|
|
503
|
+
// app.config.ts
|
|
504
|
+
import { provideModal } from '@scania-nl/tegel-angular-extensions';
|
|
505
|
+
|
|
506
|
+
export const appConfig: ApplicationConfig = {
|
|
507
|
+
providers: [
|
|
508
|
+
provideModal({
|
|
509
|
+
size: 'md', // Modal size
|
|
510
|
+
actionsPosition: 'static', // Actions slot behavior
|
|
511
|
+
prevent: false, // Prevent overlay click from closing the modal
|
|
512
|
+
closable: true, // Show or hide the close [X] button
|
|
513
|
+
alertDialog: 'dialog', // ARIA role of the modal component
|
|
514
|
+
lazy: false, // Render body only while open
|
|
515
|
+
startOpen: true, // Open modal on creation
|
|
516
|
+
removeOnClose: true, // Remove modal from DOM when closed
|
|
517
|
+
}),
|
|
518
|
+
],
|
|
519
|
+
};
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Most of these options are inherited from `tds-modal`.
|
|
523
|
+
|
|
524
|
+
> Note: The configuration is optional, all values shown above are the default settings.
|
|
525
|
+
|
|
526
|
+
### Use in components
|
|
527
|
+
|
|
528
|
+
`create()` returns a `ModalRef` that can control the modal instance.
|
|
529
|
+
|
|
530
|
+
```ts
|
|
531
|
+
import { inject } from '@angular/core';
|
|
532
|
+
import { ModalService } from '@scania-nl/tegel-angular-extensions';
|
|
533
|
+
|
|
534
|
+
export class MyComponent {
|
|
535
|
+
private readonly modalService = inject(ModalService);
|
|
536
|
+
|
|
537
|
+
openModal() {
|
|
538
|
+
const ref = this.modalService.create({
|
|
539
|
+
header: 'Demo Modal',
|
|
540
|
+
body: 'Hello from modal',
|
|
541
|
+
startOpen: false,
|
|
542
|
+
removeOnClose: false,
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
ref.open(); // Opens the modal
|
|
546
|
+
ref.close(); // Closes (hides) the modal
|
|
547
|
+
ref.remove(); // Removes the modal from the DOM
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
You get a `ModalRef` back from `create()`, which you can use to control that specific modal instance (`open()`, `close()`, `remove()`).
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
## Modal Configuration Options
|
|
559
|
+
|
|
560
|
+
| Option | Type | Default | Description |
|
|
561
|
+
| ----------------- | ------------------------------ | -------- | --------------------------- |
|
|
562
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `md` | Modal size |
|
|
563
|
+
| `actionsPosition` | `'static' \| 'sticky'` | `static` | Actions slot behavior |
|
|
564
|
+
| `prevent` | `boolean` | `false` | Prevent overlay close |
|
|
565
|
+
| `closable` | `boolean` | `true` | Show/hide close button |
|
|
566
|
+
| `alertDialog` | `'dialog' \| 'alertdialog'` | `dialog` | ARIA role |
|
|
567
|
+
| `lazy` | `boolean` | `false` | Render body only while open |
|
|
568
|
+
| `startOpen` | `boolean` | `true` | Open immediately on create |
|
|
569
|
+
| `removeOnClose` | `boolean` | `true` | Remove modal after close |
|
|
570
|
+
|
|
571
|
+
> Be aware that when `removeOnClose` is set to `false`, the modal content is hidden but **not destroyed**. If your body uses a component with active subscriptions, timers, or sockets, they will continue to run while the modal is hidden. Consider `removeOnClose: true` for component bodies if you want their resources to be disposed on close.
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
### Per-modal options (create)
|
|
578
|
+
|
|
579
|
+
These options are passed to `modalService.create()` and override defaults from `provideModal()` on a per‑modal basis. For shared defaults like `size`, `actionsPosition`, `prevent`, `closable`, `alertDialog`, `lazy`, `startOpen`, and `removeOnClose`, see [Modal Configuration Options](#modal-configuration-options) above.
|
|
580
|
+
|
|
581
|
+
| Option | Type | Description |
|
|
582
|
+
| ------------- | ------------------------------------------------------------------ | ---------------------------------------------------- |
|
|
583
|
+
| `header` | `string \| TemplateRef<unknown>` | Modal header text or template |
|
|
584
|
+
| `body` | `string \| TemplateRef<unknown> \| { component, inputs, outputs }` | Modal body content (string, template, or component) |
|
|
585
|
+
| `buttons` | `ModalButton[]` | Action buttons to render in the actions slot |
|
|
586
|
+
| `selector` | `string` | CSS selector for focus return element |
|
|
587
|
+
| `referenceEl` | `HTMLElement` | Element to return focus to (preferred over selector) |
|
|
588
|
+
| `onClosed` | `() => void \| Promise<void>` | Called when the modal is closed |
|
|
589
|
+
| `onRemoved` | `() => void \| Promise<void>` | Called after the modal is removed |
|
|
590
|
+
|
|
591
|
+
> Note: If you want focus to return to the element that opened the modal, pass either `selector` or `referenceEl` when creating the modal. This avoids Tegel's "Missing focus origin" warning.
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
### Body content options
|
|
598
|
+
|
|
599
|
+
The modal body can be provided as a simple string, a `TemplateRef`, or a component descriptor.
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
#### 1) String body
|
|
604
|
+
|
|
605
|
+
```ts
|
|
606
|
+
this.modalService.create({
|
|
607
|
+
header: 'Simple',
|
|
608
|
+
body: 'This is a simple modal body',
|
|
609
|
+
});
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
#### 2) TemplateRef body
|
|
615
|
+
|
|
616
|
+
```html
|
|
617
|
+
<ng-template #bodyTpl>
|
|
618
|
+
<strong>Template body</strong>
|
|
619
|
+
</ng-template>
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
```ts
|
|
623
|
+
const bodyTpl = viewChild<TemplateRef<unknown>>('bodyTpl');
|
|
624
|
+
this.modalService.create({
|
|
625
|
+
header: 'Template',
|
|
626
|
+
body: bodyTpl(),
|
|
627
|
+
});
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
#### 3) Component body (with inputs/outputs)
|
|
633
|
+
|
|
634
|
+
When you pass a component as the modal body, the `inputs` and `outputs` objects are fully typed. This means you get IntelliSense for signal inputs/outputs, and any `input.required(...)` fields are enforced at compile time (missing required inputs will fail the build).
|
|
635
|
+
|
|
636
|
+
```ts
|
|
637
|
+
export class ExampleComponent {
|
|
638
|
+
readonly requiredField = input.required<string>();
|
|
639
|
+
readonly optionalField = input<string>();
|
|
640
|
+
readonly outputField = output<string>();
|
|
641
|
+
}
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
```ts
|
|
645
|
+
const ref = this.modalService.create({
|
|
646
|
+
header: 'Example',
|
|
647
|
+
body: {
|
|
648
|
+
component: ExampleComponent,
|
|
649
|
+
inputs: {
|
|
650
|
+
requiredField: 'Required',
|
|
651
|
+
// optionalField: 'Optional'
|
|
652
|
+
},
|
|
653
|
+
outputs: {
|
|
654
|
+
outputField: (value: string) => {
|
|
655
|
+
console.log('Value:', value);
|
|
656
|
+
ref.close();
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
### Action buttons
|
|
666
|
+
|
|
667
|
+
```ts
|
|
668
|
+
this.modalService.create({
|
|
669
|
+
header: 'Confirm',
|
|
670
|
+
body: 'Are you sure?',
|
|
671
|
+
buttons: [
|
|
672
|
+
{ text: 'OK', variant: 'primary', onClick: async () => console.log('OK') },
|
|
673
|
+
{ text: 'Cancel', variant: 'secondary', dismiss: true },
|
|
674
|
+
],
|
|
675
|
+
startOpen: true,
|
|
676
|
+
});
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
- `dismiss`: true adds `data-dismiss-modal` for Tegel's built‑in close behavior.
|
|
680
|
+
- `onClick` supports sync or async handlers.
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
#### ModalButton options
|
|
685
|
+
|
|
686
|
+
Modal action buttons map directly to Tegel's `tds-button` configuration. The following options are supported:
|
|
687
|
+
|
|
688
|
+
| Option | Type | Description |
|
|
689
|
+
| ---------- | ------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
690
|
+
| `text` | `string` | Button label text |
|
|
691
|
+
| `variant` | `'primary' \| 'secondary' \| 'success' \| 'danger'` | Visual variant |
|
|
692
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | Button size |
|
|
693
|
+
| `disabled` | `boolean` | Disable the button |
|
|
694
|
+
| `dismiss` | `boolean` | Adds `data-dismiss-modal` to trigger Tegel's close behavior |
|
|
695
|
+
| `onClick` | `() => void \| Promise<void>` | Optional click handler (sync or async) |
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
## ModalService API
|
|
702
|
+
|
|
703
|
+
The `ModalService` provides a signal-based API to create, manage, and dismiss modal instances. It is available after registering `provideModal()` in your `app.config.ts`.
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
### ModalService Properties
|
|
708
|
+
|
|
709
|
+
| Property | Type | Description |
|
|
710
|
+
| -------- | ---------------------------- | -------------------------------------------------- |
|
|
711
|
+
| `modals` | `Signal<Map<string, Modal>>` | Read-only map of all registered modals keyed by id |
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
### ModalService Methods
|
|
716
|
+
|
|
717
|
+
#### `create<T>(options?: ModalOptions<T>): ModalRef`
|
|
718
|
+
|
|
719
|
+
Creates and registers a new modal. Returns a `ModalRef` for controlling that instance.
|
|
720
|
+
|
|
721
|
+
```ts
|
|
722
|
+
const ref = modalService.create({
|
|
723
|
+
header: 'Hello',
|
|
724
|
+
body: 'Modal content',
|
|
725
|
+
startOpen: false,
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
ref.open();
|
|
729
|
+
ref.close();
|
|
730
|
+
ref.remove();
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
#### ModalRef
|
|
736
|
+
|
|
737
|
+
`create()` returns a `ModalRef` with `open()`, `close()`, and `remove()` methods to control that specific modal instance.
|
|
738
|
+
|
|
739
|
+
#### `open(id: string): void`
|
|
740
|
+
|
|
741
|
+
Opens an existing modal by id.
|
|
742
|
+
|
|
743
|
+
Example:
|
|
744
|
+
|
|
745
|
+
```ts
|
|
746
|
+
const ref = modalService.create({
|
|
747
|
+
header: 'Example',
|
|
748
|
+
body: 'Hello',
|
|
749
|
+
startOpen: false,
|
|
750
|
+
});
|
|
751
|
+
modalService.open(ref.id); // Equivalent to ref.open()
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
#### `close(id: string): void`
|
|
757
|
+
|
|
758
|
+
Closes (hides) a modal by id. If `removeOnClose` is `true`, it is removed from the DOM after closing.
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
#### `remove(id: string): void`
|
|
763
|
+
|
|
764
|
+
Removes a modal from the registry/DOM. If the modal is open, it is closed first.
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
#### `closeAll(): void`
|
|
769
|
+
|
|
770
|
+
Closes all registered modals.
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
#### `removeAll(): void`
|
|
775
|
+
|
|
776
|
+
Removes all registered modals.
|
|
777
|
+
|
|
778
|
+
---
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
### Modal Lifecycle Hooks
|
|
783
|
+
|
|
784
|
+
Each modal supports optional lifecycle callbacks:
|
|
785
|
+
|
|
786
|
+
| Callback | Description |
|
|
787
|
+
| ------------- | ------------------------------------------------------- |
|
|
788
|
+
| `onClosed()` | Called when the modal is closed |
|
|
789
|
+
| `onRemoved()` | Called after the modal is removed from the registry/DOM |
|
|
790
|
+
|
|
791
|
+
Example:
|
|
792
|
+
|
|
793
|
+
```ts
|
|
794
|
+
modalService.create({
|
|
795
|
+
header: 'Example',
|
|
796
|
+
body: 'Hello',
|
|
797
|
+
onClosed: () => console.log('Modal closed'),
|
|
798
|
+
onRemoved: () => console.log('Modal removed'),
|
|
799
|
+
});
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
# Components & Directives
|
|
453
807
|
|
|
454
808
|
This library includes a set of standalone UI components and utility directives, all prefixed with **`tae`**, designed to extend and complement the Tegel Angular ecosystem. Each piece is lightweight, fully typed, and easy to import into any Angular 19+ application.
|
|
455
809
|
|
|
456
810
|
|
|
457
|
-
##
|
|
811
|
+
## Components
|
|
458
812
|
|
|
459
813
|
### Footer Component (`tae-footer`)
|
|
460
814
|
|
|
@@ -480,7 +834,7 @@ This makes it ideal for full-viewport layouts that benefit from space efficiency
|
|
|
480
834
|
|
|
481
835
|
|
|
482
836
|
|
|
483
|
-
##
|
|
837
|
+
## Directives
|
|
484
838
|
|
|
485
839
|
### Hard Refresh Directive (`taeHardRefresh`)
|
|
486
840
|
|
|
@@ -490,10 +844,10 @@ This is especially useful for hard-reloading tablet or mobile applications which
|
|
|
490
844
|
|
|
491
845
|
**Inputs:**
|
|
492
846
|
|
|
493
|
-
| Property | Type | Default
|
|
494
|
-
| ---------------- | -------- |
|
|
495
|
-
| `clicksRequired` | `number` | `3`
|
|
496
|
-
| `clickWindowMs` | `number` | `500`
|
|
847
|
+
| Property | Type | Default | Description |
|
|
848
|
+
| ---------------- | -------- | ------- | ---------------------------------------------------------------------- |
|
|
849
|
+
| `clicksRequired` | `number` | `3` | Number of clicks required within the window to trigger a hard refresh. |
|
|
850
|
+
| `clickWindowMs` | `number` | `500` | Time window in milliseconds between two subsequent clicks. |
|
|
497
851
|
|
|
498
852
|
**Example:**
|
|
499
853
|
|
|
@@ -517,16 +871,16 @@ It operates outside of Angular's zone to prevent unnecessary change detection cy
|
|
|
517
871
|
|
|
518
872
|
**Inputs:**
|
|
519
873
|
|
|
520
|
-
| Input
|
|
521
|
-
|
|
|
522
|
-
| `inputWindowMs`
|
|
523
|
-
| `terminatorKey`
|
|
874
|
+
| Input | Type | Default | Description |
|
|
875
|
+
| --------------- | -------- | --------- | ------------------------------------------------------------------ |
|
|
876
|
+
| `inputWindowMs` | `number` | `100` | Max time allowed between consecutive keypresses before discarding. |
|
|
877
|
+
| `terminatorKey` | `string` | `'Enter'` | The key that signals the end of a barcode sequence. |
|
|
524
878
|
|
|
525
879
|
**Outputs:**
|
|
526
880
|
|
|
527
|
-
| Output | Type
|
|
528
|
-
| ---------------- |
|
|
529
|
-
| `barcodeScanned` | `string`
|
|
881
|
+
| Output | Type | Description |
|
|
882
|
+
| ---------------- | -------- | ----------------------------------------------------------- |
|
|
883
|
+
| `barcodeScanned` | `string` | **Required**. Emits the full barcode string once completed. |
|
|
530
884
|
|
|
531
885
|
**Example:**
|
|
532
886
|
|
|
@@ -597,7 +951,9 @@ CMD ["nginx", "-c", "/etc/nginx/nginx.conf", "-g", "daemon off;"]
|
|
|
597
951
|
|
|
598
952
|
---
|
|
599
953
|
|
|
600
|
-
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
# License
|
|
601
957
|
|
|
602
958
|
Copyright 2025 Scania CV AB.
|
|
603
959
|
|
package/esm2022/index.mjs
CHANGED
|
@@ -5,6 +5,12 @@ export { provideToast } from './lib/toast/provide-toast';
|
|
|
5
5
|
export { DEFAULT_TOAST_CONFIG, TOAST_CONFIG, } from './lib/toast/toast.config';
|
|
6
6
|
export { ToastService } from './lib/toast/toast.service';
|
|
7
7
|
// --------------------------------------------------
|
|
8
|
+
// Modal Module Exports
|
|
9
|
+
// --------------------------------------------------
|
|
10
|
+
export { ModalService } from './lib/modal/modal.service';
|
|
11
|
+
export { provideModal } from './lib/modal/provide-modal';
|
|
12
|
+
export { DEFAULT_MODAL_CONFIG, MODAL_CONFIG, } from './lib/modal/schema/modal.config';
|
|
13
|
+
// --------------------------------------------------
|
|
8
14
|
// Env Module Exports
|
|
9
15
|
// --------------------------------------------------
|
|
10
16
|
// Core
|
|
@@ -22,4 +28,4 @@ export { HardRefreshDirective } from './lib/directives/hard-refresh.directive';
|
|
|
22
28
|
// Component Module Exports
|
|
23
29
|
// --------------------------------------------------
|
|
24
30
|
export { TaeFooterComponent } from './lib/components/tae-footer/tae-footer.component';
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJzL3RlZ2VsLWFuZ3VsYXItZXh0ZW5zaW9ucy9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscURBQXFEO0FBQ3JELHVCQUF1QjtBQUN2QixxREFBcUQ7QUFDckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsWUFBWSxHQUViLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBS3pELHFEQUFxRDtBQUNyRCx1QkFBdUI7QUFDdkIscURBQXFEO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFekQsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixZQUFZLEdBRWIsTUFBTSxpQ0FBaUMsQ0FBQztBQVN6QyxxREFBcUQ7QUFDckQscUJBQXFCO0FBQ3JCLHFEQUFxRDtBQUNyRCxPQUFPO0FBQ1AsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUU3RCxVQUFVO0FBQ1YsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDaEYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFFOUUscURBQXFEO0FBQ3JELDJCQUEyQjtBQUMzQixxREFBcUQ7QUFDckQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDckYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFFL0UscURBQXFEO0FBQ3JELDJCQUEyQjtBQUMzQixxREFBcUQ7QUFDckQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0RBQWtELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVG9hc3QgTW9kdWxlIEV4cG9ydHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5leHBvcnQgeyBwcm92aWRlVG9hc3QgfSBmcm9tICcuL2xpYi90b2FzdC9wcm92aWRlLXRvYXN0JztcbmV4cG9ydCB7XG4gIERFRkFVTFRfVE9BU1RfQ09ORklHLFxuICBUT0FTVF9DT05GSUcsXG4gIFRvYXN0Q29uZmlnLFxufSBmcm9tICcuL2xpYi90b2FzdC90b2FzdC5jb25maWcnO1xuZXhwb3J0IHsgVG9hc3RTZXJ2aWNlIH0gZnJvbSAnLi9saWIvdG9hc3QvdG9hc3Quc2VydmljZSc7XG5cbi8vIE1vZGVsc1xuZXhwb3J0IHsgVG9hc3QsIFRvYXN0T3B0aW9ucyB9IGZyb20gJy4vbGliL3RvYXN0L21vZGVscy90b2FzdC5tb2RlbCc7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBNb2RhbCBNb2R1bGUgRXhwb3J0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmV4cG9ydCB7IE1vZGFsU2VydmljZSB9IGZyb20gJy4vbGliL21vZGFsL21vZGFsLnNlcnZpY2UnO1xuZXhwb3J0IHsgcHJvdmlkZU1vZGFsIH0gZnJvbSAnLi9saWIvbW9kYWwvcHJvdmlkZS1tb2RhbCc7XG5leHBvcnQgeyBNb2RhbFJlZiB9IGZyb20gJy4vbGliL21vZGFsL3NjaGVtYS9tb2RhbC1yZWYnO1xuZXhwb3J0IHtcbiAgREVGQVVMVF9NT0RBTF9DT05GSUcsXG4gIE1PREFMX0NPTkZJRyxcbiAgTW9kYWxDb25maWcsXG59IGZyb20gJy4vbGliL21vZGFsL3NjaGVtYS9tb2RhbC5jb25maWcnO1xuZXhwb3J0IHsgTW9kYWwsIE1vZGFsT3B0aW9ucyB9IGZyb20gJy4vbGliL21vZGFsL3NjaGVtYS9tb2RhbC5tb2RlbCc7XG5leHBvcnQge1xuICBNb2RhbEFjdGlvbnNQb3NpdGlvbixcbiAgTW9kYWxBbGVydERpYWxvZ1JvbGUsXG4gIE1vZGFsQnV0dG9uLFxuICBNb2RhbFNpemUsXG59IGZyb20gJy4vbGliL21vZGFsL3NjaGVtYS9tb2RhbC50eXBlcyc7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBFbnYgTW9kdWxlIEV4cG9ydHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDb3JlXG5leHBvcnQgeyBjcmVhdGVFbnZLaXQgfSBmcm9tICcuL2xpYi9lbnYvY29yZS9jcmVhdGUtZW52LWtpdCc7XG5leHBvcnQgeyBwYXJzZUVudkZpbGUgfSBmcm9tICcuL2xpYi9lbnYvY29yZS9wYXJzZS1lbnYtZmlsZSc7XG5cbi8vIEFuZ3VsYXJcbmV4cG9ydCB7IHByb3ZpZGVSdW50aW1lQ29uZmlnIH0gZnJvbSAnLi9saWIvZW52L2FuZ3VsYXIvcHJvdmlkZS1ydW50aW1lLWNvbmZpZyc7XG5leHBvcnQgeyBwcm92aWRlU3RhdGljQ29uZmlnIH0gZnJvbSAnLi9saWIvZW52L2FuZ3VsYXIvcHJvdmlkZS1zdGF0aWMtY29uZmlnJztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIERpcmVjdGl2ZSBNb2R1bGUgRXhwb3J0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmV4cG9ydCB7IEJhcmNvZGVTY2FubmVyRGlyZWN0aXZlIH0gZnJvbSAnLi9saWIvZGlyZWN0aXZlcy9iYXJjb2RlLXNjYW5uZXIuZGlyZWN0aXZlJztcbmV4cG9ydCB7IEhhcmRSZWZyZXNoRGlyZWN0aXZlIH0gZnJvbSAnLi9saWIvZGlyZWN0aXZlcy9oYXJkLXJlZnJlc2guZGlyZWN0aXZlJztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENvbXBvbmVudCBNb2R1bGUgRXhwb3J0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmV4cG9ydCB7IFRhZUZvb3RlckNvbXBvbmVudCB9IGZyb20gJy4vbGliL2NvbXBvbmVudHMvdGFlLWZvb3Rlci90YWUtZm9vdGVyLmNvbXBvbmVudCc7XG4iXX0=
|