@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 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 both standalone components and Angular forms.
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
- - [Setup](#setup)
10
- - [CSS Integration Using Tailwind (Recommended)](#css-integration-using-tailwind-recommended)
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
- - [CSS Integration Without Tailwind (Not Recommended)](#css-integration-without-tailwind-not-recommended)
17
- - [Nova Font Pro Integration](#nova-font-pro-integration)
18
- - [Option 1: Angular.json Configuration (Recommended)](#option-1-angularjson-configuration-recommended)
19
- - [Option 2: Import in Styles.css](#option-2-import-in-stylescss)
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
- ## Setup
52
+ ## Setting up Tailwind
56
53
 
57
- ### CSS Integration Using Tailwind (Recommended)
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
- Visit the official [Tailwind CSS Angular documentation](https://tailwindcss.com/docs/installation/framework-guides/angular) for more detailed installation instructions.
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
- ### CSS Integration Without Tailwind (Not Recommended)
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
- ### Nova Font Pro Integration
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, please contact us via Teams or get the URL in the Nova Design System [internal wiki](https://dev.azure.com/elia-digitization/Nova/_wiki/wikis/Nova.wiki/30245/Nova-Font-Pro).
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
- #### Option 1: Angular.json Configuration (Recommended)
141
+ ### Option 1: Angular.json Configuration (Recommended)
156
142
 
157
- Add the Nova Font Pro CDN URL to the styles array in your `angular.json` configuration:
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
- "https://novaassets.azureedge.net/fonts/nova-fonts-pro.css"
147
+ "contact-us-for-URL/nova-fonts-pro.css"
162
148
  ]
163
149
  ```
164
150
 
165
- #### Option 2: Import in Styles.css
151
+ ### Option 2: Import in Styles.css
166
152
 
167
153
  ```css
168
- @import url('https://novaassets.azureedge.net/fonts/nova-fonts-pro.css');
154
+ @import url('contact-us-for-URL');
169
155
  ```
170
156
 
171
- #### Option 3: HTML Integration
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="https://novaassets.azureedge.net/fonts/nova-fonts-pro.css">
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 `provideNovaComponents` function as a provider in your application configuration:
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 2 way binding. Ensure to also include the `NovaComponentsModule`:
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
- <form>
343
- <nv-fieldtext [(ngModel)]="inputValue" name="input"></nv-fieldtext>
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
- In your component:
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