minahil 0.1.0 β†’ 0.1.2

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