@brickclay-org/ui 0.0.3 β†’ 0.0.5

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,842 +1,1047 @@
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
- *More components coming soon...*
26
-
27
- ## Installation
28
-
29
- ```bash
30
- npm install @brickclay-org/ui
31
- ```
32
-
33
- ### Peer Dependencies
34
-
35
- This library requires Angular 20.3.0 or higher:
36
-
37
- ```bash
38
- npm install @angular/common@^20.3.0 @angular/core@^20.3.0 moment
39
- ```
40
-
41
- ## Quick Start
42
-
43
- ### Standalone Component Usage (Recommended)
44
-
45
- ```typescript
46
- import { Component } from '@angular/core';
47
- import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
48
-
49
- @Component({
50
- standalone: true,
51
- selector: 'app-my-component',
52
- imports: [CustomCalendarComponent],
53
- template: `
54
- <brickclay-custom-calendar
55
- (selected)="onDateSelected($event)">
56
- </brickclay-custom-calendar>
57
- `
58
- })
59
- export class MyComponent {
60
- onDateSelected(selection: CalendarSelection) {
61
- console.log('Selected:', selection);
62
- }
63
- }
64
- ```
65
-
66
- ### Module-based Usage
67
-
68
- ```typescript
69
- import { NgModule } from '@angular/core';
70
- import { CalendarModule } from '@brickclay/ui';
71
-
72
- @NgModule({
73
- imports: [CalendarModule],
74
- // ...
75
- })
76
- export class AppModule {}
77
- ```
78
-
79
- ## πŸ“… Calendar
80
-
81
- 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`.
82
-
83
- ### Components Overview
84
-
85
- 1. **CustomCalendarComponent** (`brickclay-custom-calendar`) - Main calendar component with support for single date, date range, and multiple date selection
86
- 2. **ScheduledDatePickerComponent** (`brickclay-scheduled-date-picker`) - Advanced scheduling component with time configuration for events
87
- 3. **TimePickerComponent** (`brickclay-time-picker`) - Standalone time selection component with scrollable pickers
88
-
89
- ### CustomCalendarComponent
90
-
91
- A versatile calendar component that supports single date, date range, and multiple date selection modes.
92
-
93
- #### Basic Example
94
-
95
- ```typescript
96
- import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
97
-
98
- @Component({
99
- template: `
100
- <brickclay-custom-calendar
101
- [singleDatePicker]="false"
102
- [dualCalendar]="true"
103
- [enableTimepicker]="true"
104
- [showRanges]="true"
105
- [placeholder]="'Select date range'"
106
- (selected)="onDateSelected($event)">
107
- </brickclay-custom-calendar>
108
- `
109
- })
110
- export class MyComponent {
111
- onDateSelected(selection: CalendarSelection) {
112
- console.log('Start:', selection.startDate);
113
- console.log('End:', selection.endDate);
114
- }
115
- }
116
- ```
117
-
118
- #### Component Selector
119
-
120
- `<brickclay-custom-calendar>`
121
-
122
- #### Inputs
123
-
124
- | Input | Type | Default | Description |
125
- |-------|------|---------|-------------|
126
- | `enableTimepicker` | `boolean` | `false` | Enable time selection |
127
- | `autoApply` | `boolean` | `false` | Automatically apply selection when date is chosen |
128
- | `closeOnAutoApply` | `boolean` | `false` | Close calendar after auto-apply |
129
- | `showCancel` | `boolean` | `true` | Show cancel button in footer |
130
- | `singleDatePicker` | `boolean` | `false` | Enable single date selection mode |
131
- | `dualCalendar` | `boolean` | `false` | Show two calendars side-by-side |
132
- | `showRanges` | `boolean` | `true` | Show predefined date range buttons |
133
- | `multiDateSelection` | `boolean` | `false` | Enable multiple date selection |
134
- | `inline` | `boolean` | `false` | Always show calendar (no dropdown) |
135
- | `minDate` | `Date` | `undefined` | Minimum selectable date |
136
- | `maxDate` | `Date` | `undefined` | Maximum selectable date |
137
- | `placeholder` | `string` | `'Select date range'` | Input placeholder text |
138
- | `opens` | `'left' \| 'right' \| 'center'` | `'left'` | Dropdown alignment |
139
- | `drop` | `'up' \| 'down'` | `'down'` | Dropdown direction |
140
- | `displayFormat` | `string` | `'MM/DD/YYYY'` | Date display format (moment format) |
141
- | `customRanges` | `Record<string, CalendarRange>` | `undefined` | Custom predefined ranges |
142
- | `selectedValue` | `CalendarSelection \| null` | `null` | Pre-selected date(s) |
143
- | `isDisplayCrossIcon` | `boolean` | `true` | Show/hide clear button |
144
-
145
- #### Outputs
146
-
147
- | Output | Type | Description |
148
- |--------|------|-------------|
149
- | `selected` | `EventEmitter<CalendarSelection>` | Emitted when date selection changes |
150
- | `opened` | `EventEmitter<void>` | Emitted when calendar opens |
151
- | `closed` | `EventEmitter<void>` | Emitted when calendar closes |
152
-
153
- #### Usage Examples
154
-
155
- **Single Date Selection:**
156
-
157
- ```typescript
158
- <brickclay-custom-calendar
159
- [singleDatePicker]="true"
160
- [placeholder]="'Select a date'"
161
- (selected)="onDateSelected($event)">
162
- </brickclay-custom-calendar>
163
- ```
164
-
165
- **Date Range with Time Picker:**
166
-
167
- ```typescript
168
- <brickclay-custom-calendar
169
- [dualCalendar]="true"
170
- [enableTimepicker]="true"
171
- [enableSeconds]="true"
172
- (selected)="onRangeSelected($event)">
173
- </brickclay-custom-calendar>
174
- ```
175
-
176
- **Multiple Date Selection:**
177
-
178
- ```typescript
179
- <brickclay-custom-calendar
180
- [multiDateSelection]="true"
181
- [inline]="true"
182
- (selected)="onMultipleDatesSelected($event)">
183
- </brickclay-custom-calendar>
184
- ```
185
-
186
- **Inline Calendar:**
187
-
188
- ```typescript
189
- <brickclay-custom-calendar
190
- [inline]="true"
191
- [dualCalendar]="false"
192
- [showRanges]="false"
193
- (selected)="onDateSelected($event)">
194
- </brickclay-custom-calendar>
195
- ```
196
-
197
- **Custom Date Ranges:**
198
-
199
- ```typescript
200
- import { CalendarRange } from '@brickclay/ui';
201
-
202
- const customRanges: Record<string, CalendarRange> = {
203
- 'Last Week': {
204
- start: new Date(2024, 0, 1),
205
- end: new Date(2024, 0, 7)
206
- },
207
- 'This Quarter': {
208
- start: new Date(2024, 0, 1),
209
- end: new Date(2024, 2, 31)
210
- }
211
- };
212
-
213
- <brickclay-custom-calendar
214
- [customRanges]="customRanges"
215
- [showRanges]="true"
216
- (selected)="onDateSelected($event)">
217
- </brickclay-custom-calendar>
218
- ```
219
-
220
- **Date Constraints:**
221
-
222
- ```typescript
223
- <brickclay-custom-calendar
224
- [minDate]="new Date(2024, 0, 1)"
225
- [maxDate]="new Date(2024, 11, 31)"
226
- (selected)="onDateSelected($event)">
227
- </brickclay-custom-calendar>
228
- ```
229
-
230
- **Pre-selected Values:**
231
-
232
- ```typescript
233
- export class MyComponent {
234
- selectedValue: CalendarSelection = {
235
- startDate: new Date(2024, 5, 15),
236
- endDate: new Date(2024, 5, 20)
237
- };
238
-
239
- onDateChange() {
240
- this.selectedValue = {
241
- startDate: new Date(),
242
- endDate: new Date()
243
- };
244
- }
245
- }
246
-
247
- <brickclay-custom-calendar
248
- [selectedValue]="selectedValue"
249
- (selected)="onDateSelected($event)">
250
- </brickclay-custom-calendar>
251
- ```
252
-
253
- ### ScheduledDatePickerComponent
254
-
255
- A comprehensive date and time scheduling component with three modes: single date, multiple dates, and date range, each with time configuration.
256
-
257
- #### Basic Example
258
-
259
- ```typescript
260
- import { ScheduledDatePickerComponent, ScheduledDateSelection } from '@brickclay/ui';
261
-
262
- @Component({
263
- template: `
264
- <brickclay-scheduled-date-picker
265
- [timeFormat]="12"
266
- (scheduled)="onScheduled($event)">
267
- </brickclay-scheduled-date-picker>
268
- `
269
- })
270
- export class MyComponent {
271
- onScheduled(selection: ScheduledDateSelection) {
272
- console.log('Mode:', selection.mode);
273
- if (selection.mode === 'single' && selection.singleDate) {
274
- console.log('Start:', selection.singleDate.startDate);
275
- console.log('End:', selection.singleDate.endDate);
276
- console.log('All Day:', selection.singleDate.allDay);
277
- }
278
- }
279
- }
280
- ```
281
-
282
- #### Component Selector
283
-
284
- `<brickclay-scheduled-date-picker>`
285
-
286
- #### Inputs
287
-
288
- | Input | Type | Default | Description |
289
- |-------|------|---------|-------------|
290
- | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
291
- | `enableSeconds` | `boolean` | `false` | Enable seconds in time picker |
292
-
293
- #### Outputs
294
-
295
- | Output | Type | Description |
296
- |--------|------|-------------|
297
- | `scheduled` | `EventEmitter<ScheduledDateSelection>` | Emitted when selection changes |
298
- | `cleared` | `EventEmitter<void>` | Emitted when clear button is clicked |
299
-
300
- #### Features
301
-
302
- - **Single Date Mode**: Select one date with optional start and end times
303
- - **Multiple Dates Mode**: Select multiple dates, each with individual time configuration
304
- - **Date Range Mode**: Select a date range with start and end times
305
- - **All Day Toggle**: Mark dates as all-day events
306
- - **Time Configuration**: Individual time pickers for each date/range
307
-
308
- ### TimePickerComponent
309
-
310
- A standalone time picker component with scrollable hour, minute, and AM/PM selectors.
311
-
312
- #### Basic Example
313
-
314
- ```typescript
315
- import { TimePickerComponent } from '@brickclay/ui';
316
-
317
- @Component({
318
- template: `
319
- <brickclay-time-picker
320
- [value]="selectedTime"
321
- [label]="'Start Time'"
322
- [timeFormat]="12"
323
- (timeChange)="onTimeChange($event)">
324
- </brickclay-time-picker>
325
- `
326
- })
327
- export class MyComponent {
328
- selectedTime = '1:00 AM';
329
-
330
- onTimeChange(time: string) {
331
- this.selectedTime = time;
332
- console.log('New time:', time);
333
- }
334
- }
335
- ```
336
-
337
- #### Component Selector
338
-
339
- `<brickclay-time-picker>`
340
-
341
- #### Inputs
342
-
343
- | Input | Type | Default | Description |
344
- |-------|------|---------|-------------|
345
- | `value` | `string` | `'1:00 AM'` | Current time value (format: "H:MM AM/PM" or "HH:MM") |
346
- | `label` | `string` | `'Time'` | Label text |
347
- | `placeholder` | `string` | `'Select time'` | Placeholder text |
348
- | `position` | `'left' \| 'right'` | `'left'` | Dropdown position |
349
- | `pickerId` | `string` | `''` | Unique identifier for the picker |
350
- | `closePicker` | `number` | `0` | Counter to trigger picker close |
351
- | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
352
- | `showSeconds` | `boolean` | `false` | Show seconds selector |
353
-
354
- #### Outputs
355
-
356
- | Output | Type | Description |
357
- |--------|------|-------------|
358
- | `timeChange` | `EventEmitter<string>` | Emitted when time changes |
359
- | `pickerOpened` | `EventEmitter<string>` | Emitted when picker opens |
360
- | `pickerClosed` | `EventEmitter<string>` | Emitted when picker closes |
361
-
362
- #### Features
363
-
364
- - Scrollable time selectors
365
- - Keyboard navigation support
366
- - 12-hour and 24-hour formats
367
- - Optional seconds support
368
- - Multiple picker coordination (only one open at a time)
369
- - Click outside to close
370
-
371
- #### Time Format Examples
372
-
373
- **12-hour format:**
374
- ```typescript
375
- value="1:00 AM"
376
- value="12:30 PM"
377
- value="11:45 PM"
378
- ```
379
-
380
- **24-hour format:**
381
- ```typescript
382
- value="01:00"
383
- value="13:30"
384
- value="23:45"
385
- ```
386
-
387
- ## πŸ”˜ Toggle
388
-
389
- 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.
390
-
391
- ### ToggleComponent
392
-
393
- A standalone toggle component that implements `ControlValueAccessor` for seamless Angular forms integration.
394
-
395
- #### Basic Example
396
-
397
- ```typescript
398
- import { ToggleComponent } from '@brickclay/ui';
399
- import { FormsModule } from '@angular/forms';
400
-
401
- @Component({
402
- template: `
403
- <brickclay-toggle
404
- [(ngModel)]="isEnabled"
405
- [label]="'Enable notifications'"
406
- (change)="onToggleChange($event)">
407
- </brickclay-toggle>
408
- `,
409
- imports: [ToggleComponent, FormsModule]
410
- })
411
- export class MyComponent {
412
- isEnabled = false;
413
-
414
- onToggleChange(value: boolean) {
415
- console.log('Toggle state:', value);
416
- }
417
- }
418
- ```
419
-
420
- #### Component Selector
421
-
422
- `<brickclay-toggle>`
423
-
424
- #### Inputs
425
-
426
- | Input | Type | Default | Description |
427
- |-------|------|---------|-------------|
428
- | `label` | `string` | `''` | Optional label text displayed next to the toggle |
429
- | `disabled` | `boolean` | `false` | Disables the toggle interaction |
430
- | `toggleClass` | `string` | `'toggle-md'` | CSS class for size styling. Options: `'toggle-sm'`, `'toggle-md'`, `'toggle-lg'` |
431
-
432
- #### Outputs
433
-
434
- | Output | Type | Description |
435
- |--------|------|-------------|
436
- | `change` | `EventEmitter<boolean>` | Emitted when toggle state changes (returns new boolean value) |
437
-
438
- #### Features
439
-
440
- - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
441
- - βœ… **Three Size Variants** - Small (`toggle-sm`), Medium (`toggle-md`), Large (`toggle-lg`)
442
- - βœ… **Accessibility** - ARIA attributes, keyboard navigation, and screen reader support
443
- - βœ… **Disabled State** - Visual and functional disabled state
444
- - βœ… **Customizable Styling** - Custom CSS classes for size and appearance
445
- - βœ… **Event Handling** - `change` event for state change notifications
446
-
447
- #### Usage Examples
448
-
449
- **Basic Toggle with ngModel:**
450
-
451
- ```typescript
452
- import { ToggleComponent } from '@brickclay/ui';
453
- import { FormsModule } from '@angular/forms';
454
-
455
- @Component({
456
- template: `
457
- <brickclay-toggle
458
- [(ngModel)]="isActive"
459
- [label]="'Active Status'">
460
- </brickclay-toggle>
461
- `,
462
- imports: [ToggleComponent, FormsModule]
463
- })
464
- export class MyComponent {
465
- isActive = true;
466
- }
467
- ```
468
-
469
- **Different Sizes:**
470
-
471
- ```typescript
472
- <brickclay-toggle
473
- [(ngModel)]="value1"
474
- [toggleClass]="'toggle-sm'"
475
- [label]="'Small Toggle'">
476
- </brickclay-toggle>
477
-
478
- <brickclay-toggle
479
- [(ngModel)]="value2"
480
- [toggleClass]="'toggle-md'"
481
- [label]="'Medium Toggle'">
482
- </brickclay-toggle>
483
-
484
- <brickclay-toggle
485
- [(ngModel)]="value3"
486
- [toggleClass]="'toggle-lg'"
487
- [label]="'Large Toggle'">
488
- </brickclay-toggle>
489
- ```
490
-
491
- **Disabled State:**
492
-
493
- ```typescript
494
- <brickclay-toggle
495
- [ngModel]="true"
496
- [disabled]="true"
497
- [label]="'Disabled Toggle'">
498
- </brickclay-toggle>
499
- ```
500
-
501
- **With Event Handler:**
502
-
503
- ```typescript
504
- @Component({
505
- template: `
506
- <brickclay-toggle
507
- [(ngModel)]="notificationsEnabled"
508
- [label]="'Email Notifications'"
509
- (change)="onNotificationToggle($event)">
510
- </brickclay-toggle>
511
- `
512
- })
513
- export class MyComponent {
514
- notificationsEnabled = false;
515
-
516
- onNotificationToggle(enabled: boolean) {
517
- if (enabled) {
518
- this.enableNotifications();
519
- } else {
520
- this.disableNotifications();
521
- }
522
- }
523
- }
524
- ```
525
-
526
- **Reactive Forms Integration:**
527
-
528
- ```typescript
529
- import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
530
- import { ToggleComponent } from '@brickclay/ui';
531
-
532
- @Component({
533
- template: `
534
- <form [formGroup]="settingsForm">
535
- <brickclay-toggle
536
- formControlName="darkMode"
537
- [label]="'Dark Mode'">
538
- </brickclay-toggle>
539
-
540
- <brickclay-toggle
541
- formControlName="notifications"
542
- [label]="'Push Notifications'">
543
- </brickclay-toggle>
544
- </form>
545
- `,
546
- imports: [ToggleComponent, ReactiveFormsModule]
547
- })
548
- export class SettingsComponent {
549
- settingsForm: FormGroup;
550
-
551
- constructor(private fb: FormBuilder) {
552
- this.settingsForm = this.fb.group({
553
- darkMode: [false],
554
- notifications: [true]
555
- });
556
- }
557
- }
558
- ```
559
-
560
- **Without Label:**
561
-
562
- ```typescript
563
- <brickclay-toggle
564
- [(ngModel)]="isEnabled"
565
- [toggleClass]="'toggle-md'">
566
- </brickclay-toggle>
567
- ```
568
-
569
- #### Styling
570
-
571
- The toggle component uses CSS classes for size variants:
572
-
573
- - **Small**: `toggle-sm` - Width: 28px (w-7)
574
- - **Medium**: `toggle-md` - Width: 36px (w-9) - Default
575
- - **Large**: `toggle-lg` - Width: 44px (w-11)
576
-
577
- The component includes built-in styles for:
578
- - On state (green background: `#22973F`)
579
- - Off state (gray background: `#BBBDC5`)
580
- - Disabled state (light gray: `#D6D7DC`)
581
- - Hover states
582
- - Focus ring for accessibility
583
- - Smooth transitions
584
-
585
- #### Accessibility
586
-
587
- The toggle component includes:
588
- - `role="switch"` for screen readers
589
- - `aria-checked` attribute that reflects the current state
590
- - Keyboard navigation support
591
- - Focus visible ring for keyboard users
592
- - Disabled state properly communicated to assistive technologies
593
-
594
- ## πŸ“ TypeScript Interfaces
595
-
596
- ### CalendarRange
597
-
598
- ```typescript
599
- interface CalendarRange {
600
- start: Date;
601
- end: Date;
602
- }
603
- ```
604
-
605
- ### CalendarSelection
606
-
607
- ```typescript
608
- interface CalendarSelection {
609
- startDate: Date | null;
610
- endDate: Date | null;
611
- selectedDates?: Date[]; // For multi-date selection
612
- }
613
- ```
614
-
615
- ### TimeConfiguration
616
-
617
- ```typescript
618
- interface TimeConfiguration {
619
- date: Date;
620
- allDay: boolean;
621
- startTime: string; // Format: "HH:mm" or "HH:mm:ss"
622
- endTime: string;
623
- }
624
- ```
625
-
626
- ### ScheduledDateSelection
627
-
628
- ```typescript
629
- interface ScheduledDateSelection {
630
- mode: 'single' | 'multiple' | 'range';
631
- singleDate?: {
632
- startDate: Date;
633
- endDate: Date;
634
- allDay: boolean;
635
- startTime: string;
636
- endTime: string;
637
- };
638
- multipleDates?: TimeConfiguration[];
639
- dateRange?: {
640
- startDate: Date;
641
- endDate: Date;
642
- allDay: boolean;
643
- startTime: string;
644
- endTime: string;
645
- };
646
- }
647
- ```
648
-
649
- ## 🎯 Common Use Cases
650
-
651
- ### Form Integration
652
-
653
- ```typescript
654
- import { FormBuilder, FormGroup, Validators } from '@angular/forms';
655
- import { CustomCalendarComponent } from '@brickclay/ui';
656
-
657
- export class BookingFormComponent {
658
- bookingForm: FormGroup;
659
-
660
- constructor(private fb: FormBuilder) {
661
- this.bookingForm = this.fb.group({
662
- checkIn: [null, Validators.required],
663
- checkOut: [null, Validators.required]
664
- });
665
- }
666
-
667
- onDateSelected(selection: CalendarSelection) {
668
- this.bookingForm.patchValue({
669
- checkIn: selection.startDate,
670
- checkOut: selection.endDate
671
- });
672
- }
673
- }
674
- ```
675
-
676
- ### Reactive Forms
677
-
678
- ```typescript
679
- <brickclay-custom-calendar
680
- [selectedValue]="form.get('dateRange')?.value"
681
- (selected)="form.patchValue({ dateRange: $event })">
682
- </brickclay-custom-calendar>
683
- ```
684
-
685
- ### Date Filtering
686
-
687
- ```typescript
688
- export class DataTableComponent {
689
- filterDates: CalendarSelection = { startDate: null, endDate: null };
690
-
691
- onDateFilter(selection: CalendarSelection) {
692
- this.filterDates = selection;
693
- this.loadFilteredData();
694
- }
695
-
696
- loadFilteredData() {
697
- const filtered = this.data.filter(item => {
698
- if (!this.filterDates.startDate || !this.filterDates.endDate) {
699
- return true;
700
- }
701
- return item.date >= this.filterDates.startDate! &&
702
- item.date <= this.filterDates.endDate!;
703
- });
704
- }
705
- }
706
- ```
707
-
708
- ## πŸ“¦ Assets Configuration
709
-
710
- The calendar components require SVG icons. After installing `@brickclay-org/ui`, configure your `angular.json` to copy assets from the package:
711
-
712
- ### Option 1: Automatic Asset Copying (Recommended)
713
-
714
- Add the following to your `angular.json` under `projects.[your-project].architect.build.options.assets`:
715
-
716
- ```json
717
- {
718
- "glob": "**/*",
719
- "input": "node_modules/@brickclay-org/ui/assets",
720
- "output": "assets"
721
- }
722
- ```
723
-
724
- **Example complete assets configuration:**
725
-
726
- ```json
727
- {
728
- "projects": {
729
- "your-app": {
730
- "architect": {
731
- "build": {
732
- "options": {
733
- "assets": [
734
- {
735
- "glob": "**/*",
736
- "input": "public"
737
- },
738
- {
739
- "glob": "**/*",
740
- "input": "node_modules/@brickclay-org/ui/assets",
741
- "output": "assets"
742
- }
743
- ]
744
- }
745
- }
746
- }
747
- }
748
- }
749
- }
750
- ```
751
-
752
- ### Option 2: Manual Asset Copying
753
-
754
- If you prefer to copy assets manually, copy them from:
755
- ```
756
- node_modules/@brickclay-org/ui/assets/calender/* β†’ your-app/public/assets/calender/
757
- ```
758
-
759
- ### Option 3: Custom Asset Path
760
-
761
- If your assets are in a different location, you can configure the component to use a custom path:
762
-
763
- ```typescript
764
- <brickclay-custom-calendar
765
- [assetsPath]="'custom/path/to/assets/calender'"
766
- (selected)="onDateSelected($event)">
767
- </brickclay-custom-calendar>
768
- ```
769
-
770
- **Note:** After updating `angular.json`, restart your development server for the changes to take effect.
771
-
772
- ## πŸ”§ Service
773
-
774
- ### CalendarManagerService
775
-
776
- 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`.
777
-
778
- ## 🌐 Browser Support
779
-
780
- - Chrome (latest)
781
- - Firefox (latest)
782
- - Safari (latest)
783
- - Edge (latest)
784
-
785
- ## πŸ“¦ Dependencies
786
-
787
- - Angular 20.3.0+
788
- - moment (for date formatting)
789
-
790
- ## 🀝 Contributing
791
-
792
- We welcome contributions! Please see our contributing guidelines for more information.
793
-
794
- ## πŸ“„ License
795
-
796
- MIT
797
-
798
- ## πŸ“ž Support
799
-
800
- For issues, feature requests, or contributions, please visit our [GitHub repository](https://github.com/brickclay/ui).
801
-
802
- ## πŸ—ΊοΈ Roadmap
803
-
804
- - [ ] Button components
805
- - [ ] Input components
806
- - [ ] Card components
807
- - [ ] Modal/Dialog components
808
- - [ ] Table components
809
- - [ ] Form components
810
- - [ ] Navigation components
811
- - [ ] Loading/Spinner components
812
- - [ ] Toast/Notification components
813
- - [ ] More calendar features
814
-
815
- ## πŸ“ Changelog
816
-
817
- ### Version 0.0.1
818
-
819
- **Initial Release:**
820
- - βœ… Calendar component suite
821
- - Single date selection
822
- - Date range selection
823
- - Multiple date selection
824
- - Time picker integration
825
- - Inline and dropdown modes
826
- - Dual calendar view
827
- - Custom date ranges
828
- - Date constraints (min/max)
829
- - βœ… Scheduled date picker component
830
- - βœ… Standalone time picker component
831
- - βœ… Toggle/Switch component
832
- - Angular forms integration (ngModel & reactive forms)
833
- - Three size variants (small, medium, large)
834
- - Disabled state support
835
- - Full accessibility features
836
- - Customizable styling
837
- - βœ… TypeScript definitions
838
- - βœ… Comprehensive documentation
839
-
840
- ---
841
-
842
- **Built with ❀️ by the Brickclay team**
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 four size variants (small, medium, large, extra-large), disabled state, keyboard navigation, and seamless integration with both template-driven and reactive forms.
28
+
29
+ *More components coming soon...*
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm i @brickclay-org/ui@0.0.5
35
+ ```
36
+
37
+ ### Peer Dependencies
38
+
39
+ This library requires Angular 20.3.0 or higher:
40
+
41
+ ```bash
42
+ npm install @angular/common@^20.3.0 @angular/core@^20.3.0 moment
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ### Standalone Component Usage (Recommended)
48
+
49
+ ```typescript
50
+ import { Component } from '@angular/core';
51
+ import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
52
+
53
+ @Component({
54
+ standalone: true,
55
+ selector: 'app-my-component',
56
+ imports: [CustomCalendarComponent],
57
+ template: `
58
+ <brickclay-custom-calendar
59
+ (selected)="onDateSelected($event)">
60
+ </brickclay-custom-calendar>
61
+ `
62
+ })
63
+ export class MyComponent {
64
+ onDateSelected(selection: CalendarSelection) {
65
+ console.log('Selected:', selection);
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Module-based Usage
71
+
72
+ ```typescript
73
+ import { NgModule } from '@angular/core';
74
+ import { CalendarModule } from '@brickclay/ui';
75
+
76
+ @NgModule({
77
+ imports: [CalendarModule],
78
+ // ...
79
+ })
80
+ export class AppModule {}
81
+ ```
82
+
83
+ ## πŸ“… Calendar
84
+
85
+ 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`.
86
+
87
+ ### Components Overview
88
+
89
+ 1. **CustomCalendarComponent** (`brickclay-custom-calendar`) - Main calendar component with support for single date, date range, and multiple date selection
90
+ 2. **ScheduledDatePickerComponent** (`brickclay-scheduled-date-picker`) - Advanced scheduling component with time configuration for events
91
+ 3. **TimePickerComponent** (`brickclay-time-picker`) - Standalone time selection component with scrollable pickers
92
+
93
+ ### CustomCalendarComponent
94
+
95
+ A versatile calendar component that supports single date, date range, and multiple date selection modes.
96
+
97
+ #### Basic Example
98
+
99
+ ```typescript
100
+ import { CustomCalendarComponent, CalendarSelection } from '@brickclay/ui';
101
+
102
+ @Component({
103
+ template: `
104
+ <brickclay-custom-calendar
105
+ [singleDatePicker]="false"
106
+ [dualCalendar]="true"
107
+ [enableTimepicker]="true"
108
+ [showRanges]="true"
109
+ [placeholder]="'Select date range'"
110
+ (selected)="onDateSelected($event)">
111
+ </brickclay-custom-calendar>
112
+ `
113
+ })
114
+ export class MyComponent {
115
+ onDateSelected(selection: CalendarSelection) {
116
+ console.log('Start:', selection.startDate);
117
+ console.log('End:', selection.endDate);
118
+ }
119
+ }
120
+ ```
121
+
122
+ #### Component Selector
123
+
124
+ `<brickclay-custom-calendar>`
125
+
126
+ #### Inputs
127
+
128
+ | Input | Type | Default | Description |
129
+ |-------|------|---------|-------------|
130
+ | `enableTimepicker` | `boolean` | `false` | Enable time selection |
131
+ | `autoApply` | `boolean` | `false` | Automatically apply selection when date is chosen |
132
+ | `closeOnAutoApply` | `boolean` | `false` | Close calendar after auto-apply |
133
+ | `showCancel` | `boolean` | `true` | Show cancel button in footer |
134
+ | `singleDatePicker` | `boolean` | `false` | Enable single date selection mode |
135
+ | `dualCalendar` | `boolean` | `false` | Show two calendars side-by-side |
136
+ | `showRanges` | `boolean` | `true` | Show predefined date range buttons |
137
+ | `multiDateSelection` | `boolean` | `false` | Enable multiple date selection |
138
+ | `inline` | `boolean` | `false` | Always show calendar (no dropdown) |
139
+ | `minDate` | `Date` | `undefined` | Minimum selectable date |
140
+ | `maxDate` | `Date` | `undefined` | Maximum selectable date |
141
+ | `placeholder` | `string` | `'Select date range'` | Input placeholder text |
142
+ | `opens` | `'left' \| 'right' \| 'center'` | `'left'` | Dropdown alignment |
143
+ | `drop` | `'up' \| 'down'` | `'down'` | Dropdown direction |
144
+ | `displayFormat` | `string` | `'MM/DD/YYYY'` | Date display format (moment format) |
145
+ | `customRanges` | `Record<string, CalendarRange>` | `undefined` | Custom predefined ranges |
146
+ | `selectedValue` | `CalendarSelection \| null` | `null` | Pre-selected date(s) |
147
+ | `isDisplayCrossIcon` | `boolean` | `true` | Show/hide clear button |
148
+
149
+ #### Outputs
150
+
151
+ | Output | Type | Description |
152
+ |--------|------|-------------|
153
+ | `selected` | `EventEmitter<CalendarSelection>` | Emitted when date selection changes |
154
+ | `opened` | `EventEmitter<void>` | Emitted when calendar opens |
155
+ | `closed` | `EventEmitter<void>` | Emitted when calendar closes |
156
+
157
+ #### Usage Examples
158
+
159
+ **Single Date Selection:**
160
+
161
+ ```typescript
162
+ <brickclay-custom-calendar
163
+ [singleDatePicker]="true"
164
+ [placeholder]="'Select a date'"
165
+ (selected)="onDateSelected($event)">
166
+ </brickclay-custom-calendar>
167
+ ```
168
+
169
+ **Date Range with Time Picker:**
170
+
171
+ ```typescript
172
+ <brickclay-custom-calendar
173
+ [dualCalendar]="true"
174
+ [enableTimepicker]="true"
175
+ [enableSeconds]="true"
176
+ (selected)="onRangeSelected($event)">
177
+ </brickclay-custom-calendar>
178
+ ```
179
+
180
+ **Multiple Date Selection:**
181
+
182
+ ```typescript
183
+ <brickclay-custom-calendar
184
+ [multiDateSelection]="true"
185
+ [inline]="true"
186
+ (selected)="onMultipleDatesSelected($event)">
187
+ </brickclay-custom-calendar>
188
+ ```
189
+
190
+ **Inline Calendar:**
191
+
192
+ ```typescript
193
+ <brickclay-custom-calendar
194
+ [inline]="true"
195
+ [dualCalendar]="false"
196
+ [showRanges]="false"
197
+ (selected)="onDateSelected($event)">
198
+ </brickclay-custom-calendar>
199
+ ```
200
+
201
+ **Custom Date Ranges:**
202
+
203
+ ```typescript
204
+ import { CalendarRange } from '@brickclay/ui';
205
+
206
+ const customRanges: Record<string, CalendarRange> = {
207
+ 'Last Week': {
208
+ start: new Date(2024, 0, 1),
209
+ end: new Date(2024, 0, 7)
210
+ },
211
+ 'This Quarter': {
212
+ start: new Date(2024, 0, 1),
213
+ end: new Date(2024, 2, 31)
214
+ }
215
+ };
216
+
217
+ <brickclay-custom-calendar
218
+ [customRanges]="customRanges"
219
+ [showRanges]="true"
220
+ (selected)="onDateSelected($event)">
221
+ </brickclay-custom-calendar>
222
+ ```
223
+
224
+ **Date Constraints:**
225
+
226
+ ```typescript
227
+ <brickclay-custom-calendar
228
+ [minDate]="new Date(2024, 0, 1)"
229
+ [maxDate]="new Date(2024, 11, 31)"
230
+ (selected)="onDateSelected($event)">
231
+ </brickclay-custom-calendar>
232
+ ```
233
+
234
+ **Pre-selected Values:**
235
+
236
+ ```typescript
237
+ export class MyComponent {
238
+ selectedValue: CalendarSelection = {
239
+ startDate: new Date(2024, 5, 15),
240
+ endDate: new Date(2024, 5, 20)
241
+ };
242
+
243
+ onDateChange() {
244
+ this.selectedValue = {
245
+ startDate: new Date(),
246
+ endDate: new Date()
247
+ };
248
+ }
249
+ }
250
+
251
+ <brickclay-custom-calendar
252
+ [selectedValue]="selectedValue"
253
+ (selected)="onDateSelected($event)">
254
+ </brickclay-custom-calendar>
255
+ ```
256
+
257
+ ### ScheduledDatePickerComponent
258
+
259
+ A comprehensive date and time scheduling component with three modes: single date, multiple dates, and date range, each with time configuration.
260
+
261
+ #### Basic Example
262
+
263
+ ```typescript
264
+ import { ScheduledDatePickerComponent, ScheduledDateSelection } from '@brickclay/ui';
265
+
266
+ @Component({
267
+ template: `
268
+ <brickclay-scheduled-date-picker
269
+ [timeFormat]="12"
270
+ (scheduled)="onScheduled($event)">
271
+ </brickclay-scheduled-date-picker>
272
+ `
273
+ })
274
+ export class MyComponent {
275
+ onScheduled(selection: ScheduledDateSelection) {
276
+ console.log('Mode:', selection.mode);
277
+ if (selection.mode === 'single' && selection.singleDate) {
278
+ console.log('Start:', selection.singleDate.startDate);
279
+ console.log('End:', selection.singleDate.endDate);
280
+ console.log('All Day:', selection.singleDate.allDay);
281
+ }
282
+ }
283
+ }
284
+ ```
285
+
286
+ #### Component Selector
287
+
288
+ `<brickclay-scheduled-date-picker>`
289
+
290
+ #### Inputs
291
+
292
+ | Input | Type | Default | Description |
293
+ |-------|------|---------|-------------|
294
+ | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
295
+ | `enableSeconds` | `boolean` | `false` | Enable seconds in time picker |
296
+
297
+ #### Outputs
298
+
299
+ | Output | Type | Description |
300
+ |--------|------|-------------|
301
+ | `scheduled` | `EventEmitter<ScheduledDateSelection>` | Emitted when selection changes |
302
+ | `cleared` | `EventEmitter<void>` | Emitted when clear button is clicked |
303
+
304
+ #### Features
305
+
306
+ - **Single Date Mode**: Select one date with optional start and end times
307
+ - **Multiple Dates Mode**: Select multiple dates, each with individual time configuration
308
+ - **Date Range Mode**: Select a date range with start and end times
309
+ - **All Day Toggle**: Mark dates as all-day events
310
+ - **Time Configuration**: Individual time pickers for each date/range
311
+
312
+ ### TimePickerComponent
313
+
314
+ A standalone time picker component with scrollable hour, minute, and AM/PM selectors.
315
+
316
+ #### Basic Example
317
+
318
+ ```typescript
319
+ import { TimePickerComponent } from '@brickclay/ui';
320
+
321
+ @Component({
322
+ template: `
323
+ <brickclay-time-picker
324
+ [value]="selectedTime"
325
+ [label]="'Start Time'"
326
+ [timeFormat]="12"
327
+ (timeChange)="onTimeChange($event)">
328
+ </brickclay-time-picker>
329
+ `
330
+ })
331
+ export class MyComponent {
332
+ selectedTime = '1:00 AM';
333
+
334
+ onTimeChange(time: string) {
335
+ this.selectedTime = time;
336
+ console.log('New time:', time);
337
+ }
338
+ }
339
+ ```
340
+
341
+ #### Component Selector
342
+
343
+ `<brickclay-time-picker>`
344
+
345
+ #### Inputs
346
+
347
+ | Input | Type | Default | Description |
348
+ |-------|------|---------|-------------|
349
+ | `value` | `string` | `'1:00 AM'` | Current time value (format: "H:MM AM/PM" or "HH:MM") |
350
+ | `label` | `string` | `'Time'` | Label text |
351
+ | `placeholder` | `string` | `'Select time'` | Placeholder text |
352
+ | `position` | `'left' \| 'right'` | `'left'` | Dropdown position |
353
+ | `pickerId` | `string` | `''` | Unique identifier for the picker |
354
+ | `closePicker` | `number` | `0` | Counter to trigger picker close |
355
+ | `timeFormat` | `12 \| 24` | `12` | Time format (12-hour or 24-hour) |
356
+ | `showSeconds` | `boolean` | `false` | Show seconds selector |
357
+
358
+ #### Outputs
359
+
360
+ | Output | Type | Description |
361
+ |--------|------|-------------|
362
+ | `timeChange` | `EventEmitter<string>` | Emitted when time changes |
363
+ | `pickerOpened` | `EventEmitter<string>` | Emitted when picker opens |
364
+ | `pickerClosed` | `EventEmitter<string>` | Emitted when picker closes |
365
+
366
+ #### Features
367
+
368
+ - Scrollable time selectors
369
+ - Keyboard navigation support
370
+ - 12-hour and 24-hour formats
371
+ - Optional seconds support
372
+ - Multiple picker coordination (only one open at a time)
373
+ - Click outside to close
374
+
375
+ #### Time Format Examples
376
+
377
+ **12-hour format:**
378
+ ```typescript
379
+ value="1:00 AM"
380
+ value="12:30 PM"
381
+ value="11:45 PM"
382
+ ```
383
+
384
+ **24-hour format:**
385
+ ```typescript
386
+ value="01:00"
387
+ value="13:30"
388
+ value="23:45"
389
+ ```
390
+
391
+ ## πŸ”˜ Toggle
392
+
393
+ 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.
394
+
395
+ ### ToggleComponent
396
+
397
+ A standalone toggle component that implements `ControlValueAccessor` for seamless Angular forms integration.
398
+
399
+ #### Basic Example
400
+
401
+ ```typescript
402
+ import { ToggleComponent } from '@brickclay/ui';
403
+ import { FormsModule } from '@angular/forms';
404
+
405
+ @Component({
406
+ template: `
407
+ <brickclay-toggle
408
+ [(ngModel)]="isEnabled"
409
+ [label]="'Enable notifications'"
410
+ (change)="onToggleChange($event)">
411
+ </brickclay-toggle>
412
+ `,
413
+ imports: [ToggleComponent, FormsModule]
414
+ })
415
+ export class MyComponent {
416
+ isEnabled = false;
417
+
418
+ onToggleChange(value: boolean) {
419
+ console.log('Toggle state:', value);
420
+ }
421
+ }
422
+ ```
423
+
424
+ #### Component Selector
425
+
426
+ `<brickclay-toggle>`
427
+
428
+ #### Inputs
429
+
430
+ | Input | Type | Default | Description |
431
+ |-------|------|---------|-------------|
432
+ | `label` | `string` | `''` | Optional label text displayed next to the toggle |
433
+ | `disabled` | `boolean` | `false` | Disables the toggle interaction |
434
+ | `toggleClass` | `string` | `'toggle-md'` | CSS class for size styling. Options: `'toggle-sm'`, `'toggle-md'`, `'toggle-lg'` |
435
+
436
+ #### Outputs
437
+
438
+ | Output | Type | Description |
439
+ |--------|------|-------------|
440
+ | `change` | `EventEmitter<boolean>` | Emitted when toggle state changes (returns new boolean value) |
441
+
442
+ #### Features
443
+
444
+ - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
445
+ - βœ… **Three Size Variants** - Small (`toggle-sm`), Medium (`toggle-md`), Large (`toggle-lg`)
446
+ - βœ… **Accessibility** - ARIA attributes, keyboard navigation, and screen reader support
447
+ - βœ… **Disabled State** - Visual and functional disabled state
448
+ - βœ… **Customizable Styling** - Custom CSS classes for size and appearance
449
+ - βœ… **Event Handling** - `change` event for state change notifications
450
+
451
+ #### Usage Examples
452
+
453
+ **Basic Toggle with ngModel:**
454
+
455
+ ```typescript
456
+ import { ToggleComponent } from '@brickclay/ui';
457
+ import { FormsModule } from '@angular/forms';
458
+
459
+ @Component({
460
+ template: `
461
+ <brickclay-toggle
462
+ [(ngModel)]="isActive"
463
+ [label]="'Active Status'">
464
+ </brickclay-toggle>
465
+ `,
466
+ imports: [ToggleComponent, FormsModule]
467
+ })
468
+ export class MyComponent {
469
+ isActive = true;
470
+ }
471
+ ```
472
+
473
+ **Different Sizes:**
474
+
475
+ ```typescript
476
+ <brickclay-toggle
477
+ [(ngModel)]="value1"
478
+ [toggleClass]="'toggle-sm'"
479
+ [label]="'Small Toggle'">
480
+ </brickclay-toggle>
481
+
482
+ <brickclay-toggle
483
+ [(ngModel)]="value2"
484
+ [toggleClass]="'toggle-md'"
485
+ [label]="'Medium Toggle'">
486
+ </brickclay-toggle>
487
+
488
+ <brickclay-toggle
489
+ [(ngModel)]="value3"
490
+ [toggleClass]="'toggle-lg'"
491
+ [label]="'Large Toggle'">
492
+ </brickclay-toggle>
493
+ ```
494
+
495
+ **Disabled State:**
496
+
497
+ ```typescript
498
+ <brickclay-toggle
499
+ [ngModel]="true"
500
+ [disabled]="true"
501
+ [label]="'Disabled Toggle'">
502
+ </brickclay-toggle>
503
+ ```
504
+
505
+ **With Event Handler:**
506
+
507
+ ```typescript
508
+ @Component({
509
+ template: `
510
+ <brickclay-toggle
511
+ [(ngModel)]="notificationsEnabled"
512
+ [label]="'Email Notifications'"
513
+ (change)="onNotificationToggle($event)">
514
+ </brickclay-toggle>
515
+ `
516
+ })
517
+ export class MyComponent {
518
+ notificationsEnabled = false;
519
+
520
+ onNotificationToggle(enabled: boolean) {
521
+ if (enabled) {
522
+ this.enableNotifications();
523
+ } else {
524
+ this.disableNotifications();
525
+ }
526
+ }
527
+ }
528
+ ```
529
+
530
+ **Reactive Forms Integration:**
531
+
532
+ ```typescript
533
+ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
534
+ import { ToggleComponent } from '@brickclay/ui';
535
+
536
+ @Component({
537
+ template: `
538
+ <form [formGroup]="settingsForm">
539
+ <brickclay-toggle
540
+ formControlName="darkMode"
541
+ [label]="'Dark Mode'">
542
+ </brickclay-toggle>
543
+
544
+ <brickclay-toggle
545
+ formControlName="notifications"
546
+ [label]="'Push Notifications'">
547
+ </brickclay-toggle>
548
+ </form>
549
+ `,
550
+ imports: [ToggleComponent, ReactiveFormsModule]
551
+ })
552
+ export class SettingsComponent {
553
+ settingsForm: FormGroup;
554
+
555
+ constructor(private fb: FormBuilder) {
556
+ this.settingsForm = this.fb.group({
557
+ darkMode: [false],
558
+ notifications: [true]
559
+ });
560
+ }
561
+ }
562
+ ```
563
+
564
+ **Without Label:**
565
+
566
+ ```typescript
567
+ <brickclay-toggle
568
+ [(ngModel)]="isEnabled"
569
+ [toggleClass]="'toggle-md'">
570
+ </brickclay-toggle>
571
+ ```
572
+
573
+ #### Styling
574
+
575
+ The toggle component uses CSS classes for size variants:
576
+
577
+ - **Small**: `toggle-sm` - Width: 28px (w-7)
578
+ - **Medium**: `toggle-md` - Width: 36px (w-9) - Default
579
+ - **Large**: `toggle-lg` - Width: 44px (w-11)
580
+
581
+ The component includes built-in styles for:
582
+ - On state (green background: `#22973F`)
583
+ - Off state (gray background: `#BBBDC5`)
584
+ - Disabled state (light gray: `#D6D7DC`)
585
+ - Hover states
586
+ - Focus ring for accessibility
587
+ - Smooth transitions
588
+
589
+ #### Accessibility
590
+
591
+ The toggle component includes:
592
+ - `role="switch"` for screen readers
593
+ - `aria-checked` attribute that reflects the current state
594
+ - Keyboard navigation support
595
+ - Focus visible ring for keyboard users
596
+ - Disabled state properly communicated to assistive technologies
597
+
598
+ ## β˜‘οΈ Checkbox
599
+
600
+ A fully accessible checkbox component that integrates seamlessly with Angular forms. Supports both template-driven forms (`ngModel`) and reactive forms, with four size variants and comprehensive accessibility features.
601
+
602
+ ### CheckboxComponent
603
+
604
+ A standalone checkbox component that implements `ControlValueAccessor` for seamless Angular forms integration.
605
+
606
+ #### Basic Example
607
+
608
+ ```typescript
609
+ import { CheckboxComponent } from '@brickclay/ui';
610
+ import { FormsModule } from '@angular/forms';
611
+
612
+ @Component({
613
+ template: `
614
+ <brickclay-checkbox
615
+ [(ngModel)]="isAccepted"
616
+ [label]="'I agree to the terms and conditions'"
617
+ (changed)="onCheckboxChange($event)">
618
+ </brickclay-checkbox>
619
+ `,
620
+ imports: [CheckboxComponent, FormsModule]
621
+ })
622
+ export class MyComponent {
623
+ isAccepted = false;
624
+
625
+ onCheckboxChange(value: boolean) {
626
+ console.log('Checkbox state:', value);
627
+ }
628
+ }
629
+ ```
630
+
631
+ #### Component Selector
632
+
633
+ `<brickclay-checkbox>`
634
+
635
+ #### Inputs
636
+
637
+ | Input | Type | Default | Description |
638
+ |-------|------|---------|-------------|
639
+ | `label` | `string` | `''` | Optional label text displayed next to the checkbox |
640
+ | `disabled` | `boolean` | `false` | Disables the checkbox interaction |
641
+ | `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Size of the checkbox. Options: `'sm'` (14px), `'md'` (16px), `'lg'` (18px), `'xl'` (20px) |
642
+
643
+ #### Outputs
644
+
645
+ | Output | Type | Description |
646
+ |--------|------|-------------|
647
+ | `changed` | `EventEmitter<boolean>` | Emitted when checkbox state changes (returns new boolean value) |
648
+
649
+ #### Features
650
+
651
+ - βœ… **Angular Forms Integration** - Full support for `ngModel` and reactive forms
652
+ - βœ… **Four Size Variants** - Small (14px), Medium (16px), Large (18px), Extra Large (20px)
653
+ - βœ… **Accessibility** - ARIA attributes, keyboard navigation (Enter/Space), and screen reader support
654
+ - βœ… **Disabled State** - Visual and functional disabled state
655
+ - βœ… **Keyboard Support** - Full keyboard navigation with Enter and Space keys
656
+ - βœ… **Focus Management** - Focus visible ring for keyboard users
657
+ - βœ… **Event Handling** - `changed` event for state change notifications
658
+
659
+ #### Usage Examples
660
+
661
+ **Basic Checkbox with ngModel:**
662
+
663
+ ```typescript
664
+ import { CheckboxComponent } from '@brickclay/ui';
665
+ import { FormsModule } from '@angular/forms';
666
+
667
+ @Component({
668
+ template: `
669
+ <brickclay-checkbox
670
+ [(ngModel)]="isChecked"
671
+ [label]="'Accept terms'">
672
+ </brickclay-checkbox>
673
+ `,
674
+ imports: [CheckboxComponent, FormsModule]
675
+ })
676
+ export class MyComponent {
677
+ isChecked = false;
678
+ }
679
+ ```
680
+
681
+ **Different Sizes:**
682
+
683
+ ```typescript
684
+ <brickclay-checkbox
685
+ [(ngModel)]="value1"
686
+ [size]="'sm'"
687
+ [label]="'Small Checkbox'">
688
+ </brickclay-checkbox>
689
+
690
+ <brickclay-checkbox
691
+ [(ngModel)]="value2"
692
+ [size]="'md'"
693
+ [label]="'Medium Checkbox'">
694
+ </brickclay-checkbox>
695
+
696
+ <brickclay-checkbox
697
+ [(ngModel)]="value3"
698
+ [size]="'lg'"
699
+ [label]="'Large Checkbox'">
700
+ </brickclay-checkbox>
701
+
702
+ <brickclay-checkbox
703
+ [(ngModel)]="value4"
704
+ [size]="'xl'"
705
+ [label]="'Extra Large Checkbox'">
706
+ </brickclay-checkbox>
707
+ ```
708
+
709
+ **Disabled State:**
710
+
711
+ ```typescript
712
+ <brickclay-checkbox
713
+ [ngModel]="true"
714
+ [disabled]="true"
715
+ [label]="'Disabled Checkbox'">
716
+ </brickclay-checkbox>
717
+ ```
718
+
719
+ **With Event Handler:**
720
+
721
+ ```typescript
722
+ @Component({
723
+ template: `
724
+ <brickclay-checkbox
725
+ [(ngModel)]="newsletterSubscribed"
726
+ [label]="'Subscribe to newsletter'"
727
+ (changed)="onNewsletterToggle($event)">
728
+ </brickclay-checkbox>
729
+ `
730
+ })
731
+ export class MyComponent {
732
+ newsletterSubscribed = false;
733
+
734
+ onNewsletterToggle(subscribed: boolean) {
735
+ if (subscribed) {
736
+ this.subscribeToNewsletter();
737
+ } else {
738
+ this.unsubscribeFromNewsletter();
739
+ }
740
+ }
741
+ }
742
+ ```
743
+
744
+ **Reactive Forms Integration:**
745
+
746
+ ```typescript
747
+ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
748
+ import { CheckboxComponent } from '@brickclay/ui';
749
+
750
+ @Component({
751
+ template: `
752
+ <form [formGroup]="registrationForm">
753
+ <brickclay-checkbox
754
+ formControlName="acceptTerms"
755
+ [label]="'I accept the terms and conditions'">
756
+ </brickclay-checkbox>
757
+
758
+ <brickclay-checkbox
759
+ formControlName="receiveUpdates"
760
+ [label]="'Receive product updates'">
761
+ </brickclay-checkbox>
762
+ </form>
763
+ `,
764
+ imports: [CheckboxComponent, ReactiveFormsModule]
765
+ })
766
+ export class RegistrationComponent {
767
+ registrationForm: FormGroup;
768
+
769
+ constructor(private fb: FormBuilder) {
770
+ this.registrationForm = this.fb.group({
771
+ acceptTerms: [false, Validators.requiredTrue],
772
+ receiveUpdates: [false]
773
+ });
774
+ }
775
+ }
776
+ ```
777
+
778
+ **Without Label:**
779
+
780
+ ```typescript
781
+ <brickclay-checkbox
782
+ [(ngModel)]="isSelected"
783
+ [size]="'md'">
784
+ </brickclay-checkbox>
785
+ ```
786
+
787
+ **Multiple Checkboxes:**
788
+
789
+ ```typescript
790
+ @Component({
791
+ template: `
792
+ <div>
793
+ <brickclay-checkbox
794
+ *ngFor="let option of options"
795
+ [(ngModel)]="option.selected"
796
+ [label]="option.label"
797
+ (changed)="onOptionChange(option)">
798
+ </brickclay-checkbox>
799
+ </div>
800
+ `
801
+ })
802
+ export class MyComponent {
803
+ options = [
804
+ { label: 'Option 1', selected: false },
805
+ { label: 'Option 2', selected: false },
806
+ { label: 'Option 3', selected: false }
807
+ ];
808
+
809
+ onOptionChange(option: any) {
810
+ console.log(`${option.label} is now ${option.selected ? 'selected' : 'deselected'}`);
811
+ }
812
+ }
813
+ ```
814
+
815
+ #### Styling
816
+
817
+ The checkbox component uses size variants:
818
+
819
+ - **Small**: `sm` - 14px Γ— 14px
820
+ - **Medium**: `md` - 16px Γ— 16px (Default)
821
+ - **Large**: `lg` - 18px Γ— 18px
822
+ - **Extra Large**: `xl` - 20px Γ— 20px
823
+
824
+ The component includes built-in styles for:
825
+ - Checked state (black background with white checkmark)
826
+ - Unchecked state (white background with gray border)
827
+ - Hover states (darker border on hover)
828
+ - Disabled states (gray background and border)
829
+ - Focus ring for accessibility (blue ring with offset)
830
+
831
+ #### Accessibility
832
+
833
+ The checkbox component includes:
834
+ - Keyboard navigation support (Enter and Space keys)
835
+ - Focus visible ring for keyboard users
836
+ - Proper ARIA attributes
837
+ - Disabled state properly communicated to assistive technologies
838
+ - Tab navigation support
839
+
840
+ ## πŸ“ TypeScript Interfaces
841
+
842
+ ### CalendarRange
843
+
844
+ ```typescript
845
+ interface CalendarRange {
846
+ start: Date;
847
+ end: Date;
848
+ }
849
+ ```
850
+
851
+ ### CalendarSelection
852
+
853
+ ```typescript
854
+ interface CalendarSelection {
855
+ startDate: Date | null;
856
+ endDate: Date | null;
857
+ selectedDates?: Date[]; // For multi-date selection
858
+ }
859
+ ```
860
+
861
+ ### TimeConfiguration
862
+
863
+ ```typescript
864
+ interface TimeConfiguration {
865
+ date: Date;
866
+ allDay: boolean;
867
+ startTime: string; // Format: "HH:mm" or "HH:mm:ss"
868
+ endTime: string;
869
+ }
870
+ ```
871
+
872
+ ### ScheduledDateSelection
873
+
874
+ ```typescript
875
+ interface ScheduledDateSelection {
876
+ mode: 'single' | 'multiple' | 'range';
877
+ singleDate?: {
878
+ startDate: Date;
879
+ endDate: Date;
880
+ allDay: boolean;
881
+ startTime: string;
882
+ endTime: string;
883
+ };
884
+ multipleDates?: TimeConfiguration[];
885
+ dateRange?: {
886
+ startDate: Date;
887
+ endDate: Date;
888
+ allDay: boolean;
889
+ startTime: string;
890
+ endTime: string;
891
+ };
892
+ }
893
+ ```
894
+
895
+ ## 🎯 Common Use Cases
896
+
897
+ ### Form Integration
898
+
899
+ ```typescript
900
+ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
901
+ import { CustomCalendarComponent } from '@brickclay/ui';
902
+
903
+ export class BookingFormComponent {
904
+ bookingForm: FormGroup;
905
+
906
+ constructor(private fb: FormBuilder) {
907
+ this.bookingForm = this.fb.group({
908
+ checkIn: [null, Validators.required],
909
+ checkOut: [null, Validators.required]
910
+ });
911
+ }
912
+
913
+ onDateSelected(selection: CalendarSelection) {
914
+ this.bookingForm.patchValue({
915
+ checkIn: selection.startDate,
916
+ checkOut: selection.endDate
917
+ });
918
+ }
919
+ }
920
+ ```
921
+
922
+ ### Reactive Forms
923
+
924
+ ```typescript
925
+ <brickclay-custom-calendar
926
+ [selectedValue]="form.get('dateRange')?.value"
927
+ (selected)="form.patchValue({ dateRange: $event })">
928
+ </brickclay-custom-calendar>
929
+ ```
930
+
931
+ ### Date Filtering
932
+
933
+ ```typescript
934
+ export class DataTableComponent {
935
+ filterDates: CalendarSelection = { startDate: null, endDate: null };
936
+
937
+ onDateFilter(selection: CalendarSelection) {
938
+ this.filterDates = selection;
939
+ this.loadFilteredData();
940
+ }
941
+
942
+ loadFilteredData() {
943
+ const filtered = this.data.filter(item => {
944
+ if (!this.filterDates.startDate || !this.filterDates.endDate) {
945
+ return true;
946
+ }
947
+ return item.date >= this.filterDates.startDate! &&
948
+ item.date <= this.filterDates.endDate!;
949
+ });
950
+ }
951
+ }
952
+ ```
953
+
954
+ ## πŸ“¦ Assets Configuration
955
+
956
+ The calendar components require SVG icons. Configure your `angular.json` to copy assets:
957
+
958
+ ```json
959
+ {
960
+ "glob": "**/*",
961
+ "input": "node_modules/@brickclay/ui/assets",
962
+ "output": "assets"
963
+ }
964
+ ```
965
+
966
+ Or manually copy assets from:
967
+ ```
968
+ node_modules/@brickclay/ui/assets/calender/* β†’ your-app/public/assets/calender/
969
+ ```
970
+
971
+ ## πŸ”§ Service
972
+
973
+ ### CalendarManagerService
974
+
975
+ 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`.
976
+
977
+ ## 🌐 Browser Support
978
+
979
+ - Chrome (latest)
980
+ - Firefox (latest)
981
+ - Safari (latest)
982
+ - Edge (latest)
983
+
984
+ ## πŸ“¦ Dependencies
985
+
986
+ - Angular 20.3.0+
987
+ - moment (for date formatting)
988
+
989
+ ## 🀝 Contributing
990
+
991
+ We welcome contributions! Please see our contributing guidelines for more information.
992
+
993
+ ## πŸ“„ License
994
+
995
+ MIT
996
+
997
+ ## πŸ“ž Support
998
+
999
+ For issues, feature requests, or contributions, please visit our [GitHub repository](https://github.com/brickclay/ui).
1000
+
1001
+ ## πŸ—ΊοΈ Roadmap
1002
+
1003
+ - [ ] Button components
1004
+ - [ ] Input components
1005
+ - [ ] Card components
1006
+ - [ ] Modal/Dialog components
1007
+ - [ ] Table components
1008
+ - [ ] Form components
1009
+ - [ ] Navigation components
1010
+ - [ ] Loading/Spinner components
1011
+ - [ ] Toast/Notification components
1012
+ - [ ] More calendar features
1013
+
1014
+ ## πŸ“ Changelog
1015
+
1016
+ ### Version 0.0.1
1017
+
1018
+ **Initial Release:**
1019
+ - βœ… Calendar component suite
1020
+ - Single date selection
1021
+ - Date range selection
1022
+ - Multiple date selection
1023
+ - Time picker integration
1024
+ - Inline and dropdown modes
1025
+ - Dual calendar view
1026
+ - Custom date ranges
1027
+ - Date constraints (min/max)
1028
+ - βœ… Scheduled date picker component
1029
+ - βœ… Standalone time picker component
1030
+ - βœ… Toggle/Switch component
1031
+ - Angular forms integration (ngModel & reactive forms)
1032
+ - Three size variants (small, medium, large)
1033
+ - Disabled state support
1034
+ - Full accessibility features
1035
+ - Customizable styling
1036
+ - βœ… Checkbox component
1037
+ - Angular forms integration (ngModel & reactive forms)
1038
+ - Four size variants (small, medium, large, extra-large)
1039
+ - Disabled state support
1040
+ - Full keyboard navigation support
1041
+ - Complete accessibility features
1042
+ - βœ… TypeScript definitions
1043
+ - βœ… Comprehensive documentation
1044
+
1045
+ ---
1046
+
1047
+ **Built with ❀️ by the Brickclay team**