@tacdaed/fragments 1.0.0-beta.0 → 1.0.0-beta.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.
Files changed (248) hide show
  1. package/README.md +2 -18
  2. package/ng-package.json +25 -0
  3. package/package.json +22 -29
  4. package/src/lib/components/accordion/accordion.component.html +103 -0
  5. package/src/lib/components/accordion/accordion.component.scss +382 -0
  6. package/src/lib/components/accordion/accordion.component.spec.ts +147 -0
  7. package/src/lib/components/accordion/accordion.component.ts +211 -0
  8. package/src/lib/components/accordion/accordion.type.ts +82 -0
  9. package/src/lib/components/breadcrumb/breadcrumb.component.html +43 -0
  10. package/src/lib/components/breadcrumb/breadcrumb.component.scss +112 -0
  11. package/src/lib/components/breadcrumb/breadcrumb.component.spec.ts +33 -0
  12. package/src/lib/components/breadcrumb/breadcrumb.component.ts +103 -0
  13. package/src/lib/components/breadcrumb/breadcrumb.interface.ts +7 -0
  14. package/src/lib/components/button/button.component.html +57 -0
  15. package/src/lib/components/button/button.component.scss +445 -0
  16. package/src/lib/components/button/button.component.spec.ts +99 -0
  17. package/src/lib/components/button/button.component.ts +143 -0
  18. package/src/lib/components/button/button.type.ts +7 -0
  19. package/src/lib/components/card/card.component.html +44 -0
  20. package/src/lib/components/card/card.component.scss +114 -0
  21. package/src/lib/components/card/card.component.spec.ts +65 -0
  22. package/src/lib/components/card/card.component.ts +21 -0
  23. package/src/lib/components/card/card.type.ts +3 -0
  24. package/src/lib/components/code-block/code-block.component.html +55 -0
  25. package/src/lib/components/code-block/code-block.component.scss +122 -0
  26. package/src/lib/components/code-block/code-block.component.spec.ts +81 -0
  27. package/src/lib/components/code-block/code-block.component.ts +302 -0
  28. package/src/lib/components/code-block/code-block.interface.ts +28 -0
  29. package/src/lib/components/code-block/code-block.type.ts +73 -0
  30. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.html +14 -0
  31. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.scss +20 -0
  32. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.spec.ts +38 -0
  33. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.ts +181 -0
  34. package/src/lib/components/input/input-base.ts +187 -0
  35. package/src/lib/components/input/input-calendar/input-calendar.component.html +76 -0
  36. package/src/lib/components/input/input-calendar/input-calendar.component.scss +179 -0
  37. package/src/lib/components/input/input-calendar/input-calendar.component.spec.ts +44 -0
  38. package/src/lib/components/input/input-calendar/input-calendar.component.ts +299 -0
  39. package/src/lib/components/input/input-checkbox/input-checkbox.component.html +37 -0
  40. package/src/lib/components/input/input-checkbox/input-checkbox.component.scss +128 -0
  41. package/src/lib/components/input/input-checkbox/input-checkbox.component.spec.ts +43 -0
  42. package/src/lib/components/input/input-checkbox/input-checkbox.component.ts +112 -0
  43. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.html +43 -0
  44. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.scss +140 -0
  45. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.spec.ts +62 -0
  46. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.ts +136 -0
  47. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.html +81 -0
  48. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.scss +228 -0
  49. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.spec.ts +62 -0
  50. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.ts +178 -0
  51. package/src/lib/components/input/input-consts.ts +132 -0
  52. package/src/lib/components/input/input-date/input-date-validators.ts +41 -0
  53. package/src/lib/components/input/input-date/input-date.component.html +41 -0
  54. package/src/lib/components/input/input-date/input-date.component.scss +95 -0
  55. package/src/lib/components/input/input-date/input-date.component.spec.ts +43 -0
  56. package/src/lib/components/input/input-date/input-date.component.ts +359 -0
  57. package/src/lib/components/input/input-date-time/input-date-time.component.html +70 -0
  58. package/src/lib/components/input/input-date-time/input-date-time.component.scss +133 -0
  59. package/src/lib/components/input/input-date-time/input-date-time.component.spec.ts +36 -0
  60. package/src/lib/components/input/input-date-time/input-date-time.component.ts +387 -0
  61. package/src/lib/components/input/input-file-upload/input-file-upload.component.html +89 -0
  62. package/src/lib/components/input/input-file-upload/input-file-upload.component.scss +171 -0
  63. package/src/lib/components/input/input-file-upload/input-file-upload.component.spec.ts +43 -0
  64. package/src/lib/components/input/input-file-upload/input-file-upload.component.ts +351 -0
  65. package/src/lib/components/input/input-interface.ts +8 -0
  66. package/src/lib/components/input/input-number/input-number-validators.ts +0 -0
  67. package/src/lib/components/input/input-number/input-number.component.html +51 -0
  68. package/src/lib/components/input/input-number/input-number.component.scss +140 -0
  69. package/src/lib/components/input/input-number/input-number.component.spec.ts +44 -0
  70. package/src/lib/components/input/input-number/input-number.component.ts +343 -0
  71. package/src/lib/components/input/input-radio-group/input-radio-group.component.html +44 -0
  72. package/src/lib/components/input/input-radio-group/input-radio-group.component.scss +139 -0
  73. package/src/lib/components/input/input-radio-group/input-radio-group.component.spec.ts +58 -0
  74. package/src/lib/components/input/input-radio-group/input-radio-group.component.ts +132 -0
  75. package/src/lib/components/input/input-slider/input-slider.component.html +111 -0
  76. package/src/lib/components/input/input-slider/input-slider.component.scss +203 -0
  77. package/src/lib/components/input/input-slider/input-slider.component.spec.ts +46 -0
  78. package/src/lib/components/input/input-slider/input-slider.component.ts +410 -0
  79. package/src/lib/components/input/input-text/input-text-validators.ts +67 -0
  80. package/src/lib/components/input/input-text/input-text.component.html +71 -0
  81. package/src/lib/components/input/input-text/input-text.component.scss +118 -0
  82. package/src/lib/components/input/input-text/input-text.component.spec.ts +55 -0
  83. package/src/lib/components/input/input-text/input-text.component.ts +215 -0
  84. package/src/lib/components/input/input-time/input-time-validators.ts +42 -0
  85. package/src/lib/components/input/input-time/input-time.component.html +92 -0
  86. package/src/lib/components/input/input-time/input-time.component.scss +191 -0
  87. package/src/lib/components/input/input-time/input-time.component.spec.ts +39 -0
  88. package/src/lib/components/input/input-time/input-time.component.ts +691 -0
  89. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.html +36 -0
  90. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.scss +121 -0
  91. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.spec.ts +54 -0
  92. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.ts +117 -0
  93. package/src/lib/components/input/input-type.ts +18 -0
  94. package/src/lib/components/input/input-validation/input-validation.component.html +19 -0
  95. package/src/lib/components/input/input-validation/input-validation.component.scss +39 -0
  96. package/src/lib/components/input/input-validation/input-validation.component.spec.ts +45 -0
  97. package/src/lib/components/input/input-validation/input-validation.component.ts +13 -0
  98. package/src/lib/components/input/input.pipe.ts +14 -0
  99. package/src/lib/components/layout/container/container.component.html +1 -0
  100. package/src/lib/components/layout/container/container.component.scss +33 -0
  101. package/src/lib/components/layout/container/container.component.ts +32 -0
  102. package/src/lib/components/layout/container/container.type.ts +1 -0
  103. package/src/lib/components/layout/divider/divider.component.html +1 -0
  104. package/src/lib/components/layout/divider/divider.component.scss +60 -0
  105. package/src/lib/components/layout/divider/divider.component.ts +38 -0
  106. package/src/lib/components/layout/divider/divider.type.ts +2 -0
  107. package/src/lib/components/layout/section/section.component.html +21 -0
  108. package/src/lib/components/layout/section/section.component.scss +43 -0
  109. package/src/lib/components/layout/section/section.component.ts +33 -0
  110. package/src/lib/components/layout/section/section.type.ts +2 -0
  111. package/src/lib/components/layout/separator/separator.component.html +9 -0
  112. package/src/lib/components/layout/separator/separator.component.scss +52 -0
  113. package/src/lib/components/layout/separator/separator.component.ts +25 -0
  114. package/src/lib/components/layout/separator/separator.type.ts +1 -0
  115. package/src/lib/components/loader/content-blur/content-blur.component.html +13 -0
  116. package/src/lib/components/loader/content-blur/content-blur.component.scss +43 -0
  117. package/src/lib/components/loader/content-blur/content-blur.component.spec.ts +42 -0
  118. package/src/lib/components/loader/content-blur/content-blur.component.ts +34 -0
  119. package/src/lib/components/loader/loader.type.ts +2 -0
  120. package/src/lib/components/loader/progress-bar/progress-bar.component.html +26 -0
  121. package/src/lib/components/loader/progress-bar/progress-bar.component.scss +151 -0
  122. package/src/lib/components/loader/progress-bar/progress-bar.component.spec.ts +47 -0
  123. package/src/lib/components/loader/progress-bar/progress-bar.component.ts +28 -0
  124. package/src/lib/components/loader/progress-bar/progress-bar.type.ts +8 -0
  125. package/src/lib/components/loader/pulse-loader/pulse-loader.component.html +12 -0
  126. package/src/lib/components/loader/pulse-loader/pulse-loader.component.scss +202 -0
  127. package/src/lib/components/loader/pulse-loader/pulse-loader.component.spec.ts +55 -0
  128. package/src/lib/components/loader/pulse-loader/pulse-loader.component.ts +73 -0
  129. package/src/lib/components/loader/pulse-loader/pulse-loader.type.ts +6 -0
  130. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.html +13 -0
  131. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.scss +113 -0
  132. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.spec.ts +37 -0
  133. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.ts +51 -0
  134. package/src/lib/components/loader/skeleton-loader/skeleton-loader.type.ts +6 -0
  135. package/src/lib/components/loader/spinner/spinner.component.html +20 -0
  136. package/src/lib/components/loader/spinner/spinner.component.scss +137 -0
  137. package/src/lib/components/loader/spinner/spinner.component.spec.ts +43 -0
  138. package/src/lib/components/loader/spinner/spinner.component.ts +32 -0
  139. package/src/lib/components/loader/spinner/spinner.type.ts +6 -0
  140. package/src/lib/components/modal/modal.component.html +47 -0
  141. package/src/lib/components/modal/modal.component.scss +139 -0
  142. package/src/lib/components/modal/modal.component.spec.ts +60 -0
  143. package/src/lib/components/modal/modal.component.ts +83 -0
  144. package/src/lib/components/modal/modal.type.ts +9 -0
  145. package/src/lib/components/morph/blob-moph/blob-moprh.component.spec.ts +79 -0
  146. package/src/lib/components/morph/blob-moph/blob-moprh.component.ts +96 -0
  147. package/src/lib/components/morph/blob-moph/blob-morph.component.html +34 -0
  148. package/src/lib/components/morph/blob-moph/blob-morph.component.scss +7 -0
  149. package/src/lib/components/morph/morph.abstract.ts +13 -0
  150. package/src/lib/components/pagination/pagination.interface.ts +4 -0
  151. package/src/lib/components/pagination/small-pagination/small-pagination.component.html +61 -0
  152. package/src/lib/components/pagination/small-pagination/small-pagination.component.scss +187 -0
  153. package/src/lib/components/pagination/small-pagination/small-pagination.component.spec.ts +88 -0
  154. package/src/lib/components/pagination/small-pagination/small-pagination.component.ts +177 -0
  155. package/src/lib/components/selection-lists/multi-select/multi-select.component.html +170 -0
  156. package/src/lib/components/selection-lists/multi-select/multi-select.component.scss +312 -0
  157. package/src/lib/components/selection-lists/multi-select/multi-select.component.spec.ts +61 -0
  158. package/src/lib/components/selection-lists/multi-select/multi-select.component.ts +372 -0
  159. package/src/lib/components/selection-lists/selection-list/selection-list.component.html +125 -0
  160. package/src/lib/components/selection-lists/selection-list/selection-list.component.scss +267 -0
  161. package/src/lib/components/selection-lists/selection-list/selection-list.component.spec.ts +66 -0
  162. package/src/lib/components/selection-lists/selection-list/selection-list.component.ts +315 -0
  163. package/src/lib/components/selection-lists/selection-lists-base.ts +35 -0
  164. package/src/lib/components/selection-lists/selection-lists-const.ts +17 -0
  165. package/src/lib/components/selection-lists/selection-lists-interface.ts +7 -0
  166. package/src/lib/components/selection-lists/selection-lists.type.ts +1 -0
  167. package/src/lib/components/side-nav/side-nav.component.html +101 -0
  168. package/src/lib/components/side-nav/side-nav.component.scss +295 -0
  169. package/src/lib/components/side-nav/side-nav.component.spec.ts +0 -0
  170. package/src/lib/components/side-nav/side-nav.component.ts +18 -0
  171. package/src/lib/components/side-nav/side-nav.type.ts +28 -0
  172. package/src/lib/components/snackbar/snackbar.component.html +33 -0
  173. package/src/lib/components/snackbar/snackbar.component.scss +195 -0
  174. package/src/lib/components/snackbar/snackbar.component.ts +112 -0
  175. package/src/lib/components/snackbar/snackbar.type.ts +27 -0
  176. package/src/lib/components/status/chip/chip.component.html +51 -0
  177. package/src/lib/components/status/chip/chip.component.scss +149 -0
  178. package/src/lib/components/status/chip/chip.component.spec.ts +62 -0
  179. package/src/lib/components/status/chip/chip.component.ts +83 -0
  180. package/src/lib/components/status/chip/chip.type.ts +42 -0
  181. package/src/lib/components/status/directives/badge/badge.directive.spec.ts +60 -0
  182. package/src/lib/components/status/directives/badge/badge.directive.ts +190 -0
  183. package/src/lib/components/status/directives/badge/badge.interface.ts +19 -0
  184. package/src/lib/components/status/pill/pill.component.html +40 -0
  185. package/src/lib/components/status/pill/pill.component.scss +113 -0
  186. package/src/lib/components/status/pill/pill.component.spec.ts +47 -0
  187. package/src/lib/components/status/pill/pill.component.ts +83 -0
  188. package/src/lib/components/status/pill/pill.type.ts +42 -0
  189. package/src/lib/components/status/status.interface.ts +57 -0
  190. package/src/lib/components/status/status.type.ts +62 -0
  191. package/src/lib/components/status/tag/tag.component.html +39 -0
  192. package/src/lib/components/status/tag/tag.component.scss +140 -0
  193. package/src/lib/components/status/tag/tag.component.spec.ts +47 -0
  194. package/src/lib/components/status/tag/tag.component.ts +83 -0
  195. package/src/lib/components/status/tag/tag.type.ts +42 -0
  196. package/src/lib/components/stepper/stepper.component.html +83 -0
  197. package/src/lib/components/stepper/stepper.component.scss +196 -0
  198. package/src/lib/components/stepper/stepper.component.ts +482 -0
  199. package/src/lib/components/stepper/stepper.type.ts +60 -0
  200. package/src/lib/components/table/table.component.html +438 -0
  201. package/src/lib/components/table/table.component.scss +259 -0
  202. package/src/lib/components/table/table.component.spec.ts +117 -0
  203. package/src/lib/components/table/table.component.ts +215 -0
  204. package/src/lib/components/table/table.enum.ts +4 -0
  205. package/src/lib/components/table/table.function.ts +47 -0
  206. package/src/lib/components/table/table.interface.ts +143 -0
  207. package/src/lib/components/table/table.pipe.ts +62 -0
  208. package/src/lib/components/table/table.type.ts +15 -0
  209. package/src/lib/components/tabs/tabs.component.html +88 -0
  210. package/src/lib/components/tabs/tabs.component.scss +305 -0
  211. package/src/lib/components/tabs/tabs.component.spec.ts +94 -0
  212. package/src/lib/components/tabs/tabs.component.ts +282 -0
  213. package/src/lib/components/tabs/tabs.type.ts +81 -0
  214. package/src/lib/components/title-bar/title-bar.component.html +21 -0
  215. package/src/lib/components/title-bar/title-bar.component.scss +139 -0
  216. package/src/lib/components/title-bar/title-bar.component.spec.ts +44 -0
  217. package/src/lib/components/title-bar/title-bar.component.ts +13 -0
  218. package/src/lib/components/toast/toast.component.html +36 -0
  219. package/src/lib/components/toast/toast.component.scss +241 -0
  220. package/src/lib/components/toast/toast.component.ts +165 -0
  221. package/src/lib/components/toast/toast.type.ts +37 -0
  222. package/src/lib/components/toast-stack/toast-stack.component.html +30 -0
  223. package/src/lib/components/toast-stack/toast-stack.component.scss +35 -0
  224. package/src/lib/components/toast-stack/toast-stack.component.ts +51 -0
  225. package/src/lib/consts/country-prefix.ts +244 -0
  226. package/src/lib/directives/tooltip/popover.directive.ts +274 -0
  227. package/src/lib/directives/tooltip/tooltip.directive.spec.ts +86 -0
  228. package/src/lib/directives/tooltip/tooltip.directive.ts +234 -0
  229. package/src/lib/directives/tooltip/tooltip.interface.ts +29 -0
  230. package/src/lib/directives/tooltip/tooltip.type.ts +9 -0
  231. package/src/lib/interfaces/common.interfaces.ts +4 -0
  232. package/src/lib/pipes/chunk.pipe.ts +16 -0
  233. package/src/lib/pipes/safe-html.pipe.ts +14 -0
  234. package/src/lib/pipes/sanitize-html.pipe.ts +23 -0
  235. package/src/lib/types/base.types.ts +23 -0
  236. package/src/lib/types/common.types.ts +98 -0
  237. package/src/lib/types/form.types.ts +5 -0
  238. package/src/lib/utils/common.utils.ts +53 -0
  239. package/src/lib/utils/date.utils.ts +474 -0
  240. package/src/lib/utils/number.utils.ts +16 -0
  241. package/src/lib/utils/uuid.utils.ts +39 -0
  242. package/src/public-api.ts +114 -0
  243. package/tsconfig.lib.json +17 -0
  244. package/tsconfig.lib.prod.json +10 -0
  245. package/tsconfig.spec.json +9 -0
  246. package/fesm2022/fragments.mjs +0 -8928
  247. package/fesm2022/fragments.mjs.map +0 -1
  248. package/index.d.ts +0 -3929
