minahil 0.1.18 β†’ 0.1.20

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
@@ -1,1431 +1,1431 @@
1
- # Minahil - Angular UI Component Library
2
-
3
- A comprehensive Angular UI component library featuring a rich collection of customizable, accessible components. Built with modern Angular standards, this library provides everything you need to build beautiful and functional user interfaces.
4
-
5
- ## 🌟 Features
6
-
7
- - πŸ“¦ **Comprehensive Component Library** - Rich set of UI components for common use cases
8
- - β™Ώ **Accessible by Default** - WCAG compliant components with keyboard navigation and screen reader support
9
- - πŸš€ **Angular 17-21 Support** - Built with modern Angular features and standalone components
10
- - πŸ“± **Responsive Design** - Mobile-first components that work on all screen sizes
11
- - 🎯 **Type-Safe** - Full TypeScript support with comprehensive type definitions
12
- - ⚑ **Lightweight** - Tree-shakeable and optimized for performance
13
- - πŸŽ›οΈ **Highly Customizable** - Extensive configuration options for every component
14
- - πŸ”§ **Easy Setup** - One-command installation with automatic dependency management
15
-
16
- ## πŸ“š Available Components
17
-
18
- ### Calendar Components
19
-
20
- A powerful calendar suite with advanced date and time selection capabilities. The calendar components support single date selection, date ranges, multiple date selection, and integrated time pickers.
21
-
22
- ### Toggle Component
23
-
24
- A customizable toggle/switch component with support for Angular forms integration via `ngModel` and reactive forms. Features three size variants (small, medium, large), disabled state, and full accessibility support.
25
-
26
- ### Checkbox Component
27
-
28
- A fully accessible checkbox component with Angular forms integration. Features customizable styling via CSS classes, disabled state, keyboard navigation, and seamless integration with both template-driven and reactive forms.
29
-
30
- ### Radio Component
31
-
32
- A fully accessible radio button component with Angular forms integration. Features two visual variants (dot and tick), customizable styling, disabled state, keyboard navigation, and seamless integration with both template-driven and reactive forms.
33
-
34
- _More components coming soon..._
35
-
36
- ## πŸš€ Quick Start
37
-
38
- ### Automatic Installation (Recommended)
39
-
40
- The easiest way to install Minahil is using Angular CLI's `ng add` command. This automatically installs the library along with matching versions of Angular CDK and other dependencies:
41
-
42
- ```bash
43
- ng add minahil
44
- ```
45
-
46
- This will:
47
-
48
- - βœ… Detect your Angular version (17, 18, 19, 20, or 21)
49
- - βœ… Install Minahil library
50
- - βœ… Install matching @angular/cdk version
51
- - βœ… Install moment.js dependency
52
- - βœ… Configure everything automatically
53
-
54
- ### Manual Installation
55
-
56
- If you prefer manual installation:
57
-
58
- ```bash
59
- npm install minahil
60
- ```
61
-
62
- **Important:** You must also install peer dependencies that match your Angular version:
63
-
64
- ```bash
65
- # For Angular 19 projects
66
- npm install @angular/cdk@^19.0.0 moment@^2.29.0
67
-
68
- # For Angular 17 projects
69
- npm install @angular/cdk@^17.0.0 moment@^2.29.0
70
-
71
- # For Angular 21 projects
72
- npm install @angular/cdk@^21.0.0 moment@^2.29.0
73
- ```
74
-
75
- ### Supported Angular Versions
76
-
77
- Minahil supports Angular versions **17 through 21**. The library will automatically work with any Angular version in this range.
78
-
79
- ### Asset Configuration (Required)
80
-
81
- After installing the library, you need to configure your `angular.json` to include the library's assets (icons, etc.). Add the following to your project's `assets` array in the `build` options:
82
-
83
- ```json
84
- {
85
- "projects": {
86
- "your-app-name": {
87
- "architect": {
88
- "build": {
89
- "options": {
90
- "assets": [
91
- "src/favicon.ico",
92
- "src/assets",
93
- {
94
- "glob": "**/*",
95
- "input": "node_modules/@brickclay-org/ui/assets",
96
- "output": "/assets/brickclay-lib/"
97
- }
98
- ]
99
- }
100
- }
101
- }
102
- }
103
- }
104
- }
105
- ```
106
-
107
- This configuration copies the library's assets (SVG icons, etc.) to your application's output folder during build. Without this, the component icons will not display correctly.
108
-
109
- ## Quick Start
110
-
111
- ### Standalone Component Usage (Recommended)
112
-
113
- ```typescript
114
- import { Component } from '@angular/core';
115
- import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
116
-
117
- @Component({
118
- standalone: true,
119
- selector: 'app-my-component',
120
- imports: [CustomCalendarComponent],
121
- template: `
122
- <brickclay-custom-calendar (selected)="onDateSelected($event)"> </brickclay-custom-calendar>
123
- `,
124
- })
125
- export class MyComponent {
126
- onDateSelected(selection: CalendarSelection) {
127
- console.log('Selected:', selection);
128
- }
129
- }
130
- ```
131
-
132
- ### Module-based Usage
133
-
134
- ```typescript
135
- import { NgModule } from '@angular/core';
136
- import { CalendarModule } from '@brickclay/ui';
137
-
138
- @NgModule({
139
- imports: [CalendarModule],
140
- // ...
141
- })
142
- export class AppModule {}
143
- ```
144
-
145
- ## πŸ“… Calendar
146
-
147
- The calendar components provide a complete solution for date and time selection in your Angular applications. All components are standalone and can be imported individually or as part of the `CalendarModule`.
148
-
149
- ### Components Overview
150
-
151
- 1. **CustomCalendarComponent** (`brickclay-custom-calendar`) - Main calendar component with support for single date, date range, and multiple date selection
152
- 2. **ScheduledDatePickerComponent** (`brickclay-scheduled-date-picker`) - Advanced scheduling component with time configuration for events
153
- 3. **TimePickerComponent** (`brickclay-time-picker`) - Standalone time selection component with scrollable pickers
154
-
155
- ### CustomCalendarComponent
156
-
157
- A versatile calendar component that supports single date, date range, and multiple date selection modes.
158
-
159
- #### Basic Example
160
-
161
- ```typescript
162
- import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
163
-
164
- @Component({
165
- template: `
166
- <brickclay-custom-calendar
167
- [singleDatePicker]="false"
168
- [dualCalendar]="true"
169
- [enableTimepicker]="true"
170
- [showRanges]="true"
171
- [placeholder]="'Select date range'"
172
- (selected)="onDateSelected($event)"
173
- >
174
- </brickclay-custom-calendar>
175
- `,
176
- })
177
- export class MyComponent {
178
- onDateSelected(selection: CalendarSelection) {
179
- console.log('Start:', selection.startDate);
180
- console.log('End:', selection.endDate);
181
- }
182
- }
183
- ```
184
-
185
- #### Component Selector
186
-
187
- `<brickclay-custom-calendar>`
188
-
189
- #### Inputs
190
-
191
- | Input | Type | Default | Description |
192
- | -------------------- | ------------------------------- | --------------------- | ------------------------------------------------- |
193
- | `enableTimepicker` | `boolean` | `false` | Enable time selection |
194
- | `autoApply` | `boolean` | `false` | Automatically apply selection when date is chosen |
195
- | `closeOnAutoApply` | `boolean` | `false` | Close calendar after auto-apply |
196
- | `showCancel` | `boolean` | `true` | Show cancel button in footer |
197
- | `singleDatePicker` | `boolean` | `false` | Enable single date selection mode |
198
- | `dualCalendar` | `boolean` | `false` | Show two calendars side-by-side |
199
- | `showRanges` | `boolean` | `true` | Show predefined date range buttons |
200
- | `multiDateSelection` | `boolean` | `false` | Enable multiple date selection |
201
- | `inline` | `boolean` | `false` | Always show calendar (no dropdown) |
202
- | `minDate` | `Date` | `undefined` | Minimum selectable date |
203
- | `maxDate` | `Date` | `undefined` | Maximum selectable date |
204
- | `placeholder` | `string` | `'Select date range'` | Input placeholder text |
205
- | `opens` | `'left' \| 'right' \| 'center'` | `'left'` | Dropdown alignment |
206
- | `drop` | `'up' \| 'down'` | `'down'` | Dropdown direction |
207
- | `displayFormat` | `string` | `'MM/DD/YYYY'` | Date display format (moment format) |
208
- | `customRanges` | `Record<string, CalendarRange>` | `undefined` | Custom predefined ranges |
209
- | `selectedValue` | `CalendarSelection \| null` | `null` | Pre-selected date(s) |
210
- | `isDisplayCrossIcon` | `boolean` | `true` | Show/hide clear button |
211
-
212
- #### Outputs
213
-
214
- | Output | Type | Description |
215
- | ---------- | --------------------------------- | ----------------------------------- |
216
- | `selected` | `EventEmitter<CalendarSelection>` | Emitted when date selection changes |
217
- | `opened` | `EventEmitter<void>` | Emitted when calendar opens |
218
- | `closed` | `EventEmitter<void>` | Emitted when calendar closes |
219
-
220
- #### Usage Examples
221
-
222
- **Single Date Selection:**
223
-
224
- ```typescript
225
- <brickclay-custom-calendar
226
- [singleDatePicker]="true"
227
- [placeholder]="'Select a date'"
228
- (selected)="onDateSelected($event)">
229
- </brickclay-custom-calendar>
230
- ```
231
-
232
- **Date Range with Time Picker:**
233
-
234
- ```typescript
235
- <brickclay-custom-calendar
236
- [dualCalendar]="true"
237
- [enableTimepicker]="true"
238
- [enableSeconds]="true"
239
- (selected)="onRangeSelected($event)">
240
- </brickclay-custom-calendar>
241
- ```
242
-
243
- **Multiple Date Selection:**
244
-
245
- ```typescript
246
- <brickclay-custom-calendar
247
- [multiDateSelection]="true"
248
- [inline]="true"
249
- (selected)="onMultipleDatesSelected($event)">
250
- </brickclay-custom-calendar>
251
- ```
252
-
253
- **Inline Calendar:**
254
-
255
- ```typescript
256
- <brickclay-custom-calendar
257
- [inline]="true"
258
- [dualCalendar]="false"
259
- [showRanges]="false"
260
- (selected)="onDateSelected($event)">
261
- </brickclay-custom-calendar>
262
- ```
263
-
264
- **Custom Date Ranges:**
265
-
266
- ```typescript
267
- import { CalendarRange } from '@brickclay/ui';
268
-
269
- const customRanges: Record<string, CalendarRange> = {
270
- 'Last Week': {
271
- start: new Date(2024, 0, 1),
272
- end: new Date(2024, 0, 7)
273
- },
274
- 'This Quarter': {
275
- start: new Date(2024, 0, 1),
276
- end: new Date(2024, 2, 31)
277
- }
278
- };
279
-
280
- <brickclay-custom-calendar
281
- [customRanges]="customRanges"
282
- [showRanges]="true"
283
- (selected)="onDateSelected($event)">
284
- </brickclay-custom-calendar>
285
- ```
286
-
287
- **Date Constraints:**
288
-
289
- ```typescript
290
- <brickclay-custom-calendar
291
- [minDate]="new Date(2024, 0, 1)"
292
- [maxDate]="new Date(2024, 11, 31)"
293
- (selected)="onDateSelected($event)">
294
- </brickclay-custom-calendar>
295
- ```
296
-
297
- **Pre-selected Values:**
298
-
299
- ```typescript
300
- export class MyComponent {
301
- selectedValue: CalendarSelection = {
302
- startDate: new Date(2024, 5, 15),
303
- endDate: new Date(2024, 5, 20)
304
- };
305
-
306
- onDateChange() {
307
- this.selectedValue = {
308
- startDate: new Date(),
309
- endDate: new Date()
310
- };
311
- }
312
- }
313
-
314
- <brickclay-custom-calendar
315
- [selectedValue]="selectedValue"
316
- (selected)="onDateSelected($event)">
317
- </brickclay-custom-calendar>
318
- ```
319
-
320
- ### ScheduledDatePickerComponent
321
-
322
- A comprehensive date and time scheduling component with three modes: single date, multiple dates, and date range, each with time configuration.
323
-
324
- #### Basic Example
325
-
326
- ```typescript
327
- import { ScheduledDatePickerComponent, ScheduledDateSelection } from '@brickclay/ui';
328
-
329
- @Component({
330
- template: `
331
- <brickclay-scheduled-date-picker [timeFormat]="12" (scheduled)="onScheduled($event)">
332
- </brickclay-scheduled-date-picker>
333
- `,
334
- })
335
- export class MyComponent {
336
- onScheduled(selection: ScheduledDateSelection) {
337
- console.log('Mode:', selection.mode);
338
- if (selection.mode === 'single' && selection.singleDate) {
339
- console.log('Start:', selection.singleDate.startDate);
340
- console.log('End:', selection.singleDate.endDate);
341
- console.log('All Day:', selection.singleDate.allDay);
342
- }
343
- }
344
- }
345
- ```
346
-
347
- #### Component Selector
348
-
349
- `<brickclay-scheduled-date-picker>`
350
-
351
- #### Inputs
352
-
353
- | Input | Type | Default | Description |
354
- | --------------- | ---------- | ------- | -------------------------------- |
355
- | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
356
- | `enableSeconds` | `boolean` | `false` | Enable seconds in time picker |
357
-
358
- #### Outputs
359
-
360
- | Output | Type | Description |
361
- | ----------- | -------------------------------------- | ------------------------------------ |
362
- | `scheduled` | `EventEmitter<ScheduledDateSelection>` | Emitted when selection changes |
363
- | `cleared` | `EventEmitter<void>` | Emitted when clear button is clicked |
364
-
365
- #### Features
366
-
367
- - **Single Date Mode**: Select one date with optional start and end times
368
- - **Multiple Dates Mode**: Select multiple dates, each with individual time configuration
369
- - **Date Range Mode**: Select a date range with start and end times
370
- - **All Day Toggle**: Mark dates as all-day events
371
- - **Time Configuration**: Individual time pickers for each date/range
372
-
373
- ### TimePickerComponent
374
-
375
- A standalone time picker component with scrollable hour, minute, and AM/PM selectors.
376
-
377
- #### Basic Example
378
-
379
- ```typescript
380
- import { TimePickerComponent } from '@brickclay/ui';
381
-
382
- @Component({
383
- template: `
384
- <brickclay-time-picker
385
- [value]="selectedTime"
386
- [label]="'Start Time'"
387
- [timeFormat]="12"
388
- (timeChange)="onTimeChange($event)"
389
- >
390
- </brickclay-time-picker>
391
- `,
392
- })
393
- export class MyComponent {
394
- selectedTime = '1:00 AM';
395
-
396
- onTimeChange(time: string) {
397
- this.selectedTime = time;
398
- console.log('New time:', time);
399
- }
400
- }
401
- ```
402
-
403
- #### Component Selector
404
-
405
- `<brickclay-time-picker>`
406
-
407
- #### Inputs
408
-
409
- | Input | Type | Default | Description |
410
- | ------------- | ------------------- | --------------- | ---------------------------------------------------- |
411
- | `value` | `string` | `'1:00 AM'` | Current time value (format: "H:MM AM/PM" or "HH:MM") |
412
- | `label` | `string` | `'Time'` | Label text |
413
- | `placeholder` | `string` | `'Select time'` | Placeholder text |
414
- | `position` | `'left' \| 'right'` | `'left'` | Dropdown position |
415
- | `pickerId` | `string` | `''` | Unique identifier for the picker |
416
- | `closePicker` | `number` | `0` | Counter to trigger picker close |
417
- | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
418
- | `showSeconds` | `boolean` | `false` | Show seconds selector |
419
-
420
- #### Outputs
421
-
422
- | Output | Type | Description |
423
- | -------------- | ---------------------- | -------------------------- |
424
- | `timeChange` | `EventEmitter<string>` | Emitted when time changes |
425
- | `pickerOpened` | `EventEmitter<string>` | Emitted when picker opens |
426
- | `pickerClosed` | `EventEmitter<string>` | Emitted when picker closes |
427
-
428
- #### Features
429
-
430
- - Scrollable time selectors
431
- - Keyboard navigation support
432
- - 12-hour and 24-hour formats
433
- - Optional seconds support
434
- - Multiple picker coordination (only one open at a time)
435
- - Click outside to close
436
-
437
- #### Time Format Examples
438
-
439
- **12-hour format:**
440
-
441
- ```typescript
442
- value = '1:00 AM';
443
- value = '12:30 PM';
444
- value = '11:45 PM';
445
- ```
446
-
447
- **24-hour format:**
448
-
449
- ```typescript
450
- value = '01:00';
451
- value = '13:30';
452
- value = '23:45';
453
- ```
454
-
455
- ## πŸ”˜ Toggle
456
-
457
- A versatile toggle/switch component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with full accessibility features and keyboard navigation.
458
-
459
- ### ToggleComponent
460
-
461
- A standalone toggle component that implements `ControlValueAccessor` for seamless Angular forms integration.
462
-
463
- #### Basic Example
464
-
465
- ```typescript
466
- import { ToggleComponent } from '@brickclay/ui';
467
- import { FormsModule } from '@angular/forms';
468
-
469
- @Component({
470
- template: `
471
- <brickclay-toggle
472
- [(ngModel)]="isEnabled"
473
- [label]="'Enable notifications'"
474
- (change)="onToggleChange($event)"
475
- >
476
- </brickclay-toggle>
477
- `,
478
- imports: [ToggleComponent, FormsModule],
479
- })
480
- export class MyComponent {
481
- isEnabled = false;
482
-
483
- onToggleChange(value: boolean) {
484
- console.log('Toggle state:', value);
485
- }
486
- }
487
- ```
488
-
489
- #### Component Selector
490
-
491
- `<brickclay-toggle>`
492
-
493
- #### Inputs
494
-
495
- | Input | Type | Default | Description |
496
- | ------------- | --------- | ------------- | -------------------------------------------------------------------------------- |
497
- | `label` | `string` | `''` | Optional label text displayed next to the toggle |
498
- | `disabled` | `boolean` | `false` | Disables the toggle interaction |
499
- | `toggleClass` | `string` | `'toggle-md'` | CSS class for size styling. Options: `'toggle-sm'`, `'toggle-md'`, `'toggle-lg'` |
500
-
501
- #### Outputs
502
-
503
- | Output | Type | Description |
504
- | -------- | ----------------------- | ------------------------------------------------------------- |
505
- | `change` | `EventEmitter<boolean>` | Emitted when toggle state changes (returns new boolean value) |
506
-
507
- #### Features
508
-
509
- - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
510
- - βœ… **Three Size Variants** - Small (`toggle-sm`), Medium (`toggle-md`), Large (`toggle-lg`)
511
- - βœ… **Accessibility** - ARIA attributes, keyboard navigation, and screen reader support
512
- - βœ… **Disabled State** - Visual and functional disabled state
513
- - βœ… **Customizable Styling** - Custom CSS classes for size and appearance
514
- - βœ… **Event Handling** - `change` event for state change notifications
515
-
516
- #### Usage Examples
517
-
518
- **Basic Toggle with ngModel:**
519
-
520
- ```typescript
521
- import { ToggleComponent } from '@brickclay/ui';
522
- import { FormsModule } from '@angular/forms';
523
-
524
- @Component({
525
- template: `
526
- <brickclay-toggle [(ngModel)]="isActive" [label]="'Active Status'"> </brickclay-toggle>
527
- `,
528
- imports: [ToggleComponent, FormsModule],
529
- })
530
- export class MyComponent {
531
- isActive = true;
532
- }
533
- ```
534
-
535
- **Different Sizes:**
536
-
537
- ```typescript
538
- <brickclay-toggle
539
- [(ngModel)]="value1"
540
- [toggleClass]="'toggle-sm'"
541
- [label]="'Small Toggle'">
542
- </brickclay-toggle>
543
-
544
- <brickclay-toggle
545
- [(ngModel)]="value2"
546
- [toggleClass]="'toggle-md'"
547
- [label]="'Medium Toggle'">
548
- </brickclay-toggle>
549
-
550
- <brickclay-toggle
551
- [(ngModel)]="value3"
552
- [toggleClass]="'toggle-lg'"
553
- [label]="'Large Toggle'">
554
- </brickclay-toggle>
555
- ```
556
-
557
- **Disabled State:**
558
-
559
- ```typescript
560
- <brickclay-toggle
561
- [ngModel]="true"
562
- [disabled]="true"
563
- [label]="'Disabled Toggle'">
564
- </brickclay-toggle>
565
- ```
566
-
567
- **With Event Handler:**
568
-
569
- ```typescript
570
- @Component({
571
- template: `
572
- <brickclay-toggle
573
- [(ngModel)]="notificationsEnabled"
574
- [label]="'Email Notifications'"
575
- (change)="onNotificationToggle($event)"
576
- >
577
- </brickclay-toggle>
578
- `,
579
- })
580
- export class MyComponent {
581
- notificationsEnabled = false;
582
-
583
- onNotificationToggle(enabled: boolean) {
584
- if (enabled) {
585
- this.enableNotifications();
586
- } else {
587
- this.disableNotifications();
588
- }
589
- }
590
- }
591
- ```
592
-
593
- **Reactive Forms Integration:**
594
-
595
- ```typescript
596
- import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
597
- import { ToggleComponent } from '@brickclay/ui';
598
-
599
- @Component({
600
- template: `
601
- <form [formGroup]="settingsForm">
602
- <brickclay-toggle formControlName="darkMode" [label]="'Dark Mode'"> </brickclay-toggle>
603
-
604
- <brickclay-toggle formControlName="notifications" [label]="'Push Notifications'">
605
- </brickclay-toggle>
606
- </form>
607
- `,
608
- imports: [ToggleComponent, ReactiveFormsModule],
609
- })
610
- export class SettingsComponent {
611
- settingsForm: FormGroup;
612
-
613
- constructor(private fb: FormBuilder) {
614
- this.settingsForm = this.fb.group({
615
- darkMode: [false],
616
- notifications: [true],
617
- });
618
- }
619
- }
620
- ```
621
-
622
- **Without Label:**
623
-
624
- ```typescript
625
- <brickclay-toggle
626
- [(ngModel)]="isEnabled"
627
- [toggleClass]="'toggle-md'">
628
- </brickclay-toggle>
629
- ```
630
-
631
- #### Styling
632
-
633
- The toggle component uses CSS classes for size variants:
634
-
635
- - **Small**: `toggle-sm` - Width: 28px (w-7)
636
- - **Medium**: `toggle-md` - Width: 36px (w-9) - Default
637
- - **Large**: `toggle-lg` - Width: 44px (w-11)
638
-
639
- The component includes built-in styles for:
640
-
641
- - On state (green background: `#22973F`)
642
- - Off state (gray background: `#BBBDC5`)
643
- - Disabled state (light gray: `#D6D7DC`)
644
- - Hover states
645
- - Focus ring for accessibility
646
- - Smooth transitions
647
-
648
- #### Accessibility
649
-
650
- The toggle component includes:
651
-
652
- - `role="switch"` for screen readers
653
- - `aria-checked` attribute that reflects the current state
654
- - Keyboard navigation support
655
- - Focus visible ring for keyboard users
656
- - Disabled state properly communicated to assistive technologies
657
-
658
- ## β˜‘οΈ Checkbox
659
-
660
- A fully accessible checkbox component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with customizable styling and comprehensive accessibility features.
661
-
662
- ### CheckboxComponent
663
-
664
- A standalone checkbox component that implements `ControlValueAccessor` for seamless Angular forms integration.
665
-
666
- #### Basic Example
667
-
668
- ```typescript
669
- import { CheckboxComponent } from '@brickclay/ui';
670
- import { FormsModule } from '@angular/forms';
671
-
672
- @Component({
673
- template: `
674
- <brickclay-checkbox
675
- [(ngModel)]="isAccepted"
676
- [label]="'I agree to the terms and conditions'"
677
- (change)="onCheckboxChange($event)"
678
- >
679
- </brickclay-checkbox>
680
- `,
681
- imports: [CheckboxComponent, FormsModule],
682
- })
683
- export class MyComponent {
684
- isAccepted = false;
685
-
686
- onCheckboxChange(value: boolean) {
687
- console.log('Checkbox state:', value);
688
- }
689
- }
690
- ```
691
-
692
- #### Component Selector
693
-
694
- `<brickclay-checkbox>`
695
-
696
- #### Inputs
697
-
698
- | Input | Type | Default | Description |
699
- | --------------- | --------- | ------- | -------------------------------------------------------------------- |
700
- | `label` | `string` | `''` | Optional label text displayed next to the checkbox |
701
- | `disabled` | `boolean` | `false` | Disables the checkbox interaction |
702
- | `checkboxClass` | `string` | `''` | CSS class for size styling. Options: `'xsm'`, `'sm'`, `'md'`, `'lg'` |
703
- | `labelClass` | `string` | `''` | Custom CSS classes for the label text |
704
-
705
- #### Outputs
706
-
707
- | Output | Type | Description |
708
- | -------- | ----------------------- | --------------------------------------------------------------- |
709
- | `change` | `EventEmitter<boolean>` | Emitted when checkbox state changes (returns new boolean value) |
710
-
711
- #### Features
712
-
713
- - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
714
- - βœ… **Four Size Variants** - Extra Small (`xsm`), Small (`sm`), Medium (`md`), Large (`lg`)
715
- - βœ… **Accessibility** - ARIA attributes, keyboard navigation (Enter/Space), and screen reader support
716
- - βœ… **Disabled State** - Visual and functional disabled state
717
- - βœ… **Keyboard Support** - Full keyboard navigation with Enter and Space keys
718
- - βœ… **Focus Management** - Focus visible ring for keyboard users
719
- - βœ… **Event Handling** - `change` event for state change notifications
720
-
721
- #### Usage Examples
722
-
723
- **Basic Checkbox with ngModel:**
724
-
725
- ```typescript
726
- import { CheckboxComponent } from '@brickclay/ui';
727
- import { FormsModule } from '@angular/forms';
728
-
729
- @Component({
730
- template: `
731
- <brickclay-checkbox [(ngModel)]="isChecked" [label]="'Accept terms'"> </brickclay-checkbox>
732
- `,
733
- imports: [CheckboxComponent, FormsModule],
734
- })
735
- export class MyComponent {
736
- isChecked = false;
737
- }
738
- ```
739
-
740
- **Different Sizes:**
741
-
742
- ```typescript
743
- <!-- Extra Small checkbox -->
744
- <brickclay-checkbox
745
- [(ngModel)]="value1"
746
- [checkboxClass]="'xsm'"
747
- [label]="'Extra Small Checkbox'">
748
- </brickclay-checkbox>
749
-
750
- <!-- Small checkbox -->
751
- <brickclay-checkbox
752
- [(ngModel)]="value2"
753
- [checkboxClass]="'sm'"
754
- [label]="'Small Checkbox'">
755
- </brickclay-checkbox>
756
-
757
- <!-- Medium checkbox -->
758
- <brickclay-checkbox
759
- [(ngModel)]="value3"
760
- [checkboxClass]="'md'"
761
- [label]="'Medium Checkbox'">
762
- </brickclay-checkbox>
763
-
764
- <!-- Large checkbox with custom label styling -->
765
- <brickclay-checkbox
766
- [(ngModel)]="value4"
767
- [checkboxClass]="'lg'"
768
- [labelClass]="'text-lg font-bold'"
769
- [label]="'Large Checkbox'">
770
- </brickclay-checkbox>
771
- ```
772
-
773
- **Disabled State:**
774
-
775
- ```typescript
776
- <brickclay-checkbox
777
- [ngModel]="true"
778
- [disabled]="true"
779
- [label]="'Disabled Checkbox'">
780
- </brickclay-checkbox>
781
- ```
782
-
783
- **With Event Handler:**
784
-
785
- ```typescript
786
- @Component({
787
- template: `
788
- <brickclay-checkbox
789
- [(ngModel)]="newsletterSubscribed"
790
- [label]="'Subscribe to newsletter'"
791
- (change)="onNewsletterToggle($event)"
792
- >
793
- </brickclay-checkbox>
794
- `,
795
- })
796
- export class MyComponent {
797
- newsletterSubscribed = false;
798
-
799
- onNewsletterToggle(subscribed: boolean) {
800
- if (subscribed) {
801
- this.subscribeToNewsletter();
802
- } else {
803
- this.unsubscribeFromNewsletter();
804
- }
805
- }
806
- }
807
- ```
808
-
809
- **Reactive Forms Integration:**
810
-
811
- ```typescript
812
- import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
813
- import { CheckboxComponent } from '@brickclay/ui';
814
-
815
- @Component({
816
- template: `
817
- <form [formGroup]="registrationForm">
818
- <brickclay-checkbox
819
- formControlName="acceptTerms"
820
- [label]="'I accept the terms and conditions'"
821
- >
822
- </brickclay-checkbox>
823
-
824
- <brickclay-checkbox formControlName="receiveUpdates" [label]="'Receive product updates'">
825
- </brickclay-checkbox>
826
- </form>
827
- `,
828
- imports: [CheckboxComponent, ReactiveFormsModule],
829
- })
830
- export class RegistrationComponent {
831
- registrationForm: FormGroup;
832
-
833
- constructor(private fb: FormBuilder) {
834
- this.registrationForm = this.fb.group({
835
- acceptTerms: [false, Validators.requiredTrue],
836
- receiveUpdates: [false],
837
- });
838
- }
839
- }
840
- ```
841
-
842
- **Without Label:**
843
-
844
- ```typescript
845
- <brickclay-checkbox
846
- [(ngModel)]="isSelected"
847
- [checkboxClass]="'md'">
848
- </brickclay-checkbox>
849
- ```
850
-
851
- **Multiple Checkboxes:**
852
-
853
- ```typescript
854
- @Component({
855
- template: `
856
- <div>
857
- <brickclay-checkbox
858
- *ngFor="let option of options"
859
- [(ngModel)]="option.selected"
860
- [label]="option.label"
861
- (change)="onOptionChange(option)"
862
- >
863
- </brickclay-checkbox>
864
- </div>
865
- `,
866
- })
867
- export class MyComponent {
868
- options = [
869
- { label: 'Option 1', selected: false },
870
- { label: 'Option 2', selected: false },
871
- { label: 'Option 3', selected: false },
872
- ];
873
-
874
- onOptionChange(option: any) {
875
- console.log(`${option.label} is now ${option.selected ? 'selected' : 'deselected'}`);
876
- }
877
- }
878
- ```
879
-
880
- #### Styling
881
-
882
- The checkbox component supports predefined size classes:
883
-
884
- - **Extra Small**: `xsm` - 14px Γ— 14px
885
- - **Small**: `sm` - 16px Γ— 16px
886
- - **Medium**: `md` - 18px Γ— 18px
887
- - **Large**: `lg` - 20px Γ— 20px
888
-
889
- Use `labelClass` to style the label text (font size, weight, color, etc.)
890
-
891
- The component includes built-in styles for:
892
-
893
- - Checked state (black background with white checkmark/tick icon)
894
- - Unchecked state (white background with gray border)
895
- - Hover states (darker border on hover)
896
- - Disabled states (gray background and border)
897
- - Focus ring for accessibility (blue ring with offset)
898
- - Smooth transitions for state changes
899
-
900
- #### Accessibility
901
-
902
- The checkbox component includes:
903
-
904
- - Keyboard navigation support (Enter and Space keys)
905
- - Focus visible ring for keyboard users
906
- - Proper ARIA attributes
907
- - Disabled state properly communicated to assistive technologies
908
- - Tab navigation support
909
-
910
- ## πŸ”˜ Radio Button
911
-
912
- A fully accessible radio button component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with two visual variants (dot and tick) and comprehensive accessibility features.
913
-
914
- ### RadioComponent
915
-
916
- A standalone radio button component that implements `ControlValueAccessor` for seamless Angular forms integration. Radio buttons are used when only one option can be selected from a group.
917
-
918
- #### Basic Example
919
-
920
- ```typescript
921
- import { RadioComponent } from '@brickclay/ui';
922
- import { FormsModule } from '@angular/forms';
923
-
924
- @Component({
925
- template: `
926
- <brickclay-radio-button
927
- [(ngModel)]="selectedOption"
928
- [value]="'option1'"
929
- [label]="'Option 1'"
930
- (change)="onRadioChange($event)"
931
- >
932
- </brickclay-radio-button>
933
-
934
- <brickclay-radio-button [(ngModel)]="selectedOption" [value]="'option2'" [label]="'Option 2'">
935
- </brickclay-radio-button>
936
- `,
937
- imports: [RadioComponent, FormsModule],
938
- })
939
- export class MyComponent {
940
- selectedOption = 'option1';
941
-
942
- onRadioChange(value: any) {
943
- console.log('Selected option:', value);
944
- }
945
- }
946
- ```
947
-
948
- #### Component Selector
949
-
950
- `<brickclay-radio-button>`
951
-
952
- #### Inputs
953
-
954
- | Input | Type | Default | Description |
955
- | ------------ | ----------------- | ----------- | ------------------------------------------------------------------------- |
956
- | `label` | `string` | `''` | Optional label text displayed next to the radio button |
957
- | `value` | `any` | `undefined` | The value associated with this radio button (required for radio groups) |
958
- | `disabled` | `boolean` | `false` | Disables the radio button interaction |
959
- | `variant` | `'dot' \| 'tick'` | `'dot'` | Visual variant. `'dot'` shows a filled circle, `'tick'` shows a checkmark |
960
- | `radioClass` | `string` | `''` | CSS class for size styling. Options: `'xsm'`, `'sm'`, `'md'`, `'lg'` |
961
- | `labelClass` | `string` | `''` | Custom CSS classes for the label text |
962
-
963
- #### Outputs
964
-
965
- | Output | Type | Description |
966
- | -------- | ------------------- | --------------------------------------------------------- |
967
- | `change` | `EventEmitter<any>` | Emitted when radio button is selected (returns the value) |
968
-
969
- #### Features
970
-
971
- - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
972
- - βœ… **Two Visual Variants** - Dot (filled circle) and Tick (checkmark) styles
973
- - βœ… **Four Size Variants** - Extra Small (`xsm`), Small (`sm`), Medium (`md`), Large (`lg`)
974
- - βœ… **Radio Groups** - Automatically groups radio buttons with the same `ngModel` binding
975
- - βœ… **Accessibility** - ARIA attributes, keyboard navigation (Enter/Space), and screen reader support
976
- - βœ… **Disabled State** - Visual and functional disabled state
977
- - βœ… **Keyboard Support** - Full keyboard navigation with Enter and Space keys
978
- - βœ… **Focus Management** - Focus visible ring for keyboard users
979
- - βœ… **Event Handling** - `change` event for selection notifications
980
-
981
- #### Usage Examples
982
-
983
- **Basic Radio Group with ngModel:**
984
-
985
- ```typescript
986
- import { RadioComponent } from '@brickclay/ui';
987
- import { FormsModule } from '@angular/forms';
988
-
989
- @Component({
990
- template: `
991
- <brickclay-radio-button
992
- [(ngModel)]="selectedPayment"
993
- [value]="'credit'"
994
- [label]="'Credit Card'"
995
- >
996
- </brickclay-radio-button>
997
-
998
- <brickclay-radio-button [(ngModel)]="selectedPayment" [value]="'debit'" [label]="'Debit Card'">
999
- </brickclay-radio-button>
1000
-
1001
- <brickclay-radio-button [(ngModel)]="selectedPayment" [value]="'paypal'" [label]="'PayPal'">
1002
- </brickclay-radio-button>
1003
- `,
1004
- imports: [RadioComponent, FormsModule],
1005
- })
1006
- export class MyComponent {
1007
- selectedPayment = 'credit';
1008
- }
1009
- ```
1010
-
1011
- **Dot Variant (Default):**
1012
-
1013
- ```typescript
1014
- <brickclay-radio-button
1015
- [(ngModel)]="selectedOption"
1016
- [value]="'option1'"
1017
- [variant]="'dot'"
1018
- [label]="'Option with Dot'">
1019
- </brickclay-radio-button>
1020
- ```
1021
-
1022
- **Tick Variant:**
1023
-
1024
- ```typescript
1025
- <brickclay-radio-button
1026
- [(ngModel)]="selectedOption"
1027
- [value]="'option2'"
1028
- [variant]="'tick'"
1029
- [label]="'Option with Tick'">
1030
- </brickclay-radio-button>
1031
- ```
1032
-
1033
- **Different Sizes:**
1034
-
1035
- ```typescript
1036
- <!-- Extra Small radio -->
1037
- <brickclay-radio-button
1038
- [(ngModel)]="selectedOption"
1039
- [value]="'xsm'"
1040
- [radioClass]="'xsm'"
1041
- [label]="'Extra Small Radio'">
1042
- </brickclay-radio-button>
1043
-
1044
- <!-- Small radio -->
1045
- <brickclay-radio-button
1046
- [(ngModel)]="selectedOption"
1047
- [value]="'sm'"
1048
- [radioClass]="'sm'"
1049
- [label]="'Small Radio'">
1050
- </brickclay-radio-button>
1051
-
1052
- <!-- Medium radio -->
1053
- <brickclay-radio-button
1054
- [(ngModel)]="selectedOption"
1055
- [value]="'md'"
1056
- [radioClass]="'md'"
1057
- [label]="'Medium Radio'">
1058
- </brickclay-radio-button>
1059
-
1060
- <!-- Large radio with custom label styling -->
1061
- <brickclay-radio-button
1062
- [(ngModel)]="selectedOption"
1063
- [value]="'lg'"
1064
- [radioClass]="'lg'"
1065
- [labelClass]="'text-lg font-bold'"
1066
- [label]="'Large Radio'">
1067
- </brickclay-radio-button>
1068
- ```
1069
-
1070
- **Disabled State:**
1071
-
1072
- ```typescript
1073
- <brickclay-radio-button
1074
- [(ngModel)]="selectedOption"
1075
- [value]="'disabled-option'"
1076
- [disabled]="true"
1077
- [label]="'Disabled Option'">
1078
- </brickclay-radio-button>
1079
- ```
1080
-
1081
- **With Event Handler:**
1082
-
1083
- ```typescript
1084
- @Component({
1085
- template: `
1086
- <brickclay-radio-button
1087
- *ngFor="let option of options"
1088
- [(ngModel)]="selectedOption"
1089
- [value]="option.value"
1090
- [label]="option.label"
1091
- (change)="onOptionChange($event)"
1092
- >
1093
- </brickclay-radio-button>
1094
- `,
1095
- })
1096
- export class MyComponent {
1097
- options = [
1098
- { value: 'option1', label: 'Option 1' },
1099
- { value: 'option2', label: 'Option 2' },
1100
- { value: 'option3', label: 'Option 3' },
1101
- ];
1102
- selectedOption = 'option1';
1103
-
1104
- onOptionChange(value: any) {
1105
- console.log('Selected:', value);
1106
- }
1107
- }
1108
- ```
1109
-
1110
- **Reactive Forms Integration:**
1111
-
1112
- ```typescript
1113
- import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
1114
- import { RadioComponent } from '@brickclay/ui';
1115
-
1116
- @Component({
1117
- template: `
1118
- <form [formGroup]="surveyForm">
1119
- <brickclay-radio-button formControlName="rating" [value]="'excellent'" [label]="'Excellent'">
1120
- </brickclay-radio-button>
1121
-
1122
- <brickclay-radio-button formControlName="rating" [value]="'good'" [label]="'Good'">
1123
- </brickclay-radio-button>
1124
-
1125
- <brickclay-radio-button formControlName="rating" [value]="'fair'" [label]="'Fair'">
1126
- </brickclay-radio-button>
1127
- </form>
1128
- `,
1129
- imports: [RadioComponent, ReactiveFormsModule],
1130
- })
1131
- export class SurveyComponent {
1132
- surveyForm: FormGroup;
1133
-
1134
- constructor(private fb: FormBuilder) {
1135
- this.surveyForm = this.fb.group({
1136
- rating: ['good', Validators.required],
1137
- });
1138
- }
1139
- }
1140
- ```
1141
-
1142
- **Without Label:**
1143
-
1144
- ```typescript
1145
- <brickclay-radio-button
1146
- [(ngModel)]="selectedOption"
1147
- [value]="'option1'"
1148
- [radioClass]="'md'">
1149
- </brickclay-radio-button>
1150
- ```
1151
-
1152
- **Dynamic Radio Group:**
1153
-
1154
- ```typescript
1155
- @Component({
1156
- template: `
1157
- <div>
1158
- <brickclay-radio-button
1159
- *ngFor="let item of items"
1160
- [(ngModel)]="selectedItem"
1161
- [value]="item.id"
1162
- [label]="item.name"
1163
- [variant]="item.variant || 'dot'"
1164
- >
1165
- </brickclay-radio-button>
1166
- </div>
1167
- `,
1168
- })
1169
- export class MyComponent {
1170
- items = [
1171
- { id: 1, name: 'Item 1', variant: 'dot' },
1172
- { id: 2, name: 'Item 2', variant: 'tick' },
1173
- { id: 3, name: 'Item 3', variant: 'dot' },
1174
- ];
1175
- selectedItem = 1;
1176
- }
1177
- ```
1178
-
1179
- #### Styling
1180
-
1181
- The radio button component supports predefined size classes:
1182
-
1183
- - **Extra Small**: `xsm` - 14px Γ— 14px
1184
- - **Small**: `sm` - 16px Γ— 16px
1185
- - **Medium**: `md` - 18px Γ— 18px
1186
- - **Large**: `lg` - 19px Γ— 19px
1187
-
1188
- Use `labelClass` to style the label text (font size, weight, color, etc.)
1189
-
1190
- The component includes built-in styles for:
1191
-
1192
- - **Dot Variant**: Filled circle indicator when selected (size varies by radioClass)
1193
- - **Tick Variant**: Checkmark indicator when selected (size varies by radioClass)
1194
- - Unselected state (white background with gray border)
1195
- - Hover states (darker border on hover)
1196
- - Disabled states (gray background and border)
1197
- - Focus ring for accessibility (blue ring with offset)
1198
- - Smooth transitions for state changes
1199
-
1200
- #### Accessibility
1201
-
1202
- The radio button component includes:
1203
-
1204
- - Keyboard navigation support (Enter and Space keys)
1205
- - Focus visible ring for keyboard users
1206
- - Proper ARIA attributes
1207
- - Disabled state properly communicated to assistive technologies
1208
- - Tab navigation support
1209
- - Radio group semantics for screen readers
1210
-
1211
- #### Radio Groups
1212
-
1213
- Radio buttons are automatically grouped when they share the same `ngModel` binding. Only one radio button in a group can be selected at a time. When a radio button is selected, the previously selected one in the same group is automatically deselected.
1214
-
1215
- ## πŸ“ TypeScript Interfaces
1216
-
1217
- ### CalendarRange
1218
-
1219
- ```typescript
1220
- interface CalendarRange {
1221
- start: Date;
1222
- end: Date;
1223
- }
1224
- ```
1225
-
1226
- ### CalendarSelection
1227
-
1228
- ```typescript
1229
- interface CalendarSelection {
1230
- startDate: Date | null;
1231
- endDate: Date | null;
1232
- selectedDates?: Date[]; // For multi-date selection
1233
- }
1234
- ```
1235
-
1236
- ### TimeConfiguration
1237
-
1238
- ```typescript
1239
- interface TimeConfiguration {
1240
- date: Date;
1241
- allDay: boolean;
1242
- startTime: string; // Format: "HH:mm" or "HH:mm:ss"
1243
- endTime: string;
1244
- }
1245
- ```
1246
-
1247
- ### ScheduledDateSelection
1248
-
1249
- ```typescript
1250
- interface ScheduledDateSelection {
1251
- mode: 'single' | 'multiple' | 'range';
1252
- singleDate?: {
1253
- startDate: Date;
1254
- endDate: Date;
1255
- allDay: boolean;
1256
- startTime: string;
1257
- endTime: string;
1258
- };
1259
- multipleDates?: TimeConfiguration[];
1260
- dateRange?: {
1261
- startDate: Date;
1262
- endDate: Date;
1263
- allDay: boolean;
1264
- startTime: string;
1265
- endTime: string;
1266
- };
1267
- }
1268
- ```
1269
-
1270
- ## 🎯 Common Use Cases
1271
-
1272
- ### Form Integration
1273
-
1274
- ```typescript
1275
- import { FormBuilder, FormGroup, Validators } from '@angular/forms';
1276
- import { CustomCalendarComponent } from '@brickclay/ui';
1277
-
1278
- export class BookingFormComponent {
1279
- bookingForm: FormGroup;
1280
-
1281
- constructor(private fb: FormBuilder) {
1282
- this.bookingForm = this.fb.group({
1283
- checkIn: [null, Validators.required],
1284
- checkOut: [null, Validators.required],
1285
- });
1286
- }
1287
-
1288
- onDateSelected(selection: CalendarSelection) {
1289
- this.bookingForm.patchValue({
1290
- checkIn: selection.startDate,
1291
- checkOut: selection.endDate,
1292
- });
1293
- }
1294
- }
1295
- ```
1296
-
1297
- ### Reactive Forms
1298
-
1299
- ```typescript
1300
- <brickclay-custom-calendar
1301
- [selectedValue]="form.get('dateRange')?.value"
1302
- (selected)="form.patchValue({ dateRange: $event })">
1303
- </brickclay-custom-calendar>
1304
- ```
1305
-
1306
- ### Date Filtering
1307
-
1308
- ```typescript
1309
- export class DataTableComponent {
1310
- filterDates: CalendarSelection = { startDate: null, endDate: null };
1311
-
1312
- onDateFilter(selection: CalendarSelection) {
1313
- this.filterDates = selection;
1314
- this.loadFilteredData();
1315
- }
1316
-
1317
- loadFilteredData() {
1318
- const filtered = this.data.filter((item) => {
1319
- if (!this.filterDates.startDate || !this.filterDates.endDate) {
1320
- return true;
1321
- }
1322
- return item.date >= this.filterDates.startDate! && item.date <= this.filterDates.endDate!;
1323
- });
1324
- }
1325
- }
1326
- ```
1327
-
1328
- ## πŸ“¦ Assets Configuration
1329
-
1330
- The calendar components require SVG icons. Configure your `angular.json` to copy assets:
1331
-
1332
- ```json
1333
- {
1334
- "glob": "**/*",
1335
- "input": "node_modules/@brickclay/ui/assets",
1336
- "output": "assets"
1337
- }
1338
- ```
1339
-
1340
- Or manually copy assets from:
1341
-
1342
- ```
1343
- node_modules/@brickclay/ui/assets/calender/* β†’ your-app/public/assets/calender/
1344
- ```
1345
-
1346
- ## πŸ”§ Service
1347
-
1348
- ### CalendarManagerService
1349
-
1350
- A service that manages multiple calendar instances, ensuring only one calendar is open at a time when not in inline mode. Used internally by `CustomCalendarComponent`.
1351
-
1352
- ## 🌐 Browser Support
1353
-
1354
- - Chrome (latest)
1355
- - Firefox (latest)
1356
- - Safari (latest)
1357
- - Edge (latest)
1358
-
1359
- ## πŸ“¦ Dependencies
1360
-
1361
- - Angular 20.3.0+
1362
- - moment (for date formatting)
1363
-
1364
- ## 🀝 Contributing
1365
-
1366
- We welcome contributions! Please see our contributing guidelines for more information.
1367
-
1368
- ## πŸ“„ License
1369
-
1370
- MIT
1371
-
1372
- ## πŸ“ž Support
1373
-
1374
- For issues, feature requests, or contributions, please visit our [GitHub repository](https://github.com/brickclay/ui).
1375
-
1376
- ## πŸ—ΊοΈ Roadmap
1377
-
1378
- - [ ] Button components
1379
- - [ ] Input components
1380
- - [ ] Card components
1381
- - [ ] Modal/Dialog components
1382
- - [ ] Table components
1383
- - [ ] Form components
1384
- - [ ] Navigation components
1385
- - [ ] Loading/Spinner components
1386
- - [ ] Toast/Notification components
1387
- - [ ] More calendar features
1388
-
1389
- ## πŸ“ Changelog
1390
-
1391
- ### Version 0.0.1
1392
-
1393
- **Initial Release:**
1394
-
1395
- - βœ… Calendar component suite
1396
- - Single date selection
1397
- - Date range selection
1398
- - Multiple date selection
1399
- - Time picker integration
1400
- - Inline and dropdown modes
1401
- - Dual calendar view
1402
- - Custom date ranges
1403
- - Date constraints (min/max)
1404
- - βœ… Scheduled date picker component
1405
- - βœ… Standalone time picker component
1406
- - βœ… Toggle/Switch component
1407
- - Angular forms integration (ngModel & reactive forms)
1408
- - Three size variants (small, medium, large)
1409
- - Disabled state support
1410
- - Full accessibility features
1411
- - Customizable styling
1412
- - βœ… Checkbox component
1413
- - Angular forms integration (ngModel & reactive forms)
1414
- - Customizable styling via CSS classes
1415
- - Disabled state support
1416
- - Full keyboard navigation support
1417
- - Complete accessibility features
1418
- - βœ… Radio button component
1419
- - Angular forms integration (ngModel & reactive forms)
1420
- - Two visual variants (dot and tick)
1421
- - Radio group support
1422
- - Customizable styling via CSS classes
1423
- - Disabled state support
1424
- - Full keyboard navigation support
1425
- - Complete accessibility features
1426
- - βœ… TypeScript definitions
1427
- - βœ… Comprehensive documentation
1428
-
1429
- ---
1430
-
1431
- **Built with ❀️ by the Brickclay team**
1
+ # Minahil - Angular UI Component Library
2
+
3
+ A comprehensive Angular UI component library featuring a rich collection of customizable, accessible components. Built with modern Angular standards, this library provides everything you need to build beautiful and functional user interfaces.
4
+
5
+ ## 🌟 Features
6
+
7
+ - πŸ“¦ **Comprehensive Component Library** - Rich set of UI components for common use cases
8
+ - β™Ώ **Accessible by Default** - WCAG compliant components with keyboard navigation and screen reader support
9
+ - πŸš€ **Angular 17-21 Support** - Built with modern Angular features and standalone components
10
+ - πŸ“± **Responsive Design** - Mobile-first components that work on all screen sizes
11
+ - 🎯 **Type-Safe** - Full TypeScript support with comprehensive type definitions
12
+ - ⚑ **Lightweight** - Tree-shakeable and optimized for performance
13
+ - πŸŽ›οΈ **Highly Customizable** - Extensive configuration options for every component
14
+ - πŸ”§ **Easy Setup** - One-command installation with automatic dependency management
15
+
16
+ ## πŸ“š Available Components
17
+
18
+ ### Calendar Components
19
+
20
+ A powerful calendar suite with advanced date and time selection capabilities. The calendar components support single date selection, date ranges, multiple date selection, and integrated time pickers.
21
+
22
+ ### Toggle Component
23
+
24
+ A customizable toggle/switch component with support for Angular forms integration via `ngModel` and reactive forms. Features three size variants (small, medium, large), disabled state, and full accessibility support.
25
+
26
+ ### Checkbox Component
27
+
28
+ A fully accessible checkbox component with Angular forms integration. Features customizable styling via CSS classes, disabled state, keyboard navigation, and seamless integration with both template-driven and reactive forms.
29
+
30
+ ### Radio Component
31
+
32
+ A fully accessible radio button component with Angular forms integration. Features two visual variants (dot and tick), customizable styling, disabled state, keyboard navigation, and seamless integration with both template-driven and reactive forms.
33
+
34
+ _More components coming soon..._
35
+
36
+ ## πŸš€ Quick Start
37
+
38
+ ### Automatic Installation (Recommended)
39
+
40
+ The easiest way to install Minahil is using Angular CLI's `ng add` command. This automatically installs the library along with matching versions of Angular CDK and other dependencies:
41
+
42
+ ```bash
43
+ ng add minahil
44
+ ```
45
+
46
+ This will:
47
+
48
+ - βœ… Detect your Angular version (17, 18, 19, 20, or 21)
49
+ - βœ… Install Minahil library
50
+ - βœ… Install matching @angular/cdk version
51
+ - βœ… Install moment.js dependency
52
+ - βœ… Configure everything automatically
53
+
54
+ ### Manual Installation
55
+
56
+ If you prefer manual installation:
57
+
58
+ ```bash
59
+ npm install minahil
60
+ ```
61
+
62
+ **Important:** You must also install peer dependencies that match your Angular version:
63
+
64
+ ```bash
65
+ # For Angular 19 projects
66
+ npm install @angular/cdk@^19.0.0 moment@^2.29.0
67
+
68
+ # For Angular 17 projects
69
+ npm install @angular/cdk@^17.0.0 moment@^2.29.0
70
+
71
+ # For Angular 21 projects
72
+ npm install @angular/cdk@^21.0.0 moment@^2.29.0
73
+ ```
74
+
75
+ ### Supported Angular Versions
76
+
77
+ Minahil supports Angular versions **17 through 21**. The library will automatically work with any Angular version in this range.
78
+
79
+ ### Asset Configuration (Required)
80
+
81
+ After installing the library, you need to configure your `angular.json` to include the library's assets (icons, etc.). Add the following to your project's `assets` array in the `build` options:
82
+
83
+ ```json
84
+ {
85
+ "projects": {
86
+ "your-app-name": {
87
+ "architect": {
88
+ "build": {
89
+ "options": {
90
+ "assets": [
91
+ "src/favicon.ico",
92
+ "src/assets",
93
+ {
94
+ "glob": "**/*",
95
+ "input": "node_modules/@brickclay-org/ui/assets",
96
+ "output": "/assets/brickclay-lib/"
97
+ }
98
+ ]
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ This configuration copies the library's assets (SVG icons, etc.) to your application's output folder during build. Without this, the component icons will not display correctly.
108
+
109
+ ## Quick Start
110
+
111
+ ### Standalone Component Usage (Recommended)
112
+
113
+ ```typescript
114
+ import { Component } from '@angular/core';
115
+ import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
116
+
117
+ @Component({
118
+ standalone: true,
119
+ selector: 'app-my-component',
120
+ imports: [CustomCalendarComponent],
121
+ template: `
122
+ <brickclay-custom-calendar (selected)="onDateSelected($event)"> </brickclay-custom-calendar>
123
+ `,
124
+ })
125
+ export class MyComponent {
126
+ onDateSelected(selection: CalendarSelection) {
127
+ console.log('Selected:', selection);
128
+ }
129
+ }
130
+ ```
131
+
132
+ ### Module-based Usage
133
+
134
+ ```typescript
135
+ import { NgModule } from '@angular/core';
136
+ import { CalendarModule } from '@brickclay/ui';
137
+
138
+ @NgModule({
139
+ imports: [CalendarModule],
140
+ // ...
141
+ })
142
+ export class AppModule {}
143
+ ```
144
+
145
+ ## πŸ“… Calendar
146
+
147
+ The calendar components provide a complete solution for date and time selection in your Angular applications. All components are standalone and can be imported individually or as part of the `CalendarModule`.
148
+
149
+ ### Components Overview
150
+
151
+ 1. **CustomCalendarComponent** (`brickclay-custom-calendar`) - Main calendar component with support for single date, date range, and multiple date selection
152
+ 2. **ScheduledDatePickerComponent** (`brickclay-scheduled-date-picker`) - Advanced scheduling component with time configuration for events
153
+ 3. **TimePickerComponent** (`brickclay-time-picker`) - Standalone time selection component with scrollable pickers
154
+
155
+ ### CustomCalendarComponent
156
+
157
+ A versatile calendar component that supports single date, date range, and multiple date selection modes.
158
+
159
+ #### Basic Example
160
+
161
+ ```typescript
162
+ import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
163
+
164
+ @Component({
165
+ template: `
166
+ <brickclay-custom-calendar
167
+ [singleDatePicker]="false"
168
+ [dualCalendar]="true"
169
+ [enableTimepicker]="true"
170
+ [showRanges]="true"
171
+ [placeholder]="'Select date range'"
172
+ (selected)="onDateSelected($event)"
173
+ >
174
+ </brickclay-custom-calendar>
175
+ `,
176
+ })
177
+ export class MyComponent {
178
+ onDateSelected(selection: CalendarSelection) {
179
+ console.log('Start:', selection.startDate);
180
+ console.log('End:', selection.endDate);
181
+ }
182
+ }
183
+ ```
184
+
185
+ #### Component Selector
186
+
187
+ `<brickclay-custom-calendar>`
188
+
189
+ #### Inputs
190
+
191
+ | Input | Type | Default | Description |
192
+ | -------------------- | ------------------------------- | --------------------- | ------------------------------------------------- |
193
+ | `enableTimepicker` | `boolean` | `false` | Enable time selection |
194
+ | `autoApply` | `boolean` | `false` | Automatically apply selection when date is chosen |
195
+ | `closeOnAutoApply` | `boolean` | `false` | Close calendar after auto-apply |
196
+ | `showCancel` | `boolean` | `true` | Show cancel button in footer |
197
+ | `singleDatePicker` | `boolean` | `false` | Enable single date selection mode |
198
+ | `dualCalendar` | `boolean` | `false` | Show two calendars side-by-side |
199
+ | `showRanges` | `boolean` | `true` | Show predefined date range buttons |
200
+ | `multiDateSelection` | `boolean` | `false` | Enable multiple date selection |
201
+ | `inline` | `boolean` | `false` | Always show calendar (no dropdown) |
202
+ | `minDate` | `Date` | `undefined` | Minimum selectable date |
203
+ | `maxDate` | `Date` | `undefined` | Maximum selectable date |
204
+ | `placeholder` | `string` | `'Select date range'` | Input placeholder text |
205
+ | `opens` | `'left' \| 'right' \| 'center'` | `'left'` | Dropdown alignment |
206
+ | `drop` | `'up' \| 'down'` | `'down'` | Dropdown direction |
207
+ | `displayFormat` | `string` | `'MM/DD/YYYY'` | Date display format (moment format) |
208
+ | `customRanges` | `Record<string, CalendarRange>` | `undefined` | Custom predefined ranges |
209
+ | `selectedValue` | `CalendarSelection \| null` | `null` | Pre-selected date(s) |
210
+ | `isDisplayCrossIcon` | `boolean` | `true` | Show/hide clear button |
211
+
212
+ #### Outputs
213
+
214
+ | Output | Type | Description |
215
+ | ---------- | --------------------------------- | ----------------------------------- |
216
+ | `selected` | `EventEmitter<CalendarSelection>` | Emitted when date selection changes |
217
+ | `opened` | `EventEmitter<void>` | Emitted when calendar opens |
218
+ | `closed` | `EventEmitter<void>` | Emitted when calendar closes |
219
+
220
+ #### Usage Examples
221
+
222
+ **Single Date Selection:**
223
+
224
+ ```typescript
225
+ <brickclay-custom-calendar
226
+ [singleDatePicker]="true"
227
+ [placeholder]="'Select a date'"
228
+ (selected)="onDateSelected($event)">
229
+ </brickclay-custom-calendar>
230
+ ```
231
+
232
+ **Date Range with Time Picker:**
233
+
234
+ ```typescript
235
+ <brickclay-custom-calendar
236
+ [dualCalendar]="true"
237
+ [enableTimepicker]="true"
238
+ [enableSeconds]="true"
239
+ (selected)="onRangeSelected($event)">
240
+ </brickclay-custom-calendar>
241
+ ```
242
+
243
+ **Multiple Date Selection:**
244
+
245
+ ```typescript
246
+ <brickclay-custom-calendar
247
+ [multiDateSelection]="true"
248
+ [inline]="true"
249
+ (selected)="onMultipleDatesSelected($event)">
250
+ </brickclay-custom-calendar>
251
+ ```
252
+
253
+ **Inline Calendar:**
254
+
255
+ ```typescript
256
+ <brickclay-custom-calendar
257
+ [inline]="true"
258
+ [dualCalendar]="false"
259
+ [showRanges]="false"
260
+ (selected)="onDateSelected($event)">
261
+ </brickclay-custom-calendar>
262
+ ```
263
+
264
+ **Custom Date Ranges:**
265
+
266
+ ```typescript
267
+ import { CalendarRange } from '@brickclay/ui';
268
+
269
+ const customRanges: Record<string, CalendarRange> = {
270
+ 'Last Week': {
271
+ start: new Date(2024, 0, 1),
272
+ end: new Date(2024, 0, 7)
273
+ },
274
+ 'This Quarter': {
275
+ start: new Date(2024, 0, 1),
276
+ end: new Date(2024, 2, 31)
277
+ }
278
+ };
279
+
280
+ <brickclay-custom-calendar
281
+ [customRanges]="customRanges"
282
+ [showRanges]="true"
283
+ (selected)="onDateSelected($event)">
284
+ </brickclay-custom-calendar>
285
+ ```
286
+
287
+ **Date Constraints:**
288
+
289
+ ```typescript
290
+ <brickclay-custom-calendar
291
+ [minDate]="new Date(2024, 0, 1)"
292
+ [maxDate]="new Date(2024, 11, 31)"
293
+ (selected)="onDateSelected($event)">
294
+ </brickclay-custom-calendar>
295
+ ```
296
+
297
+ **Pre-selected Values:**
298
+
299
+ ```typescript
300
+ export class MyComponent {
301
+ selectedValue: CalendarSelection = {
302
+ startDate: new Date(2024, 5, 15),
303
+ endDate: new Date(2024, 5, 20)
304
+ };
305
+
306
+ onDateChange() {
307
+ this.selectedValue = {
308
+ startDate: new Date(),
309
+ endDate: new Date()
310
+ };
311
+ }
312
+ }
313
+
314
+ <brickclay-custom-calendar
315
+ [selectedValue]="selectedValue"
316
+ (selected)="onDateSelected($event)">
317
+ </brickclay-custom-calendar>
318
+ ```
319
+
320
+ ### ScheduledDatePickerComponent
321
+
322
+ A comprehensive date and time scheduling component with three modes: single date, multiple dates, and date range, each with time configuration.
323
+
324
+ #### Basic Example
325
+
326
+ ```typescript
327
+ import { ScheduledDatePickerComponent, ScheduledDateSelection } from '@brickclay/ui';
328
+
329
+ @Component({
330
+ template: `
331
+ <brickclay-scheduled-date-picker [timeFormat]="12" (scheduled)="onScheduled($event)">
332
+ </brickclay-scheduled-date-picker>
333
+ `,
334
+ })
335
+ export class MyComponent {
336
+ onScheduled(selection: ScheduledDateSelection) {
337
+ console.log('Mode:', selection.mode);
338
+ if (selection.mode === 'single' && selection.singleDate) {
339
+ console.log('Start:', selection.singleDate.startDate);
340
+ console.log('End:', selection.singleDate.endDate);
341
+ console.log('All Day:', selection.singleDate.allDay);
342
+ }
343
+ }
344
+ }
345
+ ```
346
+
347
+ #### Component Selector
348
+
349
+ `<brickclay-scheduled-date-picker>`
350
+
351
+ #### Inputs
352
+
353
+ | Input | Type | Default | Description |
354
+ | --------------- | ---------- | ------- | -------------------------------- |
355
+ | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
356
+ | `enableSeconds` | `boolean` | `false` | Enable seconds in time picker |
357
+
358
+ #### Outputs
359
+
360
+ | Output | Type | Description |
361
+ | ----------- | -------------------------------------- | ------------------------------------ |
362
+ | `scheduled` | `EventEmitter<ScheduledDateSelection>` | Emitted when selection changes |
363
+ | `cleared` | `EventEmitter<void>` | Emitted when clear button is clicked |
364
+
365
+ #### Features
366
+
367
+ - **Single Date Mode**: Select one date with optional start and end times
368
+ - **Multiple Dates Mode**: Select multiple dates, each with individual time configuration
369
+ - **Date Range Mode**: Select a date range with start and end times
370
+ - **All Day Toggle**: Mark dates as all-day events
371
+ - **Time Configuration**: Individual time pickers for each date/range
372
+
373
+ ### TimePickerComponent
374
+
375
+ A standalone time picker component with scrollable hour, minute, and AM/PM selectors.
376
+
377
+ #### Basic Example
378
+
379
+ ```typescript
380
+ import { TimePickerComponent } from '@brickclay/ui';
381
+
382
+ @Component({
383
+ template: `
384
+ <brickclay-time-picker
385
+ [value]="selectedTime"
386
+ [label]="'Start Time'"
387
+ [timeFormat]="12"
388
+ (timeChange)="onTimeChange($event)"
389
+ >
390
+ </brickclay-time-picker>
391
+ `,
392
+ })
393
+ export class MyComponent {
394
+ selectedTime = '1:00 AM';
395
+
396
+ onTimeChange(time: string) {
397
+ this.selectedTime = time;
398
+ console.log('New time:', time);
399
+ }
400
+ }
401
+ ```
402
+
403
+ #### Component Selector
404
+
405
+ `<brickclay-time-picker>`
406
+
407
+ #### Inputs
408
+
409
+ | Input | Type | Default | Description |
410
+ | ------------- | ------------------- | --------------- | ---------------------------------------------------- |
411
+ | `value` | `string` | `'1:00 AM'` | Current time value (format: "H:MM AM/PM" or "HH:MM") |
412
+ | `label` | `string` | `'Time'` | Label text |
413
+ | `placeholder` | `string` | `'Select time'` | Placeholder text |
414
+ | `position` | `'left' \| 'right'` | `'left'` | Dropdown position |
415
+ | `pickerId` | `string` | `''` | Unique identifier for the picker |
416
+ | `closePicker` | `number` | `0` | Counter to trigger picker close |
417
+ | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
418
+ | `showSeconds` | `boolean` | `false` | Show seconds selector |
419
+
420
+ #### Outputs
421
+
422
+ | Output | Type | Description |
423
+ | -------------- | ---------------------- | -------------------------- |
424
+ | `timeChange` | `EventEmitter<string>` | Emitted when time changes |
425
+ | `pickerOpened` | `EventEmitter<string>` | Emitted when picker opens |
426
+ | `pickerClosed` | `EventEmitter<string>` | Emitted when picker closes |
427
+
428
+ #### Features
429
+
430
+ - Scrollable time selectors
431
+ - Keyboard navigation support
432
+ - 12-hour and 24-hour formats
433
+ - Optional seconds support
434
+ - Multiple picker coordination (only one open at a time)
435
+ - Click outside to close
436
+
437
+ #### Time Format Examples
438
+
439
+ **12-hour format:**
440
+
441
+ ```typescript
442
+ value = '1:00 AM';
443
+ value = '12:30 PM';
444
+ value = '11:45 PM';
445
+ ```
446
+
447
+ **24-hour format:**
448
+
449
+ ```typescript
450
+ value = '01:00';
451
+ value = '13:30';
452
+ value = '23:45';
453
+ ```
454
+
455
+ ## πŸ”˜ Toggle
456
+
457
+ A versatile toggle/switch component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with full accessibility features and keyboard navigation.
458
+
459
+ ### ToggleComponent
460
+
461
+ A standalone toggle component that implements `ControlValueAccessor` for seamless Angular forms integration.
462
+
463
+ #### Basic Example
464
+
465
+ ```typescript
466
+ import { ToggleComponent } from '@brickclay/ui';
467
+ import { FormsModule } from '@angular/forms';
468
+
469
+ @Component({
470
+ template: `
471
+ <brickclay-toggle
472
+ [(ngModel)]="isEnabled"
473
+ [label]="'Enable notifications'"
474
+ (change)="onToggleChange($event)"
475
+ >
476
+ </brickclay-toggle>
477
+ `,
478
+ imports: [ToggleComponent, FormsModule],
479
+ })
480
+ export class MyComponent {
481
+ isEnabled = false;
482
+
483
+ onToggleChange(value: boolean) {
484
+ console.log('Toggle state:', value);
485
+ }
486
+ }
487
+ ```
488
+
489
+ #### Component Selector
490
+
491
+ `<brickclay-toggle>`
492
+
493
+ #### Inputs
494
+
495
+ | Input | Type | Default | Description |
496
+ | ------------- | --------- | ------------- | -------------------------------------------------------------------------------- |
497
+ | `label` | `string` | `''` | Optional label text displayed next to the toggle |
498
+ | `disabled` | `boolean` | `false` | Disables the toggle interaction |
499
+ | `toggleClass` | `string` | `'toggle-md'` | CSS class for size styling. Options: `'toggle-sm'`, `'toggle-md'`, `'toggle-lg'` |
500
+
501
+ #### Outputs
502
+
503
+ | Output | Type | Description |
504
+ | -------- | ----------------------- | ------------------------------------------------------------- |
505
+ | `change` | `EventEmitter<boolean>` | Emitted when toggle state changes (returns new boolean value) |
506
+
507
+ #### Features
508
+
509
+ - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
510
+ - βœ… **Three Size Variants** - Small (`toggle-sm`), Medium (`toggle-md`), Large (`toggle-lg`)
511
+ - βœ… **Accessibility** - ARIA attributes, keyboard navigation, and screen reader support
512
+ - βœ… **Disabled State** - Visual and functional disabled state
513
+ - βœ… **Customizable Styling** - Custom CSS classes for size and appearance
514
+ - βœ… **Event Handling** - `change` event for state change notifications
515
+
516
+ #### Usage Examples
517
+
518
+ **Basic Toggle with ngModel:**
519
+
520
+ ```typescript
521
+ import { ToggleComponent } from '@brickclay/ui';
522
+ import { FormsModule } from '@angular/forms';
523
+
524
+ @Component({
525
+ template: `
526
+ <brickclay-toggle [(ngModel)]="isActive" [label]="'Active Status'"> </brickclay-toggle>
527
+ `,
528
+ imports: [ToggleComponent, FormsModule],
529
+ })
530
+ export class MyComponent {
531
+ isActive = true;
532
+ }
533
+ ```
534
+
535
+ **Different Sizes:**
536
+
537
+ ```typescript
538
+ <brickclay-toggle
539
+ [(ngModel)]="value1"
540
+ [toggleClass]="'toggle-sm'"
541
+ [label]="'Small Toggle'">
542
+ </brickclay-toggle>
543
+
544
+ <brickclay-toggle
545
+ [(ngModel)]="value2"
546
+ [toggleClass]="'toggle-md'"
547
+ [label]="'Medium Toggle'">
548
+ </brickclay-toggle>
549
+
550
+ <brickclay-toggle
551
+ [(ngModel)]="value3"
552
+ [toggleClass]="'toggle-lg'"
553
+ [label]="'Large Toggle'">
554
+ </brickclay-toggle>
555
+ ```
556
+
557
+ **Disabled State:**
558
+
559
+ ```typescript
560
+ <brickclay-toggle
561
+ [ngModel]="true"
562
+ [disabled]="true"
563
+ [label]="'Disabled Toggle'">
564
+ </brickclay-toggle>
565
+ ```
566
+
567
+ **With Event Handler:**
568
+
569
+ ```typescript
570
+ @Component({
571
+ template: `
572
+ <brickclay-toggle
573
+ [(ngModel)]="notificationsEnabled"
574
+ [label]="'Email Notifications'"
575
+ (change)="onNotificationToggle($event)"
576
+ >
577
+ </brickclay-toggle>
578
+ `,
579
+ })
580
+ export class MyComponent {
581
+ notificationsEnabled = false;
582
+
583
+ onNotificationToggle(enabled: boolean) {
584
+ if (enabled) {
585
+ this.enableNotifications();
586
+ } else {
587
+ this.disableNotifications();
588
+ }
589
+ }
590
+ }
591
+ ```
592
+
593
+ **Reactive Forms Integration:**
594
+
595
+ ```typescript
596
+ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
597
+ import { ToggleComponent } from '@brickclay/ui';
598
+
599
+ @Component({
600
+ template: `
601
+ <form [formGroup]="settingsForm">
602
+ <brickclay-toggle formControlName="darkMode" [label]="'Dark Mode'"> </brickclay-toggle>
603
+
604
+ <brickclay-toggle formControlName="notifications" [label]="'Push Notifications'">
605
+ </brickclay-toggle>
606
+ </form>
607
+ `,
608
+ imports: [ToggleComponent, ReactiveFormsModule],
609
+ })
610
+ export class SettingsComponent {
611
+ settingsForm: FormGroup;
612
+
613
+ constructor(private fb: FormBuilder) {
614
+ this.settingsForm = this.fb.group({
615
+ darkMode: [false],
616
+ notifications: [true],
617
+ });
618
+ }
619
+ }
620
+ ```
621
+
622
+ **Without Label:**
623
+
624
+ ```typescript
625
+ <brickclay-toggle
626
+ [(ngModel)]="isEnabled"
627
+ [toggleClass]="'toggle-md'">
628
+ </brickclay-toggle>
629
+ ```
630
+
631
+ #### Styling
632
+
633
+ The toggle component uses CSS classes for size variants:
634
+
635
+ - **Small**: `toggle-sm` - Width: 28px (w-7)
636
+ - **Medium**: `toggle-md` - Width: 36px (w-9) - Default
637
+ - **Large**: `toggle-lg` - Width: 44px (w-11)
638
+
639
+ The component includes built-in styles for:
640
+
641
+ - On state (green background: `#22973F`)
642
+ - Off state (gray background: `#BBBDC5`)
643
+ - Disabled state (light gray: `#D6D7DC`)
644
+ - Hover states
645
+ - Focus ring for accessibility
646
+ - Smooth transitions
647
+
648
+ #### Accessibility
649
+
650
+ The toggle component includes:
651
+
652
+ - `role="switch"` for screen readers
653
+ - `aria-checked` attribute that reflects the current state
654
+ - Keyboard navigation support
655
+ - Focus visible ring for keyboard users
656
+ - Disabled state properly communicated to assistive technologies
657
+
658
+ ## β˜‘οΈ Checkbox
659
+
660
+ A fully accessible checkbox component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with customizable styling and comprehensive accessibility features.
661
+
662
+ ### CheckboxComponent
663
+
664
+ A standalone checkbox component that implements `ControlValueAccessor` for seamless Angular forms integration.
665
+
666
+ #### Basic Example
667
+
668
+ ```typescript
669
+ import { CheckboxComponent } from '@brickclay/ui';
670
+ import { FormsModule } from '@angular/forms';
671
+
672
+ @Component({
673
+ template: `
674
+ <brickclay-checkbox
675
+ [(ngModel)]="isAccepted"
676
+ [label]="'I agree to the terms and conditions'"
677
+ (change)="onCheckboxChange($event)"
678
+ >
679
+ </brickclay-checkbox>
680
+ `,
681
+ imports: [CheckboxComponent, FormsModule],
682
+ })
683
+ export class MyComponent {
684
+ isAccepted = false;
685
+
686
+ onCheckboxChange(value: boolean) {
687
+ console.log('Checkbox state:', value);
688
+ }
689
+ }
690
+ ```
691
+
692
+ #### Component Selector
693
+
694
+ `<brickclay-checkbox>`
695
+
696
+ #### Inputs
697
+
698
+ | Input | Type | Default | Description |
699
+ | --------------- | --------- | ------- | -------------------------------------------------------------------- |
700
+ | `label` | `string` | `''` | Optional label text displayed next to the checkbox |
701
+ | `disabled` | `boolean` | `false` | Disables the checkbox interaction |
702
+ | `checkboxClass` | `string` | `''` | CSS class for size styling. Options: `'xsm'`, `'sm'`, `'md'`, `'lg'` |
703
+ | `labelClass` | `string` | `''` | Custom CSS classes for the label text |
704
+
705
+ #### Outputs
706
+
707
+ | Output | Type | Description |
708
+ | -------- | ----------------------- | --------------------------------------------------------------- |
709
+ | `change` | `EventEmitter<boolean>` | Emitted when checkbox state changes (returns new boolean value) |
710
+
711
+ #### Features
712
+
713
+ - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
714
+ - βœ… **Four Size Variants** - Extra Small (`xsm`), Small (`sm`), Medium (`md`), Large (`lg`)
715
+ - βœ… **Accessibility** - ARIA attributes, keyboard navigation (Enter/Space), and screen reader support
716
+ - βœ… **Disabled State** - Visual and functional disabled state
717
+ - βœ… **Keyboard Support** - Full keyboard navigation with Enter and Space keys
718
+ - βœ… **Focus Management** - Focus visible ring for keyboard users
719
+ - βœ… **Event Handling** - `change` event for state change notifications
720
+
721
+ #### Usage Examples
722
+
723
+ **Basic Checkbox with ngModel:**
724
+
725
+ ```typescript
726
+ import { CheckboxComponent } from '@brickclay/ui';
727
+ import { FormsModule } from '@angular/forms';
728
+
729
+ @Component({
730
+ template: `
731
+ <brickclay-checkbox [(ngModel)]="isChecked" [label]="'Accept terms'"> </brickclay-checkbox>
732
+ `,
733
+ imports: [CheckboxComponent, FormsModule],
734
+ })
735
+ export class MyComponent {
736
+ isChecked = false;
737
+ }
738
+ ```
739
+
740
+ **Different Sizes:**
741
+
742
+ ```typescript
743
+ <!-- Extra Small checkbox -->
744
+ <brickclay-checkbox
745
+ [(ngModel)]="value1"
746
+ [checkboxClass]="'xsm'"
747
+ [label]="'Extra Small Checkbox'">
748
+ </brickclay-checkbox>
749
+
750
+ <!-- Small checkbox -->
751
+ <brickclay-checkbox
752
+ [(ngModel)]="value2"
753
+ [checkboxClass]="'sm'"
754
+ [label]="'Small Checkbox'">
755
+ </brickclay-checkbox>
756
+
757
+ <!-- Medium checkbox -->
758
+ <brickclay-checkbox
759
+ [(ngModel)]="value3"
760
+ [checkboxClass]="'md'"
761
+ [label]="'Medium Checkbox'">
762
+ </brickclay-checkbox>
763
+
764
+ <!-- Large checkbox with custom label styling -->
765
+ <brickclay-checkbox
766
+ [(ngModel)]="value4"
767
+ [checkboxClass]="'lg'"
768
+ [labelClass]="'text-lg font-bold'"
769
+ [label]="'Large Checkbox'">
770
+ </brickclay-checkbox>
771
+ ```
772
+
773
+ **Disabled State:**
774
+
775
+ ```typescript
776
+ <brickclay-checkbox
777
+ [ngModel]="true"
778
+ [disabled]="true"
779
+ [label]="'Disabled Checkbox'">
780
+ </brickclay-checkbox>
781
+ ```
782
+
783
+ **With Event Handler:**
784
+
785
+ ```typescript
786
+ @Component({
787
+ template: `
788
+ <brickclay-checkbox
789
+ [(ngModel)]="newsletterSubscribed"
790
+ [label]="'Subscribe to newsletter'"
791
+ (change)="onNewsletterToggle($event)"
792
+ >
793
+ </brickclay-checkbox>
794
+ `,
795
+ })
796
+ export class MyComponent {
797
+ newsletterSubscribed = false;
798
+
799
+ onNewsletterToggle(subscribed: boolean) {
800
+ if (subscribed) {
801
+ this.subscribeToNewsletter();
802
+ } else {
803
+ this.unsubscribeFromNewsletter();
804
+ }
805
+ }
806
+ }
807
+ ```
808
+
809
+ **Reactive Forms Integration:**
810
+
811
+ ```typescript
812
+ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
813
+ import { CheckboxComponent } from '@brickclay/ui';
814
+
815
+ @Component({
816
+ template: `
817
+ <form [formGroup]="registrationForm">
818
+ <brickclay-checkbox
819
+ formControlName="acceptTerms"
820
+ [label]="'I accept the terms and conditions'"
821
+ >
822
+ </brickclay-checkbox>
823
+
824
+ <brickclay-checkbox formControlName="receiveUpdates" [label]="'Receive product updates'">
825
+ </brickclay-checkbox>
826
+ </form>
827
+ `,
828
+ imports: [CheckboxComponent, ReactiveFormsModule],
829
+ })
830
+ export class RegistrationComponent {
831
+ registrationForm: FormGroup;
832
+
833
+ constructor(private fb: FormBuilder) {
834
+ this.registrationForm = this.fb.group({
835
+ acceptTerms: [false, Validators.requiredTrue],
836
+ receiveUpdates: [false],
837
+ });
838
+ }
839
+ }
840
+ ```
841
+
842
+ **Without Label:**
843
+
844
+ ```typescript
845
+ <brickclay-checkbox
846
+ [(ngModel)]="isSelected"
847
+ [checkboxClass]="'md'">
848
+ </brickclay-checkbox>
849
+ ```
850
+
851
+ **Multiple Checkboxes:**
852
+
853
+ ```typescript
854
+ @Component({
855
+ template: `
856
+ <div>
857
+ <brickclay-checkbox
858
+ *ngFor="let option of options"
859
+ [(ngModel)]="option.selected"
860
+ [label]="option.label"
861
+ (change)="onOptionChange(option)"
862
+ >
863
+ </brickclay-checkbox>
864
+ </div>
865
+ `,
866
+ })
867
+ export class MyComponent {
868
+ options = [
869
+ { label: 'Option 1', selected: false },
870
+ { label: 'Option 2', selected: false },
871
+ { label: 'Option 3', selected: false },
872
+ ];
873
+
874
+ onOptionChange(option: any) {
875
+ console.log(`${option.label} is now ${option.selected ? 'selected' : 'deselected'}`);
876
+ }
877
+ }
878
+ ```
879
+
880
+ #### Styling
881
+
882
+ The checkbox component supports predefined size classes:
883
+
884
+ - **Extra Small**: `xsm` - 14px Γ— 14px
885
+ - **Small**: `sm` - 16px Γ— 16px
886
+ - **Medium**: `md` - 18px Γ— 18px
887
+ - **Large**: `lg` - 20px Γ— 20px
888
+
889
+ Use `labelClass` to style the label text (font size, weight, color, etc.)
890
+
891
+ The component includes built-in styles for:
892
+
893
+ - Checked state (black background with white checkmark/tick icon)
894
+ - Unchecked state (white background with gray border)
895
+ - Hover states (darker border on hover)
896
+ - Disabled states (gray background and border)
897
+ - Focus ring for accessibility (blue ring with offset)
898
+ - Smooth transitions for state changes
899
+
900
+ #### Accessibility
901
+
902
+ The checkbox component includes:
903
+
904
+ - Keyboard navigation support (Enter and Space keys)
905
+ - Focus visible ring for keyboard users
906
+ - Proper ARIA attributes
907
+ - Disabled state properly communicated to assistive technologies
908
+ - Tab navigation support
909
+
910
+ ## πŸ”˜ Radio Button
911
+
912
+ A fully accessible radio button component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with two visual variants (dot and tick) and comprehensive accessibility features.
913
+
914
+ ### RadioComponent
915
+
916
+ A standalone radio button component that implements `ControlValueAccessor` for seamless Angular forms integration. Radio buttons are used when only one option can be selected from a group.
917
+
918
+ #### Basic Example
919
+
920
+ ```typescript
921
+ import { RadioComponent } from '@brickclay/ui';
922
+ import { FormsModule } from '@angular/forms';
923
+
924
+ @Component({
925
+ template: `
926
+ <brickclay-radio-button
927
+ [(ngModel)]="selectedOption"
928
+ [value]="'option1'"
929
+ [label]="'Option 1'"
930
+ (change)="onRadioChange($event)"
931
+ >
932
+ </brickclay-radio-button>
933
+
934
+ <brickclay-radio-button [(ngModel)]="selectedOption" [value]="'option2'" [label]="'Option 2'">
935
+ </brickclay-radio-button>
936
+ `,
937
+ imports: [RadioComponent, FormsModule],
938
+ })
939
+ export class MyComponent {
940
+ selectedOption = 'option1';
941
+
942
+ onRadioChange(value: any) {
943
+ console.log('Selected option:', value);
944
+ }
945
+ }
946
+ ```
947
+
948
+ #### Component Selector
949
+
950
+ `<brickclay-radio-button>`
951
+
952
+ #### Inputs
953
+
954
+ | Input | Type | Default | Description |
955
+ | ------------ | ----------------- | ----------- | ------------------------------------------------------------------------- |
956
+ | `label` | `string` | `''` | Optional label text displayed next to the radio button |
957
+ | `value` | `any` | `undefined` | The value associated with this radio button (required for radio groups) |
958
+ | `disabled` | `boolean` | `false` | Disables the radio button interaction |
959
+ | `variant` | `'dot' \| 'tick'` | `'dot'` | Visual variant. `'dot'` shows a filled circle, `'tick'` shows a checkmark |
960
+ | `radioClass` | `string` | `''` | CSS class for size styling. Options: `'xsm'`, `'sm'`, `'md'`, `'lg'` |
961
+ | `labelClass` | `string` | `''` | Custom CSS classes for the label text |
962
+
963
+ #### Outputs
964
+
965
+ | Output | Type | Description |
966
+ | -------- | ------------------- | --------------------------------------------------------- |
967
+ | `change` | `EventEmitter<any>` | Emitted when radio button is selected (returns the value) |
968
+
969
+ #### Features
970
+
971
+ - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
972
+ - βœ… **Two Visual Variants** - Dot (filled circle) and Tick (checkmark) styles
973
+ - βœ… **Four Size Variants** - Extra Small (`xsm`), Small (`sm`), Medium (`md`), Large (`lg`)
974
+ - βœ… **Radio Groups** - Automatically groups radio buttons with the same `ngModel` binding
975
+ - βœ… **Accessibility** - ARIA attributes, keyboard navigation (Enter/Space), and screen reader support
976
+ - βœ… **Disabled State** - Visual and functional disabled state
977
+ - βœ… **Keyboard Support** - Full keyboard navigation with Enter and Space keys
978
+ - βœ… **Focus Management** - Focus visible ring for keyboard users
979
+ - βœ… **Event Handling** - `change` event for selection notifications
980
+
981
+ #### Usage Examples
982
+
983
+ **Basic Radio Group with ngModel:**
984
+
985
+ ```typescript
986
+ import { RadioComponent } from '@brickclay/ui';
987
+ import { FormsModule } from '@angular/forms';
988
+
989
+ @Component({
990
+ template: `
991
+ <brickclay-radio-button
992
+ [(ngModel)]="selectedPayment"
993
+ [value]="'credit'"
994
+ [label]="'Credit Card'"
995
+ >
996
+ </brickclay-radio-button>
997
+
998
+ <brickclay-radio-button [(ngModel)]="selectedPayment" [value]="'debit'" [label]="'Debit Card'">
999
+ </brickclay-radio-button>
1000
+
1001
+ <brickclay-radio-button [(ngModel)]="selectedPayment" [value]="'paypal'" [label]="'PayPal'">
1002
+ </brickclay-radio-button>
1003
+ `,
1004
+ imports: [RadioComponent, FormsModule],
1005
+ })
1006
+ export class MyComponent {
1007
+ selectedPayment = 'credit';
1008
+ }
1009
+ ```
1010
+
1011
+ **Dot Variant (Default):**
1012
+
1013
+ ```typescript
1014
+ <brickclay-radio-button
1015
+ [(ngModel)]="selectedOption"
1016
+ [value]="'option1'"
1017
+ [variant]="'dot'"
1018
+ [label]="'Option with Dot'">
1019
+ </brickclay-radio-button>
1020
+ ```
1021
+
1022
+ **Tick Variant:**
1023
+
1024
+ ```typescript
1025
+ <brickclay-radio-button
1026
+ [(ngModel)]="selectedOption"
1027
+ [value]="'option2'"
1028
+ [variant]="'tick'"
1029
+ [label]="'Option with Tick'">
1030
+ </brickclay-radio-button>
1031
+ ```
1032
+
1033
+ **Different Sizes:**
1034
+
1035
+ ```typescript
1036
+ <!-- Extra Small radio -->
1037
+ <brickclay-radio-button
1038
+ [(ngModel)]="selectedOption"
1039
+ [value]="'xsm'"
1040
+ [radioClass]="'xsm'"
1041
+ [label]="'Extra Small Radio'">
1042
+ </brickclay-radio-button>
1043
+
1044
+ <!-- Small radio -->
1045
+ <brickclay-radio-button
1046
+ [(ngModel)]="selectedOption"
1047
+ [value]="'sm'"
1048
+ [radioClass]="'sm'"
1049
+ [label]="'Small Radio'">
1050
+ </brickclay-radio-button>
1051
+
1052
+ <!-- Medium radio -->
1053
+ <brickclay-radio-button
1054
+ [(ngModel)]="selectedOption"
1055
+ [value]="'md'"
1056
+ [radioClass]="'md'"
1057
+ [label]="'Medium Radio'">
1058
+ </brickclay-radio-button>
1059
+
1060
+ <!-- Large radio with custom label styling -->
1061
+ <brickclay-radio-button
1062
+ [(ngModel)]="selectedOption"
1063
+ [value]="'lg'"
1064
+ [radioClass]="'lg'"
1065
+ [labelClass]="'text-lg font-bold'"
1066
+ [label]="'Large Radio'">
1067
+ </brickclay-radio-button>
1068
+ ```
1069
+
1070
+ **Disabled State:**
1071
+
1072
+ ```typescript
1073
+ <brickclay-radio-button
1074
+ [(ngModel)]="selectedOption"
1075
+ [value]="'disabled-option'"
1076
+ [disabled]="true"
1077
+ [label]="'Disabled Option'">
1078
+ </brickclay-radio-button>
1079
+ ```
1080
+
1081
+ **With Event Handler:**
1082
+
1083
+ ```typescript
1084
+ @Component({
1085
+ template: `
1086
+ <brickclay-radio-button
1087
+ *ngFor="let option of options"
1088
+ [(ngModel)]="selectedOption"
1089
+ [value]="option.value"
1090
+ [label]="option.label"
1091
+ (change)="onOptionChange($event)"
1092
+ >
1093
+ </brickclay-radio-button>
1094
+ `,
1095
+ })
1096
+ export class MyComponent {
1097
+ options = [
1098
+ { value: 'option1', label: 'Option 1' },
1099
+ { value: 'option2', label: 'Option 2' },
1100
+ { value: 'option3', label: 'Option 3' },
1101
+ ];
1102
+ selectedOption = 'option1';
1103
+
1104
+ onOptionChange(value: any) {
1105
+ console.log('Selected:', value);
1106
+ }
1107
+ }
1108
+ ```
1109
+
1110
+ **Reactive Forms Integration:**
1111
+
1112
+ ```typescript
1113
+ import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
1114
+ import { RadioComponent } from '@brickclay/ui';
1115
+
1116
+ @Component({
1117
+ template: `
1118
+ <form [formGroup]="surveyForm">
1119
+ <brickclay-radio-button formControlName="rating" [value]="'excellent'" [label]="'Excellent'">
1120
+ </brickclay-radio-button>
1121
+
1122
+ <brickclay-radio-button formControlName="rating" [value]="'good'" [label]="'Good'">
1123
+ </brickclay-radio-button>
1124
+
1125
+ <brickclay-radio-button formControlName="rating" [value]="'fair'" [label]="'Fair'">
1126
+ </brickclay-radio-button>
1127
+ </form>
1128
+ `,
1129
+ imports: [RadioComponent, ReactiveFormsModule],
1130
+ })
1131
+ export class SurveyComponent {
1132
+ surveyForm: FormGroup;
1133
+
1134
+ constructor(private fb: FormBuilder) {
1135
+ this.surveyForm = this.fb.group({
1136
+ rating: ['good', Validators.required],
1137
+ });
1138
+ }
1139
+ }
1140
+ ```
1141
+
1142
+ **Without Label:**
1143
+
1144
+ ```typescript
1145
+ <brickclay-radio-button
1146
+ [(ngModel)]="selectedOption"
1147
+ [value]="'option1'"
1148
+ [radioClass]="'md'">
1149
+ </brickclay-radio-button>
1150
+ ```
1151
+
1152
+ **Dynamic Radio Group:**
1153
+
1154
+ ```typescript
1155
+ @Component({
1156
+ template: `
1157
+ <div>
1158
+ <brickclay-radio-button
1159
+ *ngFor="let item of items"
1160
+ [(ngModel)]="selectedItem"
1161
+ [value]="item.id"
1162
+ [label]="item.name"
1163
+ [variant]="item.variant || 'dot'"
1164
+ >
1165
+ </brickclay-radio-button>
1166
+ </div>
1167
+ `,
1168
+ })
1169
+ export class MyComponent {
1170
+ items = [
1171
+ { id: 1, name: 'Item 1', variant: 'dot' },
1172
+ { id: 2, name: 'Item 2', variant: 'tick' },
1173
+ { id: 3, name: 'Item 3', variant: 'dot' },
1174
+ ];
1175
+ selectedItem = 1;
1176
+ }
1177
+ ```
1178
+
1179
+ #### Styling
1180
+
1181
+ The radio button component supports predefined size classes:
1182
+
1183
+ - **Extra Small**: `xsm` - 14px Γ— 14px
1184
+ - **Small**: `sm` - 16px Γ— 16px
1185
+ - **Medium**: `md` - 18px Γ— 18px
1186
+ - **Large**: `lg` - 19px Γ— 19px
1187
+
1188
+ Use `labelClass` to style the label text (font size, weight, color, etc.)
1189
+
1190
+ The component includes built-in styles for:
1191
+
1192
+ - **Dot Variant**: Filled circle indicator when selected (size varies by radioClass)
1193
+ - **Tick Variant**: Checkmark indicator when selected (size varies by radioClass)
1194
+ - Unselected state (white background with gray border)
1195
+ - Hover states (darker border on hover)
1196
+ - Disabled states (gray background and border)
1197
+ - Focus ring for accessibility (blue ring with offset)
1198
+ - Smooth transitions for state changes
1199
+
1200
+ #### Accessibility
1201
+
1202
+ The radio button component includes:
1203
+
1204
+ - Keyboard navigation support (Enter and Space keys)
1205
+ - Focus visible ring for keyboard users
1206
+ - Proper ARIA attributes
1207
+ - Disabled state properly communicated to assistive technologies
1208
+ - Tab navigation support
1209
+ - Radio group semantics for screen readers
1210
+
1211
+ #### Radio Groups
1212
+
1213
+ Radio buttons are automatically grouped when they share the same `ngModel` binding. Only one radio button in a group can be selected at a time. When a radio button is selected, the previously selected one in the same group is automatically deselected.
1214
+
1215
+ ## πŸ“ TypeScript Interfaces
1216
+
1217
+ ### CalendarRange
1218
+
1219
+ ```typescript
1220
+ interface CalendarRange {
1221
+ start: Date;
1222
+ end: Date;
1223
+ }
1224
+ ```
1225
+
1226
+ ### CalendarSelection
1227
+
1228
+ ```typescript
1229
+ interface CalendarSelection {
1230
+ startDate: Date | null;
1231
+ endDate: Date | null;
1232
+ selectedDates?: Date[]; // For multi-date selection
1233
+ }
1234
+ ```
1235
+
1236
+ ### TimeConfiguration
1237
+
1238
+ ```typescript
1239
+ interface TimeConfiguration {
1240
+ date: Date;
1241
+ allDay: boolean;
1242
+ startTime: string; // Format: "HH:mm" or "HH:mm:ss"
1243
+ endTime: string;
1244
+ }
1245
+ ```
1246
+
1247
+ ### ScheduledDateSelection
1248
+
1249
+ ```typescript
1250
+ interface ScheduledDateSelection {
1251
+ mode: 'single' | 'multiple' | 'range';
1252
+ singleDate?: {
1253
+ startDate: Date;
1254
+ endDate: Date;
1255
+ allDay: boolean;
1256
+ startTime: string;
1257
+ endTime: string;
1258
+ };
1259
+ multipleDates?: TimeConfiguration[];
1260
+ dateRange?: {
1261
+ startDate: Date;
1262
+ endDate: Date;
1263
+ allDay: boolean;
1264
+ startTime: string;
1265
+ endTime: string;
1266
+ };
1267
+ }
1268
+ ```
1269
+
1270
+ ## 🎯 Common Use Cases
1271
+
1272
+ ### Form Integration
1273
+
1274
+ ```typescript
1275
+ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
1276
+ import { CustomCalendarComponent } from '@brickclay/ui';
1277
+
1278
+ export class BookingFormComponent {
1279
+ bookingForm: FormGroup;
1280
+
1281
+ constructor(private fb: FormBuilder) {
1282
+ this.bookingForm = this.fb.group({
1283
+ checkIn: [null, Validators.required],
1284
+ checkOut: [null, Validators.required],
1285
+ });
1286
+ }
1287
+
1288
+ onDateSelected(selection: CalendarSelection) {
1289
+ this.bookingForm.patchValue({
1290
+ checkIn: selection.startDate,
1291
+ checkOut: selection.endDate,
1292
+ });
1293
+ }
1294
+ }
1295
+ ```
1296
+
1297
+ ### Reactive Forms
1298
+
1299
+ ```typescript
1300
+ <brickclay-custom-calendar
1301
+ [selectedValue]="form.get('dateRange')?.value"
1302
+ (selected)="form.patchValue({ dateRange: $event })">
1303
+ </brickclay-custom-calendar>
1304
+ ```
1305
+
1306
+ ### Date Filtering
1307
+
1308
+ ```typescript
1309
+ export class DataTableComponent {
1310
+ filterDates: CalendarSelection = { startDate: null, endDate: null };
1311
+
1312
+ onDateFilter(selection: CalendarSelection) {
1313
+ this.filterDates = selection;
1314
+ this.loadFilteredData();
1315
+ }
1316
+
1317
+ loadFilteredData() {
1318
+ const filtered = this.data.filter((item) => {
1319
+ if (!this.filterDates.startDate || !this.filterDates.endDate) {
1320
+ return true;
1321
+ }
1322
+ return item.date >= this.filterDates.startDate! && item.date <= this.filterDates.endDate!;
1323
+ });
1324
+ }
1325
+ }
1326
+ ```
1327
+
1328
+ ## πŸ“¦ Assets Configuration
1329
+
1330
+ The calendar components require SVG icons. Configure your `angular.json` to copy assets:
1331
+
1332
+ ```json
1333
+ {
1334
+ "glob": "**/*",
1335
+ "input": "node_modules/@brickclay/ui/assets",
1336
+ "output": "assets"
1337
+ }
1338
+ ```
1339
+
1340
+ Or manually copy assets from:
1341
+
1342
+ ```
1343
+ node_modules/@brickclay/ui/assets/calender/* β†’ your-app/public/assets/calender/
1344
+ ```
1345
+
1346
+ ## πŸ”§ Service
1347
+
1348
+ ### CalendarManagerService
1349
+
1350
+ A service that manages multiple calendar instances, ensuring only one calendar is open at a time when not in inline mode. Used internally by `CustomCalendarComponent`.
1351
+
1352
+ ## 🌐 Browser Support
1353
+
1354
+ - Chrome (latest)
1355
+ - Firefox (latest)
1356
+ - Safari (latest)
1357
+ - Edge (latest)
1358
+
1359
+ ## πŸ“¦ Dependencies
1360
+
1361
+ - Angular 20.3.0+
1362
+ - moment (for date formatting)
1363
+
1364
+ ## 🀝 Contributing
1365
+
1366
+ We welcome contributions! Please see our contributing guidelines for more information.
1367
+
1368
+ ## πŸ“„ License
1369
+
1370
+ MIT
1371
+
1372
+ ## πŸ“ž Support
1373
+
1374
+ For issues, feature requests, or contributions, please visit our [GitHub repository](https://github.com/brickclay/ui).
1375
+
1376
+ ## πŸ—ΊοΈ Roadmap
1377
+
1378
+ - [ ] Button components
1379
+ - [ ] Input components
1380
+ - [ ] Card components
1381
+ - [ ] Modal/Dialog components
1382
+ - [ ] Table components
1383
+ - [ ] Form components
1384
+ - [ ] Navigation components
1385
+ - [ ] Loading/Spinner components
1386
+ - [ ] Toast/Notification components
1387
+ - [ ] More calendar features
1388
+
1389
+ ## πŸ“ Changelog
1390
+
1391
+ ### Version 0.0.1
1392
+
1393
+ **Initial Release:**
1394
+
1395
+ - βœ… Calendar component suite
1396
+ - Single date selection
1397
+ - Date range selection
1398
+ - Multiple date selection
1399
+ - Time picker integration
1400
+ - Inline and dropdown modes
1401
+ - Dual calendar view
1402
+ - Custom date ranges
1403
+ - Date constraints (min/max)
1404
+ - βœ… Scheduled date picker component
1405
+ - βœ… Standalone time picker component
1406
+ - βœ… Toggle/Switch component
1407
+ - Angular forms integration (ngModel & reactive forms)
1408
+ - Three size variants (small, medium, large)
1409
+ - Disabled state support
1410
+ - Full accessibility features
1411
+ - Customizable styling
1412
+ - βœ… Checkbox component
1413
+ - Angular forms integration (ngModel & reactive forms)
1414
+ - Customizable styling via CSS classes
1415
+ - Disabled state support
1416
+ - Full keyboard navigation support
1417
+ - Complete accessibility features
1418
+ - βœ… Radio button component
1419
+ - Angular forms integration (ngModel & reactive forms)
1420
+ - Two visual variants (dot and tick)
1421
+ - Radio group support
1422
+ - Customizable styling via CSS classes
1423
+ - Disabled state support
1424
+ - Full keyboard navigation support
1425
+ - Complete accessibility features
1426
+ - βœ… TypeScript definitions
1427
+ - βœ… Comprehensive documentation
1428
+
1429
+ ---
1430
+
1431
+ **Built with ❀️ by the Brickclay team**