@kern-ux-annex/kern-angular-kit 0.3.4 → 0.3.6

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/COMPONENTS.md ADDED
@@ -0,0 +1,816 @@
1
+ # KERN Angular Kit Components
2
+
3
+ This document provides comprehensive documentation for all components available in the `@kern-ux-annex/kern-angular-kit` library. The library follows the KERN Design System and provides Angular 20.1+ compatible components with InputSignal support and modern patterns.
4
+
5
+ **Current Version:** 0.1.2 (July 25, 2025)
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Getting Started](#getting-started)
11
+ - [Form Input Components](#form-input-components)
12
+ - [UI Components](#ui-components)
13
+ - [Services](#services)
14
+ - [Common Patterns](#common-patterns)
15
+ - [Examples](#examples)
16
+
17
+ ## Installation
18
+
19
+ Install the library via npm:
20
+
21
+ ```bash
22
+ npm install @kern-ux-annex/kern-angular-kit
23
+ ```
24
+
25
+ ## Getting Started
26
+
27
+ ### Import the Module
28
+
29
+ You can import the entire module or individual components:
30
+
31
+ ```typescript
32
+ // Option 1: Import the entire module (NgModule approach)
33
+ import { NgModule } from '@angular/core';
34
+ import { KernAngularKitModule } from '@kern-ux-annex/kern-angular-kit';
35
+
36
+ @NgModule({
37
+ imports: [KernAngularKitModule]
38
+ // ...
39
+ })
40
+ export class AppModule {}
41
+
42
+ // Option 2: Import individual components (Standalone approach - Recommended)
43
+ import { Component } from '@angular/core';
44
+ import {
45
+ KernInputText,
46
+ KernInputCheckbox,
47
+ KernAlert
48
+ } from '@kern-ux-annex/kern-angular-kit';
49
+
50
+ @Component({
51
+ selector: 'app-example',
52
+ imports: [KernInputText, KernInputCheckbox, KernAlert],
53
+ template: `...`
54
+ })
55
+ export class ExampleComponent {}
56
+ ```
57
+
58
+ ### Required CSS
59
+
60
+ Make sure to include the KERN UX CSS framework:
61
+
62
+ ```bash
63
+ npm install @kern-ux/native
64
+ ```
65
+
66
+ Add to your `angular.json` or main CSS file:
67
+
68
+ ```css
69
+ @import '@kern-ux/native/dist/kern.min.css';
70
+ ```
71
+
72
+ ### Peer Dependencies
73
+
74
+ The library requires these Angular packages:
75
+
76
+ - `@angular/core`: ^20.1.0
77
+ - `@angular/common`: ^20.1.0
78
+ - `@angular/forms`: ^20.1.0
79
+
80
+ ## Form Input Components
81
+
82
+ All form input components implement Angular's `ControlValueAccessor` interface and support Angular Forms (Template-driven and Reactive).
83
+
84
+ ### Common Properties
85
+
86
+ All form input components share these common properties:
87
+
88
+ | Property | Type | Required | Default | Description |
89
+ | ----------- | ---------------- | -------- | -------------- | ------------------------------------ |
90
+ | `inputId` | `string` | No | Auto-generated | Custom ID for the input element |
91
+ | `labelText` | `string` | **Yes** | - | Label text for the input |
92
+ | `optional` | `boolean` | No | `false` | Shows "Optional" indicator |
93
+ | `required` | `boolean` | No | `false` | Marks field as required |
94
+ | `readonly` | `boolean` | No | `false` | Makes input read-only |
95
+ | `hintText` | `string \| null` | No | `null` | Helper text below the input |
96
+ | `errorText` | `string \| null` | No | `null` | Error message (triggers error state) |
97
+
98
+ ### KernInputText
99
+
100
+ Text input component for general text input.
101
+
102
+ **Selector:** `kern-input-text`
103
+
104
+ **Additional Properties:**
105
+
106
+ | Property | Type | Default | Description |
107
+ | -------------- | -------------------------------- | ------- | ------------------------ |
108
+ | `inputmode` | `'decimal' \| 'numeric' \| null` | `null` | Virtual keyboard hint |
109
+ | `maxlength` | `number \| null` | `null` | Maximum character length |
110
+ | `autocomplete` | `string \| null` | `null` | Autocomplete attribute |
111
+
112
+ **Example:**
113
+
114
+ ```html
115
+ <kern-input-text
116
+ labelText="Full Name"
117
+ hintText="Enter your first and last name"
118
+ [maxlength]="50"
119
+ autocomplete="name"
120
+ [(ngModel)]="fullName"
121
+ >
122
+ </kern-input-text>
123
+
124
+ <!-- With Reactive Forms -->
125
+ <kern-input-text
126
+ labelText="Username"
127
+ autocomplete="username"
128
+ [formControl]="usernameControl"
129
+ >
130
+ </kern-input-text>
131
+ ```
132
+
133
+ ### KernInputEmail
134
+
135
+ Email input component with built-in email validation.
136
+
137
+ **Selector:** `kern-input-email`
138
+
139
+ **Additional Properties:**
140
+
141
+ | Property | Type | Default | Description |
142
+ | ----------- | ---------------- | ------- | ------------------------ |
143
+ | `maxlength` | `number \| null` | `null` | Maximum character length |
144
+
145
+ **Example:**
146
+
147
+ ```html
148
+ <kern-input-email
149
+ labelText="Email Address"
150
+ autocomplete="email"
151
+ [required]="true"
152
+ [(ngModel)]="email"
153
+ >
154
+ </kern-input-email>
155
+ ```
156
+
157
+ ### KernInputPassword
158
+
159
+ Password input component with visibility toggle.
160
+
161
+ **Selector:** `kern-input-password`
162
+
163
+ **Additional Properties:**
164
+
165
+ | Property | Type | Default | Description |
166
+ | -------------- | ---------------- | ------- | ---------------------- |
167
+ | `autocomplete` | `string \| null` | `null` | Autocomplete attribute |
168
+
169
+ **Example:**
170
+
171
+ ```html
172
+ <kern-input-password
173
+ labelText="Password"
174
+ autocomplete="current-password"
175
+ [required]="true"
176
+ [(ngModel)]="password"
177
+ >
178
+ </kern-input-password>
179
+ ```
180
+
181
+ ### KernInputTextarea
182
+
183
+ Multi-line text input component.
184
+
185
+ **Selector:** `kern-input-textarea`
186
+
187
+ **Additional Properties:**
188
+
189
+ | Property | Type | Default | Description |
190
+ | ----------- | ---------------- | ------- | ------------------------ |
191
+ | `rows` | `number \| null` | `null` | Number of visible rows |
192
+ | `maxlength` | `number \| null` | `null` | Maximum character length |
193
+
194
+ **Example:**
195
+
196
+ ```html
197
+ <kern-input-textarea
198
+ labelText="Description"
199
+ hintText="Provide a detailed description"
200
+ [rows]="4"
201
+ [maxlength]="500"
202
+ [(ngModel)]="description"
203
+ >
204
+ </kern-input-textarea>
205
+ ```
206
+
207
+ ### KernInputCheckbox
208
+
209
+ Checkbox input component.
210
+
211
+ **Selector:** `kern-input-checkbox`
212
+
213
+ **Properties:**
214
+
215
+ | Property | Type | Required | Default | Description |
216
+ | ----------- | --------- | -------- | -------------- | --------------------------- |
217
+ | `inputId` | `string` | No | Auto-generated | Custom ID for the input |
218
+ | `labelText` | `string` | **Yes** | - | Label text for the checkbox |
219
+ | `error` | `boolean` | No | `false` | Shows error state |
220
+
221
+ **Example:**
222
+
223
+ ```html
224
+ <kern-input-checkbox
225
+ labelText="I agree to the terms and conditions"
226
+ [(ngModel)]="agreedToTerms"
227
+ >
228
+ </kern-input-checkbox>
229
+
230
+ <kern-input-checkbox
231
+ labelText="Subscribe to newsletter"
232
+ [error]="newsletterError"
233
+ [formControl]="newsletterControl"
234
+ >
235
+ </kern-input-checkbox>
236
+ ```
237
+
238
+ ### KernInputRadio
239
+
240
+ Radio button group component.
241
+
242
+ **Selector:** `kern-input-radio`
243
+
244
+ **Additional Properties:**
245
+
246
+ | Property | Type | Default | Description |
247
+ | --------------------- | --------------------------------------- | ------------ | ----------------- |
248
+ | `options` | `Array<{value: string, label: string}>` | **Required** | Radio options |
249
+ | `horizontalAlignment` | `boolean` | `false` | Horizontal layout |
250
+
251
+ **Example:**
252
+
253
+ ```html
254
+ <kern-input-radio
255
+ labelText="Preferred Contact Method"
256
+ [options]="contactOptions"
257
+ [horizontalAlignment]="true"
258
+ [(ngModel)]="contactMethod"
259
+ >
260
+ </kern-input-radio>
261
+ ```
262
+
263
+ ````typescript
264
+ ```typescript
265
+ export class MyComponent {
266
+ contactOptions = [
267
+ { value: 'email', label: 'Email' },
268
+ { value: 'phone', label: 'Phone' },
269
+ { value: 'sms', label: 'SMS' }
270
+ ];
271
+ contactMethod = 'email';
272
+ }
273
+ ````
274
+
275
+ ### KernInputSelect
276
+
277
+ Select dropdown component.
278
+
279
+ **Selector:** `kern-input-select`
280
+
281
+ **Additional Properties:**
282
+
283
+ | Property | Type | Default | Description |
284
+ | --------- | --------------------------------------- | ------------ | -------------- |
285
+ | `options` | `Array<{value: string, label: string}>` | **Required** | Select options |
286
+
287
+ **Example:**
288
+
289
+ ```html
290
+ <kern-input-select
291
+ labelText="Country"
292
+ [options]="countryOptions"
293
+ hintText="Select your country of residence"
294
+ [(ngModel)]="selectedCountry"
295
+ >
296
+ </kern-input-select>
297
+ ```
298
+
299
+ ````typescript
300
+ export class MyComponent {
301
+ countryOptions = [
302
+ { value: 'de', label: 'Germany' },
303
+ { value: 'at', label: 'Austria' },
304
+ { value: 'ch', label: 'Switzerland' }
305
+ ];
306
+ selectedCountry = 'de';
307
+ }
308
+
309
+ ### KernInputDate
310
+
311
+ Date input component with separate fields for day, month, and year.
312
+
313
+ **Selector:** `kern-input-date`
314
+
315
+ **Additional Properties:**
316
+
317
+ | Property | Type | Default | Description |
318
+ | -------- | ---------------- | ------- | ------------------------- |
319
+ | `min` | `string \| null` | `null` | Minimum date (YYYY-MM-DD) |
320
+ | `max` | `string \| null` | `null` | Maximum date (YYYY-MM-DD) |
321
+
322
+ **Example:**
323
+
324
+ ```html
325
+ <kern-input-date
326
+ labelText="Birth Date"
327
+ hintText="For example: 17 10 2015"
328
+ [max]="maxDate"
329
+ [(ngModel)]="birthDate"
330
+ >
331
+ </kern-input-date>
332
+ ````
333
+
334
+ ```typescript
335
+ export class MyComponent {
336
+ maxDate = '2025-12-31';
337
+ birthDate: string | null = null;
338
+ }
339
+ ```
340
+
341
+ ### KernInputTel
342
+
343
+ Telephone number input component with autocomplete support.
344
+
345
+ **Selector:** `kern-input-tel`
346
+
347
+ **Additional Properties:**
348
+
349
+ | Property | Type | Default | Description |
350
+ | ----------- | ---------------- | ------- | ------------------------ |
351
+ | `maxlength` | `number \| null` | `null` | Maximum character length |
352
+
353
+ **Example:**
354
+
355
+ ```html
356
+ <kern-input-tel
357
+ labelText="Phone Number"
358
+ autocomplete="tel"
359
+ hintText="Include country code if applicable"
360
+ [(ngModel)]="phoneNumber"
361
+ >
362
+ </kern-input-tel>
363
+ ```
364
+
365
+ ### KernInputUrl
366
+
367
+ URL input component with validation.
368
+
369
+ **Selector:** `kern-input-url`
370
+
371
+ **Additional Properties:**
372
+
373
+ | Property | Type | Default | Description |
374
+ | ----------- | ---------------- | ------- | ------------------------ |
375
+ | `maxlength` | `number \| null` | `null` | Maximum character length |
376
+
377
+ **Example:**
378
+
379
+ ```html
380
+ <kern-input-url
381
+ labelText="Website"
382
+ hintText="Enter your website URL (e.g., https://example.com)"
383
+ [(ngModel)]="website"
384
+ >
385
+ </kern-input-url>
386
+ ```
387
+
388
+ ### KernInputFile
389
+
390
+ File upload input component.
391
+
392
+ **Selector:** `kern-input-file`
393
+
394
+ **Additional Properties:**
395
+
396
+ | Property | Type | Default | Description |
397
+ | ---------- | ---------------- | ------- | -------------------- |
398
+ | `accept` | `string \| null` | `null` | Accepted file types |
399
+ | `multiple` | `boolean` | `false` | Allow multiple files |
400
+
401
+ **Example:**
402
+
403
+ ```html
404
+ <kern-input-file
405
+ labelText="Upload Documents"
406
+ accept=".pdf,.doc,.docx"
407
+ [multiple]="true"
408
+ [(ngModel)]="uploadedFiles"
409
+ >
410
+ </kern-input-file>
411
+ ```
412
+
413
+ ## UI Components
414
+
415
+ ### KernAlert
416
+
417
+ Alert/notification component for displaying messages.
418
+
419
+ **Selector:** `kern-alert`
420
+
421
+ **Properties:**
422
+
423
+ | Property | Type | Default | Description |
424
+ | -------- | ---------------------------------------------- | ------------ | ----------- |
425
+ | `title` | `string` | **Required** | Alert title |
426
+ | `type` | `'info' \| 'success' \| 'warning' \| 'danger'` | `'info'` | Alert type |
427
+
428
+ **Example:**
429
+
430
+ ```html
431
+ <kern-alert title="Success!" type="success">
432
+ Your form has been submitted successfully.
433
+ </kern-alert>
434
+
435
+ <kern-alert title="Warning" type="warning">
436
+ Please check your input before proceeding.
437
+ </kern-alert>
438
+ ```
439
+
440
+ ### KernAccordion
441
+
442
+ Collapsible content component.
443
+
444
+ **Selector:** `kern-accordion`
445
+
446
+ **Properties:**
447
+
448
+ | Property | Type | Default | Description |
449
+ | -------- | --------- | ------------ | -------------------- |
450
+ | `title` | `string` | **Required** | Accordion title |
451
+ | `open` | `boolean` | `false` | Initially open state |
452
+
453
+ **Example:**
454
+
455
+ ```html
456
+ <kern-accordion title="Frequently Asked Questions" [open]="true">
457
+ <p>This is the accordion content that can be collapsed or expanded.</p>
458
+ <ul>
459
+ <li>Item 1</li>
460
+ <li>Item 2</li>
461
+ </ul>
462
+ </kern-accordion>
463
+ ```
464
+
465
+ ### KernDialog
466
+
467
+ Modal dialog component.
468
+
469
+ **Selector:** `kern-dialog`
470
+
471
+ **Properties:**
472
+
473
+ | Property | Type | Default | Description |
474
+ | ----------------------- | ---------------- | -------------- | --------------------- |
475
+ | `dialogId` | `string` | Auto-generated | Custom dialog ID |
476
+ | `title` | `string` | **Required** | Dialog title |
477
+ | `btnCloseLabelText` | `string` | `'Schließen'` | Close button text |
478
+ | `btnPrimaryLabelText` | `string \| null` | `null` | Primary button text |
479
+ | `btnSecondaryLabelText` | `string \| null` | `null` | Secondary button text |
480
+
481
+ **Events:**
482
+
483
+ | Event | Type | Description |
484
+ | ------------------------ | ------- | ------------------------------------- |
485
+ | `cancelEvent` | `Event` | Emitted when dialog is cancelled |
486
+ | `btnPrimaryClickEvent` | `Event` | Emitted when primary button clicked |
487
+ | `btnSecondaryClickEvent` | `Event` | Emitted when secondary button clicked |
488
+
489
+ **Example:**
490
+
491
+ ```html
492
+ <kern-dialog
493
+ title="Confirm Action"
494
+ btnPrimaryLabelText="Confirm"
495
+ btnSecondaryLabelText="Cancel"
496
+ (btnPrimaryClickEvent)="onConfirm($event)"
497
+ (btnSecondaryClickEvent)="onCancel($event)"
498
+ >
499
+ <p>Are you sure you want to perform this action?</p>
500
+ </kern-dialog>
501
+ ```
502
+
503
+ ```typescript
504
+ export class MyComponent {
505
+ onConfirm(event: Event) {
506
+ console.log('User confirmed');
507
+ }
508
+
509
+ onCancel(event: Event) {
510
+ console.log('User cancelled');
511
+ }
512
+ }
513
+ ```
514
+
515
+ ### KernLoader
516
+
517
+ Loading spinner component.
518
+
519
+ **Selector:** `kern-loader`
520
+
521
+ **Properties:**
522
+
523
+ | Property | Type | Default | Description |
524
+ | -------- | -------- | -------------- | ------------------ |
525
+ | `text` | `string` | `'Loading...'` | Screen reader text |
526
+
527
+ **Example:**
528
+
529
+ ```html
530
+ <kern-loader text="Loading data..."></kern-loader>
531
+
532
+ <!-- Show conditionally -->
533
+ @if (isLoading) {
534
+ <kern-loader text="Saving your changes..."></kern-loader>
535
+ }
536
+ ```
537
+
538
+ ## Services
539
+
540
+ ### UniqueIdService
541
+
542
+ Service for generating unique IDs for form elements and accessibility.
543
+
544
+ **Methods:**
545
+
546
+ | Method | Parameters | Returns | Description |
547
+ | --------------- | ----------------- | -------- | ---------------------------------------- |
548
+ | `getUniqueId()` | `prefix?: string` | `string` | Generates unique ID with optional prefix |
549
+
550
+ **Example:**
551
+
552
+ ```typescript
553
+ import { UniqueIdService } from '@kern-ux-annex/kern-angular-kit';
554
+
555
+ export class MyComponent {
556
+ constructor(private uniqueIdService: UniqueIdService) {
557
+ const id = this.uniqueIdService.getUniqueId('my-component');
558
+ console.log(id); // "my-component_0"
559
+
560
+ const anotherId = this.uniqueIdService.getUniqueId('input');
561
+ console.log(anotherId); // "input_1"
562
+ }
563
+ }
564
+ ```
565
+
566
+ ## Common Patterns
567
+
568
+ ### Form Validation
569
+
570
+ ```typescript
571
+ import { Component } from '@angular/core';
572
+ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
573
+ import { KernInputText, KernInputEmail } from '@kern-ux-annex/kern-angular-kit';
574
+
575
+ @Component({
576
+ selector: 'app-user-form',
577
+ imports: [ReactiveFormsModule, KernInputText, KernInputEmail],
578
+ template: `
579
+ <form [formGroup]="userForm" (ngSubmit)="onSubmit()">
580
+ <kern-input-text
581
+ labelText="Full Name"
582
+ [required]="true"
583
+ [errorText]="getErrorText('name')"
584
+ formControlName="name"
585
+ >
586
+ </kern-input-text>
587
+
588
+ <kern-input-email
589
+ labelText="Email"
590
+ [required]="true"
591
+ [errorText]="getErrorText('email')"
592
+ formControlName="email"
593
+ >
594
+ </kern-input-email>
595
+
596
+ <button type="submit" [disabled]="userForm.invalid">Submit</button>
597
+ </form>
598
+ `
599
+ })
600
+ export class UserFormComponent {
601
+ userForm: FormGroup;
602
+
603
+ constructor(private fb: FormBuilder) {
604
+ this.userForm = this.fb.group({
605
+ name: ['', [Validators.required, Validators.minLength(2)]],
606
+ email: ['', [Validators.required, Validators.email]]
607
+ });
608
+ }
609
+
610
+ getErrorText(fieldName: string): string | null {
611
+ const field = this.userForm.get(fieldName);
612
+ if (field?.invalid && field?.touched) {
613
+ if (field.errors?.['required']) return 'This field is required';
614
+ if (field.errors?.['email']) return 'Please enter a valid email';
615
+ if (field.errors?.['minlength']) return 'Minimum 2 characters required';
616
+ }
617
+ return null;
618
+ }
619
+
620
+ onSubmit() {
621
+ if (this.userForm.valid) {
622
+ console.log(this.userForm.value);
623
+ }
624
+ }
625
+ }
626
+ ```
627
+
628
+ ### Dynamic Forms
629
+
630
+ ```typescript
631
+ @Component({
632
+ template: `
633
+ @for (field of formFields; track field.name) {
634
+ @switch (field.type) {
635
+ @case ('text') {
636
+ <kern-input-text
637
+ [labelText]="field.label"
638
+ [required]="field.required"
639
+ [(ngModel)]="formData[field.name]"
640
+ >
641
+ </kern-input-text>
642
+ }
643
+ @case ('email') {
644
+ <kern-input-email
645
+ [labelText]="field.label"
646
+ [required]="field.required"
647
+ [(ngModel)]="formData[field.name]"
648
+ >
649
+ </kern-input-email>
650
+ }
651
+ @case ('select') {
652
+ <kern-input-select
653
+ [labelText]="field.label"
654
+ [options]="field.options"
655
+ [required]="field.required"
656
+ [(ngModel)]="formData[field.name]"
657
+ >
658
+ </kern-input-select>
659
+ }
660
+ }
661
+ }
662
+ `
663
+ })
664
+ export class DynamicFormComponent {
665
+ formFields = [
666
+ { name: 'firstName', type: 'text', label: 'First Name', required: true },
667
+ { name: 'email', type: 'email', label: 'Email', required: true },
668
+ {
669
+ name: 'country',
670
+ type: 'select',
671
+ label: 'Country',
672
+ required: false,
673
+ options: [
674
+ { value: 'de', label: 'Germany' },
675
+ { value: 'at', label: 'Austria' }
676
+ ]
677
+ }
678
+ ];
679
+
680
+ formData: Record<string, any> = {};
681
+ }
682
+ ```
683
+
684
+ ## Examples
685
+
686
+ ### Complete Registration Form
687
+
688
+ ```typescript
689
+ import { Component } from '@angular/core';
690
+ import {
691
+ KernInputText,
692
+ KernInputEmail,
693
+ KernInputPassword,
694
+ KernInputCheckbox,
695
+ KernInputSelect,
696
+ KernAlert
697
+ } from '@kern-ux-annex/kern-angular-kit';
698
+
699
+ @Component({
700
+ selector: 'app-registration',
701
+ imports: [
702
+ FormsModule,
703
+ KernInputText,
704
+ KernInputEmail,
705
+ KernInputPassword,
706
+ KernInputCheckbox,
707
+ KernInputSelect,
708
+ KernAlert
709
+ ],
710
+ template: `
711
+ @if (showSuccess) {
712
+ <kern-alert title="Registration Successful!" type="success">
713
+ Welcome to our platform!
714
+ </kern-alert>
715
+ }
716
+
717
+ <form (ngSubmit)="onSubmit()" #form="ngForm">
718
+ <kern-input-text
719
+ labelText="Full Name"
720
+ [required]="true"
721
+ [(ngModel)]="user.fullName"
722
+ name="fullName"
723
+ >
724
+ </kern-input-text>
725
+
726
+ <kern-input-email
727
+ labelText="Email Address"
728
+ [required]="true"
729
+ [(ngModel)]="user.email"
730
+ name="email"
731
+ >
732
+ </kern-input-email>
733
+
734
+ <kern-input-password
735
+ labelText="Password"
736
+ [required]="true"
737
+ [(ngModel)]="user.password"
738
+ name="password"
739
+ >
740
+ </kern-input-password>
741
+
742
+ <kern-input-select
743
+ labelText="Country"
744
+ [options]="countryOptions"
745
+ [(ngModel)]="user.country"
746
+ name="country"
747
+ >
748
+ </kern-input-select>
749
+
750
+ <kern-input-checkbox
751
+ labelText="I agree to the Terms of Service"
752
+ [required]="true"
753
+ [(ngModel)]="user.agreedToTerms"
754
+ name="agreedToTerms"
755
+ >
756
+ </kern-input-checkbox>
757
+
758
+ <button
759
+ type="submit"
760
+ [disabled]="form.invalid"
761
+ class="kern-btn kern-btn--primary"
762
+ >
763
+ Register
764
+ </button>
765
+ </form>
766
+ `
767
+ })
768
+ export class RegistrationComponent {
769
+ showSuccess = false;
770
+
771
+ user = {
772
+ fullName: '',
773
+ email: '',
774
+ password: '',
775
+ country: '',
776
+ agreedToTerms: false
777
+ };
778
+
779
+ countryOptions = [
780
+ { value: 'de', label: 'Germany' },
781
+ { value: 'at', label: 'Austria' },
782
+ { value: 'ch', label: 'Switzerland' }
783
+ ];
784
+
785
+ onSubmit() {
786
+ console.log('User registration:', this.user);
787
+ this.showSuccess = true;
788
+ }
789
+ }
790
+ ```
791
+
792
+ ## Browser Support
793
+
794
+ - Chrome 90+
795
+ - Firefox 90+
796
+ - Safari 14+
797
+ - Edge 90+
798
+
799
+ ## Accessibility
800
+
801
+ All components follow WCAG 2.1 AA guidelines and include:
802
+
803
+ - Proper ARIA attributes
804
+ - Keyboard navigation support
805
+ - Screen reader compatibility
806
+ - Focus management
807
+ - High contrast support
808
+ - Unique IDs for form associations
809
+
810
+ ## Contributing
811
+
812
+ For contributing guidelines, please see the [CONTRIBUTING.md](./CONTRIBUTING.md) file in the repository.
813
+
814
+ ## License
815
+
816
+ This library is licensed under the EUPL-1.2 license.