@nova-design-system/nova-angular-18 3.0.0-beta.39

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/LICENSE.MD ADDED
@@ -0,0 +1,110 @@
1
+ # End-User License Agreement: Nova Design System
2
+
3
+ This End-User License Agreement ("Agreement") is entered into between:
4
+
5
+ 1. **Elia Group NV**
6
+ Located at Keizerslaan 20, 1000 Brussel, registered at the Crossroads Bank for Enterprises in Belgium under number 0476.388.378 (hereafter: "Licensor", "Elia", "We", "Our" or "Us").
7
+
8
+ 2. **Subsidiaries, Partners or Affiliates**
9
+ Collectively referred to as the "Licensee".
10
+
11
+ Licensor and Licensee may both be referred to as a “Party” and jointly as the “Parties”.
12
+
13
+ This Agreement can only be entered into by a party which can be considered as the “Licensee”. This means that, to the extent a party is not considered a Subsidiary, Affiliate or Partner, it is not possible for it to enter into this Agreement with Licensor or to use the Works. This Agreement shall not confer any rights, titles or interests to any other entities or individuals which are not the Licensee. Any attempt by Third Parties to claim rights or licenses under this Agreement shall be considered null and void, as the Agreement is strictly limited to the Licensee, as defined herein.
14
+
15
+ ---
16
+
17
+ ## 1. DEFINITIONS
18
+
19
+ - **Affiliate**: A business entity that is related to Elia through ownership, control, or shared interests, often resulting in a close operational or financial relationship (cfr. Article 1:15 of the Belgian Code of Companies and Associations).
20
+ - **Effective Date**: The date from which the Licensee accesses and downloads the Works.
21
+ - **Elia Projects**: (services performed in the context of) initiatives, projects, products, agreements or tasks directly relating to Elia’s business operations or to those of Subsidiaries, Affiliates or Partners or that otherwise support or are directly related to Elia’s business operations. Elia Projects include, without being limited to activities, works, or services performed in connection with the development, execution, or management of services, products, or solutions for, or related to Elia or its Subsidiaries or Affiliates.
22
+ - **Initial Term**: Has the meaning as set out under Article 6.2.
23
+ - **Intellectual Property Rights**: Means any intellectual property rights, including copyrights, trade and service marks, trade names, rights in logos, inventions, trade secrets and know-how, registered designs, design rights, patents, database rights, all rights of whatsoever nature in computer software and data, all intangible rights and privileges of nature similar or allied to any of the foregoing, in every case in any part of the world and whether or not registered; and including all granted registrations and all applications for registration, all renewals, reversions or extensions, the right to sue for damages for past infringement and all forms of protection of a similar nature which may subsist anywhere in the world. For the avoidance of doubt, Intellectual Property Rights include the intellectual property rights related to and vested in the Works.
24
+ - **License**: Has the meaning as described under Article 2.1.
25
+ - **Partner**: Means a business partner, subcontractor or service provider of the Licensor, which entered into a (services) agreement with Elia before and which is engaged on Elia Projects.
26
+ - **Renewal Term**: Has the meaning as set out under Article 6.2.
27
+ - **Subsidiary**: Means any entity directly or indirectly controlled by Licensee, where “control” is defined in article 1:14 of the Belgian Code of Companies and Associations.
28
+ - **Territory**: Means the entire world.
29
+ - **Third Party**: Means a person that is not a Party, nor a Subsidiary, Affiliate or Partner of the Licensor.
30
+ - **Works**: Means all elements and visuals in the UI library in the “Nova Design System” software (e.g. buttons, arrows, etc.) and the compressed versions of the respective source code of the visuals, created by, or on behalf of, Elia with the purpose of being used and incorporated in websites, platforms, applications etc. The Works can be accessed and found in the following folders [Name folders].
31
+
32
+ ---
33
+
34
+ ## 2. GRANT OF LICENSE
35
+
36
+ 2.1 Licensor hereby grants to Licensee, a non-exclusive, revocable, sublicensable and non-transferable right to use the Works within the Territory in accordance with this Agreement solely for Elia Projects. Licensor is only allowed to sublicense these rights in accordance with Article 4.1.
37
+
38
+ 2.2 The right to use the Works includes the right to reproduce, translate, and communicate to the public. The usage rights are granted for the term of the respective Intellectual Property Rights vested in the Works and they are not subject to payment of a royalty to Licensor. The exploitation rights mentioned above are not limited to any sorts of carriers or transmissions (hereafter all together referred to as the “License”).
39
+
40
+ 2.3 Licensee is obliged to inform Licensor of any infringement of Intellectual Property Rights, vested in the Works, by Third Parties as soon as possible after becoming aware of such infringement.
41
+
42
+ ---
43
+
44
+ ## 3. OWNERSHIP OF INTELLECTUAL PROPERTY RIGHTS
45
+
46
+ 3.1 The Licensee acknowledges and agrees that the Licensor is the proprietor of all right, title and interest in and to the Intellectual Property Rights vested in the Works throughout the Territory in any form or embodiment thereof and that the License does neither transfer or convey to Licensee any ownership rights in or relating to the Intellectual Property Rights vested in the Works.
47
+
48
+ 3.2 Licensor may from time to time implement updates or upgrades of the Works, add new items to the Works in the [name]folder or delete certain Works (together referred to as “Updates”). Licensor is allowed to implement these Updates without prior notification to the Licensee and/or without permission of the latter. Licensee is free to decide whether or not to implement or use these Updates. Once an Update has been implemented, it shall be deemed part of the Works and shall be subject to the provisions of this Agreement.
49
+
50
+ ---
51
+
52
+ ## 4. PERMITTED USE AND RESTRICTIONS
53
+
54
+ 4.1 The Works may only be used by employees and authorized contractors of Licensee and its Subsidiaries in the course of their employment or engagement on Elia Projects. Licensee is responsible and shall ensure that its personnel (including employees, subcontractors, authorized representatives or anyone else they would engage in the course of Elia Projects) use the Works in accordance with this Agreement.
55
+
56
+ 4.2 The Works may only be installed on devices owned or controlled by Licensee.
57
+
58
+ 4.3 Licensee shall not alter, modify or customize the Works. The Works are provided “as is”, with existing mechanisms to support flexible UI creation. Any attempts to modify the Works are prohibited.
59
+
60
+ 4.4 Licensee is not allowed and shall not:
61
+ - Use, copy, modify, sublicense, distribute, share or otherwise transfer the Works to any Third Party;
62
+ - Reverse engineer, decompile, or disassemble the Work.
63
+
64
+ ---
65
+
66
+ ## 5. LIABILITY AND DISCLAIMER OF WARRANTIES AND INDEMNIFICATIONS
67
+
68
+ 5.1 The Works are provided "as is" and "as available," without warranty of any kind. To the maximum extent permitted by applicable law, the Licensor expressly disclaims all warranties, whether express, implied, statutory, or otherwise, including, but not limited to, any implied warranties of merchantability, fitness for a particular purpose, title, non-infringement, and any warranties that may arise out of course of dealing, course of performance, usage, or trade practice. The Licensor does not warrant that the Works will meet the Licensee's requirements, achieve any intended results, be compatible or work with any other software, systems, or services, operate without interruption, meet any performance or reliability standards, be error-free, or that any errors or defects can or will be corrected. No oral or written information or advice given by the Licensor or its authorized representative shall create a warranty.
69
+
70
+ 5.2 To the fullest extent permitted by law, the Licensor shall not be liable for any indemnification obligations or liabilities whatsoever to the Licensee or any Third Party, whether arising in contract, tort, or otherwise, including, but not limited to, any claims, damages, liabilities, costs, or expenses arising out of or related to the Work, the use or inability to use the Work, or any data loss, corruption, or breaches of security associated with the Work. The Licensee acknowledges and agrees that the Licensor shall have no obligation to defend, indemnify, or hold harmless the Licensee or any third party for any reason, including but not limited to, intellectual property infringement claims, product liability claims, or any other claims or liabilities arising from the use of the Work.
71
+
72
+ 5.3 To the extent permitted by applicable law, Parties expressly agree that Licensor shall not be liable for any indirect or consequential damages, including but not limited to, damages for loss of business profits, business interruption, loss of business information, goodwill, use, data or other intangible losses resulting from the use of or the inability to use the (contents of the) Works, however caused (including by negligence), even if Licensee has been advised about the possibility of such damages.
73
+
74
+ 5.4 Licensee acknowledges and agrees that it installs the Works at its own risk and that it will be solely responsible for its use thereof and any damages that may result.
75
+
76
+ 5.5 In any case, Licensor’s liability under this Agreement is limited to the amount of 1,000 EUR.
77
+
78
+ ---
79
+
80
+ ## 6. TERM AND TERMINATION
81
+
82
+ 6.1 The initial term of this Agreement shall be effective as of the Effective Date and unless terminated earlier in accordance with this Article 6, shall be in force for an indefinite period of time.
83
+
84
+ 6.2 Either Party can terminate this Agreement by giving a written notice (including e-mail) to the other Party of one (1) month.
85
+
86
+ 6.3 This Agreement shall be automatically terminated upon a change in control, ownership, or shared interests of any Subsidiary or Affiliate, whether through sale, merger, reorganization, or otherwise, causing a change of the qualification of such Subsidiary or Affiliate into a Third Party. As regards Partners, this Agreement shall be automatically terminated upon the end of the participation of a Partner on Elia Projects.
87
+
88
+ 6.4 Licensor has the right to terminate the Agreement immediately, in case of a material breach by the Licensee, by providing the Licensee a written notice.
89
+
90
+ 6.5 Upon termination of this Agreement pursuant to this clause, Licensee shall immediately cease all use of the Works and shall destroy all copies of the Works in its possession or control. For avoidance of doubt, in this case, any use of the Works will be prohibited as from the date of the event which makes the Affiliate, Subsidiary or Partner, a Third Party.
91
+
92
+ ---
93
+
94
+ ## 7. MISCELLANEOUS
95
+
96
+ 7.1 No Party to this Agreement shall be deemed to have waived any rights arising out of the Agreement or out of any default or breach hereunder unless such Party explicitly executes the waiver in writing.
97
+
98
+ 7.2 Save as otherwise provided in this Agreement, each Party bears its own costs relating to the execution and implementation by it of this Agreement and of all other ancillary documents.
99
+
100
+ 7.3 This Agreement may not be assigned by Licensee, except with the prior written consent of the Licensor.
101
+
102
+ 7.4 If any provision of this Agreement is held to be invalid or unenforceable, then such provision will (so far as it is invalid or unenforceable) have no effect and will be deemed not to be included in this Agreement, but without invalidating any of the remaining provisions of this Agreement. The Parties must then use all reasonable endeavours to replace the invalid or unenforceable provision by a valid and enforceable substitute provision the effect of which is as close as possible to the intended effect of the invalid or unenforceable provision.
103
+
104
+ ---
105
+
106
+ ## 8. GOVERNING LAW AND JURISDICTION
107
+
108
+ 8.1 This Agreement is governed by and must be construed and interpreted in accordance with the laws of Belgium.
109
+
110
+ 8.2 The Dutch-speaking courts of Brussels will have exclusive jurisdiction to settle any dispute or claim arising out of or in connection with this Agreement, unless exclusive jurisdiction is attributed to other courts by applicable law.
package/README.md ADDED
@@ -0,0 +1,359 @@
1
+ # Nova Components Angular (Angular 18 Only)
2
+
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
+
5
+ This package leverages Angular's modern features and optimizations, offering a streamlined integration process for both standalone components and Angular forms.
6
+
7
+ - [Nova Components Angular (Angular 18 Only)](#nova-components-angular-angular-18-only)
8
+ - [Installation](#installation)
9
+ - [Setup](#setup)
10
+ - [CSS Integration Using Tailwind (Recommended)](#css-integration-using-tailwind-recommended)
11
+ - [1. Install Tailwind CSS](#1-install-tailwind-css)
12
+ - [2. Configure PostCSS Plugins](#2-configure-postcss-plugins)
13
+ - [3. Create `tailwind.config.ts`](#3-create-tailwindconfigts)
14
+ - [4. Configure Tailwind and Nova Plugin in `styles.css`](#4-configure-tailwind-and-nova-plugin-in-stylescss)
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)
21
+ - [Standalone Component Setup](#standalone-component-setup)
22
+ - [1. Provide Nova Components](#1-provide-nova-components)
23
+ - [2. Configuring Standalone Components](#2-configuring-standalone-components)
24
+ - [Module-Based Setup](#module-based-setup)
25
+ - [Handling Angular Forms with Nova Components](#handling-angular-forms-with-nova-components)
26
+ - [Standalone Component Setup with Forms](#standalone-component-setup-with-forms)
27
+ - [Module-Based Setup](#module-based-setup-1)
28
+ - [Usage Example with Angular Forms](#usage-example-with-angular-forms)
29
+ - [Conclusion](#conclusion)
30
+
31
+ ---
32
+
33
+ ## Installation
34
+
35
+ Install the necessary Nova packages using your package manager:
36
+
37
+ ```bash
38
+ npm install @nova-design-system/nova-webcomponents @nova-design-system/nova-base @nova-design-system/nova-angular-18
39
+ ```
40
+
41
+ or
42
+
43
+ ```bash
44
+ yarn add @nova-design-system/nova-webcomponents @nova-design-system/nova-base @nova-design-system/nova-angular-18
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Setup
50
+
51
+ ### CSS Integration Using Tailwind (Recommended)
52
+
53
+ 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
+
55
+ > **Tailwind Version**
56
+ > This guide is written for Tailwind v4. While compatible with v3, some features may not work as expected.
57
+
58
+ Visit the official [Tailwind CSS Angular documentation](https://tailwindcss.com/docs/installation/framework-guides/angular) for more detailed installation instructions.
59
+
60
+ #### 1. Install Tailwind CSS
61
+
62
+ ```bash
63
+ npm install tailwindcss @tailwindcss/postcss postcss
64
+ ```
65
+
66
+ #### 2. Configure PostCSS Plugins
67
+
68
+ Create a `.postcssrc.json` file in the root of your project and add the `@tailwindcss/postcss` plugin to your PostCSS configuration.
69
+
70
+ ```json
71
+ {
72
+ "plugins": {
73
+ "@tailwindcss/postcss": {}
74
+ }
75
+ }
76
+ ```
77
+
78
+ #### 3. Create `tailwind.config.ts`
79
+
80
+ In the root of your project, create a `tailwind.config.ts` file and include the Nova theme:
81
+
82
+ ```typescript
83
+ import type { Config } from 'tailwindcss'
84
+ import { novaTailwindTheme } from "@nova-design-system/nova-base/theme"
85
+
86
+ export default {
87
+ theme: novaTailwindTheme,
88
+ } satisfies Config
89
+ ```
90
+
91
+ #### 4. Configure Tailwind and Nova Plugin in `styles.css`
92
+
93
+ In `./src/styles.css`, add the Tailwind import, the config path, the dark mode class, and the Nova plugin:
94
+
95
+ ```css
96
+ @import 'tailwindcss';
97
+
98
+ @config "../tailwind.config.ts";
99
+ @plugin "@nova-design-system/nova-base/theme/plugin";
100
+ @custom-variant dark (&:where(.dark, .dark *));
101
+ ```
102
+
103
+ > **Dark Mode**
104
+ > To enable dark mode, add the `dark` class to the `<body>` element.
105
+
106
+ #### 5. Include the Nova Tokens (Spark or Ocean)
107
+
108
+ Add the Nova Tokens CSS file to the `styles` array in your `angular.json` configuration:
109
+
110
+ ```json
111
+ {
112
+ ...
113
+ "styles": [
114
+ "src/styles.css",
115
+ "@nova-design-system/nova-base/dist/css/spark.css" // or ocean.css
116
+ ],
117
+ ...
118
+ }
119
+ ```
120
+
121
+ ### CSS Integration Without Tailwind (Not Recommended)
122
+
123
+ 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.
124
+
125
+ 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:
126
+
127
+ ```json
128
+ {
129
+ ...
130
+ "styles": [
131
+ "src/styles.css",
132
+ "@nova-design-system/nova-base/dist/css/nova-utils.css",
133
+ "@nova-design-system/nova-base/dist/css/spark.css" // or ocean.css
134
+ ],
135
+ ...
136
+ }
137
+ ```
138
+
139
+ This setup ensures that the Nova styles are available throughout your application.
140
+
141
+ ### Nova Font Pro Integration
142
+
143
+ > [!WARNING]
144
+ > 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.
145
+ > 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).
146
+
147
+ Once you have the URL, you can integrate it using any of these methods:
148
+
149
+ #### Option 1: Angular.json Configuration (Recommended)
150
+
151
+ Add the Nova Font Pro CDN URL to the styles array in your `angular.json` configuration:
152
+
153
+ ```json
154
+ "styles": [
155
+ "https://novaassets.azureedge.net/fonts/nova-fonts-pro.css"
156
+ ]
157
+ ```
158
+
159
+ #### Option 2: Import in Styles.css
160
+
161
+ ```css
162
+ @import url('https://novaassets.azureedge.net/fonts/nova-fonts-pro.css');
163
+ ```
164
+
165
+ #### Option 3: HTML Integration
166
+
167
+ ```html
168
+ <!DOCTYPE html>
169
+ <html>
170
+ <head>
171
+ <link rel="stylesheet" href="https://novaassets.azureedge.net/fonts/nova-fonts-pro.css">
172
+ </head>
173
+ <body>
174
+ <app-root></app-root>
175
+ </body>
176
+ </html>
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Standalone Component Setup
182
+
183
+ Angular 18 encourages the use of standalone components with modern configuration. Follow these steps to integrate Nova Components into your Angular application:
184
+
185
+ ### 1. Provide Nova Components
186
+
187
+ To make Nova Web Components available across your application, add the `provideNovaComponents` function as a provider in your application configuration:
188
+
189
+ ```typescript
190
+ import { APP_INITIALIZER } from '@angular/core';
191
+ import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
192
+
193
+ export const appConfig: ApplicationConfig = {
194
+ providers: [
195
+ {
196
+ provide: APP_INITIALIZER,
197
+ useFactory: () => defineCustomElements, // Add the nova initializer here
198
+ deps: [],
199
+ multi: true,
200
+ },
201
+ ],
202
+ };
203
+ ```
204
+
205
+ ### 2. Configuring Standalone Components
206
+
207
+ For any standalone component where you want to use Nova Components, configure your component to include the nova-components module:
208
+
209
+ ```typescript
210
+ import { Component } from '@angular/core';
211
+ import { RouterOutlet } from '@angular/router';
212
+ import { NovaComponentsModule } from '@nova-design-system/nova-angular-18';
213
+
214
+ @Component({
215
+ selector: 'app-root',
216
+ standalone: true,
217
+ imports: [RouterOutlet, NovaComponentsModule],
218
+ templateUrl: './app.component.html',
219
+ styleUrls: ['./app.component.css']
220
+ })
221
+ export class AppComponent {
222
+ // Your component logic here
223
+ }
224
+ ```
225
+
226
+ > **Note:** Module-based setup is not supported in Angular 18. Please use the standalone component approach as shown above.
227
+
228
+ ---
229
+
230
+ ## Module-Based Setup
231
+
232
+ 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:
233
+
234
+ ```typescript
235
+ import { NgModule, APP_INITIALIZER } from '@angular/core';
236
+ import { NovaComponentsModule } from '@nova-design-system/nova-angular-18';
237
+ import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
238
+
239
+ @NgModule({
240
+ declarations: [AppComponent],
241
+ imports: [
242
+ BrowserModule,
243
+ AppRoutingModule,
244
+ NovaComponentsModule // Add NovaComponentsModule here
245
+ ],
246
+ providers: [
247
+ {
248
+ provide: APP_INITIALIZER,
249
+ useFactory: () => defineCustomElements, // Add the nova initializer here
250
+ deps: [],
251
+ multi: true,
252
+ },
253
+ ],
254
+ bootstrap: [AppComponent]
255
+ })
256
+ export class AppModule {}
257
+ ```
258
+
259
+ By including `NovaComponentsModule` in your imports, Nova's web components become available throughout the module.
260
+
261
+ ---
262
+
263
+ ## Handling Angular Forms with Nova Components
264
+
265
+ Nova Components Angular supports seamless integration with Angular's reactive and template-driven forms through the `NovaComponentsValueAccessorModule`.
266
+
267
+ ### Standalone Component Setup with Forms
268
+
269
+ 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`:
270
+
271
+ ```typescript
272
+ import { Component } from '@angular/core';
273
+ import { RouterOutlet } from '@angular/router';
274
+ import { FormsModule } from '@angular/forms';
275
+ import { NovaComponentsValueAccessorModule, NovaComponentsModule } from '@nova-design-system/nova-angular-18';
276
+
277
+ @Component({
278
+ selector: 'app-root',
279
+ standalone: true,
280
+ imports: [
281
+ RouterOutlet,
282
+ FormsModule,
283
+ NovaComponentsModule,
284
+ NovaComponentsValueAccessorModule, // Enables form integration for Nova components
285
+ ],
286
+ templateUrl: './app.component.html',
287
+ styleUrls: ['./app.component.css'],
288
+ })
289
+ export class AppComponent {
290
+ inputValue = 'hello';
291
+ }
292
+ ```
293
+
294
+ ### Module-Based Setup
295
+
296
+ If you're using Angular modules, you can also integrate the value accessors by importing the `NovaComponentsValueAccessorModule` in your module:
297
+
298
+ ```typescript
299
+ import { NgModule, APP_INITIALIZER } from '@angular/core';
300
+ import { BrowserModule } from '@angular/platform-browser';
301
+ import { FormsModule } from '@angular/forms';
302
+ import {
303
+ NovaComponentsModule,
304
+ NovaComponentsValueAccessorModule,
305
+ } from '@nova-design-system/nova-angular';
306
+ import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
307
+
308
+ @NgModule({
309
+ declarations: [AppComponent],
310
+ imports: [
311
+ BrowserModule,
312
+ FormsModule,
313
+ NovaComponentsModule, // Add NovaComponentsModule here
314
+ NovaComponentsValueAccessorModule, // Import the Value Accessor Module here
315
+ ],
316
+ providers: [
317
+ {
318
+ provide: APP_INITIALIZER,
319
+ useFactory: () => defineCustomElements, // Add the nova initializer here
320
+ deps: [],
321
+ multi: true,
322
+ },
323
+ ],
324
+ bootstrap: [AppComponent]
325
+ })
326
+ export class AppModule {}
327
+ ```
328
+
329
+ This setup ensures that Nova components are fully compatible with Angular forms throughout your module.
330
+
331
+ ### Usage Example with Angular Forms
332
+
333
+ With the value accessors set up, you can now use Nova components within Angular forms. Here's an example:
334
+
335
+ ```html
336
+ <form>
337
+ <nv-fieldtext [(ngModel)]="inputValue" name="input"></nv-fieldtext>
338
+ <button type="submit">Submit</button>
339
+ </form>
340
+ ```
341
+
342
+ In your component:
343
+
344
+ ```typescript
345
+ export class AppComponent {
346
+ inputValue = 'hello';
347
+ }
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Conclusion
353
+
354
+ Nova Components Angular provides an easy and flexible way to incorporate Nova's UI components into your Angular 18 projects. By following the steps in this guide, you'll be able to integrate Nova's native UI elements using Angular's modern standalone component architecture and fully leverage Angular forms.
355
+
356
+ 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.
357
+
358
+ Happy coding with Nova and Angular!
359
+ ```
@@ -0,0 +1,24 @@
1
+ # NovaComponents
2
+
3
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Run `ng generate component component-name --project nova-components` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project nova-components`.
8
+ > Note: Don't forget to add `--project nova-components` or else it will be added to the default project in your `angular.json` file.
9
+
10
+ ## Build
11
+
12
+ Run `ng build nova-components` to build the project. The build artifacts will be stored in the `dist/` directory.
13
+
14
+ ## Publishing
15
+
16
+ After building your library with `ng build nova-components`, go to the dist folder `cd dist/nova-components` and run `npm publish`.
17
+
18
+ ## Running unit tests
19
+
20
+ Run `ng test nova-components` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
+
22
+ ## Further help
23
+
24
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,45 @@
1
+ import { APP_INITIALIZER, NgModule } from '@angular/core';
2
+ import { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
3
+ import { DIRECTIVES } from './stencil-generated';
4
+ import { VALUE_ACCESSORS } from './stencil-generated/component-value-accessors';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "./stencil-generated/components";
7
+ import * as i2 from "./stencil-generated/component-value-accessors";
8
+ /**
9
+ * Initialize the Nova Components
10
+ *
11
+ * @returns {Provider} - The provider to be used for nova components
12
+ */
13
+ export function provideNovaComponents() {
14
+ return {
15
+ provide: APP_INITIALIZER,
16
+ useFactory: () => defineCustomElements,
17
+ multi: true,
18
+ };
19
+ }
20
+ export class NovaComponentsModule {
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.NvAlert, i1.NvAvatar, i1.NvBadge, i1.NvBase, i1.NvBreadcrumb, i1.NvBreadcrumbs, i1.NvButton, i1.NvCalendar, i1.NvCol, i1.NvDatagrid, i1.NvDatagridcolumn, i1.NvDialog, i1.NvDialogfooter, i1.NvDialogheader, i1.NvFieldcheckbox, i1.NvFielddropdown, i1.NvFielddropdownitem, i1.NvFielddropdownitemcheck, i1.NvFieldmultiselect, i1.NvFieldnumber, i1.NvFieldpassword, i1.NvFieldradio, i1.NvFieldselect, 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.NvTooltip], exports: [i1.NvAlert, i1.NvAvatar, i1.NvBadge, i1.NvBase, i1.NvBreadcrumb, i1.NvBreadcrumbs, i1.NvButton, i1.NvCalendar, i1.NvCol, i1.NvDatagrid, i1.NvDatagridcolumn, i1.NvDialog, i1.NvDialogfooter, i1.NvDialogheader, i1.NvFieldcheckbox, i1.NvFielddropdown, i1.NvFielddropdownitem, i1.NvFielddropdownitemcheck, i1.NvFieldmultiselect, i1.NvFieldnumber, i1.NvFieldpassword, i1.NvFieldradio, i1.NvFieldselect, 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.NvTooltip] }); }
23
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, providers: [provideNovaComponents()] }); }
24
+ }
25
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, decorators: [{
26
+ type: NgModule,
27
+ args: [{
28
+ declarations: [...DIRECTIVES],
29
+ exports: [...DIRECTIVES],
30
+ providers: [provideNovaComponents()],
31
+ }]
32
+ }] });
33
+ export class NovaComponentsValueAccessorModule {
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.NvFieldcheckboxValueAccessor, i2.NvFielddropdownValueAccessor, i2.NvFieldmultiselectValueAccessor, i2.NvFieldnumberValueAccessor, i2.NvFieldpasswordValueAccessor, i2.NvFieldradioValueAccessor, i2.NvFieldselectValueAccessor, i2.NvFieldtextValueAccessor, i2.NvFieldtextareaValueAccessor, i2.NvPopoverValueAccessor, i2.NvToggleValueAccessor], exports: [i2.NvAlertValueAccessor, i2.NvFieldcheckboxValueAccessor, i2.NvFielddropdownValueAccessor, i2.NvFieldmultiselectValueAccessor, i2.NvFieldnumberValueAccessor, i2.NvFieldpasswordValueAccessor, i2.NvFieldradioValueAccessor, i2.NvFieldselectValueAccessor, i2.NvFieldtextValueAccessor, i2.NvFieldtextareaValueAccessor, i2.NvPopoverValueAccessor, i2.NvToggleValueAccessor] }); }
36
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule }); }
37
+ }
38
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsValueAccessorModule, decorators: [{
39
+ type: NgModule,
40
+ args: [{
41
+ declarations: [...VALUE_ACCESSORS],
42
+ exports: [...VALUE_ACCESSORS],
43
+ }]
44
+ }] });
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm92YS1jb21wb25lbnRzLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25vdmEtY29tcG9uZW50cy9zcmMvbGliL25vdmEtY29tcG9uZW50cy5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQWlCLE1BQU0sZUFBZSxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBRXJGLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sK0NBQStDLENBQUM7Ozs7QUFFaEY7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxxQkFBcUI7SUFDbkMsT0FBTztRQUNMLE9BQU8sRUFBRSxlQUFlO1FBQ3hCLFVBQVUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxvQkFBb0I7UUFDdEMsS0FBSyxFQUFFLElBQUk7S0FDWixDQUFDO0FBQ0osQ0FBQztBQU9ELE1BQU0sT0FBTyxvQkFBb0I7K0dBQXBCLG9CQUFvQjtnSEFBcEIsb0JBQW9CO2dIQUFwQixvQkFBb0IsYUFGcEIsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDOzs0RkFFekIsb0JBQW9CO2tCQUxoQyxRQUFRO21CQUFDO29CQUNSLFlBQVksRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDO29CQUM3QixPQUFPLEVBQUUsQ0FBQyxHQUFHLFVBQVUsQ0FBQztvQkFDeEIsU0FBUyxFQUFFLENBQUMscUJBQXFCLEVBQUUsQ0FBQztpQkFDckM7O0FBT0QsTUFBTSxPQUFPLGlDQUFpQzsrR0FBakMsaUNBQWlDO2dIQUFqQyxpQ0FBaUM7Z0hBQWpDLGlDQUFpQzs7NEZBQWpDLGlDQUFpQztrQkFKN0MsUUFBUTttQkFBQztvQkFDUixZQUFZLEVBQUUsQ0FBQyxHQUFHLGVBQWUsQ0FBQztvQkFDbEMsT0FBTyxFQUFFLENBQUMsR0FBRyxlQUFlLENBQUM7aUJBQzlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQVBQX0lOSVRJQUxJWkVSLCBOZ01vZHVsZSwgdHlwZSBQcm92aWRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZGVmaW5lQ3VzdG9tRWxlbWVudHMgfSBmcm9tICdAbm92YS1kZXNpZ24tc3lzdGVtL25vdmEtd2ViY29tcG9uZW50cy9sb2FkZXInO1xuXG5pbXBvcnQgeyBESVJFQ1RJVkVTIH0gZnJvbSAnLi9zdGVuY2lsLWdlbmVyYXRlZCc7XG5pbXBvcnQgeyBWQUxVRV9BQ0NFU1NPUlMgfSBmcm9tICcuL3N0ZW5jaWwtZ2VuZXJhdGVkL2NvbXBvbmVudC12YWx1ZS1hY2Nlc3NvcnMnO1xuXG4vKipcbiAqIEluaXRpYWxpemUgdGhlIE5vdmEgQ29tcG9uZW50c1xuICpcbiAqIEByZXR1cm5zIHtQcm92aWRlcn0gLSBUaGUgcHJvdmlkZXIgdG8gYmUgdXNlZCBmb3Igbm92YSBjb21wb25lbnRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlTm92YUNvbXBvbmVudHMoKTogUHJvdmlkZXIge1xuICByZXR1cm4ge1xuICAgIHByb3ZpZGU6IEFQUF9JTklUSUFMSVpFUixcbiAgICB1c2VGYWN0b3J5OiAoKSA9PiBkZWZpbmVDdXN0b21FbGVtZW50cyxcbiAgICBtdWx0aTogdHJ1ZSxcbiAgfTtcbn1cblxuQE5nTW9kdWxlKHtcbiAgZGVjbGFyYXRpb25zOiBbLi4uRElSRUNUSVZFU10sXG4gIGV4cG9ydHM6IFsuLi5ESVJFQ1RJVkVTXSxcbiAgcHJvdmlkZXJzOiBbcHJvdmlkZU5vdmFDb21wb25lbnRzKCldLFxufSlcbmV4cG9ydCBjbGFzcyBOb3ZhQ29tcG9uZW50c01vZHVsZSB7fVxuXG5ATmdNb2R1bGUoe1xuICBkZWNsYXJhdGlvbnM6IFsuLi5WQUxVRV9BQ0NFU1NPUlNdLFxuICBleHBvcnRzOiBbLi4uVkFMVUVfQUNDRVNTT1JTXSxcbn0pXG5leHBvcnQgY2xhc3MgTm92YUNvbXBvbmVudHNWYWx1ZUFjY2Vzc29yTW9kdWxlIHt9XG4iXX0=
@@ -0,0 +1,59 @@
1
+ /* eslint-disable */
2
+ /* tslint:disable */
3
+ import { fromEvent } from 'rxjs';
4
+ export const proxyInputs = (Cmp, inputs) => {
5
+ const Prototype = Cmp.prototype;
6
+ inputs.forEach((item) => {
7
+ Object.defineProperty(Prototype, item, {
8
+ get() {
9
+ return this.el[item];
10
+ },
11
+ set(val) {
12
+ this.z.runOutsideAngular(() => (this.el[item] = val));
13
+ },
14
+ /**
15
+ * In the event that proxyInputs is called
16
+ * multiple times re-defining these inputs
17
+ * will cause an error to be thrown. As a result
18
+ * we set configurable: true to indicate these
19
+ * properties can be changed.
20
+ */
21
+ configurable: true,
22
+ });
23
+ });
24
+ };
25
+ export const proxyMethods = (Cmp, methods) => {
26
+ const Prototype = Cmp.prototype;
27
+ methods.forEach((methodName) => {
28
+ Prototype[methodName] = function () {
29
+ const args = arguments;
30
+ return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
31
+ };
32
+ });
33
+ };
34
+ export const proxyOutputs = (instance, el, events) => {
35
+ events.forEach((eventName) => (instance[eventName] = fromEvent(el, eventName)));
36
+ };
37
+ export const defineCustomElement = (tagName, customElement) => {
38
+ if (customElement !== undefined && typeof customElements !== 'undefined' && !customElements.get(tagName)) {
39
+ customElements.define(tagName, customElement);
40
+ }
41
+ };
42
+ // tslint:disable-next-line: only-arrow-functions
43
+ export function ProxyCmp(opts) {
44
+ const decorator = function (cls) {
45
+ const { defineCustomElementFn, inputs, methods } = opts;
46
+ if (defineCustomElementFn !== undefined) {
47
+ defineCustomElementFn();
48
+ }
49
+ if (inputs) {
50
+ proxyInputs(cls, inputs);
51
+ }
52
+ if (methods) {
53
+ proxyMethods(cls, methods);
54
+ }
55
+ return cls;
56
+ };
57
+ return decorator;
58
+ }
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9ub3ZhLWNvbXBvbmVudHMvc3JjL2xpYi9zdGVuY2lsLWdlbmVyYXRlZC9hbmd1bGFyLWNvbXBvbmVudC1saWIvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLG9CQUFvQjtBQUNwQixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRWpDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFDLEdBQVEsRUFBRSxNQUFnQixFQUFFLEVBQUU7SUFDeEQsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQztJQUNoQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7UUFDdEIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFO1lBQ3JDLEdBQUc7Z0JBQ0QsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3ZCLENBQUM7WUFDRCxHQUFHLENBQUMsR0FBUTtnQkFDVixJQUFJLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3hELENBQUM7WUFDRDs7Ozs7O2VBTUc7WUFDSCxZQUFZLEVBQUUsSUFBSTtTQUNuQixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxDQUFDLEdBQVEsRUFBRSxPQUFpQixFQUFFLEVBQUU7SUFDMUQsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQztJQUNoQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7UUFDN0IsU0FBUyxDQUFDLFVBQVUsQ0FBQyxHQUFHO1lBQ3RCLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQztZQUN2QixPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2xGLENBQUMsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLENBQUMsUUFBYSxFQUFFLEVBQU8sRUFBRSxNQUFnQixFQUFFLEVBQUU7SUFDdkUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsU0FBUyxDQUFDLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDbEYsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxPQUFlLEVBQUUsYUFBa0IsRUFBRSxFQUFFO0lBQ3pFLElBQUksYUFBYSxLQUFLLFNBQVMsSUFBSSxPQUFPLGNBQWMsS0FBSyxXQUFXLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDekcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDaEQsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLGlEQUFpRDtBQUNqRCxNQUFNLFVBQVUsUUFBUSxDQUFDLElBQXlFO0lBQ2hHLE1BQU0sU0FBUyxHQUFHLFVBQVUsR0FBUTtRQUNsQyxNQUFNLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQztRQUV4RCxJQUFJLHFCQUFxQixLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3hDLHFCQUFxQixFQUFFLENBQUM7UUFDMUIsQ0FBQztRQUVELElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxXQUFXLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFDRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osWUFBWSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDLENBQUM7SUFDRixPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgKi9cbi8qIHRzbGludDpkaXNhYmxlICovXG5pbXBvcnQgeyBmcm9tRXZlbnQgfSBmcm9tICdyeGpzJztcblxuZXhwb3J0IGNvbnN0IHByb3h5SW5wdXRzID0gKENtcDogYW55LCBpbnB1dHM6IHN0cmluZ1tdKSA9PiB7XG4gIGNvbnN0IFByb3RvdHlwZSA9IENtcC5wcm90b3R5cGU7XG4gIGlucHV0cy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFByb3RvdHlwZSwgaXRlbSwge1xuICAgICAgZ2V0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbFtpdGVtXTtcbiAgICAgIH0sXG4gICAgICBzZXQodmFsOiBhbnkpIHtcbiAgICAgICAgdGhpcy56LnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+ICh0aGlzLmVsW2l0ZW1dID0gdmFsKSk7XG4gICAgICB9LFxuICAgICAgLyoqXG4gICAgICAgKiBJbiB0aGUgZXZlbnQgdGhhdCBwcm94eUlucHV0cyBpcyBjYWxsZWRcbiAgICAgICAqIG11bHRpcGxlIHRpbWVzIHJlLWRlZmluaW5nIHRoZXNlIGlucHV0c1xuICAgICAgICogd2lsbCBjYXVzZSBhbiBlcnJvciB0byBiZSB0aHJvd24uIEFzIGEgcmVzdWx0XG4gICAgICAgKiB3ZSBzZXQgY29uZmlndXJhYmxlOiB0cnVlIHRvIGluZGljYXRlIHRoZXNlXG4gICAgICAgKiBwcm9wZXJ0aWVzIGNhbiBiZSBjaGFuZ2VkLlxuICAgICAgICovXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgfSk7XG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHByb3h5TWV0aG9kcyA9IChDbXA6IGFueSwgbWV0aG9kczogc3RyaW5nW10pID0+IHtcbiAgY29uc3QgUHJvdG90eXBlID0gQ21wLnByb3RvdHlwZTtcbiAgbWV0aG9kcy5mb3JFYWNoKChtZXRob2ROYW1lKSA9PiB7XG4gICAgUHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIHJldHVybiB0aGlzLnoucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4gdGhpcy5lbFttZXRob2ROYW1lXS5hcHBseSh0aGlzLmVsLCBhcmdzKSk7XG4gICAgfTtcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgcHJveHlPdXRwdXRzID0gKGluc3RhbmNlOiBhbnksIGVsOiBhbnksIGV2ZW50czogc3RyaW5nW10pID0+IHtcbiAgZXZlbnRzLmZvckVhY2goKGV2ZW50TmFtZSkgPT4gKGluc3RhbmNlW2V2ZW50TmFtZV0gPSBmcm9tRXZlbnQoZWwsIGV2ZW50TmFtZSkpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBkZWZpbmVDdXN0b21FbGVtZW50ID0gKHRhZ05hbWU6IHN0cmluZywgY3VzdG9tRWxlbWVudDogYW55KSA9PiB7XG4gIGlmIChjdXN0b21FbGVtZW50ICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGN1c3RvbUVsZW1lbnRzICE9PSAndW5kZWZpbmVkJyAmJiAhY3VzdG9tRWxlbWVudHMuZ2V0KHRhZ05hbWUpKSB7XG4gICAgY3VzdG9tRWxlbWVudHMuZGVmaW5lKHRhZ05hbWUsIGN1c3RvbUVsZW1lbnQpO1xuICB9XG59O1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG9ubHktYXJyb3ctZnVuY3Rpb25zXG5leHBvcnQgZnVuY3Rpb24gUHJveHlDbXAob3B0czogeyBkZWZpbmVDdXN0b21FbGVtZW50Rm4/OiAoKSA9PiB2b2lkOyBpbnB1dHM/OiBhbnk7IG1ldGhvZHM/OiBhbnkgfSkge1xuICBjb25zdCBkZWNvcmF0b3IgPSBmdW5jdGlvbiAoY2xzOiBhbnkpIHtcbiAgICBjb25zdCB7IGRlZmluZUN1c3RvbUVsZW1lbnRGbiwgaW5wdXRzLCBtZXRob2RzIH0gPSBvcHRzO1xuXG4gICAgaWYgKGRlZmluZUN1c3RvbUVsZW1lbnRGbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkZWZpbmVDdXN0b21FbGVtZW50Rm4oKTtcbiAgICB9XG5cbiAgICBpZiAoaW5wdXRzKSB7XG4gICAgICBwcm94eUlucHV0cyhjbHMsIGlucHV0cyk7XG4gICAgfVxuICAgIGlmIChtZXRob2RzKSB7XG4gICAgICBwcm94eU1ldGhvZHMoY2xzLCBtZXRob2RzKTtcbiAgICB9XG4gICAgcmV0dXJuIGNscztcbiAgfTtcbiAgcmV0dXJuIGRlY29yYXRvcjtcbn1cbiJdfQ==