@@ -0,0 +1,178 @@
1
+ import { AsyncPipe } from '@angular/common';
2
+ import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
3
+ import { BehaviorSubject } from 'rxjs';
4
+ import { TimeFormat } from '../../../types/common.types';
5
+ import { calculateHourDegree, calculateMinuteDegree, isMeridiemFormat } from '../../../utils/date.utils';
6
+ import { InputTimeMeridiem } from '../input-type';
7
+
8
+ @Component({
9
+ selector: 'frg-input-clock-picker',
10
+ imports: [AsyncPipe],
11
+ templateUrl: './input-clock-picker.component.html',
12
+ styleUrls: ['./input-clock-picker.component.scss'],
13
+ changeDetection: ChangeDetectionStrategy.OnPush,
14
+ })
15
+ export class InputClockPickerComponent implements OnInit {
16
+ /**Selected hour in string format ("00".."23") */
17
+ @Input() selectedHour: string | null = null;
18
+
19
+ /** Selected minute in string format ("00".."55" step 5) */
20
+ @Input() selectedMinute: string | null = null;
21
+
22
+ /** Selected meridiem for 12-hour format */
23
+ @Input() selectedMeridiem: InputTimeMeridiem = 'AM';
24
+
25
+ /** Time format configuration */
26
+ @Input() timeFormat: TimeFormat | null = null;
27
+
28
+ /** Emits the hour when user selects an hour */
29
+ @Output() selectHour: EventEmitter<string> = new EventEmitter<string>();
30
+
31
+ /** Emits the minute when user selects a minute */
32
+ @Output() selectMinute: EventEmitter<string> = new EventEmitter<string>();
33
+
34
+ /** Emits the meridiem when user toggles AM/PM */
35
+ @Output() selectMeridiem: EventEmitter<InputTimeMeridiem> = new EventEmitter<InputTimeMeridiem>();
36
+
37
+ /** Emits when the picker should be closed */
38
+ @Output() closePicker: EventEmitter<void> = new EventEmitter<void>();
39
+
40
+ /** Reference to the minute hand element */
41
+ @ViewChild('handMinutes', { static: true }) handMinutes!: ElementRef<HTMLDivElement>;
42
+
43
+ /** Reference to the hour hand element */
44
+ @ViewChild('handHours', { static: true }) handHours!: ElementRef<HTMLDivElement>;
45
+
46
+ /** Whether the minutes picker is visible */
47
+ public showMinutesPicker$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
48
+
49
+ /** Whether the hours picker is visible */
50
+ public showHoursPicker$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
51
+
52
+ private currentHourDegree: number | null = null;
53
+ private currentMinuteDegree: number | null = null;
54
+
55
+ public clockHours: Array<string> = Array.from({ length: 12 }, (_, i) => i.toString().padStart(2, '0'));
56
+ public fullClockHours: Array<string> = Array.from({ length: 12 }, (_, i) => (i + 12).toString().padStart(2, '0'));
57
+ public clockMinutes: Array<string> = Array.from({length: 12}, (_, i) => (i * 5).toString().padStart(2,'0'));
58
+
59
+ /** Returns the current time in HH:MM format */
60
+ public get timeValue(): string {
61
+ return `${this.selectedHour}:${this.selectedMinute}`;
62
+ }
63
+
64
+ /** Returns true if the time format is 12-hour */
65
+ protected get isMeridiemFormat(): boolean {
66
+ return isMeridiemFormat(this.timeFormat);
67
+ }
68
+
69
+ /**
70
+ * Initializes the hour and minute hands based on provided input values.
71
+ */
72
+ ngOnInit(): void {
73
+ if (this.selectedHour) {
74
+ this.currentHourDegree = calculateHourDegree(this.selectedHour);
75
+ this.handHours.nativeElement.style.setProperty('--angle', `${this.currentHourDegree}deg`);
76
+ }
77
+ if (this.selectedMinute) {
78
+ this.currentMinuteDegree = calculateMinuteDegree(this.selectedMinute);
79
+ this.handMinutes.nativeElement.style.setProperty('--angle', `${this.currentMinuteDegree}deg`);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Updates the hour hand to follow hover position.
85
+ * @param hour - The hour string being hovered ("00".."23").
86
+ */
87
+ protected onHourHover(hour: string): void {
88
+ const angle = calculateHourDegree(hour);
89
+ this.handHours.nativeElement.style.setProperty('--angle', `${angle}deg`);
90
+ }
91
+
92
+ /**
93
+ * Resets the hour hand to the currently selected hour when hover leaves.
94
+ */
95
+ protected onHourLeave(): void {
96
+ if (this.currentHourDegree) {
97
+ this.handHours.nativeElement.style.setProperty('--angle', `${this.currentHourDegree}deg`);
98
+ } else {
99
+ this.handHours.nativeElement.style.removeProperty('--angle');
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Handles user selection of an hour.
105
+ * @param event - The pointer event triggered by click.
106
+ * @param hour - The selected hour string ("00".."23").
107
+ */
108
+ protected onHourClick(event: PointerEvent, hour: string): void {
109
+ event.stopPropagation();
110
+ this.currentHourDegree = calculateHourDegree(hour);
111
+
112
+ this.selectedHour = hour;
113
+ this.selectHour.emit(hour);
114
+ this.showHoursPicker$.next(false);
115
+ this.showMinutesPicker$.next(true);
116
+
117
+ this.handHours.nativeElement.style.setProperty('--angle', `${this.currentHourDegree}deg`);
118
+ }
119
+
120
+ /**
121
+ * Handles AM/PM toggle for 12-hour format.
122
+ * @param event - The change event from the checkbox input.
123
+ */
124
+ protected onMeridiemChange(event: Event): void {
125
+ event.stopPropagation();
126
+ const target = event.target as HTMLInputElement;
127
+ this.selectedMeridiem = target.checked ? 'PM' : 'AM';
128
+ this.selectMeridiem.emit(this.selectedMeridiem);
129
+ }
130
+
131
+ /**
132
+ * Updates the minute hand to follow hover position.
133
+ * @param minute - The minute string being hovered ("00".."55", step 5).
134
+ */
135
+ protected onMinuteHover(minute: string): void {
136
+ const angle = calculateMinuteDegree(minute);
137
+ this.handMinutes.nativeElement.style.setProperty('--angle', `${angle}deg`);
138
+ }
139
+
140
+ /**
141
+ * Resets the minute hand to the currently selected minute when hover leaves.
142
+ */
143
+ protected onMinuteLeave(): void {
144
+ if (this.currentMinuteDegree) {
145
+ this.handMinutes.nativeElement.style.setProperty('--angle', `${this.currentMinuteDegree}deg`);
146
+ } else {
147
+ this.handMinutes.nativeElement.style.removeProperty('--angle');
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Handles user selection of a minute.
153
+ * @param event - The pointer event triggered by click.
154
+ * @param minute - The selected minute string ("00".."55", step 5).
155
+ */
156
+ protected onMinuteClick(event: PointerEvent, minute: string): void {
157
+ event.stopPropagation();
158
+ this.currentMinuteDegree = calculateMinuteDegree(minute);
159
+
160
+ this.selectedMinute = minute;
161
+ this.selectMinute.emit(minute);
162
+ this.showHoursPicker$.next(false);
163
+ this.showMinutesPicker$.next(true);
164
+
165
+ this.handMinutes.nativeElement.style.setProperty('--angle', `${this.currentMinuteDegree}deg`);
166
+ this.closePicker.emit();
167
+ }
168
+
169
+ protected showHours(): void {
170
+ this.showHoursPicker$.next(true);
171
+ this.showMinutesPicker$.next(false);
172
+ }
173
+
174
+ protected showMinutes(): void {
175
+ this.showHoursPicker$.next(false);
176
+ this.showMinutesPicker$.next(true);
177
+ }
178
+ }
@@ -0,0 +1,132 @@
1
+ //#region [ERRORS]
2
+ export const DEFAULT_INPUT_TEXT_ERROR_MESSAGES: Record<string, string> = {
3
+ required: 'This field is required.',
4
+ minlength: 'The value is too short.',
5
+ maxlength: 'The value is too long.',
6
+ pattern: 'The value does not match the required pattern.',
7
+ email: 'Please enter a valid email.',
8
+ strictEmail: 'Please enter a valid email. Format should be example@mail.com',
9
+ phone: 'Please enter a valid phone number.',
10
+ strictPhone: 'Please enter a valid phone number. Format should be +1234567890',
11
+ url: 'Please enter a url',
12
+ strictUrl: 'Please enter a valid url. Format should be https://www.google.it',
13
+ };
14
+
15
+ export const DEFAULT_INPUT_NUMBER_ERROR_MESSAGES: Record<string, string> = {
16
+ required: 'This field is required.',
17
+ min:'The value is less than minimum allowed',
18
+ max: 'The value is greather than maximum allowed',
19
+ step: 'The value does not match the required step increment value',
20
+ precision: 'The value exceeds the allowed number of decimal places value',
21
+ };
22
+
23
+ export const DEFAULT_INPUT_DATE_ERROR_MESSAGES: Record<string, string> = {
24
+ required: 'This field is required.',
25
+ min: 'The date is before the minimum allowed date: {{date}}',
26
+ max: 'The date is after the maximum allowed date: {{date}}',
27
+ };
28
+
29
+ export const DEFAULT_INPUT_TIME_ERROR_MESSAGES: Record<string, string> = {
30
+ required: 'This field is required.',
31
+ min: 'The time is before the minimum allowed time: {{time}}',
32
+ max: 'The time is after the maximum allowed time: {{time}}',
33
+ };
34
+
35
+ export const DEFAULT_INPUT_DATE_TIME_ERROR_MESSAGES: Record<string, string> = {
36
+ required: 'This field is required.',
37
+ min: 'The time is before the minimum allowed time: {{time}}',
38
+ max: 'The time is after the maximum allowed time: {{time}}',
39
+ };
40
+
41
+ export const DEFAULT_INPUT_TOGGLE_SWITCH_ERROR_MESSAGES: Record<string, string> = {
42
+ required: 'This field is required.',
43
+ };
44
+
45
+ export const DEFAULT_INPUT_CHECKBOX_ERROR_MESSAGES: Record<string, string> = {
46
+ required: 'This field is required.',
47
+ };
48
+
49
+ export const DEFAULT_INPUT_CHECKBOX_GROUP_ERROR_MESSAGES: Record<string, string> = {
50
+ required: 'This field is required.',
51
+ };
52
+
53
+ export const DEFAULT_INPUT_RADIO_GROUP_ERROR_MESSAGES: Record<string, string> = {
54
+ required: 'This field is required.',
55
+ };
56
+
57
+ export const DEFAULT_INPUT_SLIDER_ERROR_MESSAGES: Record<string, string> = {
58
+ required: 'This field is required.',
59
+ min:'The value is less than minimum allowed',
60
+ max: 'The value is greather than maximum allowed',
61
+ step: 'The value does not match the required step increment value',
62
+ };
63
+
64
+ export const DEFAULT_INPUT_FILE_UPLOAD_ERROR_MESSAGES: Record<string, string> = {
65
+ required: 'Please select a file.',
66
+ maxFiles: 'Select at most {{limit}} file(s).',
67
+ maxFileSize: 'Each file must be smaller than {{limit}}.',
68
+ maxTotalSize: 'Total size must be smaller than {{limit}}.',
69
+ accept: 'Only files of type {{accept}} are allowed.',
70
+ };
71
+ //#endregion
72
+
73
+ //#region [WARNINGS]
74
+ export const DEFAULT_INPUT_NUMBER_WARNING_MESSAGES: Record<string, string> = {
75
+ min:'The minimium value allowed is {{limit}}',
76
+ max: 'The maximum value allowed is {{limit}}',
77
+ step: 'The value does not match the required step increment value of {{limit}}',
78
+ precision: 'The value exceeds the allowed number of decimal places value of {{limit}}',
79
+ };
80
+
81
+ export const DEFAULT_INPUT_DATE_WARNINGS_MESSAGES: Record<string, string> = {
82
+ format: 'The date is not in correct format {{format}}',
83
+ min: 'The date is before the minimum allowed date: {{limit}}',
84
+ max: 'The date is after the maximum allowed date: {{limit}}'
85
+ };
86
+
87
+ export const DEFAULT_INPUT_TIME_WARNINGS_MESSAGES: Record<string, string> = {
88
+ format: 'The time is not in correct format {{format}}',
89
+ min: 'The time is before the minimum allowed time: {{limit}}',
90
+ max: 'The time is after the maximum allowed time: {{limit}}'
91
+ };
92
+
93
+ export const DEFAULT_INPUT_DATE_TIME_WARNINGS_MESSAGES: Record<string, string> = {
94
+ format: 'The date and time are not in correct format {{format}}',
95
+ min: 'The date and time are before the minimum allowed date and time: {{limit}}',
96
+ max: 'The date and time are after the maximum allowed date and time: {{limit}}'
97
+ };
98
+
99
+ export const DEFAULT_INPUT_TOGGLE_SWITCH_WARNINGS_MESSAGES: Record<string, string> = {
100
+ // No warnings for toggle switch
101
+ };
102
+
103
+ export const DEFAULT_INPUT_CHECKBOX_WARNINGS_MESSAGES: Record<string, string> = {
104
+ // No warnings for checkbox
105
+ };
106
+
107
+ export const DEFAULT_INPUT_CHECKBOX_GROUP_WARNINGS_MESSAGES: Record<string, string> = {
108
+ // No warnings for checkbox group
109
+ };
110
+
111
+ export const DEFAULT_INPUT_RADIO_GROUP_WARNINGS_MESSAGES: Record<string, string> = {
112
+ // No warnings for radio group
113
+ };
114
+
115
+ export const DEFAULT_INPUT_MULTI_SELECT_WARNINGS_MESSAGES: Record<string, string> = {
116
+ // No warnings for multi select
117
+ };
118
+
119
+ export const DEFAULT_INPUT_SELECTION_LIST_WARNINGS_MESSAGES: Record<string, string> = {
120
+ // No warnings for selection list
121
+ };
122
+
123
+ export const DEFAULT_INPUT_TEXT_WARNINGS_MESSAGES: Record<string, string> = {
124
+ // No warnings for text input
125
+ };
126
+
127
+ export const DEFAULT_INPUT_SLIDER_WARNING_MESSAGES: Record<string, string> = {
128
+ min:'The minimium value allowed is {{limit}}',
129
+ max: 'The maximum value allowed is {{limit}}',
130
+ step: 'The value does not match the required step increment value of {{limit}}',
131
+ };
132
+ //#endregion
@@ -0,0 +1,41 @@
1
+ import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
2
+
3
+ export function minDate(min: Date): ValidatorFn {
4
+ return (control: AbstractControl): ValidationErrors | null => {
5
+ const value = control.value as Date | null;
6
+ if (value && value < min) {
7
+ return { min: true };
8
+ }
9
+ return null;
10
+ };
11
+ }
12
+
13
+ export function maxDate(max: Date): ValidatorFn {
14
+ return (control: AbstractControl): ValidationErrors | null => {
15
+ const value = control.value as Date | null;
16
+ if (value && value > max) {
17
+ return { max: true };
18
+ }
19
+ return null;
20
+ };
21
+ }
22
+
23
+ export function afterDate(min: Date): ValidatorFn {
24
+ return (control: AbstractControl): ValidationErrors | null => {
25
+ const value = control.value as Date | null;
26
+ if (value && value <= min) {
27
+ return { after: true };
28
+ }
29
+ return null;
30
+ };
31
+ }
32
+
33
+ export function beforeDate(max: Date): ValidatorFn {
34
+ return (control: AbstractControl): ValidationErrors | null => {
35
+ const value = control.value as Date | null;
36
+ if (value && value >= max) {
37
+ return { before: true };
38
+ }
39
+ return null;
40
+ };
41
+ }
@@ -0,0 +1,41 @@
1
+ <div class="frg-input__wrapper"
2
+ [class.input-error]="hasError"
3
+ [class.input-warning]="hasWarning">
4
+ @if(label){
5
+ <label [for]="id">{{ label | inputRequiredLabel: required }}</label>
6
+ }
7
+ <div class="frg-input__field">
8
+ <input
9
+ [id]="id"
10
+ [type]="inputType"
11
+ [placeholder]="placeholder"
12
+ [required]="required"
13
+ [disabled]="disabled"
14
+ [value]="formatDate(value)"
15
+ (blur)="onBlur($event)"
16
+ (focus)="onFocus($event)"
17
+ (input)="onInput($event)"
18
+ />
19
+ <button class="far fa-calendar frg-input__calendar-button"
20
+ aria-label="Open calendar"
21
+ (click)="toggleCalendar()"
22
+ ></button>
23
+ </div>
24
+ @if(showCalendar$ | async){
25
+ <frg-input-calendar
26
+ [minDate]="minDate"
27
+ [maxDate]="maxDate"
28
+ [selectedValue]="value"
29
+ (selectDate)="selectDate($event)">
30
+ </frg-input-calendar>
31
+ }
32
+ </div>
33
+
34
+ @if (showValidation) {
35
+ <frg-input-validation
36
+ [errorList]="errorList"
37
+ [warningList]="warningList"
38
+ [isFormInvalid]="hasError"
39
+ >
40
+ </frg-input-validation>
41
+ }
@@ -0,0 +1,95 @@
1
+ @use "sass:color";
2
+ @use './../../../../../assets/styles/scss/variables' as *;
3
+
4
+ :host {
5
+ display: block;
6
+ font-family: $input-font-family;
7
+
8
+ label {
9
+ display: flex;
10
+ font-size: $font-size-xs;
11
+ color: $input-text-color;
12
+ padding: $input-padding;
13
+ }
14
+
15
+ .frg-input {
16
+ &__wrapper {
17
+ display: inline-block;
18
+
19
+ &.input-error label {
20
+ color: $color-danger;
21
+ }
22
+
23
+ &.input-error .frg-input__field::after {
24
+ width: 100%;
25
+ right: 0;
26
+ }
27
+ }
28
+
29
+ &__field {
30
+ display: inline-flex;
31
+ align-items: center;
32
+ justify-content: space-between;
33
+ padding: $input-padding;
34
+ border-bottom: 2px solid $input-border-color;
35
+ font-family: $input-font-family;
36
+ background: transparent;
37
+ position: relative;
38
+ width: 100%;
39
+
40
+ input {
41
+ border: none;
42
+ background: transparent;
43
+
44
+ &:focus {
45
+ outline: none;
46
+ }
47
+ }
48
+
49
+ span {
50
+ margin-left: 0.5rem;
51
+ cursor: pointer;
52
+ color: $input-text-color;
53
+ }
54
+
55
+ &::before {
56
+ content: "";
57
+ position: absolute;
58
+ bottom: -2px;
59
+ left: -50%;
60
+ width: 0;
61
+ height: 0.125rem;
62
+ background: $input-focus-border-color;
63
+ transition: width 0.3s ease, left 0.3s ease;
64
+ }
65
+
66
+ &:has(input:focus)::before {
67
+ width: 100%;
68
+ left: 0;
69
+ }
70
+
71
+ &::after {
72
+ content: "";
73
+ position: absolute;
74
+ bottom: -2px;
75
+ right: -50%;
76
+ width: 0;
77
+ height: 0.125rem;
78
+ background: $color-danger;
79
+ transition: width 0.3s ease, right 0.3s ease;
80
+ }
81
+ }
82
+
83
+ &__calendar-button {
84
+ border: none;
85
+ background: transparent;
86
+
87
+ &:focus,
88
+ &:focus-visible,
89
+ &:focus-within {
90
+ border: none;
91
+ outline: none;
92
+ }
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,43 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { By } from '@angular/platform-browser';
3
+ import { InputDateComponent } from './input-date.component';
4
+
5
+ describe('InputDateComponent', () => {
6
+ let fixture: ComponentFixture<InputDateComponent>;
7
+ let component: InputDateComponent;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [InputDateComponent]
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(InputDateComponent);
15
+ component = fixture.componentInstance;
16
+ });
17
+
18
+ it('uses text input type for date', () => {
19
+ fixture.detectChanges();
20
+
21
+ const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement;
22
+ expect(input.type).toBe('text');
23
+ });
24
+
25
+ it('toggles calendar on button click', () => {
26
+ fixture.detectChanges();
27
+
28
+ const button = fixture.debugElement.query(By.css('.frg-input__calendar-button'));
29
+ button.nativeElement.click();
30
+
31
+ expect(component.showCalendar$.value).toBeTrue();
32
+ });
33
+
34
+ it('selectDate sets value and closes calendar', () => {
35
+ const date = new Date(2024, 0, 1);
36
+ component.showCalendar$.next(true);
37
+
38
+ (component as any).selectDate(date);
39
+
40
+ expect(component.value).toEqual(date);
41
+ expect(component.showCalendar$.value).toBeFalse();
42
+ });
43
+ });