@brickclay-org/ui 0.0.39 → 0.0.40

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.
Files changed (56) hide show
  1. package/ASSETS_SETUP.md +59 -0
  2. package/ng-package.json +29 -0
  3. package/package.json +15 -26
  4. package/src/lib/assets/icons.ts +8 -0
  5. package/src/lib/badge/badge.html +24 -0
  6. package/src/lib/badge/badge.ts +42 -0
  7. package/src/lib/brickclay-lib.spec.ts +23 -0
  8. package/src/lib/brickclay-lib.ts +15 -0
  9. package/src/lib/button-group/button-group.html +12 -0
  10. package/src/lib/button-group/button-group.ts +73 -0
  11. package/src/lib/calender/calendar.module.ts +35 -0
  12. package/src/lib/calender/components/custom-calendar/custom-calendar.component.css +698 -0
  13. package/src/lib/calender/components/custom-calendar/custom-calendar.component.html +230 -0
  14. package/src/lib/calender/components/custom-calendar/custom-calendar.component.spec.ts +23 -0
  15. package/src/lib/calender/components/custom-calendar/custom-calendar.component.ts +1554 -0
  16. package/src/lib/calender/components/scheduled-date-picker/scheduled-date-picker.component.css +373 -0
  17. package/src/lib/calender/components/scheduled-date-picker/scheduled-date-picker.component.html +210 -0
  18. package/src/lib/calender/components/scheduled-date-picker/scheduled-date-picker.component.ts +361 -0
  19. package/src/lib/calender/components/time-picker/time-picker.component.css +174 -0
  20. package/src/lib/calender/components/time-picker/time-picker.component.html +60 -0
  21. package/src/lib/calender/components/time-picker/time-picker.component.ts +283 -0
  22. package/src/lib/calender/services/calendar-manager.service.ts +45 -0
  23. package/src/lib/checkbox/checkbox.html +42 -0
  24. package/src/lib/checkbox/checkbox.ts +67 -0
  25. package/src/lib/chips/chips.html +74 -0
  26. package/src/lib/chips/chips.ts +222 -0
  27. package/src/lib/grid/components/grid/grid.html +97 -0
  28. package/src/lib/grid/components/grid/grid.ts +139 -0
  29. package/src/lib/grid/models/grid.model.ts +20 -0
  30. package/src/lib/input/input.html +127 -0
  31. package/src/lib/input/input.ts +394 -0
  32. package/src/lib/pill/pill.html +24 -0
  33. package/src/lib/pill/pill.ts +39 -0
  34. package/src/lib/radio/radio.html +58 -0
  35. package/src/lib/radio/radio.ts +72 -0
  36. package/src/lib/select/select.html +111 -0
  37. package/src/lib/select/select.ts +401 -0
  38. package/src/lib/spinner/spinner.html +5 -0
  39. package/src/lib/spinner/spinner.ts +22 -0
  40. package/src/lib/tabs/tabs.html +28 -0
  41. package/src/lib/tabs/tabs.ts +48 -0
  42. package/src/lib/textarea/textarea.html +80 -0
  43. package/src/lib/textarea/textarea.ts +172 -0
  44. package/src/lib/toggle/toggle.html +24 -0
  45. package/src/lib/toggle/toggle.ts +62 -0
  46. package/src/lib/ui-button/ui-button.html +25 -0
  47. package/src/lib/ui-button/ui-button.ts +55 -0
  48. package/src/lib/ui-icon-button/ui-icon-button.html +7 -0
  49. package/src/lib/ui-icon-button/ui-icon-button.ts +38 -0
  50. package/src/public-api.ts +43 -0
  51. package/tsconfig.lib.json +19 -0
  52. package/tsconfig.lib.prod.json +11 -0
  53. package/tsconfig.spec.json +15 -0
  54. package/fesm2022/brickclay-org-ui.mjs +0 -4035
  55. package/fesm2022/brickclay-org-ui.mjs.map +0 -1
  56. package/index.d.ts +0 -857
