mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
feat(checkout): add branch selection to reward catalog - Add new select-branch-dropdown library with BranchDropdownComponent and SelectedBranchDropdownComponent for branch selection - Extend DropdownButtonComponent with filter and option subcomponents - Integrate branch selection into reward catalog page - Add BranchesResource for fetching available branches - Update CheckoutMetadataService with branch selection persistence - Add comprehensive tests for dropdown components Related work items: #5464
713 lines
19 KiB
Markdown
713 lines
19 KiB
Markdown
# @isa/ui/input-controls
|
|
|
|
A comprehensive collection of form input components and directives for Angular applications supporting reactive forms, template-driven forms, and accessibility features.
|
|
|
|
## Overview
|
|
|
|
The Input Controls library provides a complete suite of reusable form components built on Angular's reactive forms API and Angular CDK. It includes text fields, checkboxes, dropdowns, chips, checklists, listboxes, and inline inputs - all designed to work seamlessly with Angular Forms while maintaining consistent styling and behavior across the ISA application.
|
|
|
|
## Table of Contents
|
|
|
|
- [Features](#features)
|
|
- [Quick Start](#quick-start)
|
|
- [Core Concepts](#core-concepts)
|
|
- [API Reference](#api-reference)
|
|
- [Usage Examples](#usage-examples)
|
|
- [Form Integration](#form-integration)
|
|
- [Accessibility](#accessibility)
|
|
- [Testing](#testing)
|
|
- [Architecture Notes](#architecture-notes)
|
|
|
|
## Features
|
|
|
|
- **Complete form control suite** - 8 component types covering common input scenarios
|
|
- **Reactive Forms integration** - ControlValueAccessor implementation for all form controls
|
|
- **Template-driven forms** - Full ngModel support for two-way binding
|
|
- **Keyboard navigation** - Arrow keys, Enter, Escape, and Tab support
|
|
- **Accessibility (a11y)** - ARIA attributes, screen reader support, keyboard navigation
|
|
- **Customizable appearance** - Multiple size and appearance variants for each control
|
|
- **Validation support** - Integration with Angular's built-in validators
|
|
- **CDK integration** - Built on Angular CDK primitives (listbox, a11y, overlay)
|
|
- **Signal-based inputs** - Modern Angular signals for reactive property management
|
|
- **Type-safe** - Full TypeScript support with generic type parameters
|
|
|
|
## Quick Start
|
|
|
|
### 1. Import Components
|
|
|
|
```typescript
|
|
import { Component } from '@angular/core';
|
|
import {
|
|
CheckboxComponent,
|
|
DropdownButtonComponent,
|
|
DropdownFilterComponent,
|
|
DropdownOptionComponent,
|
|
TextFieldComponent,
|
|
InputControlDirective,
|
|
} from '@isa/ui/input-controls';
|
|
import { ReactiveFormsModule } from '@angular/forms';
|
|
|
|
@Component({
|
|
selector: 'app-my-form',
|
|
imports: [
|
|
ReactiveFormsModule,
|
|
CheckboxComponent,
|
|
DropdownButtonComponent,
|
|
DropdownFilterComponent,
|
|
DropdownOptionComponent,
|
|
TextFieldComponent,
|
|
InputControlDirective,
|
|
],
|
|
template: '...'
|
|
})
|
|
export class MyFormComponent {}
|
|
```
|
|
|
|
### 2. Basic Text Field
|
|
|
|
```html
|
|
<ui-text-field>
|
|
<input
|
|
type="text"
|
|
uiInputControl
|
|
formControlName="username"
|
|
placeholder="Enter username"
|
|
/>
|
|
</ui-text-field>
|
|
```
|
|
|
|
### 3. Checkbox
|
|
|
|
```html
|
|
<ui-checkbox>
|
|
<input type="checkbox" formControlName="acceptTerms" />
|
|
</ui-checkbox>
|
|
```
|
|
|
|
### 4. Dropdown
|
|
|
|
```html
|
|
<ui-dropdown [(ngModel)]="selectedOption" label="Select option">
|
|
<ui-dropdown-option [value]="1">Option 1</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="2">Option 2</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="3">Option 3</ui-dropdown-option>
|
|
</ui-dropdown>
|
|
```
|
|
|
|
### 5. Dropdown with Filter
|
|
|
|
```html
|
|
<ui-dropdown [(ngModel)]="selectedCountry" label="Select country">
|
|
<ui-dropdown-filter placeholder="Search..."></ui-dropdown-filter>
|
|
<ui-dropdown-option [value]="'de'">Germany</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'at'">Austria</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'ch'">Switzerland</ui-dropdown-option>
|
|
</ui-dropdown>
|
|
```
|
|
|
|
## Core Concepts
|
|
|
|
### Component Categories
|
|
|
|
The library provides three main categories of form controls:
|
|
|
|
#### 1. Text Input Controls
|
|
- **TextFieldComponent** - Standard text input with container, labels, and errors
|
|
- **TextareaComponent** - Multi-line text input
|
|
- **InlineInputComponent** - Compact inline text input for space-constrained UIs
|
|
|
|
#### 2. Selection Controls
|
|
- **CheckboxComponent** - Single checkbox with bullet or checkbox appearance
|
|
- **ChecklistComponent** - Multiple checkboxes working as a group
|
|
- **DropdownButtonComponent** - Select dropdown with keyboard navigation
|
|
- **ChipsComponent** - Single-select chip group
|
|
- **ListboxDirective** - CDK listbox wrapper for custom list selections
|
|
|
|
#### 3. Supporting Components
|
|
- **InputControlDirective** - Core directive for input field integration
|
|
- **TextFieldContainerComponent** - Layout container for text fields
|
|
- **TextFieldErrorsComponent** - Validation error display
|
|
- **TextFieldClearComponent** - Clear button for text inputs
|
|
- **CheckboxLabelDirective** - Label styling for checkboxes
|
|
- **ChecklistValueDirective** - Value binding for checklist items
|
|
- **ChipOptionComponent** - Individual chip option
|
|
- **DropdownOptionComponent** - Individual dropdown option
|
|
- **DropdownFilterComponent** - Filter input for dropdown options
|
|
- **ListboxItemDirective** - Individual listbox item
|
|
|
|
### Control Value Accessor Pattern
|
|
|
|
All form controls implement Angular's `ControlValueAccessor` interface, enabling seamless integration with both reactive and template-driven forms:
|
|
|
|
```typescript
|
|
export class DropdownButtonComponent<T> implements ControlValueAccessor {
|
|
value = model<T>();
|
|
disabled = model<boolean>(false);
|
|
|
|
writeValue(obj: unknown): void { ... }
|
|
registerOnChange(fn: (value: T) => void): void { ... }
|
|
registerOnTouched(fn: () => void): void { ... }
|
|
setDisabledState(isDisabled: boolean): void { ... }
|
|
}
|
|
```
|
|
|
|
### Appearance Variants
|
|
|
|
#### Checkbox Appearances
|
|
```typescript
|
|
const CheckboxAppearance = {
|
|
Bullet: 'bullet', // Round bullet-style selector
|
|
Checkbox: 'checkbox', // Traditional square checkbox (default)
|
|
} as const;
|
|
```
|
|
|
|
#### Text Field Sizes
|
|
```typescript
|
|
const TextFieldSize = {
|
|
Small: 'small',
|
|
Medium: 'medium', // Default
|
|
Large: 'large',
|
|
} as const;
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### CheckboxComponent
|
|
|
|
A customizable checkbox component supporting different visual appearances.
|
|
|
|
**Selector:** `ui-checkbox`
|
|
|
|
**Inputs:**
|
|
- `appearance: CheckboxAppearance` - Visual style ('checkbox' | 'bullet'). Default: 'checkbox'
|
|
|
|
**Usage:**
|
|
```html
|
|
<!-- Default checkbox appearance -->
|
|
<ui-checkbox>
|
|
<input type="checkbox" />
|
|
</ui-checkbox>
|
|
|
|
<!-- Bullet appearance -->
|
|
<ui-checkbox [appearance]="CheckboxAppearance.Bullet">
|
|
<input type="checkbox" />
|
|
</ui-checkbox>
|
|
```
|
|
|
|
---
|
|
|
|
### DropdownButtonComponent<T>
|
|
|
|
A dropdown select component with keyboard navigation and CDK overlay integration.
|
|
|
|
**Selector:** `ui-dropdown`
|
|
|
|
**Inputs:**
|
|
- `appearance: DropdownAppearance` - Visual style. Default: 'accent-outline'
|
|
- `label: string` - Dropdown label text
|
|
- `showSelectedValue: boolean` - Show selected option text. Default: true
|
|
- `tabIndex: number` - Tab index for keyboard navigation. Default: 0
|
|
- `id: string` - Optional element ID
|
|
- `equals: (a: T | null, b: T | null) => boolean` - Custom equality function for comparing option values. Default: `lodash.isEqual`
|
|
|
|
**Outputs:**
|
|
- `value: ModelSignal<T>` - Two-way bindable selected value
|
|
- `disabled: ModelSignal<boolean>` - Disabled state
|
|
|
|
**Methods:**
|
|
- `open(): void` - Opens the dropdown overlay
|
|
- `close(): void` - Closes the dropdown overlay
|
|
- `select(option, options?): void` - Selects an option programmatically
|
|
|
|
**Keyboard Navigation:**
|
|
- `Arrow Down/Up` - Navigate through options
|
|
- `Enter` - Select highlighted option and close
|
|
- `Escape` - Close dropdown
|
|
- `Space` - Toggle dropdown open/close (when focused)
|
|
|
|
**Usage:**
|
|
```typescript
|
|
interface Product {
|
|
id: number;
|
|
name: string;
|
|
}
|
|
|
|
products: Product[] = [
|
|
{ id: 1, name: 'Product A' },
|
|
{ id: 2, name: 'Product B' }
|
|
];
|
|
selectedProduct: Product;
|
|
```
|
|
|
|
```html
|
|
<ui-dropdown
|
|
[(value)]="selectedProduct"
|
|
label="Select Product"
|
|
appearance="accent-outline">
|
|
@for (product of products; track product.id) {
|
|
<ui-dropdown-option [value]="product">
|
|
{{ product.name }}
|
|
</ui-dropdown-option>
|
|
}
|
|
</ui-dropdown>
|
|
```
|
|
|
|
**Custom Equality Comparison:**
|
|
|
|
When working with object values, you may need custom comparison logic (e.g., comparing by ID instead of deep equality):
|
|
|
|
```typescript
|
|
// Compare products by ID instead of deep equality
|
|
readonly productEquals = (a: Product | null, b: Product | null) => a?.id === b?.id;
|
|
```
|
|
|
|
```html
|
|
<ui-dropdown
|
|
[(value)]="selectedProduct"
|
|
[equals]="productEquals"
|
|
label="Select Product">
|
|
@for (product of products; track product.id) {
|
|
<ui-dropdown-option [value]="product">
|
|
{{ product.name }}
|
|
</ui-dropdown-option>
|
|
}
|
|
</ui-dropdown>
|
|
```
|
|
|
|
---
|
|
|
|
### DropdownFilterComponent
|
|
|
|
A filter input component for use within a DropdownButtonComponent. Renders as a sticky input at the top of the options panel, allowing users to filter options by typing.
|
|
|
|
**Selector:** `ui-dropdown-filter`
|
|
|
|
**Inputs:**
|
|
- `placeholder: string` - Placeholder text for the filter input. Default: 'Suchen...'
|
|
|
|
**Features:**
|
|
- Sticky positioning at top of options panel
|
|
- Auto-focuses when dropdown opens
|
|
- Clears automatically when dropdown closes
|
|
- Arrow key navigation works while typing
|
|
- Enter key selects the highlighted option
|
|
|
|
**Usage:**
|
|
```html
|
|
<ui-dropdown [(ngModel)]="selectedCountry" label="Select country">
|
|
<ui-dropdown-filter placeholder="Search countries..."></ui-dropdown-filter>
|
|
<ui-dropdown-option [value]="'de'">Germany</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'at'">Austria</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'ch'">Switzerland</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'fr'">France</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'it'">Italy</ui-dropdown-option>
|
|
</ui-dropdown>
|
|
```
|
|
|
|
**Keyboard Navigation (when filter is focused):**
|
|
- `Arrow Down/Up` - Navigate through options
|
|
- `Enter` - Select highlighted option and close
|
|
- `Space` - Types in the input (does not toggle dropdown)
|
|
- `Escape` - Keeps focus in input
|
|
|
|
---
|
|
|
|
### DropdownOptionComponent<T>
|
|
|
|
A selectable option component for use within a DropdownButtonComponent. Implements the CDK Highlightable interface for keyboard navigation support.
|
|
|
|
**Selector:** `ui-dropdown-option`
|
|
|
|
**Inputs:**
|
|
| Input | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `value` | `T` | Yes | - | The value associated with this option |
|
|
| `disabled` | `boolean` | No | `false` | Whether this option is disabled |
|
|
|
|
**Usage:**
|
|
```html
|
|
<ui-dropdown [(ngModel)]="selected">
|
|
<ui-dropdown-option [value]="'opt1'">Option 1</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'opt2'">Option 2</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'opt3'" [disabled]="true">Disabled</ui-dropdown-option>
|
|
</ui-dropdown>
|
|
```
|
|
|
|
**Features:**
|
|
- Uses host dropdown's `equals` function for value comparison (defaults to `lodash.isEqual`)
|
|
- Automatic filtering support when used with `DropdownFilterComponent`
|
|
- CSS classes applied automatically: `active`, `selected`, `disabled`, `filtered`
|
|
- ARIA `role="option"` and `aria-selected` attributes for accessibility
|
|
|
|
---
|
|
|
|
### ChipsComponent<T>
|
|
|
|
Single-selection chip group with form integration.
|
|
|
|
**Selector:** `ui-chips`
|
|
|
|
**Outputs:**
|
|
- `value: ModelSignal<T>` - Selected chip value
|
|
- `disabled: ModelSignal<boolean>` - Disabled state
|
|
|
|
**Methods:**
|
|
- `select(value: T, options?): void` - Selects a chip
|
|
- `toggle(value: T, options?): void` - Toggles chip selection
|
|
- `isSelected(value: T): boolean` - Checks if value is selected
|
|
|
|
**Usage:**
|
|
```typescript
|
|
type Size = 'S' | 'M' | 'L' | 'XL';
|
|
selectedSize: Size = 'M';
|
|
```
|
|
|
|
```html
|
|
<ui-chips [(ngModel)]="selectedSize">
|
|
<ui-chip [value]="'S'">Small</ui-chip>
|
|
<ui-chip [value]="'M'">Medium</ui-chip>
|
|
<ui-chip [value]="'L'">Large</ui-chip>
|
|
<ui-chip [value]="'XL'">Extra Large</ui-chip>
|
|
</ui-chips>
|
|
```
|
|
|
|
---
|
|
|
|
### ChecklistComponent
|
|
|
|
Multi-select checkbox group returning an array of selected values.
|
|
|
|
**Selector:** `ui-checklist`
|
|
|
|
**Outputs:**
|
|
- `value: ModelSignal<unknown[]>` - Array of selected values
|
|
|
|
**Usage:**
|
|
```typescript
|
|
selectedFruits: string[] = ['apple', 'banana'];
|
|
```
|
|
|
|
```html
|
|
<ui-checklist [(ngModel)]="selectedFruits">
|
|
<label class="ui-checkbox-label">
|
|
<ui-checkbox>
|
|
<input type="checkbox" [uiChecklistValue]="'apple'">
|
|
</ui-checkbox>
|
|
Apple
|
|
</label>
|
|
<label class="ui-checkbox-label">
|
|
<ui-checkbox>
|
|
<input type="checkbox" [uiChecklistValue]="'banana'">
|
|
</ui-checkbox>
|
|
Banana
|
|
</label>
|
|
</ui-checklist>
|
|
```
|
|
|
|
---
|
|
|
|
### TextFieldComponent
|
|
|
|
Container component for text input fields with consistent styling.
|
|
|
|
**Selector:** `ui-text-field`
|
|
|
|
**Inputs:**
|
|
- `size: TextFieldSize` - Field size ('small' | 'medium' | 'large'). Default: 'medium'
|
|
|
|
**Content Projection:**
|
|
- Requires `InputControlDirective` on child input element
|
|
|
|
**Usage:**
|
|
```html
|
|
<ui-text-field size="medium">
|
|
<input
|
|
type="text"
|
|
uiInputControl
|
|
formControlName="email"
|
|
placeholder="Enter email"
|
|
/>
|
|
</ui-text-field>
|
|
```
|
|
|
|
---
|
|
|
|
### InlineInputComponent
|
|
|
|
Compact inline text input for space-constrained interfaces.
|
|
|
|
**Selector:** `ui-inline-input`
|
|
|
|
**Inputs:**
|
|
- `size: InlineInputSize` - Field size ('small' | 'medium'). Default: 'medium'
|
|
|
|
**Usage:**
|
|
```html
|
|
<ui-inline-input size="small">
|
|
<input type="text" uiInputControl [(ngModel)]="quantity" />
|
|
</ui-inline-input>
|
|
```
|
|
|
|
---
|
|
|
|
### ListboxDirective
|
|
|
|
Wrapper directive for Angular CDK listbox with ISA styling.
|
|
|
|
**Selector:** `[uiListbox]`
|
|
|
|
**Inputs (via CDK):**
|
|
- `value: any` - Selected value(s)
|
|
- `compareWith: (o1: any, o2: any) => boolean` - Comparison function
|
|
- `disabled: boolean` - Disabled state
|
|
|
|
**Outputs (via CDK):**
|
|
- `valueChange: EventEmitter` - Emits when selection changes
|
|
|
|
**Usage:**
|
|
```html
|
|
<div uiListbox [value]="selectedItem" (valueChange)="handleChange($event)">
|
|
<div uiListboxItem [value]="item1">Item 1</div>
|
|
<div uiListboxItem [value]="item2">Item 2</div>
|
|
</div>
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Reactive Form with Validation
|
|
|
|
```typescript
|
|
import { Component, inject } from '@angular/core';
|
|
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
import {
|
|
TextFieldComponent,
|
|
TextFieldContainerComponent,
|
|
TextFieldErrorsComponent,
|
|
InputControlDirective,
|
|
CheckboxComponent,
|
|
DropdownButtonComponent,
|
|
DropdownOptionComponent
|
|
} from '@isa/ui/input-controls';
|
|
|
|
@Component({
|
|
selector: 'app-user-form',
|
|
imports: [
|
|
ReactiveFormsModule,
|
|
TextFieldComponent,
|
|
TextFieldContainerComponent,
|
|
TextFieldErrorsComponent,
|
|
InputControlDirective,
|
|
CheckboxComponent,
|
|
DropdownButtonComponent,
|
|
DropdownOptionComponent
|
|
],
|
|
template: `
|
|
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
|
|
<ui-text-field-container>
|
|
<label>Email</label>
|
|
<ui-text-field>
|
|
<input
|
|
type="email"
|
|
uiInputControl
|
|
formControlName="email"
|
|
placeholder="user@example.com"
|
|
/>
|
|
</ui-text-field>
|
|
<ui-text-field-errors />
|
|
</ui-text-field-container>
|
|
|
|
<ui-dropdown formControlName="role" label="Select Role">
|
|
<ui-dropdown-option [value]="'admin'">Administrator</ui-dropdown-option>
|
|
<ui-dropdown-option [value]="'user'">User</ui-dropdown-option>
|
|
</ui-dropdown>
|
|
|
|
<label class="ui-checkbox-label">
|
|
<ui-checkbox>
|
|
<input type="checkbox" formControlName="acceptTerms" />
|
|
</ui-checkbox>
|
|
I accept the terms and conditions
|
|
</label>
|
|
|
|
<button type="submit" [disabled]="!userForm.valid">Submit</button>
|
|
</form>
|
|
`
|
|
})
|
|
export class UserFormComponent {
|
|
#fb = inject(FormBuilder);
|
|
|
|
userForm = this.#fb.group({
|
|
email: ['', [Validators.required, Validators.email]],
|
|
role: ['user', Validators.required],
|
|
acceptTerms: [false, Validators.requiredTrue]
|
|
});
|
|
|
|
onSubmit() {
|
|
if (this.userForm.valid) {
|
|
console.log('Form submitted:', this.userForm.value);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Form Integration
|
|
|
|
### Reactive Forms
|
|
|
|
All components implement `ControlValueAccessor` and work with `FormControl`:
|
|
|
|
```typescript
|
|
import { FormControl, Validators } from '@angular/forms';
|
|
|
|
emailControl = new FormControl('', [Validators.required, Validators.email]);
|
|
roleControl = new FormControl<string>('user');
|
|
agreeControl = new FormControl(false, Validators.requiredTrue);
|
|
```
|
|
|
|
```html
|
|
<ui-text-field>
|
|
<input uiInputControl [formControl]="emailControl" />
|
|
</ui-text-field>
|
|
|
|
<ui-dropdown [formControl]="roleControl" label="Role">...</ui-dropdown>
|
|
|
|
<ui-checkbox><input [formControl]="agreeControl" /></ui-checkbox>
|
|
```
|
|
|
|
### Template-Driven Forms
|
|
|
|
Use `ngModel` for two-way binding:
|
|
|
|
```html
|
|
<ui-text-field>
|
|
<input uiInputControl [(ngModel)]="email" name="email" />
|
|
</ui-text-field>
|
|
|
|
<ui-dropdown [(ngModel)]="role" name="role" label="Role">...</ui-dropdown>
|
|
```
|
|
|
|
## Accessibility
|
|
|
|
### Keyboard Navigation
|
|
|
|
All components support comprehensive keyboard navigation:
|
|
|
|
**Dropdown:**
|
|
- `Arrow Down/Up` - Navigate through options
|
|
- `Enter` - Select highlighted option and close
|
|
- `Escape` - Close dropdown without selection
|
|
- `Tab` - Move focus to next element
|
|
|
|
**Listbox:**
|
|
- `Arrow Down/Up` - Navigate items
|
|
- `Home/End` - Jump to first/last item
|
|
- `Space/Enter` - Select item
|
|
|
|
**Checkbox/Checklist:**
|
|
- `Space` - Toggle checkbox state
|
|
- `Tab` - Move between checkboxes
|
|
|
|
### ARIA Attributes
|
|
|
|
Components include proper ARIA attributes for screen readers:
|
|
|
|
```html
|
|
<!-- Dropdown -->
|
|
<ui-dropdown
|
|
role="combobox"
|
|
aria-haspopup="listbox"
|
|
[attr.aria-expanded]="isOpen()">
|
|
</ui-dropdown>
|
|
|
|
<!-- Listbox -->
|
|
<div uiListbox role="listbox">
|
|
<div uiListboxItem role="option"></div>
|
|
</div>
|
|
```
|
|
|
|
## Testing
|
|
|
|
The library uses **Jest** with **Spectator** for testing.
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Run tests for this library
|
|
npx nx test ui-input-controls --skip-nx-cache
|
|
|
|
# Run tests with coverage
|
|
npx nx test ui-input-controls --code-coverage --skip-nx-cache
|
|
|
|
# Run tests in watch mode
|
|
npx nx test ui-input-controls --watch
|
|
```
|
|
|
|
### Test Coverage
|
|
|
|
The library includes comprehensive unit tests covering:
|
|
|
|
- **Component rendering** - All visual states and variants
|
|
- **Form integration** - ControlValueAccessor implementation
|
|
- **Keyboard navigation** - Arrow keys, Enter, Escape, Tab
|
|
- **Validation** - Error states and validation display
|
|
- **Accessibility** - ARIA attributes and screen reader support
|
|
- **User interactions** - Click, keyboard, focus events
|
|
|
|
## Architecture Notes
|
|
|
|
### Design Patterns
|
|
|
|
#### 1. ControlValueAccessor Pattern
|
|
All form controls implement the CVA interface for seamless Angular Forms integration.
|
|
|
|
**Benefits:**
|
|
- Works with both reactive and template-driven forms
|
|
- Automatic validation integration
|
|
- Consistent API across all controls
|
|
|
|
#### 2. Signal-Based Reactivity
|
|
Components use Angular signals for reactive state management:
|
|
|
|
```typescript
|
|
appearance = input<CheckboxAppearance>(CheckboxAppearance.Checkbox);
|
|
appearanceClass = computed(() =>
|
|
this.appearance() === CheckboxAppearance.Bullet
|
|
? 'ui-checkbox__bullet'
|
|
: 'ui-checkbox__checkbox'
|
|
);
|
|
```
|
|
|
|
#### 3. CDK Integration
|
|
Leverages Angular CDK for complex interactions:
|
|
|
|
- **Overlay** - Dropdown positioning (CdkConnectedOverlay)
|
|
- **A11y** - Keyboard navigation (ActiveDescendantKeyManager)
|
|
- **Listbox** - Accessible list selection (CdkListbox)
|
|
|
|
### Performance Considerations
|
|
|
|
1. **OnPush Change Detection** - All components use OnPush strategy
|
|
2. **Signal Reactivity** - Computed signals prevent unnecessary re-renders
|
|
3. **KeyManager** - Efficient keyboard navigation without DOM queries
|
|
|
|
## Dependencies
|
|
|
|
### Required Libraries
|
|
|
|
- `@angular/core` - Angular framework
|
|
- `@angular/forms` - Forms module
|
|
- `@angular/cdk/a11y` - Accessibility utilities
|
|
- `@angular/cdk/listbox` - Listbox primitive
|
|
- `@angular/cdk/overlay` - Overlay positioning
|
|
- `@angular/cdk/collections` - SelectionModel
|
|
- `@ng-icons/core` - Icon system
|
|
- `@isa/icons` - ISA icon library
|
|
- `lodash` - Utility functions (isEqual)
|
|
|
|
### Path Alias
|
|
|
|
Import from: `@isa/ui/input-controls`
|
|
|
|
## License
|
|
|
|
Internal ISA Frontend library - not for external distribution.
|