@nova-design-system/nova-angular-18 3.12.0 → 3.14.0-beta.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/README.md +44 -137
- package/dist/nova-components/esm2022/lib/nova-components.module.mjs +2 -2
- package/dist/nova-components/esm2022/lib/providers/index.mjs +3 -0
- package/dist/nova-components/esm2022/lib/providers/notification-service.component.mjs +183 -0
- package/dist/nova-components/esm2022/lib/providers/notification.service.mjs +134 -0
- package/dist/nova-components/esm2022/lib/stencil-generated/component-value-accessors.mjs +37 -1
- package/dist/nova-components/esm2022/lib/stencil-generated/components.mjs +58 -4
- package/dist/nova-components/esm2022/lib/stencil-generated/index.mjs +3 -1
- package/dist/nova-components/esm2022/public-api.mjs +2 -1
- package/dist/nova-components/fesm2022/nova-components.mjs +409 -8
- package/dist/nova-components/fesm2022/nova-components.mjs.map +1 -1
- package/dist/nova-components/lib/nova-components.module.d.ts +2 -2
- package/dist/nova-components/lib/providers/index.d.ts +2 -0
- package/dist/nova-components/lib/providers/notification-service.component.d.ts +56 -0
- package/dist/nova-components/lib/providers/notification.service.d.ts +116 -0
- package/dist/nova-components/lib/stencil-generated/component-value-accessors.d.ts +7 -0
- package/dist/nova-components/lib/stencil-generated/components.d.ts +27 -3
- package/dist/nova-components/lib/stencil-generated/index.d.ts +1 -1
- package/dist/nova-components/public-api.d.ts +1 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -2,29 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
**Nova Components Angular** allows you to integrate Nova's native UI elements into your Angular applications. This guide is specifically designed for **Angular 18**. If you are using a different version of Angular, please visit the [@nova-design-system/nova-angular](https://www.npmjs.com/package/@nova-design-system/nova-angular) page for the corresponding documentation and support.
|
|
4
4
|
|
|
5
|
-
This package leverages Angular's modern features and optimizations, offering a streamlined integration process for
|
|
5
|
+
This package leverages Angular's modern features and optimizations, offering a streamlined integration process for standalone components and Angular forms.
|
|
6
6
|
|
|
7
7
|
- [Nova Components Angular (Angular 18 Only)](#nova-components-angular-angular-18-only)
|
|
8
8
|
- [Installation](#installation)
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
9
|
+
- [Setting up Tailwind](#setting-up-tailwind)
|
|
10
|
+
- [About Tailwind and the Nova Plugin](#about-tailwind-and-the-nova-plugin)
|
|
11
11
|
- [1. Install Tailwind CSS](#1-install-tailwind-css)
|
|
12
12
|
- [2. Configure PostCSS Plugins](#2-configure-postcss-plugins)
|
|
13
13
|
- [3. Create `tailwind.config.ts`](#3-create-tailwindconfigts)
|
|
14
14
|
- [4. Configure Tailwind and Nova Plugin in `styles.css`](#4-configure-tailwind-and-nova-plugin-in-stylescss)
|
|
15
15
|
- [5. Include the Nova Tokens (Spark or Ocean)](#5-include-the-nova-tokens-spark-or-ocean)
|
|
16
|
-
|
|
17
|
-
- [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- [Option 3: HTML Integration](#option-3-html-integration)
|
|
16
|
+
- [Nova Font Pro Integration](#nova-font-pro-integration)
|
|
17
|
+
- [Option 1: Angular.json Configuration (Recommended)](#option-1-angularjson-configuration-recommended)
|
|
18
|
+
- [Option 2: Import in Styles.css](#option-2-import-in-stylescss)
|
|
19
|
+
- [Option 3: HTML Integration](#option-3-html-integration)
|
|
21
20
|
- [Standalone Component Setup](#standalone-component-setup)
|
|
22
21
|
- [1. Provide Nova Components](#1-provide-nova-components)
|
|
23
22
|
- [2. Configuring Standalone Components](#2-configuring-standalone-components)
|
|
24
|
-
- [Module-Based Setup](#module-based-setup)
|
|
25
23
|
- [Handling Angular Forms with Nova Components](#handling-angular-forms-with-nova-components)
|
|
26
24
|
- [Standalone Component Setup with Forms](#standalone-component-setup-with-forms)
|
|
27
|
-
- [Module-Based Setup](#module-based-setup-1)
|
|
28
25
|
- [Usage Example with Angular Forms](#usage-example-with-angular-forms)
|
|
29
26
|
- [Conclusion](#conclusion)
|
|
30
27
|
|
|
@@ -45,23 +42,30 @@ yarn add @nova-design-system/nova-webcomponents @nova-design-system/nova-base @n
|
|
|
45
42
|
```
|
|
46
43
|
|
|
47
44
|
> In some case, you might experience SSL certificate issues when working on Developers' VM. As documented in the [Developers' setup guide](https://wiki.eliagroup.eu/spaces/EAing/pages/89296007/2.3.3.10+Developer+Setup#id-2.3.3.10DeveloperSetup-NPMconfig), you need to turn off the SSL certificate verification:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
npm config set strict-ssl false
|
|
51
|
-
```
|
|
45
|
+
>
|
|
46
|
+
> ```bash
|
|
47
|
+
> npm config set strict-ssl false
|
|
48
|
+
> ```
|
|
52
49
|
|
|
53
50
|
---
|
|
54
51
|
|
|
55
|
-
##
|
|
52
|
+
## Setting up Tailwind
|
|
56
53
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
We highly recommend using Tailwind CSS for styling, as it ensures an optimized bundle size and a powerful utility-first workflow. Nova offers a dedicated Tailwind plugin and theme, allowing you to seamlessly integrate Nova’s design tokens with Tailwind’s utility classes for a consistent and efficient styling workflow.
|
|
54
|
+
Nova Angular requires Tailwind CSS for styling. Tailwind provides a powerful utility-first workflow and an optimized bundle size. Nova includes a dedicated Tailwind theme and plugin that map Nova’s design tokens to Tailwind’s theme and utilities, enabling consistent, token-driven styling across your app.
|
|
60
55
|
|
|
61
56
|
> **Tailwind Version**
|
|
62
57
|
> This guide is written for Tailwind v4. While compatible with v3, some features may not work as expected.
|
|
58
|
+
> See the official [Angular + Tailwind guide](https://tailwindcss.com/docs/installation/framework-guides/angular) for more details.
|
|
59
|
+
|
|
60
|
+
### About Tailwind and the Nova Plugin
|
|
63
61
|
|
|
64
|
-
|
|
62
|
+
- **What is Tailwind?** A utility-first CSS framework with low-level, composable classes (flex, grid, spacing, color, typography) to rapidly build UIs.
|
|
63
|
+
- **Nova Tokens**: Nova ships design tokens as CSS variables (via the Spark and Ocean themes) for colors, spacing, typography, radii, shadows, and more.
|
|
64
|
+
- **Integration**:
|
|
65
|
+
- `novaTailwindTheme` wires Nova tokens into Tailwind’s theme scales.
|
|
66
|
+
- The Nova Tailwind plugin exposes utilities and variants that reference those tokens, so your Tailwind classes resolve to Nova’s token values at runtime.
|
|
67
|
+
- **Why import tokens CSS?** Import exactly one token CSS file (`spark.css` or `ocean.css`) so the underlying CSS variables exist at runtime. The Tailwind utilities generated by the plugin read from these variables.
|
|
68
|
+
- **Do not mix with legacy utilities**: When using Tailwind, do not import `@nova-design-system/nova-base/dist/css/nova-utils.css` to avoid redundant CSS and larger bundles.
|
|
65
69
|
|
|
66
70
|
#### 1. Install Tailwind CSS
|
|
67
71
|
|
|
@@ -124,57 +128,39 @@ Add the Nova Tokens CSS file to the `styles` array in your `angular.json` config
|
|
|
124
128
|
}
|
|
125
129
|
```
|
|
126
130
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
If you don’t plan to use Tailwind, Nova provides a large utility CSS file for quick prototyping. Be aware that this approach will increase your CSS bundle size, offer fewer options, and lack the flexibility and optimizations of Tailwind.
|
|
130
|
-
|
|
131
|
-
To include the Nova theme and utility styles in your Angular project, add the CSS files to the `styles` array in your `angular.json` configuration:
|
|
132
|
-
|
|
133
|
-
```json
|
|
134
|
-
{
|
|
135
|
-
...
|
|
136
|
-
"styles": [
|
|
137
|
-
"src/styles.css",
|
|
138
|
-
"@nova-design-system/nova-base/dist/css/nova-utils.css",
|
|
139
|
-
"@nova-design-system/nova-base/dist/css/spark.css" // or ocean.css
|
|
140
|
-
],
|
|
141
|
-
...
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
This setup ensures that the Nova styles are available throughout your application.
|
|
131
|
+
---
|
|
146
132
|
|
|
147
|
-
|
|
133
|
+
## Nova Font Pro Integration
|
|
148
134
|
|
|
149
135
|
> [!WARNING]
|
|
150
136
|
> Nova Fonts is a protected asset and is not included in the Nova Base package. You need to include the Nova Fonts CSS file in your project.
|
|
151
|
-
> To get the Nova Fonts URL,
|
|
137
|
+
> To get the Nova Fonts URL, **contact us via Teams** or see the Nova Design System internal wiki.
|
|
152
138
|
|
|
153
139
|
Once you have the URL, you can integrate it using any of these methods:
|
|
154
140
|
|
|
155
|
-
|
|
141
|
+
### Option 1: Angular.json Configuration (Recommended)
|
|
156
142
|
|
|
157
|
-
Add the Nova Font Pro
|
|
143
|
+
Add the Nova Font Pro URL to the styles array in your `angular.json` configuration:
|
|
158
144
|
|
|
159
145
|
```json
|
|
160
146
|
"styles": [
|
|
161
|
-
"
|
|
147
|
+
"contact-us-for-URL/nova-fonts-pro.css"
|
|
162
148
|
]
|
|
163
149
|
```
|
|
164
150
|
|
|
165
|
-
|
|
151
|
+
### Option 2: Import in Styles.css
|
|
166
152
|
|
|
167
153
|
```css
|
|
168
|
-
@import url('
|
|
154
|
+
@import url('contact-us-for-URL');
|
|
169
155
|
```
|
|
170
156
|
|
|
171
|
-
|
|
157
|
+
### Option 3: HTML Integration
|
|
172
158
|
|
|
173
159
|
```html
|
|
174
160
|
<!DOCTYPE html>
|
|
175
161
|
<html>
|
|
176
162
|
<head>
|
|
177
|
-
<link rel="stylesheet" href="
|
|
163
|
+
<link rel="stylesheet" href="contact-us-for-URL/nova-fonts-pro.css">
|
|
178
164
|
</head>
|
|
179
165
|
<body>
|
|
180
166
|
<app-root></app-root>
|
|
@@ -182,22 +168,26 @@ Add the Nova Font Pro CDN URL to the styles array in your `angular.json` configu
|
|
|
182
168
|
</html>
|
|
183
169
|
```
|
|
184
170
|
|
|
171
|
+
The font CSS includes both font definitions and a `body { font-family: ... }` rule to apply fonts across your Angular application.
|
|
172
|
+
|
|
185
173
|
---
|
|
186
174
|
|
|
187
175
|
## Standalone Component Setup
|
|
188
176
|
|
|
189
|
-
Angular 18 encourages the use of standalone components with modern configuration. Follow these steps to integrate Nova Components into your Angular application
|
|
177
|
+
Angular 18 encourages the use of standalone components with modern configuration. Follow these steps to integrate Nova Components into your Angular application.
|
|
190
178
|
|
|
191
179
|
### 1. Provide Nova Components
|
|
192
180
|
|
|
193
|
-
To make Nova Web Components available across your application, add the `
|
|
181
|
+
To make Nova Web Components available across your application, add the `defineCustomElements` function as an app initializer in your application configuration:
|
|
194
182
|
|
|
195
183
|
```typescript
|
|
196
|
-
import { APP_INITIALIZER } from '@angular/core';
|
|
184
|
+
import { ApplicationConfig, APP_INITIALIZER } from '@angular/core';
|
|
185
|
+
import { provideRouter } from '@angular/router';
|
|
197
186
|
import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
|
|
198
187
|
|
|
199
188
|
export const appConfig: ApplicationConfig = {
|
|
200
189
|
providers: [
|
|
190
|
+
provideRouter(routes),
|
|
201
191
|
{
|
|
202
192
|
provide: APP_INITIALIZER,
|
|
203
193
|
useFactory: () => defineCustomElements, // Add the nova initializer here
|
|
@@ -229,41 +219,6 @@ export class AppComponent {
|
|
|
229
219
|
}
|
|
230
220
|
```
|
|
231
221
|
|
|
232
|
-
> **Note:** Module-based setup is not supported in Angular 18. Please use the standalone component approach as shown above.
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
## Module-Based Setup
|
|
237
|
-
|
|
238
|
-
In the module where you want to use Nova components, add the `NovaComponentsModule` to the `imports` array. Additionally, you need to initialize the webcomponents using the `provideNovaComponents()` function:
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
import { NgModule, APP_INITIALIZER } from '@angular/core';
|
|
242
|
-
import { NovaComponentsModule } from '@nova-design-system/nova-angular-18';
|
|
243
|
-
import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
|
|
244
|
-
|
|
245
|
-
@NgModule({
|
|
246
|
-
declarations: [AppComponent],
|
|
247
|
-
imports: [
|
|
248
|
-
BrowserModule,
|
|
249
|
-
AppRoutingModule,
|
|
250
|
-
NovaComponentsModule // Add NovaComponentsModule here
|
|
251
|
-
],
|
|
252
|
-
providers: [
|
|
253
|
-
{
|
|
254
|
-
provide: APP_INITIALIZER,
|
|
255
|
-
useFactory: () => defineCustomElements, // Add the nova initializer here
|
|
256
|
-
deps: [],
|
|
257
|
-
multi: true,
|
|
258
|
-
},
|
|
259
|
-
],
|
|
260
|
-
bootstrap: [AppComponent]
|
|
261
|
-
})
|
|
262
|
-
export class AppModule {}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
By including `NovaComponentsModule` in your imports, Nova's web components become available throughout the module.
|
|
266
|
-
|
|
267
222
|
---
|
|
268
223
|
|
|
269
224
|
## Handling Angular Forms with Nova Components
|
|
@@ -272,7 +227,7 @@ Nova Components Angular supports seamless integration with Angular's reactive an
|
|
|
272
227
|
|
|
273
228
|
### Standalone Component Setup with Forms
|
|
274
229
|
|
|
275
|
-
When working with forms in Angular 18, import the `NovaComponentsValueAccessorModule` along with Angular’s `FormsModule` in your standalone component to enable
|
|
230
|
+
When working with forms in Angular 18, import the `NovaComponentsValueAccessorModule` along with Angular’s `FormsModule` in your standalone component to enable two-way binding. Ensure to also include the `NovaComponentsModule`:
|
|
276
231
|
|
|
277
232
|
```typescript
|
|
278
233
|
import { Component } from '@angular/core';
|
|
@@ -297,61 +252,14 @@ export class AppComponent {
|
|
|
297
252
|
}
|
|
298
253
|
```
|
|
299
254
|
|
|
300
|
-
### Module-Based Setup
|
|
301
|
-
|
|
302
|
-
If you're using Angular modules, you can also integrate the value accessors by importing the `NovaComponentsValueAccessorModule` in your module:
|
|
303
|
-
|
|
304
|
-
```typescript
|
|
305
|
-
import { NgModule, APP_INITIALIZER } from '@angular/core';
|
|
306
|
-
import { BrowserModule } from '@angular/platform-browser';
|
|
307
|
-
import { FormsModule } from '@angular/forms';
|
|
308
|
-
import {
|
|
309
|
-
NovaComponentsModule,
|
|
310
|
-
NovaComponentsValueAccessorModule,
|
|
311
|
-
} from '@nova-design-system/nova-angular';
|
|
312
|
-
import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
|
|
313
|
-
|
|
314
|
-
@NgModule({
|
|
315
|
-
declarations: [AppComponent],
|
|
316
|
-
imports: [
|
|
317
|
-
BrowserModule,
|
|
318
|
-
FormsModule,
|
|
319
|
-
NovaComponentsModule, // Add NovaComponentsModule here
|
|
320
|
-
NovaComponentsValueAccessorModule, // Import the Value Accessor Module here
|
|
321
|
-
],
|
|
322
|
-
providers: [
|
|
323
|
-
{
|
|
324
|
-
provide: APP_INITIALIZER,
|
|
325
|
-
useFactory: () => defineCustomElements, // Add the nova initializer here
|
|
326
|
-
deps: [],
|
|
327
|
-
multi: true,
|
|
328
|
-
},
|
|
329
|
-
],
|
|
330
|
-
bootstrap: [AppComponent]
|
|
331
|
-
})
|
|
332
|
-
export class AppModule {}
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
This setup ensures that Nova components are fully compatible with Angular forms throughout your module.
|
|
336
|
-
|
|
337
255
|
### Usage Example with Angular Forms
|
|
338
256
|
|
|
339
|
-
With the value accessors set up, you can now use Nova components within Angular forms. Here's an example:
|
|
340
|
-
|
|
341
257
|
```html
|
|
342
|
-
<
|
|
343
|
-
|
|
344
|
-
<button type="submit">Submit</button>
|
|
345
|
-
</form>
|
|
258
|
+
<nv-fieldtext label="Input" [(ngModel)]="inputValue"></nv-fieldtext>
|
|
259
|
+
Input Value: {{ inputValue }}
|
|
346
260
|
```
|
|
347
261
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
```typescript
|
|
351
|
-
export class AppComponent {
|
|
352
|
-
inputValue = 'hello';
|
|
353
|
-
}
|
|
354
|
-
```
|
|
262
|
+
This configuration allows Nova components to work seamlessly with Angular forms, complete with two-way binding.
|
|
355
263
|
|
|
356
264
|
---
|
|
357
265
|
|
|
@@ -362,4 +270,3 @@ Nova Components Angular provides an easy and flexible way to incorporate Nova's
|
|
|
362
270
|
If you require support for Angular versions other than 18, please refer to the [@nova-design-system/nova-angular](https://www.npmjs.com/package/@nova-design-system/nova-angular) documentation for the appropriate setup and configuration.
|
|
363
271
|
|
|
364
272
|
Happy coding with Nova and Angular!
|
|
365
|
-
```
|
|
@@ -19,7 +19,7 @@ export function provideNovaComponents() {
|
|
|
19
19
|
}
|
|
20
20
|
export class NovaComponentsModule {
|
|
21
21
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
22
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, declarations: [i1.NvAccordion, i1.NvAccordionItem, i1.NvAlert, i1.NvAvatar, i1.NvBadge, i1.NvBreadcrumb, i1.NvBreadcrumbs, i1.NvButton, i1.NvButtongroup, i1.NvCalendar, i1.NvCol, i1.NvDatagrid, i1.NvDatagridcolumn, i1.NvDialog, i1.NvDialogfooter, i1.NvDialogheader, i1.NvFieldcheckbox, i1.NvFielddate, i1.NvFielddaterange, i1.NvFielddropdown, i1.NvFielddropdownitem, i1.NvFielddropdownitemcheck, i1.NvFieldmultiselect, i1.NvFieldnumber, i1.NvFieldpassword, i1.NvFieldradio, i1.NvFieldselect, i1.NvFieldslider, i1.NvFieldtext, i1.NvFieldtextarea, i1.NvFieldtime, i1.NvIcon, i1.NvIconbutton, i1.NvLoader, i1.NvMenu, i1.NvMenuitem, i1.NvPopover, i1.NvRow, i1.NvStack, i1.NvTable, i1.NvTablecolumn, i1.NvToggle, i1.NvTogglebutton, i1.NvTogglebuttongroup, i1.NvTooltip], exports: [i1.NvAccordion, i1.NvAccordionItem, i1.NvAlert, i1.NvAvatar, i1.NvBadge, i1.NvBreadcrumb, i1.NvBreadcrumbs, i1.NvButton, i1.NvButtongroup, i1.NvCalendar, i1.NvCol, i1.NvDatagrid, i1.NvDatagridcolumn, i1.NvDialog, i1.NvDialogfooter, i1.NvDialogheader, i1.NvFieldcheckbox, i1.NvFielddate, i1.NvFielddaterange, i1.NvFielddropdown, i1.NvFielddropdownitem, i1.NvFielddropdownitemcheck, i1.NvFieldmultiselect, i1.NvFieldnumber, i1.NvFieldpassword, i1.NvFieldradio, i1.NvFieldselect, i1.NvFieldslider, i1.NvFieldtext, i1.NvFieldtextarea, i1.NvFieldtime, i1.NvIcon, i1.NvIconbutton, i1.NvLoader, i1.NvMenu, i1.NvMenuitem, i1.NvPopover, i1.NvRow, i1.NvStack, i1.NvTable, i1.NvTablecolumn, i1.NvToggle, i1.NvTogglebutton, i1.NvTogglebuttongroup, i1.NvTooltip] }); }
|
|
22
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, declarations: [i1.NvAccordion, i1.NvAccordionItem, i1.NvAlert, i1.NvAvatar, i1.NvBadge, i1.NvBreadcrumb, i1.NvBreadcrumbs, i1.NvButton, i1.NvButtongroup, i1.NvCalendar, i1.NvCol, i1.NvDatagrid, i1.NvDatagridcolumn, i1.NvDialog, i1.NvDialogfooter, i1.NvDialogheader, i1.NvFieldcheckbox, i1.NvFielddate, i1.NvFielddaterange, i1.NvFielddropdown, i1.NvFielddropdownitem, i1.NvFielddropdownitemcheck, i1.NvFieldmultiselect, i1.NvFieldnumber, i1.NvFieldpassword, i1.NvFieldradio, i1.NvFieldselect, i1.NvFieldslider, i1.NvFieldtext, i1.NvFieldtextarea, i1.NvFieldtime, i1.NvIcon, i1.NvIconbutton, i1.NvLoader, i1.NvMenu, i1.NvMenuitem, i1.NvNotification, i1.NvNotificationcontainer, i1.NvPopover, i1.NvRow, i1.NvStack, i1.NvTable, i1.NvTablecolumn, i1.NvToggle, i1.NvTogglebutton, i1.NvTogglebuttongroup, i1.NvTooltip], exports: [i1.NvAccordion, i1.NvAccordionItem, i1.NvAlert, i1.NvAvatar, i1.NvBadge, i1.NvBreadcrumb, i1.NvBreadcrumbs, i1.NvButton, i1.NvButtongroup, i1.NvCalendar, i1.NvCol, i1.NvDatagrid, i1.NvDatagridcolumn, i1.NvDialog, i1.NvDialogfooter, i1.NvDialogheader, i1.NvFieldcheckbox, i1.NvFielddate, i1.NvFielddaterange, i1.NvFielddropdown, i1.NvFielddropdownitem, i1.NvFielddropdownitemcheck, i1.NvFieldmultiselect, i1.NvFieldnumber, i1.NvFieldpassword, i1.NvFieldradio, i1.NvFieldselect, i1.NvFieldslider, i1.NvFieldtext, i1.NvFieldtextarea, i1.NvFieldtime, i1.NvIcon, i1.NvIconbutton, i1.NvLoader, i1.NvMenu, i1.NvMenuitem, i1.NvNotification, i1.NvNotificationcontainer, i1.NvPopover, i1.NvRow, i1.NvStack, i1.NvTable, i1.NvTablecolumn, i1.NvToggle, i1.NvTogglebutton, i1.NvTogglebuttongroup, i1.NvTooltip] }); }
|
|
23
23
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, providers: [provideNovaComponents()] }); }
|
|
24
24
|
}
|
|
25
25
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, decorators: [{
|
|
@@ -32,7 +32,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
32
32
|
}] });
|
|
33
33
|
export class NovaComponentsValueAccessorModule {
|
|
34
34
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
35
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule, declarations: [i2.NvAlertValueAccessor, i2.NvCalendarValueAccessor, i2.NvDatagridValueAccessor, i2.NvDialogValueAccessor, i2.NvFieldcheckboxValueAccessor, i2.NvFielddateValueAccessor, i2.NvFielddaterangeValueAccessor, i2.NvFielddropdownValueAccessor, i2.NvFieldmultiselectValueAccessor, i2.NvFieldnumberValueAccessor, i2.NvFieldpasswordValueAccessor, i2.NvFieldradioValueAccessor, i2.NvFieldselectValueAccessor, i2.NvFieldsliderValueAccessor, i2.NvFieldtextValueAccessor, i2.NvFieldtextareaValueAccessor, i2.NvPopoverValueAccessor, i2.NvToggleValueAccessor, i2.NvTogglebuttongroupValueAccessor], exports: [i2.NvAlertValueAccessor, i2.NvCalendarValueAccessor, i2.NvDatagridValueAccessor, i2.NvDialogValueAccessor, i2.NvFieldcheckboxValueAccessor, i2.NvFielddateValueAccessor, i2.NvFielddaterangeValueAccessor, i2.NvFielddropdownValueAccessor, i2.NvFieldmultiselectValueAccessor, i2.NvFieldnumberValueAccessor, i2.NvFieldpasswordValueAccessor, i2.NvFieldradioValueAccessor, i2.NvFieldselectValueAccessor, i2.NvFieldsliderValueAccessor, i2.NvFieldtextValueAccessor, i2.NvFieldtextareaValueAccessor, i2.NvPopoverValueAccessor, i2.NvToggleValueAccessor, i2.NvTogglebuttongroupValueAccessor] }); }
|
|
35
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule, declarations: [i2.NvAlertValueAccessor, i2.NvCalendarValueAccessor, i2.NvDatagridValueAccessor, i2.NvDialogValueAccessor, i2.NvFieldcheckboxValueAccessor, i2.NvFielddateValueAccessor, i2.NvFielddaterangeValueAccessor, i2.NvFielddropdownValueAccessor, i2.NvFieldmultiselectValueAccessor, i2.NvFieldnumberValueAccessor, i2.NvFieldpasswordValueAccessor, i2.NvFieldradioValueAccessor, i2.NvFieldselectValueAccessor, i2.NvFieldsliderValueAccessor, i2.NvFieldtextValueAccessor, i2.NvFieldtextareaValueAccessor, i2.NvNotificationValueAccessor, i2.NvPopoverValueAccessor, i2.NvToggleValueAccessor, i2.NvTogglebuttongroupValueAccessor], exports: [i2.NvAlertValueAccessor, i2.NvCalendarValueAccessor, i2.NvDatagridValueAccessor, i2.NvDialogValueAccessor, i2.NvFieldcheckboxValueAccessor, i2.NvFielddateValueAccessor, i2.NvFielddaterangeValueAccessor, i2.NvFielddropdownValueAccessor, i2.NvFieldmultiselectValueAccessor, i2.NvFieldnumberValueAccessor, i2.NvFieldpasswordValueAccessor, i2.NvFieldradioValueAccessor, i2.NvFieldselectValueAccessor, i2.NvFieldsliderValueAccessor, i2.NvFieldtextValueAccessor, i2.NvFieldtextareaValueAccessor, i2.NvNotificationValueAccessor, i2.NvPopoverValueAccessor, i2.NvToggleValueAccessor, i2.NvTogglebuttongroupValueAccessor] }); }
|
|
36
36
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule }); }
|
|
37
37
|
}
|
|
38
38
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule, decorators: [{
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export * from './notification.service';
|
|
2
|
+
export * from './notification-service.component';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9ub3ZhLWNvbXBvbmVudHMvc3JjL2xpYi9wcm92aWRlcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLGtDQUFrQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9ub3RpZmljYXRpb24uc2VydmljZSc7XG5leHBvcnQgKiBmcm9tICcuL25vdGlmaWNhdGlvbi1zZXJ2aWNlLmNvbXBvbmVudCc7XG4iXX0=
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { Component, Input, ViewChildren, ElementRef, CUSTOM_ELEMENTS_SCHEMA, } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "./notification.service";
|
|
5
|
+
import * as i2 from "@angular/common";
|
|
6
|
+
/**
|
|
7
|
+
* Angular component that renders the notification container with active notifications.
|
|
8
|
+
*/
|
|
9
|
+
export class NotificationServiceComponent {
|
|
10
|
+
constructor(notificationService) {
|
|
11
|
+
this.notificationService = notificationService;
|
|
12
|
+
/**
|
|
13
|
+
* Array of active notifications.
|
|
14
|
+
*/
|
|
15
|
+
this.notifications = [];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Component initialization.
|
|
19
|
+
*/
|
|
20
|
+
ngOnInit() {
|
|
21
|
+
// Use service config if no input provided
|
|
22
|
+
this.position ??= this.notificationService.config.position;
|
|
23
|
+
this.className ??= this.notificationService.config.className;
|
|
24
|
+
// Subscribe to notification changes
|
|
25
|
+
this.subscription = this.notificationService.notifications$.subscribe((list) => (this.notifications = list));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Synchronize notification elements/refs with the service.
|
|
29
|
+
*/
|
|
30
|
+
ngAfterViewInit() {
|
|
31
|
+
const sync = () => {
|
|
32
|
+
this.notificationService.clearRefs();
|
|
33
|
+
for (const elRef of this.notificationEls.toArray()) {
|
|
34
|
+
const el = elRef.nativeElement;
|
|
35
|
+
const id = el.getAttribute('data-id');
|
|
36
|
+
if (id)
|
|
37
|
+
this.notificationService.registerRef(id, el);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
sync();
|
|
41
|
+
this.notificationEls.changes.subscribe(sync);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Component cleanup.
|
|
45
|
+
*/
|
|
46
|
+
ngOnDestroy() {
|
|
47
|
+
this.subscription?.unsubscribe();
|
|
48
|
+
this.notificationService.clearRefs();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Track function for ngFor to optimize rendering.
|
|
52
|
+
*
|
|
53
|
+
* @param {number} index The index of the item
|
|
54
|
+
* @param {Notification} notification The notification item
|
|
55
|
+
* @returns {string} The notification ID
|
|
56
|
+
*/
|
|
57
|
+
trackByNotificationId(index, notification) {
|
|
58
|
+
return notification.id;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Handle notification hidden state change.
|
|
62
|
+
*
|
|
63
|
+
* @param {CustomEvent<boolean>} event The hidden changed event
|
|
64
|
+
* @param {string} id The notification ID
|
|
65
|
+
*/
|
|
66
|
+
handleHiddenChanged(event, id) {
|
|
67
|
+
if (event.detail && id) {
|
|
68
|
+
this.notificationService.remove(id);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationServiceComponent, deps: [{ token: i1.NotificationService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
72
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NotificationServiceComponent, isStandalone: true, selector: "nv-notification-service", inputs: { position: "position", className: "className" }, viewQueries: [{ propertyName: "notificationEls", predicate: ["notificationEl"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
73
|
+
<nv-notificationcontainer
|
|
74
|
+
[position]="position"
|
|
75
|
+
[class]="className"
|
|
76
|
+
data-testid="notification-container"
|
|
77
|
+
>
|
|
78
|
+
<nv-notification
|
|
79
|
+
*ngFor="
|
|
80
|
+
let notification of notifications;
|
|
81
|
+
trackBy: trackByNotificationId
|
|
82
|
+
"
|
|
83
|
+
#notificationEl
|
|
84
|
+
[attr.data-id]="notification.id"
|
|
85
|
+
[heading]="notification.heading"
|
|
86
|
+
[message]="notification.message"
|
|
87
|
+
[dismissible]="notification.dismissible"
|
|
88
|
+
[emphasis]="notification.emphasis"
|
|
89
|
+
[feedback]="notification.feedback"
|
|
90
|
+
[icon]="notification.icon"
|
|
91
|
+
[initiallyHidden]="true"
|
|
92
|
+
(hiddenChanged)="handleHiddenChanged($event, notification.id)"
|
|
93
|
+
>
|
|
94
|
+
<!-- Actions slot content for the custom element -->
|
|
95
|
+
<div
|
|
96
|
+
slot="actions"
|
|
97
|
+
class="flex gap-2"
|
|
98
|
+
*ngIf="notification.actions?.length || notification.actionSlot"
|
|
99
|
+
>
|
|
100
|
+
<!-- Config-driven actions -->
|
|
101
|
+
<nv-button
|
|
102
|
+
*ngFor="let action of notification.actions"
|
|
103
|
+
emphasis="low"
|
|
104
|
+
size="sm"
|
|
105
|
+
(click)="action.onClick()"
|
|
106
|
+
>
|
|
107
|
+
{{ action.label }}
|
|
108
|
+
</nv-button>
|
|
109
|
+
|
|
110
|
+
<!-- Component-driven actions -->
|
|
111
|
+
<ng-container
|
|
112
|
+
*ngIf="notification.actionSlot"
|
|
113
|
+
[ngComponentOutlet]="notification.actionSlot"
|
|
114
|
+
></ng-container>
|
|
115
|
+
</div>
|
|
116
|
+
</nv-notification>
|
|
117
|
+
</nv-notificationcontainer>
|
|
118
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
119
|
+
}
|
|
120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationServiceComponent, decorators: [{
|
|
121
|
+
type: Component,
|
|
122
|
+
args: [{
|
|
123
|
+
selector: 'nv-notification-service',
|
|
124
|
+
standalone: true,
|
|
125
|
+
imports: [CommonModule],
|
|
126
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
127
|
+
template: `
|
|
128
|
+
<nv-notificationcontainer
|
|
129
|
+
[position]="position"
|
|
130
|
+
[class]="className"
|
|
131
|
+
data-testid="notification-container"
|
|
132
|
+
>
|
|
133
|
+
<nv-notification
|
|
134
|
+
*ngFor="
|
|
135
|
+
let notification of notifications;
|
|
136
|
+
trackBy: trackByNotificationId
|
|
137
|
+
"
|
|
138
|
+
#notificationEl
|
|
139
|
+
[attr.data-id]="notification.id"
|
|
140
|
+
[heading]="notification.heading"
|
|
141
|
+
[message]="notification.message"
|
|
142
|
+
[dismissible]="notification.dismissible"
|
|
143
|
+
[emphasis]="notification.emphasis"
|
|
144
|
+
[feedback]="notification.feedback"
|
|
145
|
+
[icon]="notification.icon"
|
|
146
|
+
[initiallyHidden]="true"
|
|
147
|
+
(hiddenChanged)="handleHiddenChanged($event, notification.id)"
|
|
148
|
+
>
|
|
149
|
+
<!-- Actions slot content for the custom element -->
|
|
150
|
+
<div
|
|
151
|
+
slot="actions"
|
|
152
|
+
class="flex gap-2"
|
|
153
|
+
*ngIf="notification.actions?.length || notification.actionSlot"
|
|
154
|
+
>
|
|
155
|
+
<!-- Config-driven actions -->
|
|
156
|
+
<nv-button
|
|
157
|
+
*ngFor="let action of notification.actions"
|
|
158
|
+
emphasis="low"
|
|
159
|
+
size="sm"
|
|
160
|
+
(click)="action.onClick()"
|
|
161
|
+
>
|
|
162
|
+
{{ action.label }}
|
|
163
|
+
</nv-button>
|
|
164
|
+
|
|
165
|
+
<!-- Component-driven actions -->
|
|
166
|
+
<ng-container
|
|
167
|
+
*ngIf="notification.actionSlot"
|
|
168
|
+
[ngComponentOutlet]="notification.actionSlot"
|
|
169
|
+
></ng-container>
|
|
170
|
+
</div>
|
|
171
|
+
</nv-notification>
|
|
172
|
+
</nv-notificationcontainer>
|
|
173
|
+
`,
|
|
174
|
+
}]
|
|
175
|
+
}], ctorParameters: () => [{ type: i1.NotificationService }], propDecorators: { position: [{
|
|
176
|
+
type: Input
|
|
177
|
+
}], className: [{
|
|
178
|
+
type: Input
|
|
179
|
+
}], notificationEls: [{
|
|
180
|
+
type: ViewChildren,
|
|
181
|
+
args: ['notificationEl', { read: ElementRef }]
|
|
182
|
+
}] } });
|
|
183
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9uLXNlcnZpY2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbm92YS1jb21wb25lbnRzL3NyYy9saWIvcHJvdmlkZXJzL25vdGlmaWNhdGlvbi1zZXJ2aWNlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFHTCxZQUFZLEVBQ1osVUFBVSxFQUVWLHNCQUFzQixHQUN2QixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7QUFLL0M7O0dBRUc7QUFzREgsTUFBTSxPQUFPLDRCQUE0QjtJQXdCdkMsWUFBb0IsbUJBQXdDO1FBQXhDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFiNUQ7O1dBRUc7UUFDSCxrQkFBYSxHQUFtQixFQUFFLENBQUM7SUFVNEIsQ0FBQztJQUVoRTs7T0FFRztJQUNILFFBQVE7UUFDTiwwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUMzRCxJQUFJLENBQUMsU0FBUyxLQUFLLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBRTdELG9DQUFvQztRQUNwQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUNuRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxDQUN0QyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsZUFBZTtRQUNiLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRTtZQUNoQixJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDckMsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7Z0JBQ25ELE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7Z0JBQy9CLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3RDLElBQUksRUFBRTtvQkFBRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN2RCxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBQ0YsSUFBSSxFQUFFLENBQUM7UUFDUCxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNULElBQUksQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxxQkFBcUIsQ0FBQyxLQUFhLEVBQUUsWUFBMEI7UUFDN0QsT0FBTyxZQUFZLENBQUMsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILG1CQUFtQixDQUFDLEtBQTJCLEVBQUUsRUFBVztRQUMxRCxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksRUFBRSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN0QyxDQUFDO0lBQ0gsQ0FBQzsrR0FyRlUsNEJBQTRCO21HQUE1Qiw0QkFBNEIsOE5BbUJDLFVBQVUsNkJBbkV4Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThDVCwyREFoRFMsWUFBWTs7NEZBa0RYLDRCQUE0QjtrQkFyRHhDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLHlCQUF5QjtvQkFDbkMsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQztvQkFDdkIsT0FBTyxFQUFFLENBQUMsc0JBQXNCLENBQUM7b0JBQ2pDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThDVDtpQkFDRjt3RkFLVSxRQUFRO3NCQUFoQixLQUFLO2dCQUtHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBV0UsZUFBZTtzQkFEdEIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgVmlld0NoaWxkcmVuLFxuICBFbGVtZW50UmVmLFxuICBRdWVyeUxpc3QsXG4gIENVU1RPTV9FTEVNRU5UU19TQ0hFTUEsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuLy8gaW1wb3J0IHsgTm92YUNvbXBvbmVudHNNb2R1bGUgfSBmcm9tICcuLi9ub3ZhLWNvbXBvbmVudHMubW9kdWxlJztcbmltcG9ydCB7IE5vdGlmaWNhdGlvblNlcnZpY2UsIHR5cGUgTm90aWZpY2F0aW9uIH0gZnJvbSAnLi9ub3RpZmljYXRpb24uc2VydmljZSc7XG5cbi8qKlxuICogQW5ndWxhciBjb21wb25lbnQgdGhhdCByZW5kZXJzIHRoZSBub3RpZmljYXRpb24gY29udGFpbmVyIHdpdGggYWN0aXZlIG5vdGlmaWNhdGlvbnMuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ252LW5vdGlmaWNhdGlvbi1zZXJ2aWNlJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHNjaGVtYXM6IFtDVVNUT01fRUxFTUVOVFNfU0NIRU1BXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8bnYtbm90aWZpY2F0aW9uY29udGFpbmVyXG4gICAgICBbcG9zaXRpb25dPVwicG9zaXRpb25cIlxuICAgICAgW2NsYXNzXT1cImNsYXNzTmFtZVwiXG4gICAgICBkYXRhLXRlc3RpZD1cIm5vdGlmaWNhdGlvbi1jb250YWluZXJcIlxuICAgID5cbiAgICAgIDxudi1ub3RpZmljYXRpb25cbiAgICAgICAgKm5nRm9yPVwiXG4gICAgICAgICAgbGV0IG5vdGlmaWNhdGlvbiBvZiBub3RpZmljYXRpb25zO1xuICAgICAgICAgIHRyYWNrQnk6IHRyYWNrQnlOb3RpZmljYXRpb25JZFxuICAgICAgICBcIlxuICAgICAgICAjbm90aWZpY2F0aW9uRWxcbiAgICAgICAgW2F0dHIuZGF0YS1pZF09XCJub3RpZmljYXRpb24uaWRcIlxuICAgICAgICBbaGVhZGluZ109XCJub3RpZmljYXRpb24uaGVhZGluZ1wiXG4gICAgICAgIFttZXNzYWdlXT1cIm5vdGlmaWNhdGlvbi5tZXNzYWdlXCJcbiAgICAgICAgW2Rpc21pc3NpYmxlXT1cIm5vdGlmaWNhdGlvbi5kaXNtaXNzaWJsZVwiXG4gICAgICAgIFtlbXBoYXNpc109XCJub3RpZmljYXRpb24uZW1waGFzaXNcIlxuICAgICAgICBbZmVlZGJhY2tdPVwibm90aWZpY2F0aW9uLmZlZWRiYWNrXCJcbiAgICAgICAgW2ljb25dPVwibm90aWZpY2F0aW9uLmljb25cIlxuICAgICAgICBbaW5pdGlhbGx5SGlkZGVuXT1cInRydWVcIlxuICAgICAgICAoaGlkZGVuQ2hhbmdlZCk9XCJoYW5kbGVIaWRkZW5DaGFuZ2VkKCRldmVudCwgbm90aWZpY2F0aW9uLmlkKVwiXG4gICAgICA+XG4gICAgICAgIDwhLS0gQWN0aW9ucyBzbG90IGNvbnRlbnQgZm9yIHRoZSBjdXN0b20gZWxlbWVudCAtLT5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIHNsb3Q9XCJhY3Rpb25zXCJcbiAgICAgICAgICBjbGFzcz1cImZsZXggZ2FwLTJcIlxuICAgICAgICAgICpuZ0lmPVwibm90aWZpY2F0aW9uLmFjdGlvbnM/Lmxlbmd0aCB8fCBub3RpZmljYXRpb24uYWN0aW9uU2xvdFwiXG4gICAgICAgID5cbiAgICAgICAgICA8IS0tIENvbmZpZy1kcml2ZW4gYWN0aW9ucyAtLT5cbiAgICAgICAgICA8bnYtYnV0dG9uXG4gICAgICAgICAgICAqbmdGb3I9XCJsZXQgYWN0aW9uIG9mIG5vdGlmaWNhdGlvbi5hY3Rpb25zXCJcbiAgICAgICAgICAgIGVtcGhhc2lzPVwibG93XCJcbiAgICAgICAgICAgIHNpemU9XCJzbVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiYWN0aW9uLm9uQ2xpY2soKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgYWN0aW9uLmxhYmVsIH19XG4gICAgICAgICAgPC9udi1idXR0b24+XG5cbiAgICAgICAgICA8IS0tIENvbXBvbmVudC1kcml2ZW4gYWN0aW9ucyAtLT5cbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdJZj1cIm5vdGlmaWNhdGlvbi5hY3Rpb25TbG90XCJcbiAgICAgICAgICAgIFtuZ0NvbXBvbmVudE91dGxldF09XCJub3RpZmljYXRpb24uYWN0aW9uU2xvdFwiXG4gICAgICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbnYtbm90aWZpY2F0aW9uPlxuICAgIDwvbnYtbm90aWZpY2F0aW9uY29udGFpbmVyPlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBOb3RpZmljYXRpb25TZXJ2aWNlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICAvKipcbiAgICogUG9zaXRpb24gb2YgdGhlIG5vdGlmaWNhdGlvbiBjb250YWluZXIgb24gdGhlIHNjcmVlbi5cbiAgICovXG4gIEBJbnB1dCgpIHBvc2l0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIENTUyBjbGFzcyBuYW1lIGZvciB0aGUgbm90aWZpY2F0aW9uIGNvbnRhaW5lci5cbiAgICovXG4gIEBJbnB1dCgpIGNsYXNzTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQXJyYXkgb2YgYWN0aXZlIG5vdGlmaWNhdGlvbnMuXG4gICAqL1xuICBub3RpZmljYXRpb25zOiBOb3RpZmljYXRpb25bXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBSZWZlcmVuY2VzIHRvIHRoZSBub3RpZmljYXRpb24gZWxlbWVudHMuXG4gICAqL1xuICBAVmlld0NoaWxkcmVuKCdub3RpZmljYXRpb25FbCcsIHsgcmVhZDogRWxlbWVudFJlZiB9KVxuICBwcml2YXRlIG5vdGlmaWNhdGlvbkVscyE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPEhUTUxOdk5vdGlmaWNhdGlvbkVsZW1lbnQ+PjtcblxuICBwcml2YXRlIHN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5vdGlmaWNhdGlvblNlcnZpY2U6IE5vdGlmaWNhdGlvblNlcnZpY2UpIHt9XG5cbiAgLyoqXG4gICAqIENvbXBvbmVudCBpbml0aWFsaXphdGlvbi5cbiAgICovXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIFVzZSBzZXJ2aWNlIGNvbmZpZyBpZiBubyBpbnB1dCBwcm92aWRlZFxuICAgIHRoaXMucG9zaXRpb24gPz89IHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5jb25maWcucG9zaXRpb247XG4gICAgdGhpcy5jbGFzc05hbWUgPz89IHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5jb25maWcuY2xhc3NOYW1lO1xuXG4gICAgLy8gU3Vic2NyaWJlIHRvIG5vdGlmaWNhdGlvbiBjaGFuZ2VzXG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2Uubm90aWZpY2F0aW9ucyQuc3Vic2NyaWJlKFxuICAgICAgKGxpc3QpID0+ICh0aGlzLm5vdGlmaWNhdGlvbnMgPSBsaXN0KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFN5bmNocm9uaXplIG5vdGlmaWNhdGlvbiBlbGVtZW50cy9yZWZzIHdpdGggdGhlIHNlcnZpY2UuXG4gICAqL1xuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgY29uc3Qgc3luYyA9ICgpID0+IHtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5jbGVhclJlZnMoKTtcbiAgICAgIGZvciAoY29uc3QgZWxSZWYgb2YgdGhpcy5ub3RpZmljYXRpb25FbHMudG9BcnJheSgpKSB7XG4gICAgICAgIGNvbnN0IGVsID0gZWxSZWYubmF0aXZlRWxlbWVudDtcbiAgICAgICAgY29uc3QgaWQgPSBlbC5nZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnKTtcbiAgICAgICAgaWYgKGlkKSB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2UucmVnaXN0ZXJSZWYoaWQsIGVsKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHN5bmMoKTtcbiAgICB0aGlzLm5vdGlmaWNhdGlvbkVscy5jaGFuZ2VzLnN1YnNjcmliZShzeW5jKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wb25lbnQgY2xlYW51cC5cbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5jbGVhclJlZnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFjayBmdW5jdGlvbiBmb3IgbmdGb3IgdG8gb3B0aW1pemUgcmVuZGVyaW5nLlxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBpdGVtXG4gICAqIEBwYXJhbSB7Tm90aWZpY2F0aW9ufSBub3RpZmljYXRpb24gVGhlIG5vdGlmaWNhdGlvbiBpdGVtXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBub3RpZmljYXRpb24gSURcbiAgICovXG4gIHRyYWNrQnlOb3RpZmljYXRpb25JZChpbmRleDogbnVtYmVyLCBub3RpZmljYXRpb246IE5vdGlmaWNhdGlvbikge1xuICAgIHJldHVybiBub3RpZmljYXRpb24uaWQ7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIG5vdGlmaWNhdGlvbiBoaWRkZW4gc3RhdGUgY2hhbmdlLlxuICAgKlxuICAgKiBAcGFyYW0ge0N1c3RvbUV2ZW50PGJvb2xlYW4+fSBldmVudCBUaGUgaGlkZGVuIGNoYW5nZWQgZXZlbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIFRoZSBub3RpZmljYXRpb24gSURcbiAgICovXG4gIGhhbmRsZUhpZGRlbkNoYW5nZWQoZXZlbnQ6IEN1c3RvbUV2ZW50PGJvb2xlYW4+LCBpZD86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmIChldmVudC5kZXRhaWwgJiYgaWQpIHtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5yZW1vdmUoaWQpO1xuICAgIH1cbiAgfVxufVxuIl19
|