@@ -0,0 +1,361 @@
1
+ import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { BkCustomCalendar, CalendarSelection } from '../custom-calendar/custom-calendar.component';
5
+ import { BkTimePicker } from '../time-picker/time-picker.component';
6
+
7
+ export interface TimeConfiguration {
8
+ date: Date;
9
+ allDay: boolean;
10
+ startTime: string; // Format: "HH:mm" or "HH:mm:ss"
11
+ endTime: string; // Format: "HH:mm" or "HH:mm:ss"
12
+ }
13
+
14
+ export interface ScheduledDateSelection {
15
+ mode: 'single' | 'multiple' | 'range';
16
+ singleDate?: {
17
+ startDate: Date;
18
+ endDate: Date;
19
+ allDay: boolean;
20
+ startTime: string;
21
+ endTime: string;
22
+ };
23
+ multipleDates?: TimeConfiguration[];
24
+ dateRange?: {
25
+ startDate: Date;
26
+ endDate: Date;
27
+ allDay: boolean;
28
+ startTime: string;
29
+ endTime: string;
30
+ };
31
+ }
32
+
33
+ @Component({
34
+ selector: 'bk-scheduled-date-picker',
35
+ standalone: true,
36
+ imports: [CommonModule, FormsModule, BkCustomCalendar, BkTimePicker],
37
+ templateUrl: './scheduled-date-picker.component.html',
38
+ styleUrls: ['./scheduled-date-picker.component.css']
39
+ })
40
+ export class BkScheduledDatePicker implements OnInit {
41
+ @Input() timeFormat: 12 | 24 = 12;
42
+ @Input() enableSeconds = false;
43
+
44
+ @Output() scheduled = new EventEmitter<ScheduledDateSelection>();
45
+ @Output() cleared = new EventEmitter<void>();
46
+
47
+ activeTab: 'single' | 'multiple' | 'range' = 'single';
48
+ openTimePickerId: string | null = null; // Track which time picker is currently open
49
+ closePickerCounter: { [key: string]: number } = {}; // Track close signals for each picker
50
+
51
+ // Single Date
52
+ singleDate: Date | null = null;
53
+ singleAllDay = false;
54
+ singleStartTime = '1:00 AM';
55
+ singleEndTime = '2:00 AM';
56
+
57
+ // Multiple Dates
58
+ multipleDates: TimeConfiguration[] = [];
59
+
60
+ // Date Range
61
+ rangeStartDate: Date | null = null;
62
+ rangeEndDate: Date | null = null;
63
+ rangeAllDay = false;
64
+ rangeStartTime = '1:00 AM';
65
+ rangeEndTime = '2:00 AM';
66
+
67
+ ngOnInit() {
68
+ // Initialize with default time if needed
69
+ }
70
+
71
+ onTabChange(tab: 'single' | 'multiple' | 'range') {
72
+ this.activeTab = tab;
73
+ this.openTimePickerId = null; // Close any open pickers when switching tabs
74
+ }
75
+
76
+ onTimePickerOpened(pickerId: string) {
77
+ // Close all other pickers when one opens
78
+ if (this.openTimePickerId && this.openTimePickerId !== pickerId) {
79
+ // Increment close counter for the previously open picker
80
+ if (!this.closePickerCounter[this.openTimePickerId]) {
81
+ this.closePickerCounter[this.openTimePickerId] = 0;
82
+ }
83
+ this.closePickerCounter[this.openTimePickerId]++;
84
+ }
85
+ this.openTimePickerId = pickerId;
86
+ }
87
+
88
+ onTimePickerClosed(pickerId: string) {
89
+ // Reset open picker ID if this was the open one
90
+ if (this.openTimePickerId === pickerId) {
91
+ this.openTimePickerId = null;
92
+ }
93
+ }
94
+
95
+ shouldClosePicker(pickerId: string): number {
96
+ // Return the counter value for this picker (triggers change detection)
97
+ return this.closePickerCounter[pickerId] || 0;
98
+ }
99
+
100
+ // Single Date Handlers
101
+ onSingleDateSelected(event: CalendarSelection) {
102
+ if (event.startDate) {
103
+ this.singleDate = new Date(event.startDate);
104
+ // Initialize time if not all day
105
+ if (!this.singleAllDay) {
106
+ this.updateSingleDateTimes();
107
+ }
108
+ this.emitScheduled();
109
+ } else {
110
+ this.singleDate = null;
111
+ }
112
+ }
113
+
114
+ onSingleAllDayChange() {
115
+ this.singleAllDay = !this.singleAllDay;
116
+ if (this.singleDate) {
117
+ this.updateSingleDateTimes();
118
+ this.emitScheduled();
119
+ }
120
+ }
121
+
122
+ onSingleStartTimeChange(time: string) {
123
+ this.singleStartTime = time;
124
+ if (this.singleDate) {
125
+ this.updateSingleDateTimes();
126
+ this.emitScheduled();
127
+ }
128
+ }
129
+
130
+ onSingleEndTimeChange(time: string) {
131
+ this.singleEndTime = time;
132
+ if (this.singleDate) {
133
+ this.updateSingleDateTimes();
134
+ this.emitScheduled();
135
+ }
136
+ }
137
+
138
+ updateSingleDateTimes() {
139
+ if (!this.singleDate) return;
140
+ if (this.singleAllDay) {
141
+ this.singleDate.setHours(0, 0, 0, 0);
142
+ } else {
143
+ const startTime = this.parseTimeString(this.singleStartTime);
144
+ const endTime = this.parseTimeString(this.singleEndTime);
145
+ this.singleDate.setHours(startTime.hours, startTime.minutes, 0, 0);
146
+ }
147
+ }
148
+
149
+ // Multiple Dates Handlers
150
+ onMultipleDatesSelected(event: CalendarSelection) {
151
+ if (event.selectedDates && event.selectedDates.length > 0) {
152
+ const newDates: TimeConfiguration[] = [];
153
+
154
+ event.selectedDates.forEach(date => {
155
+ // const dateStr = this.getDateString(date);
156
+ const dateStr = date;
157
+ const existing = this.multipleDates.find(d => this.getDateString(d.date) === dateStr);
158
+
159
+ if (existing) {
160
+ newDates.push(existing);
161
+ } else {
162
+ // Create new time configuration for this date
163
+ newDates.push({
164
+ date: new Date(date),
165
+ allDay: false,
166
+ startTime: '1:00 AM',
167
+ endTime: '2:00 AM'
168
+ });
169
+ }
170
+ });
171
+
172
+ this.multipleDates = newDates;
173
+ this.emitScheduled();
174
+ } else {
175
+ this.multipleDates = [];
176
+ this.emitScheduled();
177
+ }
178
+ }
179
+
180
+ onMultipleDateAllDayChange(index: number) {
181
+ if (this.multipleDates[index]) {
182
+ this.multipleDates[index].allDay = !this.multipleDates[index].allDay;
183
+ if (this.multipleDates[index].allDay) {
184
+ this.multipleDates[index].date.setHours(0, 0, 0, 0);
185
+ } else {
186
+ const time = this.parseTimeString(this.multipleDates[index].startTime);
187
+ this.multipleDates[index].date.setHours(time.hours, time.minutes, 0, 0);
188
+ }
189
+ this.emitScheduled();
190
+ }
191
+ }
192
+
193
+ onMultipleDateStartTimeChange(index: number, time: string) {
194
+ if (this.multipleDates[index]) {
195
+ this.multipleDates[index].startTime = time;
196
+ if (!this.multipleDates[index].allDay) {
197
+ const parsed = this.parseTimeString(time);
198
+ this.multipleDates[index].date.setHours(parsed.hours, parsed.minutes, 0, 0);
199
+ }
200
+ this.emitScheduled();
201
+ }
202
+ }
203
+
204
+ onMultipleDateEndTimeChange(index: number, time: string) {
205
+ if (this.multipleDates[index]) {
206
+ this.multipleDates[index].endTime = time;
207
+ this.emitScheduled();
208
+ }
209
+ }
210
+
211
+ // Date Range Handlers
212
+ onRangeSelected(event: CalendarSelection) {
213
+ if (event.startDate && event.endDate) {
214
+ this.rangeStartDate = new Date(event.startDate);
215
+ this.rangeEndDate = new Date(event.endDate);
216
+ if (!this.rangeAllDay) {
217
+ this.updateRangeTimes();
218
+ }
219
+ this.emitScheduled();
220
+ } else {
221
+ this.rangeStartDate = null;
222
+ this.rangeEndDate = null;
223
+ }
224
+ }
225
+
226
+ onRangeAllDayChange() {
227
+ this.rangeAllDay = !this.rangeAllDay;
228
+ if (this.rangeStartDate && this.rangeEndDate) {
229
+ this.updateRangeTimes();
230
+ this.emitScheduled();
231
+ }
232
+ }
233
+
234
+ onRangeStartTimeChange(time: string) {
235
+ this.rangeStartTime = time;
236
+ if (this.rangeStartDate && !this.rangeAllDay) {
237
+ this.updateRangeTimes();
238
+ this.emitScheduled();
239
+ }
240
+ }
241
+
242
+ onRangeEndTimeChange(time: string) {
243
+ this.rangeEndTime = time;
244
+ if (this.rangeEndDate && !this.rangeAllDay) {
245
+ this.updateRangeTimes();
246
+ this.emitScheduled();
247
+ }
248
+ }
249
+
250
+ updateRangeTimes() {
251
+ if (!this.rangeStartDate || !this.rangeEndDate) return;
252
+
253
+ if (this.rangeAllDay) {
254
+ this.rangeStartDate.setHours(0, 0, 0, 0);
255
+ this.rangeEndDate.setHours(23, 59, 59, 999);
256
+ } else {
257
+ const startTime = this.parseTimeString(this.rangeStartTime);
258
+ const endTime = this.parseTimeString(this.rangeEndTime);
259
+ this.rangeStartDate.setHours(startTime.hours, startTime.minutes, 0, 0);
260
+ this.rangeEndDate.setHours(endTime.hours, endTime.minutes, 0, 0);
261
+ }
262
+ }
263
+
264
+ // Utility Methods
265
+ parseTimeString(timeStr: string): { hours: number; minutes: number } {
266
+ // Parse time string like "7:01 AM" or "19:01"
267
+ const parts = timeStr.split(' ');
268
+ let timePart = parts[0];
269
+ const ampm = parts[1];
270
+
271
+ const [hoursStr, minutesStr] = timePart.split(':');
272
+ let hours = parseInt(hoursStr, 10);
273
+ const minutes = parseInt(minutesStr || '0', 10);
274
+
275
+ if (ampm) {
276
+ if (ampm.toUpperCase() === 'PM' && hours !== 12) {
277
+ hours += 12;
278
+ } else if (ampm.toUpperCase() === 'AM' && hours === 12) {
279
+ hours = 0;
280
+ }
281
+ }
282
+
283
+ return { hours, minutes };
284
+ }
285
+
286
+ getDateString(date: Date): string {
287
+ return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
288
+ }
289
+
290
+ formatDate(date: Date): string {
291
+ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
292
+ return `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
293
+ }
294
+
295
+ emitScheduled() {
296
+ const selection: ScheduledDateSelection = {
297
+ mode: this.activeTab
298
+ };
299
+
300
+ if (this.activeTab === 'single' && this.singleDate) {
301
+ // For single date, create startDate and endDate with same date but different times
302
+ const startDate = new Date(this.singleDate);
303
+ const endDate = new Date(this.singleDate);
304
+
305
+ if (!this.singleAllDay) {
306
+ const startTime = this.parseTimeString(this.singleStartTime);
307
+ const endTime = this.parseTimeString(this.singleEndTime);
308
+ startDate.setHours(startTime.hours, startTime.minutes, 0, 0);
309
+ endDate.setHours(endTime.hours, endTime.minutes, 0, 0);
310
+ } else {
311
+ startDate.setHours(0, 0, 0, 0);
312
+ endDate.setHours(23, 59, 59, 999);
313
+ }
314
+
315
+ selection.singleDate = {
316
+ startDate: startDate,
317
+ endDate: endDate,
318
+ allDay: this.singleAllDay,
319
+ startTime: this.singleStartTime,
320
+ endTime: this.singleEndTime
321
+ };
322
+ } else if (this.activeTab === 'multiple') {
323
+ selection.multipleDates = this.multipleDates.map(d => ({
324
+ date: new Date(d.date),
325
+ allDay: d.allDay,
326
+ startTime: d.startTime,
327
+ endTime: d.endTime
328
+ }));
329
+ } else if (this.activeTab === 'range' && this.rangeStartDate && this.rangeEndDate) {
330
+ selection.dateRange = {
331
+ startDate: new Date(this.rangeStartDate),
332
+ endDate: new Date(this.rangeEndDate),
333
+ allDay: this.rangeAllDay,
334
+ startTime: this.rangeStartTime,
335
+ endTime: this.rangeEndTime
336
+ };
337
+ }
338
+
339
+ this.scheduled.emit(selection);
340
+ }
341
+
342
+ clear() {
343
+ this.singleDate = null;
344
+ this.multipleDates = [];
345
+ this.rangeStartDate = null;
346
+ this.rangeEndDate = null;
347
+ this.singleAllDay = false;
348
+ this.rangeAllDay = false;
349
+ this.singleStartTime = '1:00 AM';
350
+ this.singleEndTime = '2:00 AM';
351
+ this.rangeStartTime = '1:00 AM';
352
+ this.rangeEndTime = '2:00 AM';
353
+ this.cleared.emit();
354
+ }
355
+
356
+ apply() {
357
+ this.emitScheduled();
358
+ }
359
+
360
+ }
361
+
@@ -0,0 +1,174 @@
1
+ .time-picker-wrapper {
2
+ width: 100%;
3
+ font-family: 'Inter', sans-serif;
4
+ }
5
+
6
+ .time-input-group {
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: 4px;
10
+ }
11
+
12
+ .time-input-group label {
13
+ font-size: 11px;
14
+ font-weight: 500;
15
+ color: #15191E;
16
+ text-transform: uppercase;
17
+ letter-spacing: -0.28px;
18
+ }
19
+
20
+ .time-input-wrapper {
21
+ position: relative;
22
+ display: flex;
23
+ align-items: center;
24
+ }
25
+
26
+ .time-input {
27
+ padding: 8px 40px 8px 12px;
28
+ border: 1px solid #d1d5db;
29
+ border-radius: 4px;
30
+ font-size: 12px;
31
+ font-family: 'Inter', sans-serif;
32
+ color: #6F737B;
33
+ background: #ffffff;
34
+ transition: all 0.2s;
35
+ width: 100%;
36
+ box-sizing: border-box;
37
+ cursor: pointer;
38
+ }
39
+
40
+ .time-input:focus {
41
+ outline: none;
42
+ border-color: #111827;
43
+ box-shadow: 0 0 0 3px rgba(17, 24, 39, 0.1);
44
+ }
45
+
46
+ .time-input:hover {
47
+ border-color: #9ca3af;
48
+ }
49
+
50
+ .time-icon {
51
+ position: absolute;
52
+ right: 12px;
53
+ font-size: 16px;
54
+ pointer-events: none;
55
+ color: #9ca3af;
56
+ cursor: pointer;
57
+ }
58
+
59
+ /* Custom Time Picker Dropdown */
60
+ /* .custom-time-picker-dropdown {
61
+ position: absolute;
62
+ top: calc(100% + 4px);
63
+ left: 0;
64
+ z-index: 1000;
65
+ width: 172px;
66
+ min-width: 172px;
67
+ } */
68
+
69
+ .custom-time-picker-wrapper {
70
+ width: 100%;
71
+ display: flex;
72
+ justify-content: center;
73
+ }
74
+
75
+ .custom-time-picker {
76
+ display: flex;
77
+ /* align-items: center; */
78
+ gap: 8px;
79
+ background: #ffffff;
80
+ border: 1px solid #e5e7eb;
81
+ border-radius: 8px;
82
+ padding: 10px;
83
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
84
+ width:182px;
85
+ position: absolute;
86
+ top: calc(100% + 4px);
87
+ /* right: 0; */
88
+ z-index: 1000;
89
+ }
90
+ .custom-time-picker.left-position {
91
+ left: 0;
92
+ }
93
+ .custom-time-picker.right-position {
94
+ right: 0;
95
+ }
96
+ .time-column {
97
+ display: flex;
98
+ flex-direction: column;
99
+ position: relative;
100
+ }
101
+
102
+ .time-scroll {
103
+ display: flex;
104
+ flex-direction: column;
105
+ max-height: 95px;
106
+ overflow-y: auto;
107
+ overflow-x: hidden;
108
+ scrollbar-width: thin;
109
+ scrollbar-color: #cbd5e1 transparent;
110
+ /* padding: 4px 0; */
111
+ scrollbar-width: none; /* For Firefox */
112
+ -ms-overflow-style: none; /* For Internet Explorer and Edge */
113
+ }
114
+
115
+
116
+ .time-scroll::-webkit-scrollbar {
117
+ display: none; /* For Chrome, Safari, and Opera */
118
+ /* width: 4px; */
119
+ }
120
+
121
+ .time-scroll::-webkit-scrollbar-track {
122
+ background: transparent;
123
+ }
124
+
125
+ .time-scroll::-webkit-scrollbar-thumb {
126
+ background: #cbd5e1;
127
+ border-radius: 2px;
128
+ }
129
+
130
+ .time-scroll::-webkit-scrollbar-thumb:hover {
131
+ background: #94a3b8;
132
+ }
133
+
134
+ .time-item {
135
+ min-width: 40px;
136
+ width: 40px;
137
+ height: 32px;
138
+ min-height: 32px;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ font-size: 14px;
143
+ font-weight: 400;
144
+ color: #374151;
145
+ cursor: pointer;
146
+ border-radius: 4px;
147
+ transition: all 0.15s ease;
148
+ user-select: none;
149
+ font-family: 'Inter', sans-serif;
150
+ }
151
+
152
+ .time-item:hover {
153
+ background: #f3f4f6;
154
+ }
155
+
156
+ .time-item.selected {
157
+ background: #111827;
158
+ color: #ffffff;
159
+ font-weight: 500;
160
+ box-shadow: 0 1px 2px rgba(37, 99, 235, 0.3);
161
+ }
162
+
163
+ .ampm-column .time-item {
164
+ min-width: 40px;
165
+ width: 40px;
166
+ }
167
+
168
+ .time-separator {
169
+ font-size: 16px;
170
+ font-weight: 600;
171
+ color: #6b7280;
172
+ margin: 5px 0 0px;
173
+ }
174
+
@@ -0,0 +1,60 @@
1
+ <div class="time-picker-wrapper">
2
+ <div class="time-input-group">
3
+ <label *ngIf="label">{{ label }}</label>
4
+ <div class="time-input-wrapper">
5
+ <input
6
+ type="text"
7
+ class="time-input"
8
+ [value]="value"
9
+ [placeholder]="placeholder"
10
+ readonly
11
+ (click)="togglePicker()">
12
+ <span class="time-icon">
13
+ <img alt="timer" class="timer-icon" [src]='brickclayIcons.timerIcon'/>
14
+ </span>
15
+ <div class="custom-time-picker-dropdown" *ngIf="showPicker">
16
+ <div class="custom-time-picker" [ngClass]="position === 'left' ? 'left-position' : 'right-position'">
17
+ <!-- Hours Column -->
18
+ <div class="time-column">
19
+ <div class="time-scroll" #timeScroll>
20
+ <div
21
+ *ngFor="let h of getHours()"
22
+ class="time-item"
23
+ [class.selected]="currentHour === h"
24
+ (click)="onHourChange(h)">
25
+ {{ h.toString().padStart(2, '0') }}
26
+ </div>
27
+ </div>
28
+ </div>
29
+ <span class="time-separator">:</span>
30
+ <!-- Minutes Column -->
31
+ <div class="time-column">
32
+ <div class="time-scroll" #timeScroll>
33
+ <div
34
+ *ngFor="let m of getMinutes()"
35
+ class="time-item"
36
+ [class.selected]="currentMinute === m"
37
+ (click)="onMinuteChange(m)">
38
+ {{ m.toString().padStart(2, '0') }}
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <span class="time-separator">:</span>
43
+ <!-- AM/PM Column -->
44
+ <div class="time-column ampm-column">
45
+ <div class="time-scroll" #timeScroll>
46
+ <div
47
+ *ngFor="let ap of getAMPMOptions()"
48
+ class="time-item"
49
+ [class.selected]="currentAMPM === ap"
50
+ (click)="onAMPMChange(ap)">
51
+ {{ ap }}
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </div>
60
+